aboutsummaryrefslogtreecommitdiff
path: root/main/InovaLedDisplay.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'main/InovaLedDisplay.cpp')
-rw-r--r--main/InovaLedDisplay.cpp59
1 files changed, 34 insertions, 25 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) {