Firmware SDK
twr_module_lcd.c
1 #include <stm32l0xx.h>
2 #include <twr_module_lcd.h>
3 #include <twr_tca9534a.h>
4 #include <twr_scheduler.h>
5 #include <twr_ls013b7dh03.h>
6 
7 enum
8 {
9  _TWR_MODULE_LCD_BACKLIGHT_PIN = TWR_TCA9534A_PIN_P0,
10  _TWR_MODULE_LCD_BUTTON1_PIN = TWR_TCA9534A_PIN_P1,
11  _TWR_MODULE_LCD_DISP_ON_PIN = TWR_TCA9534A_PIN_P2,
12  _TWR_MODULE_LCD_BUTTON2_PIN = TWR_TCA9534A_PIN_P3,
13  _TWR_MODULE_LCD_LED_GREEN_PIN = TWR_TCA9534A_PIN_P4,
14  _TWR_MODULE_LCD_LED_RED_PIN = TWR_TCA9534A_PIN_P5,
15  _TWR_MODULE_LCD_LED_BLUE_PIN = TWR_TCA9534A_PIN_P6,
16  _TWR_MODULE_LCD_LED_DISP_CS_PIN = TWR_TCA9534A_PIN_P7
17 };
18 
19 #define _TWR_MODULE_LCD_INITIALIZED ((1 << _TWR_MODULE_LCD_BACKLIGHT_PIN) | (1 << _TWR_MODULE_LCD_LED_DISP_CS_PIN) | (1 << _TWR_MODULE_LCD_DISP_ON_PIN) | (1 << _TWR_MODULE_LCD_LED_GREEN_PIN) | (1 << _TWR_MODULE_LCD_LED_RED_PIN) | (1 << _TWR_MODULE_LCD_LED_BLUE_PIN))
20 
21 typedef struct twr_module_lcd_t
22 {
23  void (*event_handler)(twr_module_lcd_event_t, void *);
24  void *event_param;
25  bool is_tca9534a_initialized;
26  twr_tca9534a_t tca9534a;
27  twr_ls013b7dh03_t ls013b7dh03;
28  twr_gfx_t gfx;
29 
30  twr_button_t button_left;
31  twr_button_t button_right;
32 
34 
35 twr_module_lcd_t _twr_module_lcd;
36 
37 static twr_tca9534a_pin_t _twr_module_lcd_led_pin_lut[3] =
38 {
39  [TWR_MODULE_LCD_LED_RED] = TWR_TCA9534A_PIN_P5,
40  [TWR_MODULE_LCD_LED_GREEN] = TWR_TCA9534A_PIN_P4,
41  [TWR_MODULE_LCD_LED_BLUE] = TWR_TCA9534A_PIN_P6
42 };
43 
44 static twr_tca9534a_pin_t _twr_module_lcd_button_pin_lut[2] =
45 {
46  [TWR_MODULE_LCD_BUTTON_LEFT] = TWR_TCA9534A_PIN_P3,
47  [TWR_MODULE_LCD_BUTTON_RIGHT] = TWR_TCA9534A_PIN_P1
48 };
49 
50 static bool _twr_module_lcd_tca9534a_init(void);
51 
52 static bool _twr_module_lcd_cs_pin_set(bool state);
53 
54 static void _twr_module_lcd_led_init(twr_led_t *self);
55 
56 static void _twr_module_lcd_led_on(twr_led_t *self);
57 
58 static void _twr_module_lcd_led_off(twr_led_t *self);
59 
60 static void _twr_module_lcd_button_init(twr_button_t *self);
61 
62 static int _twr_module_lcd_button_get_input(twr_button_t *self);
63 
65 {
66  _twr_module_lcd_tca9534a_init();
67 
68  twr_ls013b7dh03_init(&_twr_module_lcd.ls013b7dh03, _twr_module_lcd_cs_pin_set);
69 
70  twr_gfx_init(&_twr_module_lcd.gfx, &_twr_module_lcd.ls013b7dh03, twr_ls013b7dh03_get_driver());
71 
72  twr_gfx_clear(&_twr_module_lcd.gfx);
73 }
74 
76 {
77  return &_twr_module_lcd.gfx;
78 }
79 
81 {
82  return twr_tca9534a_write_pin(&_twr_module_lcd.tca9534a, _TWR_MODULE_LCD_DISP_ON_PIN, 1);
83 }
84 
86 {
87  return twr_tca9534a_write_pin(&_twr_module_lcd.tca9534a, _TWR_MODULE_LCD_DISP_ON_PIN, 0);
88 }
89 
91 {
92  return _twr_module_lcd_tca9534a_init();
93 }
94 
96 {
97  return _twr_module_lcd_tca9534a_init() && twr_gfx_display_is_ready(&_twr_module_lcd.gfx);
98 }
99 
101 {
102  twr_gfx_clear(&_twr_module_lcd.gfx);
103 }
104 
105 void twr_module_lcd_draw_pixel(int x, int y, bool value)
106 {
107  twr_gfx_draw_pixel(&_twr_module_lcd.gfx, x, y, value);
108 }
109 
110 int twr_module_lcd_draw_char(int left, int top, uint8_t ch, bool color)
111 {
112  return twr_gfx_draw_char(&_twr_module_lcd.gfx, left, top, ch, color);
113 }
114 
115 int twr_module_lcd_draw_string(int left, int top, char *str, bool color)
116 {
117  return twr_gfx_draw_string(&_twr_module_lcd.gfx, left, top, str, color);
118 }
119 
120 
121 void twr_module_lcd_draw(const uint8_t *frame, uint8_t width, uint8_t height) // In pixels
122 {
123  (void)frame;
124  (void)width;
125  (void)height;
126 }
127 
128 void twr_module_lcd_printf(uint8_t line, /*uint8_t size, font, */const uint8_t *string/*, ...*/)
129 {
130  (void) line;
131  (void) string;
132 }
133 
134 void twr_module_lcd_draw_line(int x0, int y0, int x1, int y1, bool color)
135 {
136  twr_gfx_draw_line(&_twr_module_lcd.gfx, x0, y0, x1, y1, color);
137 }
138 
139 void twr_module_lcd_draw_rectangle(int x0, int y0, int x1, int y1, bool color)
140 {
141  twr_gfx_draw_rectangle(&_twr_module_lcd.gfx, x0, y0, x1, y1, color);
142 }
143 
144 void twr_module_lcd_draw_circle(int x0, int y0, int radius, bool color)
145 {
146  twr_gfx_draw_circle(&_twr_module_lcd.gfx, x0, y0, radius, color);
147 }
148 
149 void twr_module_lcd_draw_image(int left, int top, const twr_image_t *img)
150 {
151  uint8_t line;
152  uint8_t row;
153  uint8_t bytes_per_row = img->width / 8;
154 
155  if(img->width % 8 != 0)
156  {
157  bytes_per_row++;
158  }
159 
160  twr_tick_t start = twr_tick_get();
161 
162  for (row = 0; row < img->height; row++) {
163  for (line = 0; line < img->width; line++) {
164  uint32_t byte_offset = line / 8 + row * bytes_per_row;
165  uint32_t bit = line % 8;
166  twr_gfx_draw_pixel(&_twr_module_lcd.gfx, line + left, row + top, (img->data[byte_offset]) & (1 << bit));
167  }
168  }
169  volatile twr_tick_t duration = twr_tick_get() - start;
170  (void)duration;
171 
172 }
173 
175 {
176  return twr_gfx_update(&_twr_module_lcd.gfx);
177 }
178 
180 {
181  twr_gfx_set_font(&_twr_module_lcd.gfx, font);
182 }
183 
184 static void _twr_module_lcd_button_event_handler(twr_button_t *self, twr_button_event_t event, void *event_param)
185 {
186  (void) event_param;
187 
188  if (self == &_twr_module_lcd.button_left)
189  {
190  if (event == TWR_BUTTON_EVENT_PRESS)
191  {
192  _twr_module_lcd.event_handler(TWR_MODULE_LCD_EVENT_LEFT_PRESS, _twr_module_lcd.event_param);
193  }
194  if (event == TWR_BUTTON_EVENT_RELEASE)
195  {
196  _twr_module_lcd.event_handler(TWR_MODULE_LCD_EVENT_LEFT_RELEASE, _twr_module_lcd.event_param);
197  }
198  if (event == TWR_BUTTON_EVENT_CLICK)
199  {
200  _twr_module_lcd.event_handler(TWR_MODULE_LCD_EVENT_LEFT_CLICK, _twr_module_lcd.event_param);
201  }
202  if (event == TWR_BUTTON_EVENT_HOLD)
203  {
204  if (_twr_module_lcd.button_right._state)
205  {
206  _twr_module_lcd.event_handler(TWR_MODULE_LCD_EVENT_BOTH_HOLD, _twr_module_lcd.event_param);
207  // Force _hold_signalized to true, so the hold event of the second button won't trigger which would cause event duplication
208  _twr_module_lcd.button_right._hold_signalized = true;
209  }
210  else
211  {
212  _twr_module_lcd.event_handler(TWR_MODULE_LCD_EVENT_LEFT_HOLD, _twr_module_lcd.event_param);
213  }
214  }
215  }
216 
217  if (self == &_twr_module_lcd.button_right)
218  {
219  if (event == TWR_BUTTON_EVENT_PRESS)
220  {
221  _twr_module_lcd.event_handler(TWR_MODULE_LCD_EVENT_RIGHT_PRESS, _twr_module_lcd.event_param);
222  }
223  if (event == TWR_BUTTON_EVENT_RELEASE)
224  {
225  _twr_module_lcd.event_handler(TWR_MODULE_LCD_EVENT_RIGHT_RELEASE, _twr_module_lcd.event_param);
226  }
227  if (event == TWR_BUTTON_EVENT_CLICK)
228  {
229  _twr_module_lcd.event_handler(TWR_MODULE_LCD_EVENT_RIGHT_CLICK, _twr_module_lcd.event_param);
230  }
231  if (event == TWR_BUTTON_EVENT_HOLD)
232  {
233  if (_twr_module_lcd.button_left._state)
234  {
235  _twr_module_lcd.event_handler(TWR_MODULE_LCD_EVENT_BOTH_HOLD, _twr_module_lcd.event_param);
236  // Force _hold_signalized to true, so the hold event of the second button won't trigger which would cause event duplication
237  _twr_module_lcd.button_left._hold_signalized = true;
238  }
239  else
240  {
241  _twr_module_lcd.event_handler(TWR_MODULE_LCD_EVENT_RIGHT_HOLD, _twr_module_lcd.event_param);
242  }
243  }
244  }
245 }
246 
247 void twr_module_lcd_set_event_handler(void (*event_handler)(twr_module_lcd_event_t, void *), void *event_param)
248 {
249  _twr_module_lcd.event_handler = event_handler;
250  _twr_module_lcd.event_param = event_param;
251 
252  const twr_button_driver_t* lcdButtonDriver = twr_module_lcd_get_button_driver();
253 
254  twr_button_init_virtual(&_twr_module_lcd.button_left, 0, lcdButtonDriver, 0);
255  twr_button_init_virtual(&_twr_module_lcd.button_right, 1, lcdButtonDriver, 0);
256 
257  twr_button_set_event_handler(&_twr_module_lcd.button_left, _twr_module_lcd_button_event_handler, (int*)0);
258  twr_button_set_event_handler(&_twr_module_lcd.button_right, _twr_module_lcd_button_event_handler, (int*)1);
259 }
260 
262 {
263  twr_button_set_hold_time(&_twr_module_lcd.button_left, hold_time);
264  twr_button_set_hold_time(&_twr_module_lcd.button_right, hold_time);
265 }
266 
268 {
269  twr_button_set_scan_interval(&_twr_module_lcd.button_left, scan_interval);
270  twr_button_set_scan_interval(&_twr_module_lcd.button_right, scan_interval);
271 }
272 
274 {
275  twr_button_set_debounce_time(&_twr_module_lcd.button_left, debounce_time);
276  twr_button_set_debounce_time(&_twr_module_lcd.button_right, debounce_time);
277 }
278 
280 {
281  twr_button_set_click_timeout(&_twr_module_lcd.button_left, click_timeout);
282  twr_button_set_click_timeout(&_twr_module_lcd.button_right, click_timeout);
283 }
284 
286 {
287  twr_gfx_set_rotation(&_twr_module_lcd.gfx, rotation);
288 }
289 
291 {
292  return twr_gfx_get_rotation(&_twr_module_lcd.gfx);
293 }
294 
296 {
297  static const twr_led_driver_t twr_module_lcd_led_driver =
298  {
299  .init = _twr_module_lcd_led_init,
300  .on = _twr_module_lcd_led_on,
301  .off = _twr_module_lcd_led_off,
302  };
303 
304  return &twr_module_lcd_led_driver;
305 }
306 
308 {
309  static const twr_button_driver_t twr_module_lcd_button_driver =
310  {
311  .init = _twr_module_lcd_button_init,
312  .get_input = _twr_module_lcd_button_get_input,
313  };
314 
315  return &twr_module_lcd_button_driver;
316 }
317 
318 static bool _twr_module_lcd_tca9534a_init(void)
319 {
320  if (!_twr_module_lcd.is_tca9534a_initialized)
321  {
322  if (!twr_tca9534a_init(&_twr_module_lcd.tca9534a, TWR_I2C_I2C0, 0x3c))
323  {
324  return false;
325  }
326 
327  if (!twr_tca9534a_write_port(&_twr_module_lcd.tca9534a, _TWR_MODULE_LCD_INITIALIZED))
328  {
329  return false;
330  }
331 
332  if (!twr_tca9534a_set_port_direction(&_twr_module_lcd.tca9534a, (1 << _TWR_MODULE_LCD_BUTTON1_PIN) | (1 << _TWR_MODULE_LCD_BUTTON2_PIN)))
333  {
334  return false;
335  }
336 
337  _twr_module_lcd.is_tca9534a_initialized = true;
338  }
339 
340  return true;
341 }
342 
343 static bool _twr_module_lcd_cs_pin_set(bool state)
344 {
345  if (!_twr_module_lcd_tca9534a_init())
346  {
347  return false;
348  }
349 
350  if (!twr_tca9534a_write_pin(&_twr_module_lcd.tca9534a, _TWR_MODULE_LCD_LED_DISP_CS_PIN, state))
351  {
352  _twr_module_lcd.is_tca9534a_initialized = false;
353 
354  return false;
355  }
356 
357  return true;
358 }
359 
360 static void _twr_module_lcd_led_init(twr_led_t *self)
361 {
362  (void) self;
363 
364  _twr_module_lcd_tca9534a_init();
365 }
366 
367 static void _twr_module_lcd_led_on(twr_led_t *self)
368 {
369  if (!twr_tca9534a_write_pin(&_twr_module_lcd.tca9534a, _twr_module_lcd_led_pin_lut[self->_channel.virtual], self->_idle_state ? 0 : 1))
370  {
371  _twr_module_lcd.is_tca9534a_initialized = false;
372  }
373 }
374 
375 static void _twr_module_lcd_led_off(twr_led_t *self)
376 {
377  if (!twr_tca9534a_write_pin(&_twr_module_lcd.tca9534a, _twr_module_lcd_led_pin_lut[self->_channel.virtual], self->_idle_state ? 1 : 0))
378  {
379  _twr_module_lcd.is_tca9534a_initialized = false;
380  }
381 }
382 
383 static void _twr_module_lcd_button_init(twr_button_t *self)
384 {
385  (void) self;
386 
387  _twr_module_lcd_tca9534a_init();
388 
391 }
392 
393 static int _twr_module_lcd_button_get_input(twr_button_t *self)
394 {
396  {
397  return 0;
398  }
399 
400  int state;
401 
402  if (!twr_tca9534a_read_pin(&_twr_module_lcd.tca9534a, _twr_module_lcd_button_pin_lut[self->_channel.virtual], &state))
403  {
404  _twr_module_lcd.is_tca9534a_initialized = false;
405  return 0;
406  }
407 
408  return state;
409 }
void twr_gpio_set_mode(twr_gpio_channel_t channel, twr_gpio_mode_t mode)
Set mode of operation for GPIO channel.
Definition: twr_gpio.c:367
twr_button_event_t
Callback events.
Definition: twr_button.h:14
void twr_button_set_debounce_time(twr_button_t *self, twr_tick_t debounce_time)
Set debounce time (minimum sampling interval during which input cannot change to toggle its state) ...
Definition: twr_button.c:88
void twr_module_lcd_draw_pixel(int x, int y, bool value)
Lcd draw pixel.
Event button hold (pressed for longer time)
Definition: twr_button.h:26
twr_module_lcd_rotation_t
Rotation.
void twr_module_lcd_set_button_click_timeout(twr_tick_t click_timeout)
Set click timeout (maximum interval within which button has to be released to recognize click event) ...
void twr_module_lcd_draw_line(int x0, int y0, int x1, int y1, bool color)
Lcd draw line.
void twr_module_lcd_init()
Initialize lcd.
int twr_module_lcd_draw_string(int left, int top, char *str, bool color)
Lcd draw string.
Button driver interface.
Definition: twr_button.h:36
void twr_button_set_hold_time(twr_button_t *self, twr_tick_t hold_time)
Set hold time (interval after which hold event is recognized when button is steadily pressed) ...
Definition: twr_button.c:98
bool twr_tca9534a_write_port(twr_tca9534a_t *self, uint8_t state)
Write state to all pins.
Definition: twr_tca9534a.c:35
Event button pressed.
Definition: twr_button.h:17
const twr_led_driver_t * twr_module_lcd_get_led_driver(void)
Lcd get led driver.
LCD right button channel.
int twr_gpio_get_input(twr_gpio_channel_t channel)
Get input state for GPIO channel.
Definition: twr_gpio.c:465
void twr_ls013b7dh03_init(twr_ls013b7dh03_t *self, bool(*pin_cs_set)(bool state))
Initialize lcd driver.
GPIO channel BUTTON.
Definition: twr_gpio.h:72
twr_module_lcd_rotation_t twr_module_lcd_get_rotation(void)
Lcd get rotation.
Event button clicked (pressed and released within certain time)
Definition: twr_button.h:23
LCD red LED channel.
twr_module_lcd_event_t
Callback events.
void twr_button_set_event_handler(twr_button_t *self, void(*event_handler)(twr_button_t *, twr_button_event_t, void *), void *event_param)
Set callback function.
Definition: twr_button.c:66
void twr_module_lcd_set_event_handler(void(*event_handler)(twr_module_lcd_event_t, void *), void *event_param)
Lcd set event handler for buttons.
void twr_gfx_clear(twr_gfx_t *self)
Clear.
Definition: twr_gfx.c:22
void twr_module_lcd_set_rotation(twr_module_lcd_rotation_t rotation)
Lcd set rotation.
LCD left button channel.
bool twr_tca9534a_read_pin(twr_tca9534a_t *self, twr_tca9534a_pin_t pin, int *state)
Read pin state.
Definition: twr_tca9534a.c:47
void(* init)(twr_button_t *self)
Callback for initialization.
Definition: twr_button.h:39
void twr_module_lcd_set_button_debounce_time(twr_tick_t debounce_time)
Set debounce time (minimum sampling interval during which input cannot change to toggle its state) ...
struct twr_led_t twr_led_t
LED instance.
Definition: twr_led.h:52
void twr_gfx_draw_pixel(twr_gfx_t *self, int x, int y, uint32_t color)
Draw pixel.
Definition: twr_gfx.c:42
bool twr_tca9534a_init(twr_tca9534a_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize TCA9534A.
Definition: twr_tca9534a.c:8
int twr_gfx_draw_string(twr_gfx_t *self, int left, int top, char *str, uint32_t color)
Display draw string.
Definition: twr_gfx.c:152
bool twr_tca9534a_write_pin(twr_tca9534a_t *self, twr_tca9534a_pin_t pin, int state)
Write pin state.
Definition: twr_tca9534a.c:61
const twr_button_driver_t * twr_module_lcd_get_button_driver(void)
Lcd get button driver.
void twr_gfx_draw_rectangle(twr_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
Display draw rectangle.
Definition: twr_gfx.c:278
Instance.
Definition: twr_gfx.h:80
const twr_gfx_driver_t * twr_ls013b7dh03_get_driver(void)
Get Lcd driver.
bool twr_gfx_display_is_ready(twr_gfx_t *self)
Check if display driver is ready for commands.
Definition: twr_gfx.c:12
void twr_module_lcd_draw_circle(int x0, int y0, int radius, bool color)
Lcd draw circle.
bool twr_module_lcd_is_ready(void)
Check if lcd is ready for commands.
void twr_gpio_init(twr_gpio_channel_t channel)
Initialize GPIO channel.
Definition: twr_gpio.c:325
void twr_module_lcd_set_button_hold_time(twr_tick_t hold_time)
Set hold time (interval after which hold event is recognized when button is steadily pressed) ...
bool twr_module_lcd_on(void)
Lcd on.
void twr_module_lcd_draw_image(int left, int top, const twr_image_t *img)
Lcd draw image.
twr_gfx_t * twr_module_lcd_get_gfx()
Get gfx instance.
bool twr_gfx_update(twr_gfx_t *self)
Display update, send data.
Definition: twr_gfx.c:476
void(* init)(twr_led_t *self)
Callback for initialization.
Definition: twr_led.h:59
uint64_t twr_tick_t
Timestamp data type.
Definition: twr_tick.h:16
void twr_module_lcd_clear(void)
Lcd clear.
void twr_button_init_virtual(twr_button_t *self, int channel, const twr_button_driver_t *driver, int idle_state)
Initialize virtual button.
Definition: twr_button.c:43
Pin state.
Definition: twr_tca9534a.h:42
void twr_module_lcd_set_font(const twr_font_t *font)
Lcd set font.
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
Definition: twr_tick.c:7
bool twr_module_lcd_is_present(void)
Get LCD Module is pressent, can use without twr_module_lcd_init.
LED driver interface.
Definition: twr_led.h:56
void twr_gfx_set_rotation(twr_gfx_t *self, twr_gfx_rotation_t rotation)
Set rotation.
Definition: twr_gfx.c:32
int twr_module_lcd_draw_char(int left, int top, uint8_t ch, bool color)
Lcd draw char.
twr_tca9534a_pin_t
Individual pin names.
Definition: twr_tca9534a.h:16
LCD green LED channel.
GPIO channel operates as input.
Definition: twr_gpio.h:105
int twr_gfx_draw_char(twr_gfx_t *self, int left, int top, uint8_t ch, uint32_t color)
Display draw char.
Definition: twr_gfx.c:86
I2C channel I2C0.
Definition: twr_i2c.h:18
void twr_gfx_draw_line(twr_gfx_t *self, int x0, int y0, int x1, int y1, uint32_t color)
Display draw line.
Definition: twr_gfx.c:188
bool twr_module_lcd_update(void)
Lcd update, send data.
LCD blue LED channel.
bool twr_tca9534a_set_port_direction(twr_tca9534a_t *self, uint8_t direction)
Set direction of all pins.
Definition: twr_tca9534a.c:87
bool twr_module_lcd_off(void)
Lcd off.
void twr_gfx_init(twr_gfx_t *self, void *display, const twr_gfx_driver_t *driver)
Initialize button.
Definition: twr_gfx.c:3
twr_gfx_rotation_t twr_gfx_get_rotation(twr_gfx_t *self)
Get rotation.
Definition: twr_gfx.c:37
void twr_button_set_scan_interval(twr_button_t *self, twr_tick_t scan_interval)
Set scan interval (period of button input sampling)
Definition: twr_button.c:83
void twr_button_set_click_timeout(twr_button_t *self, twr_tick_t click_timeout)
Set click timeout (maximum interval within which button has to be released to recognize click event) ...
Definition: twr_button.c:93
void twr_module_lcd_draw_rectangle(int x0, int y0, int x1, int y1, bool color)
Lcd draw rectangle.
void twr_gfx_set_font(twr_gfx_t *self, const twr_font_t *font)
Set font.
Definition: twr_gfx.c:27
void twr_module_lcd_set_button_scan_interval(twr_tick_t scan_interval)
Set scan interval (period of button input sampling)
struct twr_button_t twr_button_t
Button instance.
Definition: twr_button.h:32
void twr_gfx_draw_circle(twr_gfx_t *self, int x0, int y0, int radius, uint32_t color)
Lcd draw circle, using Midpoint circle algorithm.
Definition: twr_gfx.c:313
Event button released.
Definition: twr_button.h:20