diff --git a/meson.build b/meson.build index b80f7ee8..90d3c2a3 100644 --- a/meson.build +++ b/meson.build @@ -415,7 +415,9 @@ dm1801_def += openrtx_def + mk22fn512_def + miosix_cm4f_def ## Module 17 ## mod17_src = ['platform/targets/Module17/platform.c', + 'platform/drivers/display/display_Mod17.c', 'platform/drivers/display/SH110x_Mod17.c', + 'platform/drivers/display/SSD1309_Mod17.c', 'platform/drivers/keyboard/keyboard_Mod17.c', 'platform/drivers/NVM/nvmem_Mod17.c', 'platform/drivers/CPS/cps_io_native_Mod17.c', diff --git a/platform/drivers/display/SH110x_Mod17.c b/platform/drivers/display/SH110x_Mod17.c index 05804b16..ccabec84 100644 --- a/platform/drivers/display/SH110x_Mod17.c +++ b/platform/drivers/display/SH110x_Mod17.c @@ -24,32 +24,15 @@ #include #include #include -#include #include #include #include +#include "SH110x_Mod17.h" - -void display_init() +void SH110x_init() { - /* - * Initialise SPI2 for external flash and LCD - */ - gpio_setMode(SPI2_CLK, ALTERNATE | ALTERNATE_FUNC(5)); - gpio_setMode(SPI2_SDO, ALTERNATE | ALTERNATE_FUNC(5)); - gpio_setMode(SPI2_SDI, ALTERNATE | ALTERNATE_FUNC(5)); - - spi2_init(); - - /* - * Initialise GPIOs for LCD control - */ - gpio_setMode(LCD_CS, OUTPUT); - gpio_setMode(LCD_RST, OUTPUT); - gpio_setMode(LCD_RS, OUTPUT); - gpio_setPin(LCD_CS); - gpio_clearPin(LCD_RS); + gpio_clearPin(LCD_DC); gpio_clearPin(LCD_RST); /* Reset controller */ delayMs(50); @@ -58,7 +41,7 @@ void display_init() gpio_clearPin(LCD_CS); - gpio_clearPin(LCD_RS); /* RS low -> command mode */ + gpio_clearPin(LCD_DC); /* DC low -> command mode */ spi2_sendRecv(0xAE); /* SH110X_DISPLAYOFF */ spi2_sendRecv(0xD5); /* SH110X_SETDISPLAYCLOCKDIV, 0x51 */ spi2_sendRecv(0x51); @@ -84,12 +67,12 @@ void display_init() gpio_setPin(LCD_CS); } -void display_terminate() +void SH110x_terminate() { - spi2_terminate(); + spi2_sendRecv(0xAE); } -void display_renderRows(uint8_t startRow, uint8_t endRow, void *fb) +void SH110x_renderRows(uint8_t startRow, uint8_t endRow, void *fb) { gpio_clearPin(LCD_CS); @@ -98,11 +81,11 @@ void display_renderRows(uint8_t startRow, uint8_t endRow, void *fb) { for(uint8_t x = 0; x < CONFIG_SCREEN_WIDTH/8; x++) { - gpio_clearPin(LCD_RS); /* RS low -> command mode */ + 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 */ - gpio_setPin(LCD_RS); /* RS high -> data mode */ + gpio_setPin(LCD_DC); /* RS high -> data mode */ size_t pos = x + y * (CONFIG_SCREEN_WIDTH/8); spi2_sendRecv(frameBuffer[pos]); @@ -112,31 +95,18 @@ void display_renderRows(uint8_t startRow, uint8_t endRow, void *fb) gpio_setPin(LCD_CS); } -void display_render(void *fb) +void SH110x_render(void *fb) { - display_renderRows(0, CONFIG_SCREEN_HEIGHT, fb); + SH110x_renderRows(0, CONFIG_SCREEN_HEIGHT, fb); } -void display_setContrast(uint8_t contrast) +void SH110x_setContrast(uint8_t contrast) { - /* OLED display do not have contrast regulation */ - (void) contrast; -} - -void display_setBacklightLevel(uint8_t level) -{ - /* - * Module17 uses an OLED display, so contrast channel is actually controlling - * the brightness. The usable range is 0 - 128, above which there is no - * noticeable change in the brightness level (already at maximum). - */ - uint16_t bl = (level * 128) / 100; - gpio_clearPin(LCD_CS); - gpio_clearPin(LCD_RS); /* RS low -> command mode */ - (void) spi2_sendRecv(0x81); /* Contrast control register */ - (void) spi2_sendRecv(bl); + 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_setPin(LCD_CS); } diff --git a/platform/drivers/display/SH110x_Mod17.h b/platform/drivers/display/SH110x_Mod17.h new file mode 100644 index 00000000..8126753e --- /dev/null +++ b/platform/drivers/display/SH110x_Mod17.h @@ -0,0 +1,48 @@ +#ifndef SH110X_MOD17_H +#define SH110X_MOD17_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize the SH110x display driver. + */ +void SH110x_init(); + +/** + * Shut down the SH110x display driver. + */ +void SH110x_terminate(); + +/** + * Do a partial framebuffer render. + * + * @param startRow: first row of the partial render. + * @param endRow: last row of the partial render. + * @param fb: pointer to framebuffer. + */ +void SH110x_renderRows(uint8_t startRow, uint8_t endRow, void *fb); + +/** + * Render the framebuffer on the screen. + * + * @param fb: pointer to framebuffer. + */ +void SH110x_render(void *fb); + +/** + * Set display contrast. + * + * @param contrast: display contrast level, 0 to 63. + */ +void SH110x_setContrast(uint8_t contrast); + +#ifdef __cplusplus +} +#endif + +#endif /* SH110X_MOD17_H */ diff --git a/platform/drivers/display/SSD1306_Mod17.c b/platform/drivers/display/SSD1306_Mod17.c index d23ef395..5b3975eb 100644 --- a/platform/drivers/display/SSD1306_Mod17.c +++ b/platform/drivers/display/SSD1306_Mod17.c @@ -38,7 +38,7 @@ * * @param row: pixel row to be be sent. */ -void display_renderRow(uint8_t row, uint8_t *frameBuffer) +void SSD1306_renderRow(uint8_t row, uint8_t *frameBuffer) { for(uint16_t i = 0; i < 64; i++) { @@ -55,24 +55,8 @@ void display_renderRow(uint8_t row, uint8_t *frameBuffer) } -void display_init() +void SSD1306_init() { - /* - * Initialise SPI2 for external flash and LCD - */ - gpio_setMode(SPI2_CLK, ALTERNATE | ALTERNATE_FUNC(5)); - gpio_setMode(SPI2_SDO, ALTERNATE | ALTERNATE_FUNC(5)); - gpio_setMode(SPI2_SDI, ALTERNATE | ALTERNATE_FUNC(5)); - - spi2_init(); - - /* - * Initialise GPIOs for LCD control - */ - gpio_setMode(LCD_CS, OUTPUT); - gpio_setMode(LCD_RST, OUTPUT); - gpio_setMode(LCD_RS, OUTPUT); - gpio_setPin(LCD_CS); gpio_clearPin(LCD_RS); @@ -109,12 +93,12 @@ void display_init() gpio_setPin(LCD_CS); } -void display_terminate() +void SSD1306_terminate() { spi2_terminate(); } -void display_renderRows(uint8_t startRow, uint8_t endRow, void *fb) +void SSD1306_renderRows(uint8_t startRow, uint8_t endRow, void *fb) { gpio_clearPin(LCD_CS); @@ -125,18 +109,18 @@ void display_renderRows(uint8_t startRow, uint8_t endRow, void *fb) (void) spi2_sendRecv(0x00); /* Set X position */ (void) spi2_sendRecv(0x10); gpio_setPin(LCD_RS); /* RS high -> data mode */ - display_renderRow(row, (uint8_t *) fb); + SSD1306_renderRow(row, (uint8_t *) fb); } gpio_setPin(LCD_CS); } -void display_render(void *fb) +void SSD1306_render(void *fb) { - display_renderRows(0, (CONFIG_SCREEN_WIDTH / 8) - 1, fb); + SSD1306_renderRows(0, (CONFIG_SCREEN_WIDTH / 8) - 1, fb); } -void display_setContrast(uint8_t contrast) +void SSD1306_setContrast(uint8_t contrast) { gpio_clearPin(LCD_CS); @@ -146,8 +130,3 @@ void display_setContrast(uint8_t contrast) gpio_setPin(LCD_CS); } - -void display_setBacklightLevel(uint8_t level) -{ - (void) level; -} diff --git a/platform/drivers/display/SSD1306_Mod17.h b/platform/drivers/display/SSD1306_Mod17.h new file mode 100644 index 00000000..f80cc92f --- /dev/null +++ b/platform/drivers/display/SSD1306_Mod17.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * Mathis Schmieder DB9MAT * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#ifndef SSD1306_MOD17_H +#define SSD1306_MOD17_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize the SSD1306 display driver. + */ +void SSD1306_init(); + +/** + * Shut down the SSD1306 display driver. + */ +void SSD1306_terminate(); + +/** + * Do a partial framebuffer render. + * + * @param startRow: first row of the partial render. + * @param endRow: last row of the partial render. + * @param fb: pointer to framebuffer. + */ +void SSD1306_renderRows(uint8_t startRow, uint8_t endRow, void *fb); + +/** + * Render the framebuffer on the screen. + * + * @param fb: pointer to framebuffer. + */ +void SSD1306_render(void *fb); + +/** + * Set display contrast. + * + * @param contrast: display contrast level, 0 to 63. + */ +void SSD1306_setContrast(uint8_t contrast); + +#ifdef __cplusplus +} +#endif + +#endif /* SSD1306_MOD17_H */ diff --git a/platform/drivers/display/SSD1309_Mod17.c b/platform/drivers/display/SSD1309_Mod17.c new file mode 100644 index 00000000..cb6ae63b --- /dev/null +++ b/platform/drivers/display/SSD1309_Mod17.c @@ -0,0 +1,150 @@ +/*************************************************************************** + * Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * Mathis Schmieder DB9MAT * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "SSD1309_Mod17.h" + +void SSD1309_init() +{ + gpio_setPin(LCD_CS); + gpio_clearPin(LCD_DC); + + gpio_clearPin(LCD_RST); // Reset controller + delayMs(50); + gpio_setPin(LCD_RST); + delayMs(50); + + 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_setPin(LCD_CS); +} + +void SSD1309_terminate() +{ + spi2_sendRecv(0xAE); +} + +void SSD1309_renderRows(uint8_t startRow, uint8_t endRow, void *fb) +{ + gpio_clearPin(LCD_CS); + + // Convert rows to pages + uint8_t startPage = startRow / 8; + uint8_t endPage = endRow / 8; + + gpio_clearPin(LCD_DC); + spi2_sendRecv(0x20); // Set page addressing mode + spi2_sendRecv(0x02); + + 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); + gpio_setPin(LCD_DC); // DC high -> data mode + + 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 + // 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; + } + spi2_sendRecv(data); + } + } + + gpio_setPin(LCD_CS); +} + +void SSD1309_render(void *fb) +{ + 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); + gpio_setPin(LCD_DC); // DC high -> data mode + + uint8_t *framebuffer = (uint8_t *)fb; + + // Refresh the whole screen 8 rows by 8 rows + for(uint8_t topRow = 0; topRow <= 56; topRow += 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 + // 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; + } + spi2_sendRecv(data); + } + } + + gpio_setPin(LCD_CS); +} + +void SSD1309_setContrast(uint8_t contrast) +{ + 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_setPin(LCD_CS); +} diff --git a/platform/drivers/display/SSD1309_Mod17.h b/platform/drivers/display/SSD1309_Mod17.h new file mode 100644 index 00000000..f790e60d --- /dev/null +++ b/platform/drivers/display/SSD1309_Mod17.h @@ -0,0 +1,69 @@ +/*************************************************************************** + * Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, * + * Niccolò Izzo IU2KIN * + * Frederik Saraci IU2NRO * + * Silvano Seva IU2KWO * + * Mathis Schmieder DB9MAT * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#ifndef SSD1309_MOD17_H +#define SSD1309_MOD17_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Initialize the SSD1309 display driver. + */ +void SSD1309_init(); + +/** + * Shut down the SSD1309 display driver. + */ +void SSD1309_terminate(); + +/** + * Do a partial framebuffer render. + * + * @param startRow: first row of the partial render. + * @param endRow: last row of the partial render. + * @param fb: pointer to framebuffer. + */ +void SSD1309_renderRows(uint8_t startRow, uint8_t endRow, void *fb); + +/** + * Render the framebuffer on the screen. + * + * @param fb: pointer to framebuffer. + */ +void SSD1309_render(void *fb); + +/** + * Set display contrast. + * + * @param contrast: display contrast level, 0 to 63. + */ +void SSD1309_setContrast(uint8_t contrast); + +#ifdef __cplusplus +} +#endif + +#endif /* SSD1309_MOD17_H */ diff --git a/platform/drivers/display/display_Mod17.c b/platform/drivers/display/display_Mod17.c new file mode 100644 index 00000000..93e55cf5 --- /dev/null +++ b/platform/drivers/display/display_Mod17.c @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2024 by Morgan Diepart ON4MOD * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 3 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, see * + ***************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "SH110x_Mod17.h" +#include "SSD1309_Mod17.h" + + +struct displayFuncs +{ + void (*init)(void); + void (*terminate)(void); + void (*renderRows)(uint8_t, uint8_t, void *); + void (*render)(void *); + void (*setContrast)(uint8_t); + void (*setBacklightLevel)(uint8_t); +}; + +static struct displayFuncs display = +{ + .init = NULL, + .terminate = NULL, + .renderRows = NULL, + .render = NULL, + .setContrast = NULL, +}; + +void display_init() +{ + const hwInfo_t *hwinfo = platform_getHwInfo(); + if(((hwinfo->flags & MOD17_FLAGS_HMI_PRESENT) != 0) && + ((hwinfo->hw_version >> 8) == MOD17_HMI_V10)) + { + display.init = SSD1309_init; + display.renderRows = SSD1309_renderRows; + display.render = SSD1309_render; + display.setContrast = SSD1309_setContrast; + display.terminate = SSD1309_terminate; + } + else + { + display.init = SH110x_init; + display.renderRows = SH110x_renderRows; + display.render = SH110x_render; + display.setContrast = SH110x_setContrast; + display.terminate = SH110x_terminate; + } + + /* + * Initialise SPI2 for external flash and LCD + */ + 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(); + + /* + * Initialise GPIOs for LCD control + */ + gpio_setMode(LCD_CS, OUTPUT); + gpio_setMode(LCD_RST, OUTPUT); + gpio_setMode(LCD_DC, OUTPUT); + + display.init(); +} + +void display_terminate() +{ + display.terminate(); + spi2_terminate(); +} + +void display_renderRows(uint8_t startRow, uint8_t endRow, void *fb) +{ + display.renderRows(startRow, endRow, fb); +} + +void display_render(void *fb) +{ + display.render(fb); +} + +void display_setContrast(uint8_t contrast) +{ + display.setContrast(contrast); +} + +void display_setBacklightLevel(uint8_t level) +{ + (void) level; +} diff --git a/platform/targets/Module17/pinmap.h b/platform/targets/Module17/pinmap.h index 3d408d56..2e74519d 100644 --- a/platform/targets/Module17/pinmap.h +++ b/platform/targets/Module17/pinmap.h @@ -29,13 +29,12 @@ #define ERR_LED GPIOA,8 /* Display */ -#define LCD_RST GPIOC,7 -#define LCD_RS GPIOC,6 -#define LCD_CS GPIOB,14 -#define SPI2_CLK GPIOB,13 -#define SPI2_SDO GPIOB,9 // UNUSED -#define SPI2_SDI GPIOB,15 -//#define LCD_BKLIGHT GPIOE,15 +#define LCD_RST GPIOC,7 +#define LCD_DC GPIOC,6 +#define LCD_CS GPIOB,14 +#define SPI2_SCK GPIOB,13 +#define SPI2_MISO GPIOB,9 // UNUSED +#define SPI2_MOSI GPIOB,15 /* Keyboard */ #define ESC_SW GPIOB,8