Module17: reorganized display drivers, implemented dynamic selection of display driver

This commit is contained in:
Morgan Diepart 2024-02-10 21:49:44 +01:00 committed by Silvano Seva
parent 30e9311a20
commit b5e49a3b4d
9 changed files with 479 additions and 81 deletions

View File

@ -415,7 +415,9 @@ dm1801_def += openrtx_def + mk22fn512_def + miosix_cm4f_def
## Module 17 ## Module 17
## ##
mod17_src = ['platform/targets/Module17/platform.c', mod17_src = ['platform/targets/Module17/platform.c',
'platform/drivers/display/display_Mod17.c',
'platform/drivers/display/SH110x_Mod17.c', 'platform/drivers/display/SH110x_Mod17.c',
'platform/drivers/display/SSD1309_Mod17.c',
'platform/drivers/keyboard/keyboard_Mod17.c', 'platform/drivers/keyboard/keyboard_Mod17.c',
'platform/drivers/NVM/nvmem_Mod17.c', 'platform/drivers/NVM/nvmem_Mod17.c',
'platform/drivers/CPS/cps_io_native_Mod17.c', 'platform/drivers/CPS/cps_io_native_Mod17.c',

View File

@ -24,32 +24,15 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <peripherals/gpio.h> #include <peripherals/gpio.h>
#include <interfaces/display.h>
#include <interfaces/delays.h> #include <interfaces/delays.h>
#include <hwconfig.h> #include <hwconfig.h>
#include <SPI2.h> #include <SPI2.h>
#include "SH110x_Mod17.h"
void SH110x_init()
void display_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_setPin(LCD_CS);
gpio_clearPin(LCD_RS); gpio_clearPin(LCD_DC);
gpio_clearPin(LCD_RST); /* Reset controller */ gpio_clearPin(LCD_RST); /* Reset controller */
delayMs(50); delayMs(50);
@ -58,7 +41,7 @@ void display_init()
gpio_clearPin(LCD_CS); 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(0xAE); /* SH110X_DISPLAYOFF */
spi2_sendRecv(0xD5); /* SH110X_SETDISPLAYCLOCKDIV, 0x51 */ spi2_sendRecv(0xD5); /* SH110X_SETDISPLAYCLOCKDIV, 0x51 */
spi2_sendRecv(0x51); spi2_sendRecv(0x51);
@ -84,12 +67,12 @@ void display_init()
gpio_setPin(LCD_CS); 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); 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++) 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(y & 0x0F); /* Set Y position */
(void) spi2_sendRecv(0x10 | ((y >> 4) & 0x07)); (void) spi2_sendRecv(0x10 | ((y >> 4) & 0x07));
(void) spi2_sendRecv(0xB0 | x); /* Set X position */ (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); size_t pos = x + y * (CONFIG_SCREEN_WIDTH/8);
spi2_sendRecv(frameBuffer[pos]); spi2_sendRecv(frameBuffer[pos]);
@ -112,31 +95,18 @@ void display_renderRows(uint8_t startRow, uint8_t endRow, void *fb)
gpio_setPin(LCD_CS); 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_CS);
gpio_clearPin(LCD_RS); /* RS low -> command mode */ gpio_clearPin(LCD_DC); /* RS low -> command mode */
(void) spi2_sendRecv(0x81); /* Contrast control register */ (void) spi2_sendRecv(0x81); /* Set Electronic Volume */
(void) spi2_sendRecv(bl); (void) spi2_sendRecv(contrast); /* Controller contrast range is 0 - 63 */
gpio_setPin(LCD_CS); gpio_setPin(LCD_CS);
} }

View File

@ -0,0 +1,48 @@
#ifndef SH110X_MOD17_H
#define SH110X_MOD17_H
#include <stdint.h>
#include <stdbool.h>
#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 */

View File

@ -38,7 +38,7 @@
* *
* @param row: pixel row to be be sent. * @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++) 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_setPin(LCD_CS);
gpio_clearPin(LCD_RS); gpio_clearPin(LCD_RS);
@ -109,12 +93,12 @@ void display_init()
gpio_setPin(LCD_CS); gpio_setPin(LCD_CS);
} }
void display_terminate() void SSD1306_terminate()
{ {
spi2_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); 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(0x00); /* Set X position */
(void) spi2_sendRecv(0x10); (void) spi2_sendRecv(0x10);
gpio_setPin(LCD_RS); /* RS high -> data mode */ gpio_setPin(LCD_RS); /* RS high -> data mode */
display_renderRow(row, (uint8_t *) fb); SSD1306_renderRow(row, (uint8_t *) fb);
} }
gpio_setPin(LCD_CS); 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); gpio_clearPin(LCD_CS);
@ -146,8 +130,3 @@ void display_setContrast(uint8_t contrast)
gpio_setPin(LCD_CS); gpio_setPin(LCD_CS);
} }
void display_setBacklightLevel(uint8_t level)
{
(void) level;
}

View File

@ -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 <http://www.gnu.org/licenses/> *
***************************************************************************/
#ifndef SSD1306_MOD17_H
#define SSD1306_MOD17_H
#include <stdint.h>
#include <stdbool.h>
#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 */

View File

@ -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 <http://www.gnu.org/licenses/> *
***************************************************************************/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <peripherals/gpio.h>
#include <interfaces/delays.h>
#include <hwconfig.h>
#include <SPI2.h>
#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);
}

View File

@ -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 <http://www.gnu.org/licenses/> *
***************************************************************************/
#ifndef SSD1309_MOD17_H
#define SSD1309_MOD17_H
#include <stdint.h>
#include <stdbool.h>
#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 */

View File

@ -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 <http://www.gnu.org/licenses/> *
***************************************************************************/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <peripherals/gpio.h>
#include <hwconfig.h>
#include <interfaces/platform.h>
#include <SPI2.h>
#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;
}

View File

@ -29,13 +29,12 @@
#define ERR_LED GPIOA,8 #define ERR_LED GPIOA,8
/* Display */ /* Display */
#define LCD_RST GPIOC,7 #define LCD_RST GPIOC,7
#define LCD_RS GPIOC,6 #define LCD_DC GPIOC,6
#define LCD_CS GPIOB,14 #define LCD_CS GPIOB,14
#define SPI2_CLK GPIOB,13 #define SPI2_SCK GPIOB,13
#define SPI2_SDO GPIOB,9 // UNUSED #define SPI2_MISO GPIOB,9 // UNUSED
#define SPI2_SDI GPIOB,15 #define SPI2_MOSI GPIOB,15
//#define LCD_BKLIGHT GPIOE,15
/* Keyboard */ /* Keyboard */
#define ESC_SW GPIOB,8 #define ESC_SW GPIOB,8