]> granicus.if.org Git - esp-idf/blob - examples/26_spi_master/main/spi_master.c
2013dfd9c954938c3dba1b67d5b49ba9a494ba2b
[esp-idf] / examples / 26_spi_master / main / spi_master.c
1 /* SPI Master example
2
3    This example code is in the Public Domain (or CC0 licensed, at your option.)
4
5    Unless required by applicable law or agreed to in writing, this
6    software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7    CONDITIONS OF ANY KIND, either express or implied.
8 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include "freertos/FreeRTOS.h"
13 #include "freertos/task.h"
14 #include "esp_system.h"
15 #include "driver/spi_master.h"
16 #include "soc/gpio_struct.h"
17 #include "driver/gpio.h"
18
19
20 /*
21  This code displays some fancy graphics on the ILI9341-based 320x240 LCD on an ESP-WROVER_KIT board.
22  It is not very fast, even when the SPI transfer itself happens at 8MHz and with DMA, because
23  the rest of the code is not very optimized. Especially calculating the image line-by-line
24  is inefficient; it would be quicker to send an entire screenful at once. This example does, however,
25  demonstrate the use of both spi_device_transmit as well as spi_device_queue_trans/spi_device_get_trans_result
26  as well as pre-transmit callbacks.
27
28  Some info about the ILI9341: It has an C/D line, which is connected to a GPIO here. It expects this
29  line to be low for a command and high for data. We use a pre-transmit callback here to control that
30  line: every transaction has as the user-definable argument the needed state of the D/C line and just
31  before the transaction is sent, the callback will set this line to the correct state.
32 */
33
34 #define PIN_NUM_MISO 25
35 #define PIN_NUM_MOSI 23
36 #define PIN_NUM_CLK  19
37 #define PIN_NUM_CS   22
38
39 #define PIN_NUM_DC   21
40 #define PIN_NUM_RST  18
41 #define PIN_NUM_BCKL 5
42
43
44 /*
45  The ILI9341 needs a bunch of command/argument values to be initialized. They are stored in this struct.
46 */
47 typedef struct {
48     uint8_t cmd;
49     uint8_t data[16];
50     uint8_t databytes; //No of data in data; bit 7 = delay after set; 0xFF = end of cmds.
51 } ili_init_cmd_t;
52
53 static const ili_init_cmd_t ili_init_cmds[]={
54     {0xCF, {0x00, 0x83, 0X30}, 3},
55     {0xED, {0x64, 0x03, 0X12, 0X81}, 4},
56     {0xE8, {0x85, 0x01, 0x79}, 3},
57     {0xCB, {0x39, 0x2C, 0x00, 0x34, 0x02}, 5},
58     {0xF7, {0x20}, 1},
59     {0xEA, {0x00, 0x00}, 2},
60     {0xC0, {0x26}, 1},
61     {0xC1, {0x11}, 1},
62     {0xC5, {0x35, 0x3E}, 2},
63     {0xC7, {0xBE}, 1},
64     {0x36, {0x28}, 1},
65     {0x3A, {0x55}, 1},
66     {0xB1, {0x00, 0x1B}, 2},
67     {0xF2, {0x08}, 1},
68     {0x26, {0x01}, 1},
69     {0xE0, {0x1F, 0x1A, 0x18, 0x0A, 0x0F, 0x06, 0x45, 0X87, 0x32, 0x0A, 0x07, 0x02, 0x07, 0x05, 0x00}, 15},
70     {0XE1, {0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3A, 0x78, 0x4D, 0x05, 0x18, 0x0D, 0x38, 0x3A, 0x1F}, 15},
71     {0x2A, {0x00, 0x00, 0x00, 0xEF}, 4},
72     {0x2B, {0x00, 0x00, 0x01, 0x3f}, 4}, 
73     {0x2C, {0}, 0},
74     {0xB7, {0x07}, 1},
75     {0xB6, {0x0A, 0x82, 0x27, 0x00}, 4},
76     {0x11, {0}, 0x80},
77     {0x29, {0}, 0x80},
78     {0, {0}, 0xff},
79 };
80
81 //Send a command to the ILI9341. Uses spi_device_transmit, which waits until the transfer is complete.
82 void ili_cmd(spi_device_handle_t spi, const uint8_t cmd) 
83 {
84     esp_err_t ret;
85     spi_transaction_t t;
86     memset(&t, 0, sizeof(t));       //Zero out the transaction
87     t.length=8;                     //Command is 8 bits
88     t.tx_buffer=&cmd;               //The data is the cmd itself
89     t.user=(void*)0;                //D/C needs to be set to 0
90     ret=spi_device_transmit(spi, &t);  //Transmit!
91     assert(ret==ESP_OK);            //Should have had no issues.
92 }
93
94 //Send data to the ILI9341. Uses spi_device_transmit, which waits until the transfer is complete.
95 void ili_data(spi_device_handle_t spi, const uint8_t *data, int len) 
96 {
97     esp_err_t ret;
98     spi_transaction_t t;
99     if (len==0) return;             //no need to send anything
100     memset(&t, 0, sizeof(t));       //Zero out the transaction
101     t.length=len*8;                 //Len is in bytes, transaction length is in bits.
102     t.tx_buffer=data;               //Data
103     t.user=(void*)1;                //D/C needs to be set to 1
104     ret=spi_device_transmit(spi, &t);  //Transmit!
105     assert(ret==ESP_OK);            //Should have had no issues.
106 }
107
108 //This function is called (in irq context!) just before a transmission starts. It will
109 //set the D/C line to the value indicated in the user field.
110 void ili_spi_pre_transfer_callback(spi_transaction_t *t) 
111 {
112     int dc=(int)t->user;
113     gpio_set_level(PIN_NUM_DC, dc);
114 }
115
116 //Initialize the display
117 void ili_init(spi_device_handle_t spi) 
118 {
119     int cmd=0;
120     //Initialize non-SPI GPIOs
121     gpio_set_direction(PIN_NUM_DC, GPIO_MODE_OUTPUT);
122     gpio_set_direction(PIN_NUM_RST, GPIO_MODE_OUTPUT);
123     gpio_set_direction(PIN_NUM_BCKL, GPIO_MODE_OUTPUT);
124
125     //Reset the display
126     gpio_set_level(PIN_NUM_RST, 0);
127     vTaskDelay(100 / portTICK_RATE_MS);
128     gpio_set_level(PIN_NUM_RST, 1);
129     vTaskDelay(100 / portTICK_RATE_MS);
130
131     //Send all the commands
132     while (ili_init_cmds[cmd].databytes!=0xff) {
133         ili_cmd(spi, ili_init_cmds[cmd].cmd);
134         ili_data(spi, ili_init_cmds[cmd].data, ili_init_cmds[cmd].databytes&0x1F);
135         if (ili_init_cmds[cmd].databytes&0x80) {
136             vTaskDelay(100 / portTICK_RATE_MS);
137         }
138         cmd++;
139     }
140
141     ///Enable backlight
142     gpio_set_level(PIN_NUM_BCKL, 0);
143 }
144
145
146 //To send a line we have to send a command, 2 data bytes, another command, 2 more data bytes and another command
147 //before sending the line data itself; a total of 6 transactions. (We can't put all of this in just one transaction
148 //because the D/C line needs to be toggled in the middle.)
149 //This routine queues these commands up so they get sent as quickly as possible.
150 void send_line(spi_device_handle_t spi, int ypos, uint16_t *line) 
151 {
152     esp_err_t ret;
153     int x;
154     //Transaction descriptors. Declared static so they're not allocated on the stack; we need this memory even when this
155     //function is finished because the SPI driver needs access to it even while we're already calculating the next line.
156     static spi_transaction_t trans[6];
157
158     //In theory, it's better to initialize trans and data only once and hang on to the initialized
159     //variables. We allocate them on the stack, so we need to re-init them each call.
160     for (x=0; x<6; x++) {
161         memset(&trans[x], 0, sizeof(spi_transaction_t));
162         if ((x&1)==0) {
163             //Even transfers are commands
164             trans[x].length=8;
165             trans[x].user=(void*)0;
166         } else {
167             //Odd transfers are data
168             trans[x].length=8*4;
169             trans[x].user=(void*)1;
170         }
171         trans[x].flags=SPI_TRANS_USE_TXDATA;
172     }
173     trans[0].tx_data[0]=0x2A;           //Column Address Set
174     trans[1].tx_data[0]=0;              //Start Col High
175     trans[1].tx_data[1]=0;              //Start Col Low
176     trans[1].tx_data[2]=(320)>>8;       //End Col High
177     trans[1].tx_data[3]=(320)&0xff;     //End Col Low
178     trans[2].tx_data[0]=0x2B;           //Page address set
179     trans[3].tx_data[0]=ypos>>8;        //Start page high
180     trans[3].tx_data[1]=ypos&0xff;      //start page low
181     trans[3].tx_data[2]=(ypos+1)>>8;    //end page high
182     trans[3].tx_data[3]=(ypos+1)&0xff;  //end page low
183     trans[4].tx_data[0]=0x2C;           //memory write
184     trans[5].tx_buffer=line;            //finally send the line data
185     trans[5].length=320*2*8;            //Data length, in bits
186     trans[5].flags=0; //undo SPI_TRANS_USE_TXDATA flag
187
188     //Queue all transactions.
189     for (x=0; x<6; x++) {
190         ret=spi_device_queue_trans(spi, &trans[x], portMAX_DELAY);
191         assert(ret==ESP_OK);
192     }
193
194     //When we are here, the SPI driver is busy (in the background) getting the transactions sent. That happens
195     //mostly using DMA, so the CPU doesn't have much to do here. We're not going to wait for the transaction to
196     //finish because we may as well spend the time calculating the next line. When that is done, we can call
197     //send_line_finish, which will wait for the transfers to be done and check their status.
198 }
199
200
201 void send_line_finish(spi_device_handle_t spi) 
202 {
203     spi_transaction_t *rtrans;
204     esp_err_t ret;
205     //Wait for all 6 transactions to be done and get back the results.
206     for (int x=0; x<6; x++) {
207         ret=spi_device_get_trans_result(spi, &rtrans, portMAX_DELAY);
208         assert(ret==ESP_OK);
209         //We could inspect rtrans now if we received any info back. The LCD is treated as write-only, though.
210     }
211 }
212
213
214 //Simple routine to generate some patterns and send them to the LCD. Don't expect anything too
215 //impressive. Because the SPI driver handles transactions in the background, we can calculate the next line 
216 //while the previous one is being sent.
217 void display_pretty_colors(spi_device_handle_t spi) 
218 {
219     uint16_t line[2][320];
220     int x, y, frame=0;
221     //Indexes of the line currently being sent to the LCD and the line we're calculating.
222     int sending_line=-1;
223     int calc_line=0;
224     
225     while(1) {
226         frame++;
227         for (y=0; y<240; y++) {
228             //Calculate a line.
229             for (x=0; x<320; x++) {
230                 line[calc_line][x]=((x<<3)^(y<<3)^(frame+x*y));
231             }
232             //Finish up the sending process of the previous line, if any
233             if (sending_line!=-1) send_line_finish(spi);
234             //Swap sending_line and calc_line
235             sending_line=calc_line;
236             calc_line=(calc_line==1)?0:1;
237             //Send the line we currently calculated.
238             send_line(spi, y, line[sending_line]);
239             //The line is queued up for sending now; the actual sending happens in the
240             //background. We can go on to calculate the next line as long as we do not
241             //touch line[sending_line]; the SPI sending process is still reading from that.
242         }
243     }
244 }
245
246
247 void app_main()
248 {
249     esp_err_t ret;
250     spi_device_handle_t spi;
251     spi_bus_config_t buscfg={
252         .spiq_io_num=PIN_NUM_MISO,
253         .spid_io_num=PIN_NUM_MOSI,
254         .spiclk_io_num=PIN_NUM_CLK,
255         .spiwp_io_num=-1,
256         .spihd_io_num=-1
257     };
258     spi_device_interface_config_t devcfg={
259         .clock_speed_hz=10000000,               //Clock out at 10 MHz
260         .mode=0,                                //SPI mode 0
261         .spics_io_num=PIN_NUM_CS,               //CS pin
262         .queue_size=7,                          //We want to be able to queue 7 transactions at a time
263         .pre_cb=ili_spi_pre_transfer_callback,  //Specify pre-transfer callback to handle D/C line
264     };
265     //Initialize the SPI bus
266     ret=spi_bus_initialize(HSPI_HOST, &buscfg, 1);
267     assert(ret==ESP_OK);
268     //Attach the LCD to the SPI bus
269     ret=spi_bus_add_device(HSPI_HOST, &devcfg, &spi);
270     assert(ret==ESP_OK);
271     //Initialize the LCD
272     ili_init(spi);
273     //Go do nice stuff.
274     display_pretty_colors(spi);
275 }