CS7000: display driver

This commit is contained in:
Silvano Seva 2024-04-29 20:54:41 +02:00
parent d85287e692
commit 7f83dbbd5f
3 changed files with 366 additions and 1 deletions

View File

@ -461,7 +461,8 @@ cs7000_src = ['platform/drivers/stubs/nvmem_stub.c',
'platform/drivers/stubs/cps_io_stub.c',
'platform/drivers/stubs/radio_stub.c',
'platform/drivers/stubs/keyboard_stub.c',
'platform/drivers/stubs/display_stub.c',
'platform/drivers/display/ST7735R_CS7000.c',
'platform/drivers/backlight/backlight_CS7000.c',
'platform/drivers/stubs/audio_stub.c',
'platform/drivers/GPIO/gpio_shiftReg.c',
'platform/drivers/SPI/spi_custom.c',

View File

@ -0,0 +1,72 @@
/***************************************************************************
* Copyright (C) 2024 by Silvano Seva IU2KWO *
* *
* 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 <interfaces/platform.h>
#include <peripherals/gpio.h>
#include <hwconfig.h>
#include "backlight.h"
void backlight_init()
{
gpio_setMode(LCD_BKLIGHT, ALTERNATE | ALTERNATE_FUNC(3));
/*
* Configure TIM8 for backlight PWM: Fpwm = 1kHz with 8 bit of resolution.
* APB2 freq. is 84MHz, but timer runs at twice this frequency.
* Then: PSC = 655 to have Ftick = 256.097kHz
* With ARR = 256, Fpwm is 1kHz;
* Backlight pin is connected to TIM8 CR1.
*/
RCC->APB2ENR |= RCC_APB2ENR_TIM8EN;
__DSB();
TIM8->ARR = 255;
TIM8->PSC = 654;
TIM8->CNT = 0;
TIM8->CR1 |= TIM_CR1_ARPE; /* LCD backlight is on PC6, TIM8-CH1 */
TIM8->CCMR2 |= TIM_CCMR1_OC2M_2
| TIM_CCMR1_OC2M_1
| TIM_CCMR1_OC2PE;
TIM8->CCER |= TIM_CCER_CC4E;
TIM8->BDTR |= TIM_BDTR_MOE;
TIM8->CCR1 = 0;
TIM8->EGR = TIM_EGR_UG; /* Update registers */
TIM8->CR1 |= TIM_CR1_CEN; /* Start timer */
}
void backlight_terminate()
{
/* Shut down backlight */
gpio_setMode(LCD_BKLIGHT, OUTPUT);
gpio_clearPin(LCD_BKLIGHT);
/* Shut down timer */
RCC->APB2ENR &= ~RCC_APB2ENR_TIM8EN;
__DSB();
}
/*
* This function is defined in display.h
*/
void display_setBacklightLevel(uint8_t level)
{
if(level > 100)
level = 100;
uint8_t pwmLevel = (2 * level) + (level * 55)/100; // Convert value to 0 - 255
TIM8->CCR4 = pwmLevel;
}

View File

@ -0,0 +1,292 @@
/***************************************************************************
* Copyright (C) 2024 by Silvano Seva IU2KWO *
* *
* 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 <peripherals/gpio.h>
#include <interfaces/display.h>
#include <interfaces/delays.h>
#include <interfaces/platform.h>
#include <backlight.h>
#include <hwconfig.h>
#include <string.h>
enum ST775RCmd
{
ST775R_CMD_NOP = 0x00,
ST775R_CMD_SWRESET = 0x01,
ST775R_CMD_RDID = 0x04,
ST775R_CMD_RDDST = 0x09,
ST775R_CMD_RDDPM = 0x0A,
ST775R_CMD_RDDMADCTL = 0x0B,
ST775R_CMD_RDDCOLMOD = 0x0C,
ST775R_CMD_RDDIM = 0x0D,
ST775R_CMD_RDDSM = 0x0E,
ST775R_CMD_SLPIN = 0x10,
ST775R_CMD_SLPOUT = 0x11,
ST775R_CMD_PTLON = 0x12,
ST775R_CMD_NORON = 0x13,
ST775R_CMD_INVOFF = 0x20,
ST775R_CMD_INVON = 0x21,
ST775R_CMD_GAMSET = 0x26,
ST775R_CMD_DISPOFF = 0x28,
ST775R_CMD_DISPON = 0x29,
ST775R_CMD_CASET = 0x2A,
ST775R_CMD_RASET = 0x2B,
ST775R_CMD_RAMWR = 0x2C,
ST775R_CMD_RGBSET = 0x2D,
ST775R_CMD_RAMRD = 0x2E,
ST775R_CMD_PTLAR = 0x30,
ST775R_CMD_TEOFF = 0x34,
ST775R_CMD_TEON = 0x35,
ST775R_CMD_MADCTL = 0x36,
ST775R_CMD_IDMOFF = 0x38,
ST775R_CMD_IDMON = 0x39,
ST775R_CMD_COLMOD = 0x3A,
ST775R_CMD_RDID1 = 0xDA,
ST775R_CMD_RDID2 = 0xDB,
ST775R_CMD_RDID3 = 0xDC
};
static inline void sendCmd(uint8_t cmd)
{
// Set D/C low (command mode), clear WR and data lines
GPIOD->BSRR = 0x30FF0000;
asm volatile(" mov r1, #21 \n"
"___loop_d: cmp r1, #0 \n"
" itt ne \n"
" subne r1, r1, #1 \n"
" bne ___loop_d \n":::"r1");
GPIOD->BSRR = cmd | (1 << 13);
}
static inline void sendData(uint8_t val)
{
// Set D/C high (data mode), clear WR and data lines
GPIOD->BSRR = 0x20FF1000;
asm volatile(" mov r1, #21 \n"
"___loop_e: cmp r1, #0 \n"
" itt ne \n"
" subne r1, r1, #1 \n"
" bne ___loop_e \n":::"r1");
GPIOD->BSRR = val | (1 << 13);
}
void display_init()
{
backlight_init();
/* Set up gpios */
gpio_setMode(LCD_D0, OUTPUT);
gpio_setMode(LCD_D1, OUTPUT);
gpio_setMode(LCD_D2, OUTPUT);
gpio_setMode(LCD_D3, OUTPUT);
gpio_setMode(LCD_D4, OUTPUT);
gpio_setMode(LCD_D5, OUTPUT);
gpio_setMode(LCD_D6, OUTPUT);
gpio_setMode(LCD_D7, OUTPUT);
gpio_setMode(LCD_WR, OUTPUT);
gpio_setMode(LCD_RD, OUTPUT);
gpio_setMode(LCD_DC, OUTPUT);
gpio_setMode(LCD_RST, OUTPUT);
gpio_setMode(LCD_CS, OUTPUT);
gpio_setOutputSpeed(LCD_D0, HIGH);
gpio_setOutputSpeed(LCD_D1, HIGH);
gpio_setOutputSpeed(LCD_D2, HIGH);
gpio_setOutputSpeed(LCD_D3, HIGH);
gpio_setOutputSpeed(LCD_D4, HIGH);
gpio_setOutputSpeed(LCD_D5, HIGH);
gpio_setOutputSpeed(LCD_D6, HIGH);
gpio_setOutputSpeed(LCD_D7, HIGH);
gpio_setOutputSpeed(LCD_WR, HIGH);
gpio_setOutputSpeed(LCD_RD, HIGH);
gpio_setOutputSpeed(LCD_DC, HIGH);
gpio_setOutputSpeed(LCD_RST, HIGH);
gpio_setOutputSpeed(LCD_CS, HIGH);
gpio_clearPin(LCD_RST); /* Put LCD in reset mode */
gpio_setPin(LCD_CS); /* CS idle state is high level */
gpio_setPin(LCD_DC); /* Idle state for DC line */
gpio_setPin(LCD_WR); /* Idle state for WR line */
gpio_setPin(LCD_RD); /* Idle state for RD line */
gpio_setPin(LCD_RST); /* Exit from reset */
delayMs(10);
gpio_clearPin(LCD_CS);
sendCmd(ST775R_CMD_SWRESET);
sendCmd(0xb1); /* Undocumented command */
sendData(5);
sendData(8);
sendData(5);
sendCmd(0xb2); /* Undocumented command */
sendData(5);
sendData(8);
sendData(5);
sendCmd(0xb3); /* Undocumented command */
sendData(5);
sendData(8);
sendData(5);
sendData(5);
sendData(8);
sendData(5);
sendCmd(0xb4); /* Undocumented command */
sendData(0);
sendCmd(0xb6); /* Undocumented command */
sendData(0xb4);
sendData(0xf0);
sendCmd(0xc0); /* Undocumented command */
sendData(0xa2);
sendData(2);
/* sendData(0x85); TODO: see original fw */
sendData(0x84);
sendCmd(0xc1); /* Undocumented command */
sendData(5);
sendCmd(0xc2); /* Undocumented command */
sendData(10);
sendData(0);
sendCmd(0xc3); /* Undocumented command */
sendData(0x8a);
sendData(0x2a);
sendCmd(0xc4); /* Undocumented command */
sendData(0x8a);
sendData(0xee);
sendCmd(0xc5); /* Undocumented command */
sendData(0xe);
sendCmd(ST775R_CMD_MADCTL);
sendData(0xB0);
sendCmd(0xe0); /* Undocumented command */
sendData(5);
/* sendData(0x28); TODO: see original fw */
/* sendData(0x28); TODO: see original fw */
sendData(0x16);
sendData(0xf);
sendData(0x18);
sendData(0x2f);
sendData(0x28);
sendData(0x20);
sendData(0x22);
sendData(0x1f);
sendData(0x1b);
sendData(0x23);
sendData(0x37);
sendData(0);
sendData(7);
sendData(2);
sendData(0x10);
sendCmd(0xe1); /* Undocumented command */
sendData(7);
/* sendData(0x28); TODO: see original fw */
/* sendData(0x28); TODO: see original fw */
sendData(0x1b);
sendData(0xf);
sendData(0x17);
sendData(0x33);
sendData(0x2c);
sendData(0x29);
sendData(0x2e);
sendData(0x30);
sendData(0x30);
sendData(0x39);
sendData(0x3f);
sendData(0);
sendData(7);
sendData(3);
sendData(0x10);
sendCmd(0xf0); /* Undocumented command */
sendData(1);
sendCmd(0xf6); /* Undocumented command */
sendData(0);
sendCmd(ST775R_CMD_COLMOD);
sendData(0x05); /* 16bpp - RGB 565 */
sendCmd(ST775R_CMD_RASET);
sendData(0);
sendData(0);
sendData(0);
sendData(0x7f); /* 128 rows */
sendCmd(ST775R_CMD_CASET);
sendData(0);
sendData(0);
sendData(0);
sendData(0x9f); /* 160 columns */
/* Exit from sleep */
sendCmd(ST775R_CMD_SLPOUT);
delayMs(120);
/* Enable display */
sendCmd(ST775R_CMD_DISPON);
gpio_setPin(LCD_CS);
}
void display_terminate()
{
}
void display_renderRows(uint8_t startRow, uint8_t endRow, void *fb)
{
/*
* Put screen data lines back to output mode, since they are in common with
* keyboard buttons and the keyboard driver sets them as inputs.
*/
gpio_setMode(LCD_D0, OUTPUT);
gpio_setMode(LCD_D1, OUTPUT);
gpio_setMode(LCD_D2, OUTPUT);
gpio_setMode(LCD_D3, OUTPUT);
gpio_setMode(LCD_D4, OUTPUT);
gpio_setMode(LCD_D5, OUTPUT);
gpio_setMode(LCD_D6, OUTPUT);
gpio_setMode(LCD_D7, OUTPUT);
/*
* Select the display, configure start and end rows in display driver and
* write to display memory.
*/
gpio_clearPin(LCD_CS);
sendCmd(ST775R_CMD_RASET);
sendData(0x00);
sendData(startRow);
sendData(0x00);
sendData(endRow);
sendCmd(ST775R_CMD_RAMWR);
for(uint8_t y = startRow; y < endRow; y++)
{
for(uint8_t x = 0; x < CONFIG_SCREEN_WIDTH; x++)
{
size_t pos = x + y * CONFIG_SCREEN_WIDTH;
uint16_t pixel = ((uint16_t *) fb)[pos];
sendData((pixel >> 8) & 0xff);
sendData(pixel & 0xff);
}
}
gpio_setPin(LCD_CS);
}
void display_render(void *fb)
{
display_renderRows(0, CONFIG_SCREEN_HEIGHT, fb);
}
void display_setContrast(uint8_t contrast)
{
/* This controller does not support contrast regulation */
(void) contrast;
}