From: Robin Krens <robin@robinkrens.nl>
Date: Tue, 17 Sep 2019 14:05:44 +0000 (+0700)
Subject: st7735s: i can draw
X-Git-Url: https://robinkrens.nl/gitweb/?a=commitdiff_plain;h=9b028a56b389fe9b49cf95cd4342514160ae0662;p=cortex-from-scratch

st7735s: i can draw
---

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 <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <stdarg.h>
 
 #include <sys/mmap.h>
 #include <sys/robsys.h>
@@ -23,43 +24,206 @@
 
 #include <drivers/st7735s.h>
 
-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();