aboutsummaryrefslogtreecommitdiff
path: root/main/main.c
blob: 5ffcb6d58f7099289585710e315048da3804fd5c (plain)
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);
    }
}