115 template<board::DigitalPin SCE, board::DigitalPin DC, board::DigitalPin RST>
class LCD5110 :
116 public spi::SPIDevice<SCE, spi::ChipSelect::ACTIVE_LOW, spi::compute_clockrate(4'000'000UL)>
145 if (bias > MAX_BIAS) bias = MAX_BIAS;
147 send_command_(FUNCTION_SET_MASK | FUNCTION_SET_EXTENDED);
148 send_command_(EXTENDED_SET_BIAS | bias);
149 send_command_(FUNCTION_SET_MASK);
161 if (contrast > MAX_VOP) contrast = MAX_VOP;
163 send_command_(FUNCTION_SET_MASK | FUNCTION_SET_EXTENDED);
164 send_command_(EXTENDED_SET_VOP | contrast);
165 send_command_(FUNCTION_SET_MASK);
179 send_command_(FUNCTION_SET_MASK | FUNCTION_SET_EXTENDED);
180 send_command_(EXTENDED_SET_BIAS | uint8_t(coef));
181 send_command_(FUNCTION_SET_MASK);
190 send_command(FUNCTION_SET_MASK | FUNCTION_SET_POWER_DOWN);
199 send_command(FUNCTION_SET_MASK);
209 send_command(DISPLAY_CONTROL_MASK | DISPLAY_CONTROL_BLANK);
219 send_command(DISPLAY_CONTROL_MASK | DISPLAY_CONTROL_FULL);
228 send_command(DISPLAY_CONTROL_MASK | DISPLAY_CONTROL_INVERSE);
238 send_command(DISPLAY_CONTROL_MASK | DISPLAY_CONTROL_NORMAL);
250 memset(display_, 0,
sizeof(display_));
254 bool set_pixel(uint8_t x, uint8_t y,
const DRAW_CONTEXT& context)
258 const uint8_t r = y / ROW_HEIGHT;
259 const uint8_t offset = y % ROW_HEIGHT;
262 uint8_t* pix_column = get_display(r, c);
264 const bool current = (*pix_column & mask);
265 const bool dest = context.draw_mode().pixel_op(current);
270 if (current)
return false;
275 if (!current)
return false;
276 *pix_column &= uint8_t(~mask);
281 bool is_valid_char_xy(
UNUSED uint8_t x, uint8_t y)
283 return (y % ROW_HEIGHT) == 0;
287 uint8_t write_char(uint8_t x, uint8_t y, uint16_t glyph_ref,
const DRAW_CONTEXT& context)
290 const uint8_t width = context.font().width();
291 uint8_t row = y / ROW_HEIGHT;
292 const uint8_t col = x;
293 bool add_interchar_space = ((col + width + 1) < WIDTH);
295 uint8_t glyph_index = 0;
296 for (uint8_t glyph_row = 0; glyph_row < context.font().glyph_rows(); ++glyph_row)
299 uint8_t* display_ptr = get_display(row, col);
301 for (uint8_t i = 0; i <= width; ++i)
303 const bool space_column = (i == width);
304 uint8_t pixel_bar = 0x00;
306 pixel_bar = context.font().get_char_glyph_byte(glyph_ref, glyph_index);
307 if ((!space_column) || add_interchar_space)
308 *display_ptr = context.draw_mode().bw_pixels_op(pixel_bar, *display_ptr);
316 return width + (add_interchar_space ? 1 : 0);
320 void update(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
322 const uint8_t size = (x2 - x1 + 1);
323 const uint8_t xmin = x1;
324 const uint8_t ymin = y1 / ROW_HEIGHT;
325 const uint8_t ymax = y2 / ROW_HEIGHT;
327 for (uint8_t y = ymin; y <= ymax; ++y)
331 const uint8_t* display = get_display(y, xmin);
340 static constexpr uint8_t ROW_HEIGHT = 8;
343 static constexpr uint8_t FUNCTION_SET_MASK =
bits::BV8(5);
344 static constexpr uint8_t FUNCTION_SET_POWER_DOWN =
bits::BV8(2);
345 static constexpr uint8_t FUNCTION_SET_EXTENDED =
bits::BV8(0);
347 static constexpr uint8_t EXTENDED_SET_BIAS =
bits::BV8(4);
348 static constexpr uint8_t EXTENDED_SET_VOP =
bits::BV8(7);
350 static constexpr uint8_t DISPLAY_CONTROL_MASK =
bits::BV8(3);
351 static constexpr uint8_t DISPLAY_CONTROL_BLANK = 0;
352 static constexpr uint8_t DISPLAY_CONTROL_NORMAL =
bits::BV8(2);
353 static constexpr uint8_t DISPLAY_CONTROL_FULL =
bits::BV8(0);
354 static constexpr uint8_t DISPLAY_CONTROL_INVERSE =
bits::BV8(0, 2);
356 static constexpr uint8_t SET_ROW_ADDRESS =
bits::BV8(6);
357 static constexpr uint8_t SET_COL_ADDRESS =
bits::BV8(7);
360 static constexpr uint8_t MAX_BIAS = 0x07;
361 static constexpr uint8_t DEFAULT_BIAS = 0x04;
362 static constexpr uint8_t MAX_VOP = 0x7F;
363 static constexpr uint8_t DEFAULT_VOP = 40;
365 void send_command_(uint8_t command)
371 void send_command(uint8_t command)
374 send_command_(command);
378 void set_rc_(uint8_t r, uint8_t c)
381 this->
transfer(r | SET_ROW_ADDRESS);
382 this->
transfer(c | SET_COL_ADDRESS);
387 uint8_t* get_display(uint8_t r, uint8_t c)
389 return &display_[r * WIDTH + c];
391 const uint8_t* get_display(uint8_t r, uint8_t c)
const
393 return &display_[r * WIDTH + c];
401 uint8_t display_[HEIGHT * WIDTH / ROW_HEIGHT];
Drawing Context passed to display devices low-level primitives set_pixel() and write_char().