1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
#include <stdio.h>
#include <string.h>
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "atascii.h"
#include "esp_log.h"
#define NUM_COL 160
#define NUM_ROW 8
#define CHAR_HEIGHT 8
#define CHAR_WIDTH 8
#define RED 1
#define GREEN 2
#define ORANGE 3
#define PIN_NUM_MISO 12
#define PIN_NUM_MOSI 13
#define PIN_NUM_CLK 14
#define PIN_NUM_CS 15
#define PIN_NUM_R_LATCH 16
#define PIN_NUM_R_CLK 17
#define PIN_NUM_R_ADDR_0 5
#define PIN_NUM_R_ADDR_1 18
#define PIN_NUM_R_ADDR_2 19
#define TAG "led_display"
static uint16_t pattern[NUM_ROW][NUM_COL / 8]; // each column is two bits, so 8 can fit in 16-bit integer
void draw_char_at_position(char character, uint16_t col_start, uint16_t row_start, uint16_t color) {
uint8_t cur_char_row;
for(int row = row_start; (row - row_start) < CHAR_HEIGHT && row < NUM_ROW; row++) {
cur_char_row = atascii_font[(uint8_t) character][row - row_start];
for(int col = col_start; (col - col_start) < CHAR_WIDTH && col < NUM_COL; col++) {
pattern[row][col / 8] = (pattern[row][col / 8] & ~(0b0000000000000011 << (2 * (col - col_start)))); // clear this column (note the bitwise inversion)
if((1 << (col - col_start)) & cur_char_row) {
pattern[row][col / 8] = ((pattern[row][col / 8]) | color << (2 * (col - col_start))); // write color to column
}
}
}
}
void app_main(void)
{
esp_err_t ret;
spi_device_handle_t spi;
spi_bus_config_t buscfg={
.miso_io_num=PIN_NUM_MISO,
.mosi_io_num=PIN_NUM_MOSI,
.sclk_io_num=PIN_NUM_CLK,
.quadwp_io_num=-1,
.quadhd_io_num=-1,
.max_transfer_sz=3*600*2*8,
.flags=SPICOMMON_BUSFLAG_DUAL
};
spi_device_interface_config_t devcfg={
.clock_speed_hz=1*1000*1000, //Clock out at 1 MHz
.mode=0, //SPI mode 0
.spics_io_num=PIN_NUM_CS, //CS pin
.queue_size=7, //We want to be able to queue 7 transactions at a time
.flags=SPI_DEVICE_HALFDUPLEX, //Needed to use both data lines for output
};
//Initialize the SPI bus and attach our device handle
ret=spi_bus_initialize(HSPI_HOST, &buscfg, SPI_DMA_CH_AUTO);
ESP_ERROR_CHECK(ret);
ret=spi_bus_add_device(HSPI_HOST, &devcfg, &spi);
ESP_ERROR_CHECK(ret);
ESP_LOGI(TAG, "Initialized SPI host.");
gpio_set_direction(PIN_NUM_R_LATCH, GPIO_MODE_OUTPUT);
gpio_set_direction(PIN_NUM_R_CLK, GPIO_MODE_OUTPUT);
gpio_set_direction(PIN_NUM_R_ADDR_0, GPIO_MODE_OUTPUT);
gpio_set_direction(PIN_NUM_R_ADDR_1, GPIO_MODE_OUTPUT);
gpio_set_direction(PIN_NUM_R_ADDR_2, GPIO_MODE_OUTPUT);
ESP_LOGI(TAG, "Setup GPIO.");
char* text = "Hello World!! 1234567890";
for(int i = 0; i < strlen(text); i++) {
draw_char_at_position(text[i], i * CHAR_WIDTH, 0, RED);
}
ESP_LOG_BUFFER_HEX(TAG, pattern[0], 16);
ESP_LOG_BUFFER_HEX(TAG, pattern[1], 16);
ESP_LOG_BUFFER_HEX(TAG, pattern[2], 16);
ESP_LOG_BUFFER_HEX(TAG, pattern[3], 16);
ESP_LOG_BUFFER_HEX(TAG, pattern[4], 16);
ESP_LOG_BUFFER_HEX(TAG, pattern[5], 16);
ESP_LOG_BUFFER_HEX(TAG, pattern[6], 16);
ESP_LOG_BUFFER_HEX(TAG, pattern[7], 16);
ESP_LOGI(TAG, "Done drawing pattern.");
uint8_t current_row = 0;
while(true) {
spi_transaction_t t;
memset(&t, 0, sizeof(t));
t.length = NUM_COL;
t.tx_buffer = pattern[current_row];
t.flags = SPI_TRANS_MODE_DIO; // output on two data lines. Even bits go to GREEN, odd to RED
ret = spi_device_polling_transmit(spi, &t);
ESP_ERROR_CHECK(ret);
gpio_set_level(PIN_NUM_R_LATCH, 0);
gpio_set_level(PIN_NUM_R_CLK, 1);
gpio_set_level(PIN_NUM_R_ADDR_0, 1 & current_row);
gpio_set_level(PIN_NUM_R_ADDR_1, 1 & (current_row >> 1));
gpio_set_level(PIN_NUM_R_ADDR_2, 1 & (current_row >> 2));
gpio_set_level(PIN_NUM_R_LATCH, 1);
gpio_set_level(PIN_NUM_R_CLK, 0);
if(++current_row == NUM_ROW) {
current_row = 0;
}
vTaskDelay((10) / portTICK_PERIOD_MS);
}
}
|