From 5cc38316ea46914bc6b64716432d310e01e2f320 Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Wed, 9 Oct 2024 21:50:37 +0200 Subject: [PATCH] Module17: updated display drivers to new SPI subsystem --- platform/drivers/display/SH110x_Mod17.c | 83 ++++++++++------- platform/drivers/display/SSD1306_Mod17.c | 79 ++++++++-------- platform/drivers/display/SSD1309_Mod17.c | 109 ++++++++++++++--------- platform/drivers/display/display_Mod17.c | 7 +- 4 files changed, 162 insertions(+), 116 deletions(-) diff --git a/platform/drivers/display/SH110x_Mod17.c b/platform/drivers/display/SH110x_Mod17.c index ccabec84..c7113b46 100644 --- a/platform/drivers/display/SH110x_Mod17.c +++ b/platform/drivers/display/SH110x_Mod17.c @@ -26,9 +26,11 @@ #include #include #include -#include +#include #include "SH110x_Mod17.h" +extern const struct spiDevice spi2; + void SH110x_init() { gpio_setPin(LCD_CS); @@ -39,37 +41,46 @@ void SH110x_init() gpio_setPin(LCD_RST); delayMs(50); - gpio_clearPin(LCD_CS); + static const uint8_t init[] = + { + 0xAE, /* SH110X_DISPLAYOFF */ + 0xD5, /* SH110X_SETDISPLAYCLOCKDIV, 0x51 */ + 0x51, + 0x81, /* SH110X_SETCONTRAST, 0x4F */ + 0x4F, + 0xAD, /* SH110X_DCDC, 0x8A */ + 0x8A, + 0xA1, /* SH110X_SEGREMAP */ + 0xC0, /* SH110X_COMSCANINC */ + 0xDC, /* SH110X_SETDISPSTARTLINE, 0x0 */ + 0x00, + 0xD3, /* SH110X_SETDISPLAYOFFSET, 0x60 */ + 0x60, + 0xD9, /* SH110X_SETPRECHARGE, 0x22 */ + 0x22, + 0xDB, /* SH110X_SETVCOMDETECT, 0x35 */ + 0x35, + 0xA8, /* SH110X_SETMULTIPLEX, 0x3F */ + 0x3F, + 0xA4, /* SH110X_DISPLAYALLON_RESUME */ + 0xA6, /* SH110X_NORMALDISPLAY */ + 0xAF /* SH110x_DISPLAYON */ + }; + gpio_clearPin(LCD_CS); gpio_clearPin(LCD_DC); /* DC low -> command mode */ - spi2_sendRecv(0xAE); /* SH110X_DISPLAYOFF */ - spi2_sendRecv(0xD5); /* SH110X_SETDISPLAYCLOCKDIV, 0x51 */ - spi2_sendRecv(0x51); - spi2_sendRecv(0x81); /* SH110X_SETCONTRAST, 0x4F */ - spi2_sendRecv(0x4F); - spi2_sendRecv(0xAD); /* SH110X_DCDC, 0x8A */ - spi2_sendRecv(0x8A); - spi2_sendRecv(0xA1); /* SH110X_SEGREMAP */ - spi2_sendRecv(0xC0); /* SH110X_COMSCANINC */ - spi2_sendRecv(0xDC); /* SH110X_SETDISPSTARTLINE, 0x0 */ - spi2_sendRecv(0x00); - spi2_sendRecv(0xD3); /* SH110X_SETDISPLAYOFFSET, 0x60 */ - spi2_sendRecv(0x60); - spi2_sendRecv(0xD9); /* SH110X_SETPRECHARGE, 0x22 */ - spi2_sendRecv(0x22); - spi2_sendRecv(0xDB); /* SH110X_SETVCOMDETECT, 0x35 */ - spi2_sendRecv(0x35); - spi2_sendRecv(0xA8); /* SH110X_SETMULTIPLEX, 0x3F */ - spi2_sendRecv(0x3F); - spi2_sendRecv(0xA4); /* SH110X_DISPLAYALLON_RESUME */ - spi2_sendRecv(0xA6); /* SH110X_NORMALDISPLAY */ - spi2_sendRecv(0xAF); /* SH110x_DISPLAYON */ + spi_send(&spi2, init, sizeof(init)); gpio_setPin(LCD_CS); } void SH110x_terminate() { - spi2_sendRecv(0xAE); + uint8_t dispOff = 0xAE; + + gpio_clearPin(LCD_CS); + gpio_clearPin(LCD_DC); /* DC low -> command mode */ + spi_send(&spi2, &dispOff, 1); + gpio_setPin(LCD_CS); } void SH110x_renderRows(uint8_t startRow, uint8_t endRow, void *fb) @@ -81,14 +92,17 @@ void SH110x_renderRows(uint8_t startRow, uint8_t endRow, void *fb) { for(uint8_t x = 0; x < CONFIG_SCREEN_WIDTH/8; x++) { + uint8_t cmd[3]; + cmd[0] = (y & 0x0F); /* Set Y position */ + cmd[1] = (0x10 | ((y >> 4) & 0x07)); + cmd[2] = (0xB0 | x); /* Set X position */ + gpio_clearPin(LCD_DC); /* RS low -> command mode */ - (void) spi2_sendRecv(y & 0x0F); /* Set Y position */ - (void) spi2_sendRecv(0x10 | ((y >> 4) & 0x07)); - (void) spi2_sendRecv(0xB0 | x); /* Set X position */ + spi_send(&spi2, cmd, sizeof(cmd)); gpio_setPin(LCD_DC); /* RS high -> data mode */ size_t pos = x + y * (CONFIG_SCREEN_WIDTH/8); - spi2_sendRecv(frameBuffer[pos]); + spi_send(&spi2, &frameBuffer[pos], 1); } } @@ -102,11 +116,12 @@ void SH110x_render(void *fb) void SH110x_setContrast(uint8_t contrast) { + uint8_t cmd[2]; + cmd[0] = 0x81; /* Set Electronic Volume */ + cmd[0] = contrast; /* Controller contrast range is 0 - 63 */ + gpio_clearPin(LCD_CS); - - gpio_clearPin(LCD_DC); /* RS low -> command mode */ - (void) spi2_sendRecv(0x81); /* Set Electronic Volume */ - (void) spi2_sendRecv(contrast); /* Controller contrast range is 0 - 63 */ - + gpio_clearPin(LCD_DC); /* RS low -> command mode */ + spi_send(&spi2, cmd, sizeof(cmd)); gpio_setPin(LCD_CS); } diff --git a/platform/drivers/display/SSD1306_Mod17.c b/platform/drivers/display/SSD1306_Mod17.c index 5b3975eb..c1f8dfd1 100644 --- a/platform/drivers/display/SSD1306_Mod17.c +++ b/platform/drivers/display/SSD1306_Mod17.c @@ -27,8 +27,9 @@ #include #include #include -#include +#include +extern const struct spiDevice spi2; /** * \internal @@ -50,7 +51,7 @@ void SSD1306_renderRow(uint8_t row, uint8_t *frameBuffer) out |= ((tmp >> (7-j)) & 0x01) << j; } - spi2_sendRecv(out); + spi_send(&spi2, &out, 1); } } @@ -65,37 +66,41 @@ void SSD1306_init() gpio_setPin(LCD_RST); delayMs(50); - gpio_clearPin(LCD_CS); + static const uint8_t init[] = + { + 0xAE, // SH110X_DISPLAYOFF + 0xD5, // SH110X_SETDISPLAYCLOCKDIV, 0x51 + 0x51, + 0x81, // SH110X_SETCONTRAST, 0x4F + 0x4F, + 0xAD, // SH110X_DCDC, 0x8A + 0x8A, + 0xA0, // SH110X_SEGREMAP + 0xC0, // SH110X_COMSCANINC + 0xDC, // SH110X_SETDISPSTARTLINE, 0x0 + 0x00, + 0xD3, // SH110X_SETDISPLAYOFFSET, 0x60 + 0x60, + 0xD9, // SH110X_SETPRECHARGE, 0x22 + 0x22, + 0xDB, // SH110X_SETVCOMDETECT, 0x35 + 0x35, + 0xA8, // SH110X_SETMULTIPLEX, 0x3F + 0x3F, + 0xA4, // SH110X_DISPLAYALLON_RESUME + 0xA6, // SH110X_NORMALDISPLAY + 0xAF // SH110x_DISPLAYON + }; - gpio_clearPin(LCD_RS);// RS low -> command mode - spi2_sendRecv(0xAE); // SH110X_DISPLAYOFF, - spi2_sendRecv(0xd5); // SH110X_SETDISPLAYCLOCKDIV, 0x51, - spi2_sendRecv(0x51); - spi2_sendRecv(0x81); // SH110X_SETCONTRAST, 0x4F, - spi2_sendRecv(0x4F); - spi2_sendRecv(0xAD); // SH110X_DCDC, 0x8A, - spi2_sendRecv(0x8A); - spi2_sendRecv(0xA0); // SH110X_SEGREMAP, - spi2_sendRecv(0xC0); // SH110X_COMSCANINC, - spi2_sendRecv(0xDC); // SH110X_SETDISPSTARTLINE, 0x0, - spi2_sendRecv(0x00); - spi2_sendRecv(0xd3); // SH110X_SETDISPLAYOFFSET, 0x60, - spi2_sendRecv(0x60); - spi2_sendRecv(0xd9); // SH110X_SETPRECHARGE, 0x22, - spi2_sendRecv(0x22); - spi2_sendRecv(0xdb); // SH110X_SETVCOMDETECT, 0x35, - spi2_sendRecv(0x35); - spi2_sendRecv(0xa8); // SH110X_SETMULTIPLEX, 0x3F, - spi2_sendRecv(0x3f); - spi2_sendRecv(0xa4); // SH110X_DISPLAYALLON_RESUME, - spi2_sendRecv(0xa6); // SH110X_NORMALDISPLAY, - spi2_sendRecv(0xAF); // SH110x_DISPLAYON + gpio_clearPin(LCD_CS); + gpio_clearPin(LCD_DC); + spi_send(&spi2, init, sizeof(init)); gpio_setPin(LCD_CS); } void SSD1306_terminate() { - spi2_terminate(); + } void SSD1306_renderRows(uint8_t startRow, uint8_t endRow, void *fb) @@ -104,10 +109,13 @@ void SSD1306_renderRows(uint8_t startRow, uint8_t endRow, void *fb) for(uint8_t row = startRow; row <= endRow; row++) { + uint8_t cmd[3]; + cmd[0] = 0xB0 | row; /* Set Y position */ + cmd[1] = 0x00; /* Set X position */ + cmd[2] = 0x10; + gpio_clearPin(LCD_RS); /* RS low -> command mode */ - (void) spi2_sendRecv(0xB0 | row); /* Set Y position */ - (void) spi2_sendRecv(0x00); /* Set X position */ - (void) spi2_sendRecv(0x10); + spi_send(&spi2, cmd, sizeof(cmd)); gpio_setPin(LCD_RS); /* RS high -> data mode */ SSD1306_renderRow(row, (uint8_t *) fb); } @@ -122,11 +130,12 @@ void SSD1306_render(void *fb) void SSD1306_setContrast(uint8_t contrast) { + uint8_t cmd[2]; + cmd[0] = 0x81; /* Set Electronic Volume */ + cmd[0] = contrast; /* Controller contrast range is 0 - 63 */ + gpio_clearPin(LCD_CS); - - gpio_clearPin(LCD_RS); /* RS low -> command mode */ - (void) spi2_sendRecv(0x81); /* Set Electronic Volume */ - (void) spi2_sendRecv(contrast); /* Controller contrast range is 0 - 63 */ - + gpio_clearPin(LCD_DC); /* RS low -> command mode */ + spi_send(&spi2, cmd, sizeof(cmd)); gpio_setPin(LCD_CS); } diff --git a/platform/drivers/display/SSD1309_Mod17.c b/platform/drivers/display/SSD1309_Mod17.c index cb6ae63b..64bf18ed 100644 --- a/platform/drivers/display/SSD1309_Mod17.c +++ b/platform/drivers/display/SSD1309_Mod17.c @@ -26,9 +26,11 @@ #include #include #include -#include +#include #include "SSD1309_Mod17.h" +extern const struct spiDevice spi2; + void SSD1309_init() { gpio_setPin(LCD_CS); @@ -39,28 +41,36 @@ void SSD1309_init() gpio_setPin(LCD_RST); delayMs(50); + static const uint8_t init[] = + { + 0xAE, // SSD1309_DISPLAYOFF, + 0xD5, // Set display clock division + 0xF0, + 0xA8, // Set multiplex ratio, 1/64 + 0x3F, + 0x81, // Set contrast control + 0x32, + 0xD9, // Set pre-charge period + 0xF1, + 0xDB, // Set VCOMH Deselect level + 0x30, + 0xAF + }; + gpio_clearPin(LCD_CS); - - gpio_clearPin(LCD_DC);// DC low -> command mode - - spi2_sendRecv(0xAE); // SSD1309_DISPLAYOFF, - spi2_sendRecv(0xD5); // Set display clock division - spi2_sendRecv(0xF0); - spi2_sendRecv(0xA8); // Set multiplex ratio, 1/64 - spi2_sendRecv(0x3F); - spi2_sendRecv(0x81); // Set contrast control - spi2_sendRecv(0x32); - spi2_sendRecv(0xD9); // Set pre-charge period - spi2_sendRecv(0xF1); - spi2_sendRecv(0xDB); // Set VCOMH Deselect level - spi2_sendRecv(0x30); - spi2_sendRecv(0xAF); + gpio_clearPin(LCD_DC); + spi_send(&spi2, init, sizeof(init)); gpio_setPin(LCD_CS); } void SSD1309_terminate() { - spi2_sendRecv(0xAE); + uint8_t dispOff = 0xAE; + + gpio_clearPin(LCD_CS); + gpio_clearPin(LCD_DC); /* DC low -> command mode */ + spi_send(&spi2, &dispOff, 1); + gpio_setPin(LCD_CS); } void SSD1309_renderRows(uint8_t startRow, uint8_t endRow, void *fb) @@ -70,34 +80,38 @@ void SSD1309_renderRows(uint8_t startRow, uint8_t endRow, void *fb) // Convert rows to pages uint8_t startPage = startRow / 8; uint8_t endPage = endRow / 8; + uint8_t cmd[3]; gpio_clearPin(LCD_DC); - spi2_sendRecv(0x20); // Set page addressing mode - spi2_sendRecv(0x02); + cmd[0] = 0x20; // Set page addressing mode + cmd[1] = 0x02; + spi_send(&spi2, cmd, 2); uint8_t *framebuffer = (uint8_t *)fb; for(uint8_t page = startPage; page < endPage; page++) { gpio_clearPin(LCD_DC); - spi2_sendRecv(0xB0 | page); - spi2_sendRecv(0x00); - spi2_sendRecv(0x10); + cmd[0] = 0xB0 | page; + cmd[1] = 0x00; + cmd[1] = 0x10; + spi_send(&spi2, cmd, 3); gpio_setPin(LCD_DC); // DC high -> data mode - uint8_t topRow = page*8; - + uint8_t topRow = page * 8; for(uint8_t col = 0; col < CONFIG_SCREEN_WIDTH; col++) { uint8_t data = 0; - uint8_t bit_offset = col%8; // Bit offset in the fb for the column we are refreshing + uint8_t bit_offset = col % 8; // Bit offset in the fb for the column we are refreshing // Gather the 8 rows of data for(uint8_t row = 0; row < 8; row++) { - uint8_t cell = framebuffer[((topRow+row)*CONFIG_SCREEN_WIDTH+col)/8]; - data |= ((cell>>bit_offset)&0x01) << row; + size_t pos = ((topRow + row) * CONFIG_SCREEN_WIDTH + col) / 8; + uint8_t cell = framebuffer[pos]; + data |= ((cell >> bit_offset) & 0x01) << row; } - spi2_sendRecv(data); + + spi_send(&spi2, &data, 1); } } @@ -106,14 +120,18 @@ void SSD1309_renderRows(uint8_t startRow, uint8_t endRow, void *fb) void SSD1309_render(void *fb) { - gpio_clearPin(LCD_CS); + static const uint8_t cmd[] = + { + 0xB0, + 0x20, // Set horizontal addressing mode + 0x00, + 0x00, + 0x10 + }; + gpio_clearPin(LCD_CS); gpio_clearPin(LCD_DC); - spi2_sendRecv(0xB0); - spi2_sendRecv(0x20); // Set horizontal addressing mode - spi2_sendRecv(0x00); - spi2_sendRecv(0x00); - spi2_sendRecv(0x10); + spi_send(&spi2, cmd, sizeof(cmd)); gpio_setPin(LCD_DC); // DC high -> data mode uint8_t *framebuffer = (uint8_t *)fb; @@ -124,27 +142,30 @@ void SSD1309_render(void *fb) for(uint8_t col = 0; col < CONFIG_SCREEN_WIDTH; col++) { uint8_t data = 0; - uint8_t bit_offset = col%8; // Bit offset in the fb for the column we are refreshing + uint8_t bit_offset = col % 8; // Bit offset in the fb for the column we are refreshing // Gather the 8 rows of data for(uint8_t subRow = 0; subRow < 8; subRow++) { - uint8_t cell = framebuffer[((topRow+subRow)*CONFIG_SCREEN_WIDTH+col)/8]; - data |= ((cell>>bit_offset)&0x01) << subRow; + size_t pos = ((topRow + subRow) * CONFIG_SCREEN_WIDTH + col) / 8; + uint8_t cell = framebuffer[pos]; + data |= ((cell >> bit_offset) & 0x01) << subRow; } - spi2_sendRecv(data); + + spi_send(&spi2, &data, 1); } } - gpio_setPin(LCD_CS); + gpio_setPin(LCD_CS); } void SSD1309_setContrast(uint8_t contrast) { + uint8_t cmd[2]; + cmd[0] = 0x81; /* Set Electronic Volume */ + cmd[0] = contrast; /* Controller contrast range is 0 - 63 */ + gpio_clearPin(LCD_CS); - - gpio_clearPin(LCD_DC); /* DC low -> command mode */ - (void) spi2_sendRecv(0x81); /* Set Electronic Volume */ - (void) spi2_sendRecv(contrast); /* Controller contrast range is 0 - 63 */ - + gpio_clearPin(LCD_DC); /* RS low -> command mode */ + spi_send(&spi2, cmd, sizeof(cmd)); gpio_setPin(LCD_CS); } diff --git a/platform/drivers/display/display_Mod17.c b/platform/drivers/display/display_Mod17.c index 93e55cf5..6024439f 100644 --- a/platform/drivers/display/display_Mod17.c +++ b/platform/drivers/display/display_Mod17.c @@ -22,10 +22,11 @@ #include #include #include -#include +#include #include "SH110x_Mod17.h" #include "SSD1309_Mod17.h" +SPI_STM32_DEVICE_DEFINE(spi2, SPI2, NULL) struct displayFuncs { @@ -73,7 +74,7 @@ void display_init() gpio_setMode(SPI2_SCK, ALTERNATE | ALTERNATE_FUNC(5)); gpio_setMode(SPI2_MOSI, ALTERNATE | ALTERNATE_FUNC(5)); gpio_setMode(SPI2_MISO, ALTERNATE | ALTERNATE_FUNC(5)); - spi2_init(); + spiStm32_init(&spi2, 1300000, 0); /* * Initialise GPIOs for LCD control @@ -88,7 +89,7 @@ void display_init() void display_terminate() { display.terminate(); - spi2_terminate(); + spiStm32_terminate(&spi2); } void display_renderRows(uint8_t startRow, uint8_t endRow, void *fb)