From 9b028a56b389fe9b49cf95cd4342514160ae0662 Mon Sep 17 00:00:00 2001 From: Robin Krens Date: Tue, 17 Sep 2019 21:05:44 +0700 Subject: [PATCH] st7735s: i can draw --- drivers/st7735s.c | 184 +++++++++++++++++++++++++++++++++++++++++++--- include/drivers/st7735s.h | 65 ++++++++++++++++ include/lib/regfunc.h | 2 +- include/sys/mmap.h | 2 +- lib/regfunc.c | 7 +- main.c | 4 +- 6 files changed, 247 insertions(+), 17 deletions(-) diff --git a/drivers/st7735s.c b/drivers/st7735s.c index bf6c763..5c80a05 100644 --- a/drivers/st7735s.c +++ b/drivers/st7735s.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -23,43 +24,206 @@ #include -void tft_command(); +#define TIMEOUT 500 + +void tft_test(); +int tft_command(uint8_t cmd, int argsc, ...); void tft_init() { /* Peripherial init */ rsetbit(RCC_APB1ENR, 14); // enable SPI2 rsetbit(RCC_APB2ENR, 3); // enable GPIOB + rsetbit(RCC_APB2ENR, 4); // enable GPIOC - /* The PINS used are respective PB12, PB13 and PB15 + /* The PINS used are PB12, PB13, PB15 and PC6 respectively * NSS (or CS): alternative function pusp-pull * NSS Output is (always high) enabled with this setting * SCK Master: alternate function push-pull - * MOSI (or DI): alternate function push-pull */ + * MOSI (or DI): alternate function push-pull + * D/CX (or A0): Command or data write line PC6 */ rwrite(GPIOB_CRH, 0xA4AA4444); + rwrite(GPIOC_CRL, 0x42444444); - /* Chip select: software enabled */ + /* Chip select: software enabled + * In case for a hardware setup, connect NSS (CS) to + * ground */ rsetbit(SPI2_CR1, 9); rsetbit(SPI2_CR1, 8); - // LOW and first edge: standard settings - rsetbit(SPI2_CR1, 15); // one-wire mode rsetbit(SPI2_CR1, 14); // start with transfer rsetbit(SPI2_CR1, 4); // FPLCK div 8 rsetbit(SPI2_CR1, 2); // master selection rsetbit(SPI2_CR1, 6); // enable SPI - tft_command(); + /* Init sequence */ + tft_command(TFT_SWRESET, 0); + _block(120000); + tft_command(0x11, 0); + _block(120000); + + /* Frame rate control */ + tft_command(TFT_FRMCTR1, 3, 0x01, 0x2C, 0x2D); + tft_command(TFT_FRMCTR2, 3, 0x01, 0x2C, 0x2D); + tft_command(TFT_FRMCTR3, 6, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D); + + /* Power control */ + tft_command(TFT_PWCTR1, 3, 0xA2, 0x02, 0x84); + tft_command(TFT_PWCTR2, 1, 0xC5); + tft_command(TFT_PWCTR3, 2, 0x0A, 0x00); + tft_command(TFT_PWCTR4, 2, 0x8A, 0x2A); + tft_command(TFT_PWCTR5, 2, 0x8A, 0xEE); + tft_command(TFT_VMCTR1, 1, 0x0E); + + + tft_command(TFT_INVOFF, 0); + tft_command(TFT_COLMOD, 1, 0x05); // 0x05 + tft_command(TFT_MADCTL, 1, 0xC0); // TODO: check + + tft_command(TFT_CASET, 4, 0x00, 0x00, 0x00, 0x7F); + tft_command(TFT_RASET, 4, 0x00, 0x00, 0x00, 0x9F); + + /* Gamma Settings */ + tft_command(TFT_GMCTRP1, 16, 0x02, 0x1C, 0x07, 0x12, + 0x37, 0x32, 0x29, 0x2D, + 0x29, 0x25, 0x2B, 0x39, + 0x00, 0x01, 0x03, 0x10); + tft_command(TFT_GMCTRN1, 16, 0x03, 0x1D, 0x07, 0x06, + 0x2E, 0x2C, 0x29, 0x2D, + 0x2E, 0x2E, 0x37, 0x3F, + 0x00, 0x00, 0x02, 0x10); + + /* Turn on */ + tft_command(TFT_NORON, 0); + _block(10000); + tft_command(TFT_DISPON, 0); + _block(100000); + + /* Test pixel */ + //tft_command(.., 3, 0xFC, 0xFC, 0xFC); + + for (int i = 0; i < 100; i ++) { + tft_command(TFT_CASET, 4, 0x00, i, 0x00, i+1); + tft_command(TFT_RASET, 4, 0x00, i, 0x00, i+1); + tft_command(TFT_RAMWR, 2, 0xFF, 0xFF); + } + + /* tft_command(TFT_RAMWR, 100, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0 + ); + + _block(10000); */ + + tft_command(TFT_CASET, 4, 0x00, 0x08, 0x00, 0x09); + tft_command(TFT_RASET, 4, 0x00, 0x08, 0x00, 0x09); + tft_command(TFT_RAMRD, 0); + + //tft_command(0x0C, 0); + //tft_command(0x0A, 0); + + rclrbit(SPI2_CR1, 14); // receive + + while(!rchkbit(SPI2_SR, 0)); + uint8_t chip_id = *SPI2_DR; + printf("COLMOD: %#x\n", chip_id); + rclrbit(SPI2_CR1, 8); // deselect } +/* Helper function */ +static int txbuf_empty () { + int cnt = 0; + while(!rchkbit(SPI2_SR, 1)) { + cnt++; + if (cnt > TIMEOUT) { + printf("Error: transmit timeout!\n"); + return 0; + } + } + return 1; + +} + + -void tft_command() { +int tft_command(uint8_t cmd, int argsc, ...) { - /* 9-bit hack */ - uint8_t cmd = 0x0A; + va_list ap; + // command + rclrbit(GPIOC_ODR, 6); + rwrite(SPI2_DR, cmd); + if (!txbuf_empty()) + return -1; + + // parameter or data + if (argsc > 0) { + + va_start(ap, argsc); + + rsetbit(GPIOC_ODR, 6); + for (int i = 0; i < argsc; i++) { + uint8_t p = (uint8_t) va_arg(ap, unsigned int); + rwrite(SPI2_DR, p); + if (!txbuf_empty()) + return -1; + //printf("%c", (uint8_t) va_arg(ap, unsigned int)); + } + + va_end(ap); + } + + return 0; +} + + +/* write command: CS stay low + * read command: */ + +void tft_test() { + + + // DC is data/command pin set and reset + + /* uint8_t cmd = 0x11; rwrite(SPI2_DR, cmd); while (!rchkbit(SPI2_SR, 1)); + + for (int i = 0; i < 10; i++) + _block(0xFFFF); */ + + uint8_t cmd = 0x3A; + uint8_t p1 = 0x5; + + // command + rwrite(SPI2_DR, cmd); + while (!rchkbit(SPI2_SR, 1)); // check line busy? + + + // paramater + rsetbit(GPIOC_ODR, 6); + rwrite(SPI2_DR, p1); + while (!rchkbit(SPI2_SR, 1)); // + + cmd = 0x0C; + rclrbit(GPIOC_ODR, 6); + rwrite(SPI2_DR, cmd); + while (!rchkbit(SPI2_SR, 1)); // + rclrbit(SPI2_CR1, 14); // receive + + while(!rchkbit(SPI2_SR, 0)); + uint8_t chip_id = *SPI2_DR; + printf("Chip id: %#x\n", chip_id); + + } diff --git a/include/drivers/st7735s.h b/include/drivers/st7735s.h index d345c10..1636214 100644 --- a/include/drivers/st7735s.h +++ b/include/drivers/st7735s.h @@ -1,6 +1,71 @@ #ifndef __ST7735S_H #define __ST7735S_H +enum CMDLIST { + TFT_NOP = 0x00, + TFT_SWRESET = 0x01, + /* READ COMMANDS: returns one or multiple bytes, + * use these for debugging to check if certain + * registers are set correctly */ + TFT_RDDID = 0x04, + TFT_RDDST = 0x09, + TFT_RDDPM = 0x0A, + TFT_RDDMADCTL = 0x0B, + TFT_RDDCOLMOD = 0x0C, + TFT_RDDIM = 0x0D, + TFT_RDDSM = 0x0E, + TFT_RDDSDR = 0x0F, + TFT_RDID1 = 0xDA, + TFT_RDID2 = 0xDB, + TFT_RDID3 = 0xDC, + TFT_RAMRD = 0x2E, + /* DISPLAY MODE COMMANDS */ + TFT_SLPIN = 0x10, + TFT_SLPOUT = 0x11, + TFT_PTLON = 0x12, + TFT_NORON = 0x13, + TFT_INVOFF = 0x20, + TFT_INVON = 0x21, + TFT_GAMSET = 0x26, + TFT_DISPOFF = 0x28, + TFT_DISPON = 0x29, + TFT_IDMOFF = 0x38, + TFT_IDMON = 0x39, + TFT_TEOFF = 0x34, + TFT_TEON = 0x35, + /* BASIC SETTINGS COMMANDS */ + TFT_CASET = 0x2A, + TFT_RASET = 0x2B, + TFT_RAMWR = 0x2C, + TFT_RGBSET = 0x2D, + TFT_PTLAR = 0x30, + TFT_SCRLAR = 0x33, + TFT_MADCTL = 0x36, + TFT_VSCSAD = 0x37, + TFT_COLMOD = 0x3A, + /* PANEL FUNCTIONS COMMANDS */ + TFT_FRMCTR1 = 0xB1, + TFT_FRMCTR2 = 0xB2, + TFT_FRMCTR3 = 0xB3, + TFT_INVCTR = 0xB4, + TFT_PWCTR1 = 0xC0, + TFT_PWCTR2 = 0xC1, + TFT_PWCTR3 = 0xC2, + TFT_PWCTR4 = 0xC3, + TFT_PWCTR5 = 0xC4, + TFT_VMCTR1 = 0xC5, + TFT_VMOFCTR = 0xC7, + TFT_WRID2 = 0xD1, + TFT_WRID3 = 0xD2, + TFT_NVCTR = 0xD9, + TFT_NVCTR2 = 0xDE, + TFT_NVCTR3 = 0xDF, + /* GAMMA SETTINGS */ + TFT_GMCTRP1 = 0xE0, + TFT_GMCTRN1 = 0xE1 + +}; + extern void tft_init(); #endif diff --git a/include/lib/regfunc.h b/include/lib/regfunc.h index 4b938c7..058d1e8 100644 --- a/include/lib/regfunc.h +++ b/include/lib/regfunc.h @@ -6,7 +6,7 @@ extern void rclrbit(volatile uint32_t *, short); extern void rsetbitsfrom(volatile uint32_t *, short, int); extern int rchkbit(volatile uint32_t *, short); extern void rwrite(volatile uint32_t *, uint32_t); -extern void _block(uint16_t us); +extern void _block(uint32_t us); /* DEPRECATED * extern void regw_u8(volatile uint32_t *, uint8_t, short, short); diff --git a/include/sys/mmap.h b/include/sys/mmap.h index 4af5c35..091d242 100644 --- a/include/sys/mmap.h +++ b/include/sys/mmap.h @@ -77,7 +77,7 @@ #define GPIOB_BSRR MEM_ADDR(0x40010C10) #define GPIOB_ODR MEM_ADDR(0x40010C0C) #define GPIOB_IDR MEM_ADDR(0x40010C08) -#define GPIOC_CRL MEM_ADDR(0x40011000) // led +#define GPIOC_CRL MEM_ADDR(0x40011000) // SPI2 uses D/CX (A0) #define GPIOC_CRH MEM_ADDR(0x40011004) #define GPIOC_ODR MEM_ADDR(0x4001100C) diff --git a/lib/regfunc.c b/lib/regfunc.c index 2e24689..2928694 100644 --- a/lib/regfunc.c +++ b/lib/regfunc.c @@ -103,8 +103,9 @@ uint32_t hextoreg(char * a) { * * Example: for a standard STM32x config board (8MHz) the maximum delay is * 0xFFFF * (1/8,000,000) * 3 = 24.58ms + * 0xFFFFFFFF * (1/8MHz) * 3 = 1610ms * */ -static void __block(uint16_t count) { +static void __block(uint32_t count) { asm volatile("b1: subs %0, %1, #1" "\n\t" "bne b1" : "=r" (count) : "r" (count)); @@ -113,9 +114,9 @@ static void __block(uint16_t count) { /* Delay us microsecond * Note: delay includes setup time (about 4 clockcycles), so is quite * inaccurate */ -void _block(uint16_t us) { +void _block(uint32_t us) { - uint16_t count = (us/3) * CLKSPEED_MHZ; // x cycles + uint32_t count = (us/3) * CLKSPEED_MHZ; // x cycles __block(count); } diff --git a/main.c b/main.c index 8de2880..30c4244 100644 --- a/main.c +++ b/main.c @@ -57,8 +57,8 @@ void main() led_init(); /* Real time clock */ - rtc_init(); - + //rtc_init(); + /* Eeprom Driver eeprom_at24c_init(); eeprom_test(); -- 2.7.4