5c80a0543115bd3c1a3f7c00491f6859d37abb24
[cortex-from-scratch] / drivers / st7735s.c
1 /* (CC-BY-NC-SA) ROBIN KRENS - ROBIN @ ROBINKRENS.NL
2  * 
3  * $LOG$
4  * 2019/9/14 - ROBIN KRENS      
5  * Initial version 
6  * 
7  * $DESCRIPTION$
8  * 
9  * $USAGE$
10  *
11  * */
12
13 #include <stdbool.h>
14 #include <stddef.h>
15 #include <stdint.h>
16 #include <stdarg.h>
17
18 #include <sys/mmap.h>
19 #include <sys/robsys.h>
20
21 #include <lib/regfunc.h>
22 #include <lib/string.h>
23 #include <lib/tinyprintf.h>
24
25 #include <drivers/st7735s.h>
26
27 #define TIMEOUT 500
28
29 void tft_test();
30 int tft_command(uint8_t cmd, int argsc, ...);
31 void tft_init() {
32
33         /* Peripherial init */
34         rsetbit(RCC_APB1ENR, 14); // enable SPI2
35         rsetbit(RCC_APB2ENR, 3); // enable GPIOB
36         rsetbit(RCC_APB2ENR, 4); // enable GPIOC
37
38         /* The PINS used are PB12, PB13, PB15 and PC6 respectively
39          * NSS (or CS): alternative function pusp-pull
40          * NSS Output is (always high) enabled with this setting
41          * SCK Master: alternate function push-pull
42          * MOSI (or DI): alternate function push-pull 
43          * D/CX (or A0): Command or data write line PC6 */
44         rwrite(GPIOB_CRH, 0xA4AA4444);
45         rwrite(GPIOC_CRL, 0x42444444);
46
47         /* Chip select: software enabled
48          * In case for a hardware setup, connect NSS (CS) to 
49          * ground  */
50         rsetbit(SPI2_CR1, 9);
51         rsetbit(SPI2_CR1, 8);
52
53         rsetbit(SPI2_CR1, 15); // one-wire mode
54         rsetbit(SPI2_CR1, 14); // start with transfer
55         rsetbit(SPI2_CR1, 4); // FPLCK div 8
56         rsetbit(SPI2_CR1, 2); // master selection
57         rsetbit(SPI2_CR1, 6); // enable SPI
58
59         /* Init sequence */
60         tft_command(TFT_SWRESET, 0);
61         _block(120000); 
62         tft_command(0x11, 0);
63         _block(120000); 
64
65         /* Frame rate control */
66         tft_command(TFT_FRMCTR1, 3, 0x01, 0x2C, 0x2D);
67         tft_command(TFT_FRMCTR2, 3, 0x01, 0x2C, 0x2D);
68         tft_command(TFT_FRMCTR3, 6, 0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D);        
69
70         /* Power control */
71         tft_command(TFT_PWCTR1, 3, 0xA2, 0x02, 0x84);
72         tft_command(TFT_PWCTR2, 1, 0xC5);
73         tft_command(TFT_PWCTR3, 2, 0x0A, 0x00);
74         tft_command(TFT_PWCTR4, 2, 0x8A, 0x2A);
75         tft_command(TFT_PWCTR5, 2, 0x8A, 0xEE);
76         tft_command(TFT_VMCTR1, 1, 0x0E);
77
78
79         tft_command(TFT_INVOFF, 0);
80         tft_command(TFT_COLMOD, 1, 0x05); // 0x05
81         tft_command(TFT_MADCTL, 1, 0xC0); // TODO: check
82
83         tft_command(TFT_CASET, 4, 0x00, 0x00, 0x00, 0x7F);
84         tft_command(TFT_RASET, 4, 0x00, 0x00, 0x00, 0x9F);
85
86         /* Gamma Settings */
87         tft_command(TFT_GMCTRP1, 16, 0x02, 0x1C, 0x07, 0x12,
88                         0x37, 0x32, 0x29, 0x2D,
89                         0x29, 0x25, 0x2B, 0x39,
90                         0x00, 0x01, 0x03, 0x10);
91         tft_command(TFT_GMCTRN1, 16, 0x03, 0x1D, 0x07, 0x06,
92                         0x2E, 0x2C, 0x29, 0x2D,
93                         0x2E, 0x2E, 0x37, 0x3F,
94                         0x00, 0x00, 0x02, 0x10);
95
96         /* Turn on */
97         tft_command(TFT_NORON, 0);
98         _block(10000);
99         tft_command(TFT_DISPON, 0);
100         _block(100000);
101
102         /* Test pixel */
103         //tft_command(.., 3, 0xFC, 0xFC, 0xFC);
104
105         for (int i = 0; i < 100; i ++) {
106                 tft_command(TFT_CASET, 4, 0x00, i, 0x00, i+1);
107                 tft_command(TFT_RASET, 4, 0x00, i, 0x00, i+1);
108                 tft_command(TFT_RAMWR, 2, 0xFF, 0xFF);
109         }
110         
111         /* tft_command(TFT_RAMWR, 100,
112                         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
113                         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
114                         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
115                         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
116                         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
117                         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
118                         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
119                         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
120                         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
121                         0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0
122                         );
123
124         _block(10000); */
125
126         tft_command(TFT_CASET, 4, 0x00, 0x08, 0x00, 0x09);
127         tft_command(TFT_RASET, 4, 0x00, 0x08, 0x00, 0x09);
128         tft_command(TFT_RAMRD, 0);
129
130         //tft_command(0x0C, 0);
131         //tft_command(0x0A, 0);
132         
133         rclrbit(SPI2_CR1, 14); // receive
134
135         while(!rchkbit(SPI2_SR, 0));
136         uint8_t chip_id = *SPI2_DR;
137         printf("COLMOD: %#x\n", chip_id);
138
139         rclrbit(SPI2_CR1, 8); // deselect
140 }
141
142 /* Helper function */
143 static int txbuf_empty () {
144         int cnt = 0;
145         while(!rchkbit(SPI2_SR, 1)) {
146                 cnt++;
147                 if (cnt > TIMEOUT) {
148                         printf("Error: transmit timeout!\n");
149                         return 0;
150                 }
151         }
152         return 1;
153
154 }
155
156
157
158 int tft_command(uint8_t cmd, int argsc, ...) {
159
160         va_list ap;
161
162         // command
163         rclrbit(GPIOC_ODR, 6);
164         rwrite(SPI2_DR, cmd);
165         if (!txbuf_empty()) 
166                 return -1;
167
168         // parameter or data
169         if (argsc > 0) {
170                 
171                 va_start(ap, argsc);
172
173                 rsetbit(GPIOC_ODR, 6);  
174                 for (int i = 0; i < argsc; i++) {
175                         uint8_t p = (uint8_t) va_arg(ap, unsigned int);
176                         rwrite(SPI2_DR, p);
177                         if (!txbuf_empty())
178                                 return -1;
179                         //printf("%c", (uint8_t) va_arg(ap, unsigned int));
180                 }
181
182                 va_end(ap);
183         }
184
185         return 0;
186 }       
187
188
189 /* write command: CS stay low
190  * read command: */
191
192 void tft_test() {
193
194         
195         // DC is data/command pin set and reset
196         
197         /* uint8_t cmd = 0x11;
198         rwrite(SPI2_DR, cmd);
199         while (!rchkbit(SPI2_SR, 1));
200
201         for (int i = 0; i < 10; i++)
202                 _block(0xFFFF); */      
203
204         uint8_t cmd = 0x3A;
205         uint8_t p1 = 0x5;
206
207         // command
208         rwrite(SPI2_DR, cmd);
209         while (!rchkbit(SPI2_SR, 1)); // check line busy?
210
211
212         // paramater 
213         rsetbit(GPIOC_ODR, 6);
214         rwrite(SPI2_DR, p1);
215         while (!rchkbit(SPI2_SR, 1)); // 
216
217         cmd = 0x0C;
218         rclrbit(GPIOC_ODR, 6);
219         rwrite(SPI2_DR, cmd);
220         while (!rchkbit(SPI2_SR, 1)); //        
221
222         rclrbit(SPI2_CR1, 14); // receive
223
224         while(!rchkbit(SPI2_SR, 0));
225         uint8_t chip_id = *SPI2_DR;
226         printf("Chip id: %#x\n", chip_id);
227
228
229 }