Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_ls013b7dh03.c
1 #include <bc_ls013b7dh03.h>
2 #include <bc_spi.h>
3 
4 #define _BC_LS013B7DH03_VCOM_PERIOD 15000
5 
6 static void _bc_ls013b7dh03_task(void *param);
7 static bool _bc_ls013b7dh03_spi_transfer(bc_ls013b7dh03_t *self, uint8_t *buffer, size_t length);
8 static void _bc_ls013b7dh03_spi_event_handler(bc_spi_event_t event, void *event_param);
9 static inline uint8_t _bc_ls013b7dh03_reverse(uint8_t b);
10 
11 void bc_ls013b7dh03_init(bc_ls013b7dh03_t *self, bool (*pin_cs_set)(bool state))
12 {
13  memset(self, 0xff, sizeof(*self));
14 
15  self->_vcom = 0;
16  self->_pin_cs_set = pin_cs_set;
17 
19 
20  // Address lines
21  uint8_t line;
22  uint32_t offs;
23  for (line = 0x01, offs = 1; line <= 128; line++, offs += 18)
24  {
25  // Fill the gate line addresses on the exact place in the buffer
26  self->_framebuffer[offs] = _bc_ls013b7dh03_reverse(line);
27  }
28 
29  self->_pin_cs_set(1);
30 
31  self->_task_id = bc_scheduler_register(_bc_ls013b7dh03_task, self, _BC_LS013B7DH03_VCOM_PERIOD);
32 }
33 
35 {
36  (void) self;
37 
38  static const bc_gfx_caps_t caps = { .width = BC_LS013B7DH03_WIDTH, .height = BC_LS013B7DH03_HEIGHT };
39 
40  return caps;
41 }
42 
44 {
45  (void) self;
46 
47  return bc_spi_is_ready();
48 }
49 
51 {
52  uint8_t line;
53  uint32_t offs;
54  uint8_t col;
55  for (line = 0x01, offs = 2; line <= 128; line++, offs += 18)
56  {
57  for (col = 0; col < 16; col++)
58  {
59  self->_framebuffer[offs + col] = 0xff;
60  }
61  }
62 }
63 
64 void bc_ls013b7dh03_draw_pixel(bc_ls013b7dh03_t *self, int x, int y, uint32_t color)
65 {
66  // Skip mode byte + addr byte
67  uint32_t byteIndex = 2;
68  // Skip lines
69  byteIndex += y * 18;
70  // Select column byte
71  byteIndex += x / 8;
72 
73  uint8_t bitMask = 1 << (7 - (x % 8));
74 
75  if (color == 0)
76  {
77  self->_framebuffer[byteIndex] |= bitMask;
78  }
79  else
80  {
81  self->_framebuffer[byteIndex] &= ~bitMask;
82  }
83 }
84 
85 uint32_t bc_ls013b7dh03_get_pixel(bc_ls013b7dh03_t *self, int x, int y)
86 {
87  // Skip mode byte + addr byte
88  uint32_t byteIndex = 2;
89  // Skip lines
90  byteIndex += y * 18;
91  // Select column byte
92  byteIndex += x / 8;
93 
94  return (self->_framebuffer[byteIndex] >> (7 - (x % 8))) & 1 ? 0 : 1;
95 }
96 
97 /*
98 
99 Framebuffer format for updating multiple lines, ideal for later DMA TX:
100 
101 || Set MODE ||------18B for line---||--next 18B 2nd line--| ...
102 || 1B || 1B | 16B | 1B || 1B | 16B | 1B |
103 || M0 M1 M2 DUMMY || ADDR | DATA | DUMMY || ADDR | DATA | DUMMY |
104 
105 */
107 {
108  if (bc_spi_is_ready())
109  {
110  if (!self->_pin_cs_set(0))
111  {
112  return false;
113  }
114 
115  self->_framebuffer[0] = 0x80 | self->_vcom;
116 
117  if (!bc_spi_async_transfer(self->_framebuffer, NULL, BC_LS013B7DH03_FRAMEBUFFER_SIZE, _bc_ls013b7dh03_spi_event_handler, self))
118  {
119  self->_pin_cs_set(1);
120 
121  return false;
122  }
123 
124  bc_scheduler_plan_relative(self->_task_id, _BC_LS013B7DH03_VCOM_PERIOD);
125 
126  self->_vcom ^= 0x40;
127 
128  return true;
129  }
130 
131  return false;
132 }
133 
135 {
136  static const bc_gfx_driver_t driver =
137  {
138  .is_ready = (bool (*)(void *)) bc_ls013b7dh03_is_ready,
139  .clear = (void (*)(void *)) bc_ls013b7dh03_clear,
140  .draw_pixel = (void (*)(void *, int, int, uint32_t)) bc_ls013b7dh03_draw_pixel,
141  .get_pixel = (uint32_t (*)(void *, int, int)) bc_ls013b7dh03_get_pixel,
142  .update = (bool (*)(void *)) bc_ls013b7dh03_update,
143  .get_caps = (bc_gfx_caps_t (*)(void *)) bc_ls013b7dh03_get_caps
144  };
145 
146  return &driver;
147 }
148 
150 {
151  uint8_t spi_data[2] = { 0x20, 0x00 };
152 
153  return _bc_ls013b7dh03_spi_transfer(self, spi_data, sizeof(spi_data));
154 }
155 
156 static void _bc_ls013b7dh03_task(void *param)
157 {
158  bc_ls013b7dh03_t *self = (bc_ls013b7dh03_t *) param;
159 
160  uint8_t spi_data[2] = {self->_vcom, 0x00};
161 
162  if (_bc_ls013b7dh03_spi_transfer(self, spi_data, sizeof(spi_data)))
163  {
164  self->_vcom ^= 0x40;
165  }
166 
167  bc_scheduler_plan_current_from_now(_BC_LS013B7DH03_VCOM_PERIOD);
168 }
169 
170 static bool _bc_ls013b7dh03_spi_transfer(bc_ls013b7dh03_t *self, uint8_t *buffer, size_t length)
171 {
172  if (!bc_spi_is_ready())
173  {
174  return false;
175  }
176 
177  if (!self->_pin_cs_set(0))
178  {
179  return false;
180  }
181 
182  bool spi_state = bc_spi_transfer(buffer, NULL, length);
183 
184  self->_pin_cs_set(1);
185 
186  return spi_state;
187 }
188 
189 static void _bc_ls013b7dh03_spi_event_handler(bc_spi_event_t event, void *event_param)
190 {
191  bc_ls013b7dh03_t *self = (bc_ls013b7dh03_t *) event_param;
192 
193  if (event == BC_SPI_EVENT_DONE)
194  {
195  self->_pin_cs_set(1);
196  }
197 }
198 
199 static inline uint8_t _bc_ls013b7dh03_reverse(uint8_t b)
200 {
201  b = (b & 0xf0) >> 4 | (b & 0x0f) << 4;
202  b = (b & 0xcc) >> 2 | (b & 0x33) << 2;
203  b = (b & 0xaa) >> 1 | (b & 0x55) << 1;
204 
205  return b;
206 }
uint32_t bc_ls013b7dh03_get_pixel(bc_ls013b7dh03_t *self, int x, int y)
Lcd get pixel.
bool bc_ls013b7dh03_is_ready(bc_ls013b7dh03_t *self)
Check if lcd is ready for commands.
Display size.
Definition: bc_gfx.h:13
const bc_gfx_driver_t * bc_ls013b7dh03_get_driver(void)
Get Lcd driver.
SPI event is completed.
Definition: bc_spi.h:63
bc_scheduler_task_id_t bc_scheduler_register(void(*task)(void *), void *param, bc_tick_t tick)
Register task in scheduler.
Definition: bc_scheduler.c:56
Display driver interface.
Definition: bc_gfx.h:22
bool bc_spi_is_ready(void)
Check if is ready for transfer.
Definition: bc_spi.c:187
bool bc_spi_async_transfer(const void *source, void *destination, size_t length, void(*event_handler)(bc_spi_event_t event, void *event_param), void(*event_param))
Execute async SPI transfer.
Definition: bc_spi.c:267
void bc_ls013b7dh03_clear(bc_ls013b7dh03_t *self)
Clear.
void bc_scheduler_plan_relative(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to tick relative from current spin.
Definition: bc_scheduler.c:129
bc_spi_event_t
SPI event.
Definition: bc_spi.h:60
void bc_spi_init(bc_spi_speed_t speed, bc_spi_mode_t mode)
Initialize SPI channel.
Definition: bc_spi.c:64
bc_gfx_caps_t bc_ls013b7dh03_get_caps(bc_ls013b7dh03_t *self)
Get capabilities.
bool bc_ls013b7dh03_update(bc_ls013b7dh03_t *self)
Lcd update, send data.
bool bc_ls013b7dh03_clear_memory_command(bc_ls013b7dh03_t *self)
Send Lcd clear memory command.
SPI communication speed is 1 MHz.
Definition: bc_spi.h:24
void bc_scheduler_plan_current_from_now(bc_tick_t tick)
Schedule current task to tick relative from now.
Definition: bc_scheduler.c:154
SPI mode of operation is 0 (CPOL = 0, CPHA = 0)
Definition: bc_spi.h:45
bool bc_spi_transfer(const void *source, void *destination, size_t length)
Execute SPI transfer.
Definition: bc_spi.c:192
void bc_ls013b7dh03_init(bc_ls013b7dh03_t *self, bool(*pin_cs_set)(bool state))
Initialize lcd driver.
void bc_ls013b7dh03_draw_pixel(bc_ls013b7dh03_t *self, int x, int y, uint32_t color)
Lcd draw pixel.