diff --git a/README.md b/README.md index 24b3a11..ab00571 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,8 @@ Scripts are in scripts directory, named appropriately. ## Development plan: - [x] Create repository. -- [ ] Build setup, get working hello-world program. -- [ ] Develop 7-segment display driver for the soburg-v2 board, which uses 32-bit shift registers. +- [x] Build setup, get working hello-world program. +- [x] Develop 7-segment display driver for the soburg-v2 board, which uses 32-bit shift registers. Ensures functional hardware interaction and interface design. - [ ] Develop WS2812b driver, would be nice to have some kind of testing for this. - [ ] Develop WS2812b interface. I like the FastLed library for Arduino so might have a lot of similar functionality. @@ -31,7 +31,7 @@ Scripts are in scripts directory, named appropriately. This is basic but hopefully can be good platform for future WS2812b projects. ## Scripts: -After cloning: $ ./scripts/repo-setup # installs esp-idf, sets up target configurations -To build: $ ./scripts/build.sh -To flash: $ ./scripts/flash.sh # note: flash.sh automatically builds -To monitor: $ ./scripts/monitor.sh +After cloning: $ ./scripts/repo-setup # installs esp-idf, sets up target configurations\ +To build: $ ./scripts/build.sh\ +To flash: $ ./scripts/flash.sh # note: flash.sh automatically builds\ +To monitor: $ ./scripts/monitor.sh\ diff --git a/src/App.cpp b/src/App.cpp index b8ebe65..e4dcc62 100644 --- a/src/App.cpp +++ b/src/App.cpp @@ -9,23 +9,20 @@ #include "pins.hpp" +#include "DemoTask.hpp" + App::App() { ESP_LOGI(TAG, "App constructor"); } uint32_t App::main() { - ESP_LOGI(TAG, "Example configured to blink GPIO LED!"); - gpio_reset_pin(gpio_onboardLed); - gpio_set_direction(gpio_onboardLed, GPIO_MODE_OUTPUT); + ESP_LOGI(__FILE__, "Running App::main()"); - while (1) { - ESP_LOGI(TAG, "Turning the LED %s!", ledState == true ? "ON" : "OFF"); - gpio_set_level(gpio_onboardLed, ledState); - /* Toggle the LED state */ - ledState = !ledState; - vTaskDelay(blinkTime / portTICK_PERIOD_MS); - } + static DemoTask demoTask{}; - return 1; // unreachable + ESP_LOGI(__FILE__, "Starting DemoTask"); + demoTask.start("DemoTask", 4096, 5, 1); + + return 1; } diff --git a/src/App.hpp b/src/App.hpp index 0e42fee..cd1acd3 100644 --- a/src/App.hpp +++ b/src/App.hpp @@ -16,6 +16,6 @@ private: uint32_t ledState = 0; uint32_t blinkTime = 250; - const char *TAG = "app"; + const char *TAG = "app"; // TODO: instead of this for logging you can use __FILE__ or __func__ }; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 14d5180..ff8896e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,9 @@ -file(GLOB SRC_FILES "*.c" "*.cpp") +file(GLOB SRC_FILES + "*.c" + "*.cpp" + "drivers/*.c" +) idf_component_register( SRCS ${SRC_FILES} diff --git a/src/DemoTask.cpp b/src/DemoTask.cpp new file mode 100644 index 0000000..a5bad7b --- /dev/null +++ b/src/DemoTask.cpp @@ -0,0 +1,34 @@ + +#include "DemoTask.hpp" + +#include "driver/gpio.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" + +#include "SsdInterface.hpp" +#include "pins.hpp" + +DemoTask::DemoTask() { + +} + +void DemoTask::run() { + + ESP_LOGI(__FILE__, "Demo Task: run()"); + + ssd_595_t dev = { gpio_ssd_data, gpio_ssd_clk, gpio_ssd_latch, true }; + SsdInterface ssd(&dev, ssdDigits); + + uint32_t delay = 500; // ms + uint8_t digit = 0; + + while(1) { + ssd.writeRaw(&digitMap[digit], 1); + digit++; + if(digit >= 16) digit = 0; + + vTaskDelay(delay / portTICK_PERIOD_MS); + } + +} \ No newline at end of file diff --git a/src/DemoTask.hpp b/src/DemoTask.hpp new file mode 100644 index 0000000..afb200e --- /dev/null +++ b/src/DemoTask.hpp @@ -0,0 +1,16 @@ + +#pragma once +#include "TaskBase.hpp" + +class DemoTask : public TaskBase { +public: + DemoTask(); + +protected: + void run() override; + +private: + + const size_t ssdDigits = 4; + +}; diff --git a/src/SsdInterface.cpp b/src/SsdInterface.cpp new file mode 100644 index 0000000..a0522dc --- /dev/null +++ b/src/SsdInterface.cpp @@ -0,0 +1,28 @@ + +#include "SsdInterface.hpp" + +SsdInterface::SsdInterface(const ssd_595_t* device, size_t numDigits) : device_(device), numDigits_(numDigits) { + + shiftInit(device_); + +} + +STATUS SsdInterface::writeRaw(uint8_t* bytes, size_t numBytes) { + shiftBytes(device_, bytes, numBytes); + return OKAY; +} + +STATUS SsdInterface::write10(int32_t value) { + // TODO: implement + return NOT_IMPLEMENTED; +} + +STATUS SsdInterface::write16(int32_t value) { + // TODO: implement + return NOT_IMPLEMENTED; +} + +STATUS SsdInterface::get(uint8_t* bytes) { + // TODO: implement + return NOT_IMPLEMENTED; +} \ No newline at end of file diff --git a/src/SsdInterface.hpp b/src/SsdInterface.hpp new file mode 100644 index 0000000..9387483 --- /dev/null +++ b/src/SsdInterface.hpp @@ -0,0 +1,43 @@ + +#pragma once + +#include "stdint.h" + +#include "drivers/ssd.h" +#include "common.h" + +class SsdInterface { + +public: + + SsdInterface(const ssd_595_t* device, size_t numDigits); + ~SsdInterface() = default; + + // Outputs the data straight to hardware, mostly for testing purposes + // bytes: the data to write, with bits targetting an led on the ssd + // Returns: execution status + STATUS writeRaw(uint8_t* bytes, size_t numBytes); + + // Displays a decimal integer on the ssd + // value: the integer to display + // Returns: execution status + STATUS write10(int32_t value); + + // Displays a hexadecimal integer on the ssd + // value: the integer to display + // Returns: execution status + STATUS write16(int32_t value); + + // Copies the data currently displayed on the ssd to bytes + // bytes: place to write to + // Returns: execution status + STATUS get(uint8_t* bytes); + +private: + + const ssd_595_t* device_; + + size_t numDigits_; // number of chained digits + uint8_t* data_; // pointer to the data written + +}; diff --git a/src/TaskBase.cpp b/src/TaskBase.cpp new file mode 100644 index 0000000..e1cedca --- /dev/null +++ b/src/TaskBase.cpp @@ -0,0 +1,17 @@ + +#include "TaskBase.hpp" + +#include "esp_log.h" + +void TaskBase::start(const char* name, uint32_t stackSize, UBaseType_t priority, BaseType_t core) { + xTaskCreatePinnedToCore(&TaskBase::taskEntryPoint, name, stackSize, this, priority, &handle, core); + return; +} + +void TaskBase::taskEntryPoint(void* param) { + auto* task = static_cast(param); + task->run(); + vTaskDelete(nullptr); + + return; +} diff --git a/src/TaskBase.hpp b/src/TaskBase.hpp new file mode 100644 index 0000000..ef9a7a9 --- /dev/null +++ b/src/TaskBase.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +class TaskBase { +public: + + virtual ~TaskBase() = default; + + void start(const char* name, uint32_t stackSize, UBaseType_t priority, BaseType_t core = tskNO_AFFINITY); + +protected: + virtual void run() = 0; + +private: + TaskHandle_t handle = nullptr; + + static void taskEntryPoint(void* param); +}; diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000..6559f1d --- /dev/null +++ b/src/common.h @@ -0,0 +1,8 @@ + +#pragma once + +enum STATUS { + OKAY = 0, + ERROR = -1, + NOT_IMPLEMENTED = -2, +}; \ No newline at end of file diff --git a/src/drivers/ssd.c b/src/drivers/ssd.c new file mode 100644 index 0000000..525f2fb --- /dev/null +++ b/src/drivers/ssd.c @@ -0,0 +1,59 @@ + +#include "ssd.h" + +#include "esp_rom_sys.h" +#include "esp_log.h" + +#ifdef __cplusplus +extern "C" { +#endif + +inline void pulse(gpio_num_t pin) { + gpio_set_level(pin, 1); + gpio_set_level(pin, 0); +} + +void shiftInit(const ssd_595_t* device) { + + gpio_reset_pin(device->dataPin); + gpio_reset_pin(device->clockPin); + gpio_reset_pin(device->latchPin); + + gpio_config_t ioConfig = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = (1ULL << device->dataPin) | + (1ULL << device->clockPin) | + (1ULL << device->latchPin), + }; + gpio_config(&ioConfig); + + gpio_set_level(device->dataPin, 0); + gpio_set_level(device->clockPin, 0); + gpio_set_level(device->latchPin, 0); + + ESP_LOGI(__FILE__, "ssd_595 initialized"); +} + +void addDecimal(uint8_t* data) { + // TODO: fix + // data = (*data | 0x01); +} + +void shiftByte(const ssd_595_t* device, uint8_t byte) { + for(int i = 0; i < __CHAR_BIT__ ; i++) { + uint32_t level = ((byte >> i) & 0x1) ^ device->commonCathode; + gpio_set_level(device->dataPin, level); + pulse(device->clockPin); + } + pulse(device->latchPin); +} + +void shiftBytes(const ssd_595_t* device, uint8_t* bytes, size_t numBytes) { + for(size_t i = 0; i < numBytes; i++) { + shiftByte(device, bytes[i]); + } +} + +#ifdef __cplusplus +} +#endif diff --git a/src/drivers/ssd.h b/src/drivers/ssd.h new file mode 100644 index 0000000..17cdebd --- /dev/null +++ b/src/drivers/ssd.h @@ -0,0 +1,70 @@ + +#pragma once + +#include +#include "driver/gpio.h" + +#define SSD_DIGIT_MAP_LENGTH 32 + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + gpio_num_t dataPin; + gpio_num_t clockPin; + gpio_num_t latchPin; + bool commonCathode; // false = common anode +} ssd_595_t; + +// encoding of digits on the seven segment display +// 0bxxxxxxxx +// ABCDEFG. +static uint8_t digitMap[SSD_DIGIT_MAP_LENGTH] = { + 0xFC, // 0 + 0x60, // 1 + 0xDA, // 2 + 0xF2, // 3 + 0x66, // 4 + 0xB6, // 5 + 0xBE, // 6 + 0xE0, // 7 + 0xFE, // 8 + 0xF6, // 9 + 0xEE, // A + 0x3E, // B + 0x9C, // C + 0x7A, // D + 0x9E, // E + 0x8E, // F + 0x02, // - + 0x01, // . + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) + 0x92, // Error code (not implemented) +}; + +// TODO: have these return error codes likewise + +void shiftInit(const ssd_595_t* device); +void pulse(gpio_num_t pin); + +void addDecimal(uint8_t* data); // adds a decimal to a single digit + +void shiftByte(const ssd_595_t* device, uint8_t byte); // outputs a serial byte, big-endian +void shiftBytes(const ssd_595_t* device, uint8_t* bytes, size_t numBytes); // outputs multiple bytes + +#ifdef __cplusplus +} +#endif