diff --git a/nrf5/drivers/display/oled_ssd1306_driver.c b/nrf5/drivers/display/oled_ssd1306_driver.c index 07b3224515..7083a66927 100644 --- a/nrf5/drivers/display/oled_ssd1306_driver.c +++ b/nrf5/drivers/display/oled_ssd1306_driver.c @@ -32,6 +32,8 @@ #include "hal_spi.h" #include "hal_time.h" +#include "framebuffer.h" + #if MICROPY_PY_DISPLAY_OLED_SSD1306 static pin_obj_t * mp_cs_pin; @@ -146,14 +148,14 @@ void driver_ssd1306_init(NRF_SPI_Type * p_instance, pin_obj_t * p_cs_pin, pin_ob static void set_col(uint16_t start_col, uint16_t end_col) { - cmd_write(SET_COL_ADDR); /* Column Command address */ + cmd_write(SET_COL_ADDR); // column command address cmd_write(start_col & 0xFF ); cmd_write(end_col & 0xFF); } static void set_page(uint16_t start_page, uint16_t end_page) { - cmd_write(SET_PAGE_ADDR); /* Column Command address */ + cmd_write(SET_PAGE_ADDR); // page command address cmd_write(start_page & 0xFF); cmd_write(end_page & 0xFF); } @@ -188,8 +190,19 @@ void driver_ssd1306_clear(uint16_t color) mp_hal_pin_high(mp_cs_pin); } -void driver_ssd1306_update_line(uint16_t line, fb_byte_t * p_bytes, uint16_t len, bool compressed) { +void driver_ssd1306_update_line(uint16_t line, framebuffer_byte_t * p_bytes, uint16_t len) { + set_col(line, line); + set_page(0, 63); + mp_hal_pin_high(mp_dc_pin); + mp_hal_pin_low(mp_cs_pin); + + for (uint8_t i = 0; i < len; i++) { + uint8_t byte = (uint8_t)((uint8_t *)p_bytes)[i]; + raw_write(byte); + } + + mp_hal_pin_high(mp_cs_pin); } #endif diff --git a/nrf5/drivers/display/oled_ssd1306_driver.h b/nrf5/drivers/display/oled_ssd1306_driver.h index 0312f87914..c9b33ab02d 100644 --- a/nrf5/drivers/display/oled_ssd1306_driver.h +++ b/nrf5/drivers/display/oled_ssd1306_driver.h @@ -30,12 +30,12 @@ #include "py/mphal.h" #include "hal_spi.h" -#include "lcd_mono_fb.h" +#include "framebuffer.h" void driver_ssd1306_init(NRF_SPI_Type * p_instance, pin_obj_t * cs_pin, pin_obj_t * dc_pin, pin_obj_t * reset_pin); void driver_ssd1306_clear(uint16_t color); -void driver_ssd1306_update_line(uint16_t line, fb_byte_t * p_bytes, uint16_t len, bool compressed); +void driver_ssd1306_update_line(uint16_t line, framebuffer_byte_t * p_bytes, uint16_t len); #endif // OLED_SSD1306_DRIVER_H__ diff --git a/nrf5/drivers/display/oled_ssd1306_obj.c b/nrf5/drivers/display/oled_ssd1306_obj.c index 655189cb74..c6410bcd8a 100644 --- a/nrf5/drivers/display/oled_ssd1306_obj.c +++ b/nrf5/drivers/display/oled_ssd1306_obj.c @@ -24,8 +24,6 @@ * THE SOFTWARE. */ -#include - #include "py/obj.h" #include "py/runtime.h" #include "py/mphal.h" @@ -38,27 +36,35 @@ /// \moduleref display /// \class SSD1306 - SSD1306 TFT LCD display driver. +#include "moddisplay.h" +#include "framebuffer.h" #include "pin.h" #include "spi.h" -#include "lcd_mono_fb.h" typedef struct _oled_ssd1306_obj_t { mp_obj_base_t base; + display_draw_callbacks_t draw_callbacks; + framebuffer_t * framebuffer; machine_hard_spi_obj_t *spi; pin_obj_t * pin_cs; pin_obj_t * pin_dc; pin_obj_t * pin_reset; - mp_obj_framebuf_t * framebuffer; } oled_ssd1306_obj_t; -static void dirty_line_update_cb(mp_obj_framebuf_t * p_framebuffer, - uint16_t line, - fb_byte_t * p_new, - fb_byte_t * p_old) { - // the lcd does not have double buffer needs, skip it. - (void)p_old; +#define OLED_SSD1306_COLOR_BLACK 0 +#define OLED_SSD1306_COLOR_WHITE 1 - driver_ssd1306_update_line(line, p_new, p_framebuffer->bytes_stride, true); +static void set_pixel(void * p_display, + uint16_t x, + uint16_t y, + uint16_t color) { + oled_ssd1306_obj_t *self = (oled_ssd1306_obj_t *)p_display; + + if (color == OLED_SSD1306_COLOR_BLACK) { + framebuffer_pixel_clear(self->framebuffer, x, y); + } else { + framebuffer_pixel_set(self->framebuffer, x, y); + } } /// \method __str__() @@ -83,9 +89,12 @@ STATIC void oled_ssd1306_print(const mp_print_t *print, mp_obj_t o, mp_print_kin self->pin_reset->port, self->pin_reset->pin); - mp_printf(print, " FB(width=%u, height=%u, dir=%u))\n", - self->framebuffer->width, - self->framebuffer->height); + mp_printf(print, " FB(width=%u, height=%u, dir=%u, fb_stride=%u, fb_dirty_stride=%u))\n", + self->framebuffer->screen_width, + self->framebuffer->screen_height, + self->framebuffer->line_orientation, + self->framebuffer->fb_stride, + self->framebuffer->fb_dirty_stride); } // for make_new @@ -100,6 +109,18 @@ enum { /* +Example for nrf51822 / pca10028: + +from machine import Pin, SPI +from display import SSD1306 +cs = Pin("A14", mode=Pin.OUT, pull=Pin.PULL_UP) +reset = Pin("A13", mode=Pin.OUT, pull=Pin.PULL_UP) +dc = Pin("A12", mode=Pin.OUT, pull=Pin.PULL_UP) +spi = SPI(0, baudrate=8000000) +d = SSD1306(128, 64, spi, cs, dc, reset) +d.text("Hello World!", 32, 32) +d.show() + Example for nrf52832 / pca10040: from machine import Pin, SPI @@ -107,7 +128,7 @@ from display import SSD1306 cs = Pin("A13", mode=Pin.OUT, pull=Pin.PULL_UP) reset = Pin("A12", mode=Pin.OUT, pull=Pin.PULL_UP) dc = Pin("A11", mode=Pin.OUT, pull=Pin.PULL_UP) -spi = SPI(0, baudrate=4000000) +spi = SPI(0, baudrate=8000000) d = SSD1306(128, 64, spi, cs, dc, reset) d.text("Hello World!", 32, 32) d.show() @@ -141,6 +162,7 @@ STATIC mp_obj_t oled_ssd1306_make_new(const mp_obj_type_t *type, size_t n_args, oled_ssd1306_obj_t *s = m_new_obj_with_finaliser(oled_ssd1306_obj_t); s->base.type = type; + s->draw_callbacks.pixel_set = set_pixel; mp_int_t width; mp_int_t height; @@ -187,15 +209,22 @@ STATIC mp_obj_t oled_ssd1306_make_new(const mp_obj_type_t *type, size_t n_args, "Display Reset Pin not set")); } - // direction arg not yet configurable - mp_int_t vertical = true; - s->framebuffer = lcd_mono_fb_helper_make_new(width, height, vertical); + framebuffer_init_t init_conf = { + .width = width, + .height = height, + .line_orientation = FRAMEBUFFER_LINE_DIR_VERTICAL, + .double_buffer = false + }; + + s->framebuffer = m_new(framebuffer_t, sizeof(framebuffer_t)); + + framebuffer_init(s->framebuffer, &init_conf); driver_ssd1306_init(s->spi->pyb->spi->instance, s->pin_cs, s->pin_dc, s->pin_reset); // Default to black background driver_ssd1306_clear(0); - // display_clear_screen(s->framebuffer, 0x0); + framebuffer_clear(s->framebuffer); return MP_OBJ_FROM_PTR(s); } @@ -207,20 +236,40 @@ STATIC mp_obj_t oled_ssd1306_make_new(const mp_obj_type_t *type, size_t n_args, STATIC mp_obj_t oled_ssd1306_fill(mp_obj_t self_in, mp_obj_t color) { oled_ssd1306_obj_t *self = MP_OBJ_TO_PTR(self_in); - driver_ssd1306_clear((uint8_t)mp_obj_get_int(color)); - - display_clear_screen(self->framebuffer, (uint8_t)mp_obj_get_int(color)); + if (color == MP_OBJ_NEW_SMALL_INT(OLED_SSD1306_COLOR_BLACK)) { + framebuffer_clear(self->framebuffer); + } else { + framebuffer_fill(self->framebuffer); + } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_2(oled_ssd1306_fill_obj, oled_ssd1306_fill); +static void render(framebuffer_t * p_framebuffer) { + for (uint16_t i = 0; i < p_framebuffer->fb_dirty_stride; i++) { + if (p_framebuffer->fb_dirty[i].byte != 0) { + for (uint16_t b = 0; b < 8; b++) { + if ((((p_framebuffer->fb_dirty[i].byte >> b) & 0x01) == 1)) { + uint16_t line_num = (i * 8) + b; + driver_ssd1306_update_line(line_num, + &p_framebuffer->fb_new[line_num * p_framebuffer->fb_stride], + p_framebuffer->fb_stride); + } + } + + p_framebuffer->fb_dirty[i].byte = 0x00; + } + } +} + /// \method show() /// Display content in framebuffer. STATIC mp_obj_t oled_ssd1306_show(size_t n_args, const mp_obj_t *args) { oled_ssd1306_obj_t *self = MP_OBJ_TO_PTR(args[0]); - display_update(self->framebuffer, false, dirty_line_update_cb); + render(self->framebuffer); + framebuffer_flip(self->framebuffer); return mp_const_none; } @@ -250,18 +299,13 @@ STATIC mp_obj_t oled_ssd1306_pixel(size_t n_args, const mp_obj_t *args) { oled_ssd1306_obj_t *self = MP_OBJ_TO_PTR(args[0]); mp_int_t x = mp_obj_get_int(args[1]); mp_int_t y = mp_obj_get_int(args[2]); - mp_int_t color; - if (n_args >= 3) { - color = mp_obj_get_int(args[3]); - } - (void)self; - (void)x; - (void)y; - (void)color; + mp_int_t color = mp_obj_get_int(args[3]); + + set_pixel(self, x, y, color); return mp_const_none; } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(oled_ssd1306_pixel_obj, 3, 4, oled_ssd1306_pixel); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(oled_ssd1306_pixel_obj, 4, 4, oled_ssd1306_pixel); /// \method pixel(text, x, y, [color]) /// Write one pixel in framebuffer. @@ -278,8 +322,12 @@ STATIC mp_obj_t oled_ssd1306_text(size_t n_args, const mp_obj_t *args) { color = mp_obj_get_int(args[3]); } - display_print_string(self->framebuffer, x, y, str); + //display_print_string(self->framebuffer, x, y, str); + (void)x; + (void)y; + (void)self; + (void)str; (void)color; return mp_const_none; @@ -304,8 +352,8 @@ STATIC const mp_map_elem_t oled_ssd1306_locals_dict_table[] = { #if 0 { MP_OBJ_NEW_QSTR(MP_QSTR_bitmap), (mp_obj_t)(&oled_ssd1306_bitmap_obj) }, #endif - { MP_OBJ_NEW_QSTR(MP_QSTR_COLOR_BLACK), MP_OBJ_NEW_SMALL_INT(LCD_BLACK) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_COLOR_WHITE), MP_OBJ_NEW_SMALL_INT(LCD_WHITE) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_COLOR_BLACK), MP_OBJ_NEW_SMALL_INT(OLED_SSD1306_COLOR_BLACK) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_COLOR_WHITE), MP_OBJ_NEW_SMALL_INT(OLED_SSD1306_COLOR_WHITE) }, { MP_OBJ_NEW_QSTR(MP_QSTR_VERTICAL), MP_OBJ_NEW_SMALL_INT(0) }, { MP_OBJ_NEW_QSTR(MP_QSTR_HORIZONTAL), MP_OBJ_NEW_SMALL_INT(1) }, };