Merge pull request #2 from Blitblank/feature/ssd-driver
Feature/ssd driver
This commit is contained in:
12
README.md
12
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\
|
||||
|
||||
19
src/App.cpp
19
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;
|
||||
}
|
||||
|
||||
@@ -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__
|
||||
|
||||
};
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
|
||||
file(GLOB SRC_FILES "*.c" "*.cpp")
|
||||
file(GLOB SRC_FILES
|
||||
"*.c"
|
||||
"*.cpp"
|
||||
"drivers/*.c"
|
||||
)
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${SRC_FILES}
|
||||
|
||||
34
src/DemoTask.cpp
Normal file
34
src/DemoTask.cpp
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
16
src/DemoTask.hpp
Normal file
16
src/DemoTask.hpp
Normal file
@@ -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;
|
||||
|
||||
};
|
||||
28
src/SsdInterface.cpp
Normal file
28
src/SsdInterface.cpp
Normal file
@@ -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;
|
||||
}
|
||||
43
src/SsdInterface.hpp
Normal file
43
src/SsdInterface.hpp
Normal file
@@ -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
|
||||
|
||||
};
|
||||
17
src/TaskBase.cpp
Normal file
17
src/TaskBase.cpp
Normal file
@@ -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<TaskBase*>(param);
|
||||
task->run();
|
||||
vTaskDelete(nullptr);
|
||||
|
||||
return;
|
||||
}
|
||||
20
src/TaskBase.hpp
Normal file
20
src/TaskBase.hpp
Normal file
@@ -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);
|
||||
};
|
||||
8
src/common.h
Normal file
8
src/common.h
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
enum STATUS {
|
||||
OKAY = 0,
|
||||
ERROR = -1,
|
||||
NOT_IMPLEMENTED = -2,
|
||||
};
|
||||
59
src/drivers/ssd.c
Normal file
59
src/drivers/ssd.c
Normal file
@@ -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
|
||||
70
src/drivers/ssd.h
Normal file
70
src/drivers/ssd.h
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#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
|
||||
Reference in New Issue
Block a user