Merge branch 'feature/ssd-driver'
This commit is contained in:
1
scripts/build.sh
Normal file → Executable file
1
scripts/build.sh
Normal file → Executable file
@@ -8,6 +8,7 @@ export IDF_PATH=${PWD}/lib/esp-idf
|
|||||||
export SDKCONFIG=${PWD}/config/sdkconfig
|
export SDKCONFIG=${PWD}/config/sdkconfig
|
||||||
export SDKCONFIG_DEFAULTS=${PWD}/config/sdkconfig.defaults
|
export SDKCONFIG_DEFAULTS=${PWD}/config/sdkconfig.defaults
|
||||||
|
|
||||||
|
export IDF_PATH_FORCE=1
|
||||||
. ${IDF_PATH}/export.sh
|
. ${IDF_PATH}/export.sh
|
||||||
|
|
||||||
idf.py set-target esp32s3
|
idf.py set-target esp32s3
|
||||||
|
|||||||
1
scripts/flash.sh
Normal file → Executable file
1
scripts/flash.sh
Normal file → Executable file
@@ -8,6 +8,7 @@ export IDF_PATH=${PWD}/lib/esp-idf
|
|||||||
export SDKCONFIG=${PWD}/config/sdkconfig
|
export SDKCONFIG=${PWD}/config/sdkconfig
|
||||||
export SDKCONFIG_DEFAULTS=${PWD}/config/sdkconfig.defaults
|
export SDKCONFIG_DEFAULTS=${PWD}/config/sdkconfig.defaults
|
||||||
|
|
||||||
|
export IDF_PATH_FORCE=1
|
||||||
. ${IDF_PATH}/export.sh
|
. ${IDF_PATH}/export.sh
|
||||||
|
|
||||||
idf.py fullclean
|
idf.py fullclean
|
||||||
|
|||||||
1
scripts/monitor.sh
Normal file → Executable file
1
scripts/monitor.sh
Normal file → Executable file
@@ -5,6 +5,7 @@ set -e
|
|||||||
export IDF_TOOLS_PATH=${PWD}/lib/idf-tools
|
export IDF_TOOLS_PATH=${PWD}/lib/idf-tools
|
||||||
export IDF_PATH=${PWD}/lib/esp-idf
|
export IDF_PATH=${PWD}/lib/esp-idf
|
||||||
|
|
||||||
|
export IDF_PATH_FORCE=1
|
||||||
. ${IDF_PATH}/export.sh
|
. ${IDF_PATH}/export.sh
|
||||||
|
|
||||||
idf.py -b 115200 monitor
|
idf.py -b 115200 monitor
|
||||||
|
|||||||
@@ -9,5 +9,6 @@ idf_component_register(
|
|||||||
SRCS ${SRC_FILES}
|
SRCS ${SRC_FILES}
|
||||||
PRIV_REQUIRES spi_flash
|
PRIV_REQUIRES spi_flash
|
||||||
REQUIRES esp_driver_gpio
|
REQUIRES esp_driver_gpio
|
||||||
|
REQUIRES esp_driver_spi
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "SsdInterface.hpp"
|
#include "SsdInterface.hpp"
|
||||||
#include "pins.hpp"
|
#include "pins.hpp"
|
||||||
|
#include "drivers/wsled.h"
|
||||||
|
|
||||||
DemoTask::DemoTask() {
|
DemoTask::DemoTask() {
|
||||||
|
|
||||||
@@ -17,8 +18,16 @@ void DemoTask::run() {
|
|||||||
|
|
||||||
ESP_LOGI(__FILE__, "Demo Task: run()");
|
ESP_LOGI(__FILE__, "Demo Task: run()");
|
||||||
|
|
||||||
ssd_595_t dev = { gpio_ssd_data, gpio_ssd_clk, gpio_ssd_latch, true };
|
// ssd device
|
||||||
SsdInterface ssd(&dev, ssdDigits);
|
ssd_595_t ssdDev = { gpio_ssd_data, gpio_ssd_clk, gpio_ssd_latch, true };
|
||||||
|
SsdInterface ssd(&ssdDev, ssdDigits);
|
||||||
|
|
||||||
|
// wsled device
|
||||||
|
size_t ledCount = 4;
|
||||||
|
wsled_t wsledDev = { gpio_ws2812b, WS2812B, ledCount};
|
||||||
|
// TODO: wsled interface
|
||||||
|
CRGB ledBuffer[4];
|
||||||
|
wsledInit(&wsledDev, (CRGB**)&ledBuffer);
|
||||||
|
|
||||||
uint32_t delay = 500; // ms
|
uint32_t delay = 500; // ms
|
||||||
uint8_t digit = 0;
|
uint8_t digit = 0;
|
||||||
@@ -28,6 +37,16 @@ void DemoTask::run() {
|
|||||||
digit++;
|
digit++;
|
||||||
if(digit >= 16) digit = 0;
|
if(digit >= 16) digit = 0;
|
||||||
|
|
||||||
|
//ledBuffer[0] = CRGB{100, 0, 80};
|
||||||
|
wsledFill(CRGB{100, 20, 20});
|
||||||
|
wsledUpdate();
|
||||||
|
|
||||||
|
vTaskDelay(delay / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
//ledBuffer[0] = CRGB{0, 0, 10};
|
||||||
|
wsledFill(CRGB{20, 20, 100});
|
||||||
|
wsledUpdate();
|
||||||
|
|
||||||
vTaskDelay(delay / portTICK_PERIOD_MS);
|
vTaskDelay(delay / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
21
src/WsledInterface.cpp
Normal file
21
src/WsledInterface.cpp
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
|
||||||
|
#include "WsledInterface.hpp"
|
||||||
|
|
||||||
|
WsledInterface::WsledInterface(const wsled_t* device) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
STATUS WsledInterface::writePixel(CRGB pixel, size_t index) {
|
||||||
|
|
||||||
|
return OKAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATUS WsledInterface::get(CRGB* pixel, size_t index) {
|
||||||
|
|
||||||
|
return OKAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATUS WsledInterface::flush() {
|
||||||
|
|
||||||
|
return OKAY;
|
||||||
|
}
|
||||||
38
src/WsledInterface.hpp
Normal file
38
src/WsledInterface.hpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "stdint.h"
|
||||||
|
|
||||||
|
#include "drivers/wsled.h"
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
class WsledInterface {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WsledInterface(const wsled_t* device);
|
||||||
|
~WsledInterface() = default;
|
||||||
|
|
||||||
|
// Sets a pixel in the leds buffer to a particular color
|
||||||
|
// index: the order in the strip of the pixel
|
||||||
|
// Returns: execution status
|
||||||
|
STATUS writePixel(CRGB pixel, size_t index);
|
||||||
|
|
||||||
|
// Copies the color currently in a pixel to the pointer
|
||||||
|
// index: the order in the strip of the pixel
|
||||||
|
// Returns: execution status
|
||||||
|
STATUS get(CRGB* pixel, size_t index);
|
||||||
|
|
||||||
|
// Writes all the data in the leds buffer to hardware
|
||||||
|
// Returns: execution status
|
||||||
|
STATUS flush();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const wsled_t* device_;
|
||||||
|
|
||||||
|
static constexpr size_t numLeds_ = 4;
|
||||||
|
|
||||||
|
CRGB leds_[numLeds_];
|
||||||
|
|
||||||
|
};
|
||||||
139
src/drivers/wsled.c
Normal file
139
src/drivers/wsled.c
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
|
||||||
|
#include "wsled.h"
|
||||||
|
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t* dmaBuffer;
|
||||||
|
CRGB* wsledPixels;
|
||||||
|
static uint32_t ledCount;
|
||||||
|
static uint32_t resetDelay;
|
||||||
|
static size_t dmaBufferSize;
|
||||||
|
WsledType type;
|
||||||
|
|
||||||
|
static spi_settings_t spiSettings = {
|
||||||
|
.host = SPI2_HOST,
|
||||||
|
.dma_chan = SPI_DMA_CH_AUTO,
|
||||||
|
.buscfg =
|
||||||
|
{
|
||||||
|
.miso_io_num = -1,
|
||||||
|
.sclk_io_num = -1,
|
||||||
|
.quadwp_io_num = -1,
|
||||||
|
.quadhd_io_num = -1,
|
||||||
|
},
|
||||||
|
.devcfg =
|
||||||
|
{
|
||||||
|
.clock_speed_hz = 3.2 * 1000 * 1000, // Clock out at 3.2 MHz
|
||||||
|
.mode = 0, // SPI mode 0
|
||||||
|
.spics_io_num = -1, // CS pin
|
||||||
|
.queue_size = 1,
|
||||||
|
.command_bits = 0,
|
||||||
|
.address_bits = 0,
|
||||||
|
//.flags = SPI_DEVICE_TXBIT_LSBFIRST,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const uint16_t timingBits[16] = {
|
||||||
|
0x1111, 0x7111, 0x1711, 0x7711, 0x1171, 0x7171, 0x1771, 0x7771,
|
||||||
|
0x1117, 0x7117, 0x1717, 0x7717, 0x1177, 0x7177, 0x1777, 0x7777};
|
||||||
|
|
||||||
|
esp_err_t wsledInit(wsled_t* dev, CRGB** buffer) {
|
||||||
|
|
||||||
|
ESP_LOGI(__FILE__, "Initializing wsled device...");
|
||||||
|
|
||||||
|
type = dev->type;
|
||||||
|
ledCount = dev->numLeds;
|
||||||
|
resetDelay = (dev->type == WS2812B) ? WSLED_12_RESET_TIME : WSLED_15_RESET_TIME;
|
||||||
|
|
||||||
|
ESP_LOGI(__FILE__, "mallocing the wsledPixel buffer with size %u bytes", sizeof(CRGB) * ledCount);
|
||||||
|
|
||||||
|
// 12 bytes for each led + bytes for initial zero and reset state
|
||||||
|
dmaBufferSize = ledCount * 12 + (resetDelay + 1) * 2;
|
||||||
|
wsledPixels = malloc(sizeof(CRGB) * ledCount);
|
||||||
|
if (wsledPixels == NULL) {
|
||||||
|
ESP_LOGI(__FILE__, "Allocating memory failed");
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
*buffer = wsledPixels;
|
||||||
|
spiSettings.buscfg.mosi_io_num = dev->pin;
|
||||||
|
spiSettings.buscfg.max_transfer_sz = dmaBufferSize;
|
||||||
|
|
||||||
|
ESP_LOGI(__FILE__, "Initializing spi interface...");
|
||||||
|
if (ESP_OK != spi_bus_initialize(spiSettings.host, &spiSettings.buscfg, spiSettings.dma_chan)) {
|
||||||
|
free(wsledPixels);
|
||||||
|
ESP_LOGI(__FILE__, "SPI initialization failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(__FILE__, "Adding spi bus device...");
|
||||||
|
if (ESP_OK != spi_bus_add_device(spiSettings.host, &spiSettings.devcfg, &spiSettings.spi)) {
|
||||||
|
free(wsledPixels);
|
||||||
|
ESP_LOGI(__FILE__, "Failed to add spi bus device");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(__FILE__, "heap_caps_malloc() with dmaBufferSize=%u...", dmaBufferSize);
|
||||||
|
dmaBuffer = heap_caps_malloc(dmaBufferSize, MALLOC_CAP_DMA);
|
||||||
|
if (NULL == dmaBuffer) {
|
||||||
|
free(wsledPixels);
|
||||||
|
ESP_LOGI(__FILE__, "Failed to heap_caps_malloc");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t wsledFill(CRGB color) {
|
||||||
|
for (int i = 0; i < ledCount; i++) {
|
||||||
|
wsledPixels[i] = color;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t wsledUpdate() {
|
||||||
|
|
||||||
|
uint32_t n = 0;
|
||||||
|
|
||||||
|
memset(dmaBuffer, 0, dmaBufferSize);
|
||||||
|
dmaBuffer[n++] = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < ledCount; i++) {
|
||||||
|
|
||||||
|
CRGB currentPixel = wsledPixels[i];
|
||||||
|
|
||||||
|
uint8_t b0 = (type == WS2812B) ? currentPixel.g : currentPixel.r;
|
||||||
|
uint8_t b1 = (type == WS2812B) ? currentPixel.r : currentPixel.g;
|
||||||
|
uint8_t b2 = currentPixel.b;
|
||||||
|
|
||||||
|
// Green
|
||||||
|
dmaBuffer[n++] = timingBits[(b0 >> 4) & 0x0F];
|
||||||
|
dmaBuffer[n++] = timingBits[b0 & 0x0F];
|
||||||
|
|
||||||
|
// Red
|
||||||
|
dmaBuffer[n++] = timingBits[(b1 >> 4) & 0x0F];
|
||||||
|
dmaBuffer[n++] = timingBits[b1 & 0x0F];
|
||||||
|
|
||||||
|
// Blue
|
||||||
|
dmaBuffer[n++] = timingBits[(b2 >> 4) & 0x0F];
|
||||||
|
dmaBuffer[n++] = timingBits[b2 & 0x0F];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset pulse
|
||||||
|
for (int i = 0; i < resetDelay; i++) {
|
||||||
|
dmaBuffer[n++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t error = spi_device_transmit(spiSettings.spi, &(spi_transaction_t) {
|
||||||
|
.length = dmaBufferSize * 8,
|
||||||
|
.tx_buffer = dmaBuffer,
|
||||||
|
});
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
50
src/drivers/wsled.h
Normal file
50
src/drivers/wsled.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "driver/spi_master.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define WSLED_12_RESET_TIME 30
|
||||||
|
#define WSLED_15_RESET_TIME 30
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t r;
|
||||||
|
uint8_t g;
|
||||||
|
uint8_t b;
|
||||||
|
} CRGB;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WS2812B = 0,
|
||||||
|
WS2815
|
||||||
|
} WsledType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
spi_host_device_t host;
|
||||||
|
spi_device_handle_t spi;
|
||||||
|
int dma_chan;
|
||||||
|
spi_device_interface_config_t devcfg;
|
||||||
|
spi_bus_config_t buscfg;
|
||||||
|
} spi_settings_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gpio_num_t pin;
|
||||||
|
WsledType type;
|
||||||
|
uint32_t numLeds;
|
||||||
|
} wsled_t;
|
||||||
|
|
||||||
|
esp_err_t wsledInit(wsled_t* dev, CRGB** buffer);
|
||||||
|
|
||||||
|
// test function
|
||||||
|
esp_err_t wsledFill(CRGB color);
|
||||||
|
|
||||||
|
esp_err_t wsledUpdate();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user