From 88f84211a549325a7733b46a232de65050df8082 Mon Sep 17 00:00:00 2001 From: gamerdonkey Date: Fri, 20 Sep 2024 22:41:23 -0500 Subject: Changing to use octal SPI transmit so that we can display all the segments. Also refactored to clean up some code. --- main/InovaLedDisplay.cpp | 59 ++++++++++++++++++++++++++++-------------------- main/InovaLedDisplay.h | 8 ++++--- main/main.cpp | 42 ++++++++-------------------------- 3 files changed, 49 insertions(+), 60 deletions(-) diff --git a/main/InovaLedDisplay.cpp b/main/InovaLedDisplay.cpp index 0d8d7e8..3da8f22 100644 --- a/main/InovaLedDisplay.cpp +++ b/main/InovaLedDisplay.cpp @@ -6,7 +6,7 @@ #include "freertos/task.h" -InovaLedDisplay::InovaLedDisplay(uint8_t r0, uint8_t g0, uint8_t clk, uint8_t cs, uint8_t latchParam, uint8_t oeParam, uint8_t addr0Param, uint8_t addr1Param, uint8_t addr2Param) : Adafruit_GFX(NUM_COL, NUM_ROW){ +InovaLedDisplay::InovaLedDisplay(uint8_t r0, uint8_t g0, uint8_t r1, uint8_t g1, uint8_t r2, uint8_t g2, uint8_t clk, uint8_t latchParam, uint8_t oeParam, uint8_t addr0Param, uint8_t addr1Param, uint8_t addr2Param) : Adafruit_GFX(NUM_COL, NUM_ROW){ latch = (gpio_num_t) latchParam; oe = (gpio_num_t) oeParam; addr0 = (gpio_num_t) addr0Param; @@ -19,18 +19,22 @@ InovaLedDisplay::InovaLedDisplay(uint8_t r0, uint8_t g0, uint8_t clk, uint8_t cs memset(&buscfg, 0, sizeof(spi_bus_config_t)); buscfg.miso_io_num=g0; buscfg.mosi_io_num=r0; + buscfg.quadwp_io_num=r1; + buscfg.quadhd_io_num=g1; + buscfg.data4_io_num=r2; + buscfg.data5_io_num=g2; + buscfg.data6_io_num=-1; + buscfg.data7_io_num=-1; buscfg.sclk_io_num=clk; - buscfg.quadwp_io_num=-1; - buscfg.quadhd_io_num=-1; buscfg.max_transfer_sz=3*600*2*8; - buscfg.flags=SPICOMMON_BUSFLAG_DUAL; + buscfg.flags=SPICOMMON_BUSFLAG_OCTAL; spi_device_interface_config_t devcfg; memset(&devcfg, 0, sizeof(spi_device_interface_config_t)); devcfg.clock_speed_hz=1*1000*1000; //Clock out at 1 MHz devcfg.mode=0; //SPI mode 0 - devcfg.spics_io_num=cs; //CS pin - devcfg.queue_size=1; //We want to be able to queue 7 transactions at a time + devcfg.spics_io_num=-1; //CS pin + devcfg.queue_size=1; //Only one transaction at a time devcfg.flags=SPI_DEVICE_HALFDUPLEX; //Needed to use both data lines for output //Initialize the SPI bus and attach our device handle @@ -53,17 +57,27 @@ void InovaLedDisplay::drawPixel(int16_t x, int16_t y, uint16_t color) { // Adafruit GFX color is 16-bit 5-6-5 rgb // We store only 2-bit rg, so we assume any amount of red or green wants that color - uint8_t r, g; + uint8_t r, g, c; r = color >> 11; // RRRRRggggggbbbbb g = (color >> 5) & 0x3F; // rrrrrGGGGGGbbbbb - color = 0; - if(g > 0) color += 1; - if(r > 0) color += 2; + c = 0; + if(g > 0) c += 1; + if(r > 0) c += 2; + c = c << 6; + // We store the 3 segments of the display 8-bit ints ready to transfer via 8-bit parallel SPI + // So 2 bits are wasted per byte, but hopefully it's worth it for transfer speed + + // b0 b1 b2 b3 b4 b5 b6 b7 b0 b1 b2 b3 b4 b5 b6 b7 + // [0][0] r(0,0) g(0,0) r(0,8) g(0,8) r(0,16) g(0,16) --- --- [0][1] r(1,0) g(1,0) r(1,8) g(1,8) r(1,16) g(1,16) --- --- [...] + // [1][0] r(0,1) g(0,1) r(0,9) g(0,9) r(0,17) g(0,17) --- --- [1][1] r(1,1) g(1,1) r(1,9) g(1,9) r(1,17) g(1,17) --- --- [...] + // [...] + + uint8_t bitwiseOffset = (y / 8) * 2; uint8_t i = backBufferIndex; - displayBuffer[i][y][x / 8] = displayBuffer[i][y][x / 8] & ~(0b0000000000000011 << (14 - (2 * (x % 8)))); // clear this column (note the bitwise inversion) - displayBuffer[i][y][x / 8] = displayBuffer[i][y][x / 8] | (color << (14 - (2 * (x % 8)))); // write color to column + displayBuffer[i][y % 8][x] = displayBuffer[i][y % 8][x] & ~(0b11000000 >> bitwiseOffset); // clear this pixel (note the bitwise inversion) + displayBuffer[i][y % 8][x] = displayBuffer[i][y % 8][x] | (c >> bitwiseOffset); // write color to pixel } @@ -81,24 +95,19 @@ void InovaLedDisplay::runDisplay(void) { const TickType_t xFrequency = 1 / portTICK_PERIOD_MS; xLastWakeTime = xTaskGetTickCount(); + spi_transaction_t t; uint8_t current_row = 0; - uint8_t i = 0; - uint16_t data; esp_err_t ret; run = true; while(run) { vTaskDelayUntil(&xLastWakeTime, xFrequency); - for(i = 0; i < (NUM_COL / 8); i++) { - spi_transaction_t t; - memset(&t, 0, sizeof(t)); - t.length = 16; - data = SPI_SWAP_DATA_TX(displayBuffer[1 - backBufferIndex][current_row][i], 16); - t.tx_buffer = &data; - 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); - } + memset(&t, 0, sizeof(t)); + t.length = _width; + t.tx_buffer = &displayBuffer[1 - backBufferIndex][current_row]; + t.flags = SPI_TRANS_MODE_OCT; // output on eight data lines (six utilized). Even bits go to GREEN, odd to RED + ret = spi_device_polling_transmit(spi, &t); + ESP_ERROR_CHECK(ret); gpio_set_level(latch, 0); gpio_set_level(oe, 1); @@ -110,7 +119,7 @@ void InovaLedDisplay::runDisplay(void) { gpio_set_level(latch, 1); gpio_set_level(oe, 0); - if(++current_row == NUM_ROW) { + if(++current_row == ROWS_PER_SEGMENT) { current_row = 0; if(shouldSwapBuffer) { diff --git a/main/InovaLedDisplay.h b/main/InovaLedDisplay.h index a1d9ad9..8b522ab 100644 --- a/main/InovaLedDisplay.h +++ b/main/InovaLedDisplay.h @@ -7,12 +7,14 @@ #define NUM_COL 160 -#define NUM_ROW 8 +#define NUM_ROW 24 +#define NUM_SEGMENTS 3 +#define ROWS_PER_SEGMENT NUM_ROW / NUM_SEGMENTS class InovaLedDisplay : public virtual Adafruit_GFX { public: - InovaLedDisplay(uint8_t r0, uint8_t g0, uint8_t clk, uint8_t cs, uint8_t latchParam, uint8_t oeParam, uint8_t addr0Param, uint8_t addr1Param, uint8_t addr2Param); + InovaLedDisplay(uint8_t r0, uint8_t g0, uint8_t r1, uint8_t g1, uint8_t r2, uint8_t g2, uint8_t clk, uint8_t latchParam, uint8_t oeParam, uint8_t addr0Param, uint8_t addr1Param, uint8_t addr2Param); void drawPixel(int16_t x, int16_t y, uint16_t c); @@ -23,7 +25,7 @@ class InovaLedDisplay : public virtual Adafruit_GFX { void stopDisplay(void); private: - uint16_t displayBuffer[2][NUM_ROW][NUM_COL / 8]; // each column is two bits, so 8 can fit in 16-bit integer + uint8_t displayBuffer[2][ROWS_PER_SEGMENT][NUM_COL]; // 3 segments of the matrix packed into bytes spi_device_handle_t spi; bool run = true; bool shouldSwapBuffer = false; diff --git a/main/main.cpp b/main/main.cpp index 7555410..22982fd 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -8,17 +8,19 @@ #include "esp_log.h" -#define CHAR_HEIGHT 8 -#define CHAR_WIDTH 8 #define BLACK 0x0000 #define RED 0xF800 #define GREEN 0x07E0 #define ORANGE 0xFFE0 -#define PIN_NUM_MISO 12 -#define PIN_NUM_MOSI 13 + +#define PIN_NUM_R0 12 // MISO +#define PIN_NUM_G0 13 // MOSI +#define PIN_NUM_R1 2 // QUADWP +#define PIN_NUM_G1 4 // QUADHD +#define PIN_NUM_R2 22 // data4 +#define PIN_NUM_G2 21 // data5 #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 @@ -29,33 +31,14 @@ #define STACK_SIZE 2000 -/* extern "C" void drawCharAtPosition(char character, int x_start, int y_start, uint16_t color) { */ -/* uint8_t cur_char_row; */ -/* for(int y = y_start; (y - y_start) < CHAR_HEIGHT && y < NUM_ROW; y++) { */ -/* cur_char_row = atascii_font[(uint8_t) character][y - y_start]; */ -/* for(int x = x_start; (x - x_start) < CHAR_WIDTH && x < NUM_COL; x++) { */ -/* if(x >= 0) { */ -/* if((0b10000000 >> (x - x_start)) & cur_char_row) { */ -/* setPixel(x, y, color); */ -/* } */ -/* else { */ -/* setPixel(x, y, 0); */ -/* } */ -/* } */ -/* } */ -/* } */ -/* } */ - - extern "C" void runDisplayTask(void* taskParams) { InovaLedDisplay* display = (InovaLedDisplay*) taskParams; display->runDisplay(); } -extern "C" void app_main(void) -{ - InovaLedDisplay display = InovaLedDisplay(PIN_NUM_MISO, PIN_NUM_MOSI, PIN_NUM_CLK, PIN_NUM_CS, PIN_NUM_R_LATCH, PIN_NUM_R_CLK, PIN_NUM_R_ADDR_0, PIN_NUM_R_ADDR_1, PIN_NUM_R_ADDR_2); +extern "C" void app_main(void) { + InovaLedDisplay display = InovaLedDisplay(PIN_NUM_R0, PIN_NUM_G0, PIN_NUM_R1, PIN_NUM_G1, PIN_NUM_R2, PIN_NUM_G2, PIN_NUM_CLK, PIN_NUM_R_LATCH, PIN_NUM_R_CLK, PIN_NUM_R_ADDR_0, PIN_NUM_R_ADDR_1, PIN_NUM_R_ADDR_2); display.fillScreen(0); @@ -65,13 +48,8 @@ extern "C" void app_main(void) display.print("Adafruit GFX 0123456789"); TaskHandle_t taskHandle; - xTaskCreate(runDisplayTask, "updateDisplay", STACK_SIZE, &display, tskIDLE_PRIORITY, &taskHandle); - - //runDisplayTask(&display); + xTaskCreate(runDisplayTask, "updateDisplay", STACK_SIZE, &display, tskIDLE_PRIORITY + 1, &taskHandle); - //while(true) { - // vTaskDelay(100 / portTICK_PERIOD_MS); - //} int j = display.width(); int color = 1; String hello = "Hello World!! 0123456789"; -- cgit v1.2.3