typedef'd all structs, unions and enums

main
Sara 2023-09-28 14:43:07 +02:00
parent f6b5d577e1
commit afb521f7a8
6 changed files with 56 additions and 56 deletions

View File

@ -10,17 +10,17 @@
#include "driver/gpio.h" #include "driver/gpio.h"
uint32_t g_serial_out_buffer[122]; uint32_t g_serial_out_buffer[122];
union Led* g_leds = ((union Led*)g_serial_out_buffer + 1); Led* g_leds = ((Led*)g_serial_out_buffer + 1);
struct Gradient g_default_gradient; Gradient g_default_gradient;
struct Gradient g_current_gradient; Gradient g_current_gradient;
int g_leds_are_default = 1; int g_leds_are_default = 1;
enum LedsSendStatus g_leds_send_state = LEDS_SEND_WAITING; LedsSendStatus g_leds_send_state = LEDS_SEND_WAITING;
SemaphoreHandle_t g_led_mutex; // mutex governing access to data for leds SemaphoreHandle_t g_led_mutex; // mutex governing access to data for leds
// use for all global data defined in this header // use for all global data defined in this header
struct LedThreadData g_led_thread_data = { LedThreadData g_led_thread_data = {
.task = 0, .task = 0,
.func = &leds_thread .func = &leds_thread
}; };
@ -40,7 +40,7 @@ uint8_t lerp_uint8(uint8_t a, uint8_t b, float t) {
} }
static inline static inline
void lerp_led(union Led* out, const union Led* from, const union Led* to, float t) { void lerp_led(Led* out, const Led* from, const Led* to, float t) {
out->components.red = lerp_uint8(from->components.red, to->components.red, t); out->components.red = lerp_uint8(from->components.red, to->components.red, t);
out->components.green = lerp_uint8(from->components.green, to->components.green, t); out->components.green = lerp_uint8(from->components.green, to->components.green, t);
out->components.blue = lerp_uint8(from->components.blue, to->components.blue, t); out->components.blue = lerp_uint8(from->components.blue, to->components.blue, t);
@ -50,7 +50,7 @@ void lerp_led(union Led* out, const union Led* from, const union Led* to, float
} }
static inline static inline
void lerp_points_between(const struct GradientPoint from, const struct GradientPoint to) { void lerp_points_between(const GradientPoint from, const GradientPoint to) {
const int dif = to.offset - from.offset; const int dif = to.offset - from.offset;
float t = 0.f; float t = 0.f;
for(int led = from.offset; led <= to.offset; ++led) { for(int led = from.offset; led <= to.offset; ++led) {
@ -112,19 +112,19 @@ void send_leds() {
} }
void set_led_range(int start, int end, union Led value) { void set_led_range(int start, int end, Led value) {
for(int i = start; i < end; ++i) { for(int i = start; i < end; ++i) {
g_leds[i] = value; g_leds[i] = value;
} }
} }
void leds_set_default_gradient(const struct Gradient* gradient) { void leds_set_default_gradient(const Gradient* gradient) {
g_default_gradient = *gradient; g_default_gradient = *gradient;
} }
void leds_set_current_gradient(const struct Gradient* gradient, int defer_send) { void leds_set_current_gradient(const Gradient* gradient, int defer_send) {
struct GradientPoint from = gradient->points[0]; GradientPoint from = gradient->points[0];
struct GradientPoint to; GradientPoint to;
set_led_range(0, gradient->points[0].offset, gradient->points[0].led); set_led_range(0, gradient->points[0].offset, gradient->points[0].led);
set_led_range(gradient->points[gradient->points_len-1].offset, 120, gradient->points[gradient->points_len-1].led); set_led_range(gradient->points[gradient->points_len-1].offset, 120, gradient->points[gradient->points_len-1].led);
@ -159,7 +159,7 @@ void memswap(void* d, void* s, size_t n) {
void leds_animate() { void leds_animate() {
for(size_t i = 0; i < g_current_gradient.points_len; ++i) { for(size_t i = 0; i < g_current_gradient.points_len; ++i) {
// The gradient point at i // The gradient point at i
struct GradientPoint* point = g_current_gradient.points + i; GradientPoint* point = g_current_gradient.points + i;
// move towards end // move towards end
if(point->movement > 0) { if(point->movement > 0) {
// without moving past it // without moving past it
@ -167,7 +167,7 @@ void leds_animate() {
// swap with next point if we pass it // swap with next point if we pass it
if(point->offset > (point+1)->offset) { if(point->offset > (point+1)->offset) {
memswap(point, point+1, sizeof(struct GradientPoint)); memswap(point, point+1, sizeof(GradientPoint));
} }
// move towards start // move towards start
} else if(point->movement < 0) { } else if(point->movement < 0) {
@ -176,7 +176,7 @@ void leds_animate() {
// swap with previous point if we fall below it // swap with previous point if we fall below it
if(point->offset < (point-1)->offset) { if(point->offset < (point-1)->offset) {
memswap(point, point-1, sizeof(struct GradientPoint)); memswap(point, point-1, sizeof(GradientPoint));
} }
} }
} }
@ -190,14 +190,17 @@ void leds_thread() {
// wait for 10 milliseconds, // wait for 10 milliseconds,
// giving FreeRTOS time to run other tasks // giving FreeRTOS time to run other tasks
vTaskDelay(10 / portTICK_RATE_MS); vTaskDelay(10 / portTICK_RATE_MS);
// tick timer by 10ms
timer += 0.01;
xSemaphoreTake(g_led_mutex, portMAX_DELAY); xSemaphoreTake(g_led_mutex, portMAX_DELAY);
{ {
send_leds(); send_leds();
leds_animate(); leds_animate();
// reset gradient, defer send until next frame
if(timer > g_current_gradient.duration) { if(timer > g_current_gradient.duration) {
timer = 0.f; timer = 0.f;
leds_set_current_gradient(&g_default_gradient, 0); leds_reset_gradient(1);
} }
} }
xSemaphoreGive(g_led_mutex); xSemaphoreGive(g_led_mutex);
@ -208,8 +211,8 @@ void leds_init() {
g_serial_out_buffer[0] = 0u; g_serial_out_buffer[0] = 0u;
g_serial_out_buffer[61] = ~0u; g_serial_out_buffer[61] = ~0u;
set_led_range(0, 120, set_led_range(0, 120,
(union Led){.components = (Led){.components =
(struct LedComponents) { (LedComponents) {
.red = 0, .red = 0,
.green = 0, .green = 0,
.blue = 0, .blue = 0,

View File

@ -12,66 +12,66 @@
#include <freertos/semphr.h> #include <freertos/semphr.h>
#include "esp_system.h" #include "esp_system.h"
enum LedsSendStatus { typedef enum LedsSendStatus {
LEDS_SEND_WAITING, LEDS_SEND_WAITING,
LEDS_SEND_REQUESTED, LEDS_SEND_REQUESTED,
LEDS_SENDING, LEDS_SENDING,
}; } LedsSendStatus;
// pack the struct to match exactly 8 * 4 = 32bits // pack the struct to match exactly 8 * 4 = 32bits
struct __attribute__((__packed__)) LedComponents { typedef struct __attribute__((__packed__)) LedComponents {
// RGB component values // RGB component values
uint8_t red; uint8_t red;
uint8_t green; uint8_t green;
uint8_t blue; uint8_t blue;
uint8_t global; // global baseline brightness, highest 3 bits should always be ones uint8_t global; // global baseline brightness, highest 3 bits should always be ones
}; } LedComponents;
// union of components and their representation as a u32 // union of components and their representation as a u32
// allows for easier sending of data over serial // allows for easier sending of data over serial
union Led { typedef union Led {
struct LedComponents components; struct LedComponents components;
uint32_t bits; uint32_t bits;
}; } Led;
// point on a gradient // point on a gradient
struct GradientPoint { typedef struct GradientPoint {
union Led led; // value of the led at this point union Led led; // value of the led at this point
size_t offset; // offset (measured in leds) from the beginning size_t offset; // offset (measured in leds) from the beginning
short movement; // direction of movement over time short movement; // direction of movement over time
}; } GradientPoint;
struct Gradient { typedef struct Gradient {
struct GradientPoint points[16]; // array of gradient points, support at most 16 points in a gradient struct GradientPoint points[16]; // array of gradient points, support at most 16 points in a gradient
size_t points_len; // number of used gradient points size_t points_len; // number of used gradient points
float duration; // amount of time to allow this gradient to last float duration; // amount of time to allow this gradient to last
// positive means an amount in second 0 or negative means indefinitely until further notice // positive means an amount in second 0 or negative means indefinitely until further notice
}; } Gradient;
struct LedThreadData { typedef struct LedThreadData {
TaskHandle_t task; TaskHandle_t task;
TaskFunction_t func; TaskFunction_t func;
}; } LedThreadData;
// buffer that will be written out to the led strip over serial // buffer that will be written out to the led strip over serial
extern uint32_t g_serial_out_buffer[122]; extern uint32_t g_serial_out_buffer[122];
// 120-long slice of the out buffer that represents the first few leds // 120-long slice of the out buffer that represents the first few leds
extern union Led* g_leds; extern Led* g_leds;
extern struct Gradient g_default_gradient; extern Gradient g_default_gradient;
extern struct Gradient g_current_gradient; extern Gradient g_current_gradient;
extern int g_leds_are_default; extern int g_leds_are_default;
extern enum LedsSendStatus g_leds_send_state; extern enum LedsSendStatus g_leds_send_state;
extern SemaphoreHandle_t g_led_mutex; extern SemaphoreHandle_t g_led_mutex;
extern struct LedThreadData g_led_thread_data; extern LedThreadData g_led_thread_data;
#define CLOCK 4 #define CLOCK 4
#define DATA 5 #define DATA 5
extern void send_leds(); extern void send_leds();
extern void set_led_range(int start, int end, union Led value); extern void set_led_range(int start, int end, Led value);
extern void leds_set_default_gradient(const struct Gradient* gradient); extern void leds_set_default_gradient(const Gradient* gradient);
extern void leds_set_current_gradient(const struct Gradient* gradient, int defer_send); extern void leds_set_current_gradient(const Gradient* gradient, int defer_send);
extern void leds_reset_gradient(int defer_send); extern void leds_reset_gradient(int defer_send);
extern void leds_thread(); extern void leds_thread();

View File

@ -5,10 +5,10 @@
// parse a URL query as described in api-doc.txt into a valid Gradient struct. // parse a URL query as described in api-doc.txt into a valid Gradient struct.
// If the gradient is invalid, the is_ok flag on the return value will be set, and error will be set to a message describing the problem. // If the gradient is invalid, the is_ok flag on the return value will be set, and error will be set to a message describing the problem.
struct result_t parse_leds_query(char* query_string, size_t query_size) { Result parse_leds_query(char* query_string, size_t query_size) {
char query_value[16]; char query_value[16];
char query_key[3]; char query_key[3];
struct Gradient* gradient = malloc(sizeof(struct Gradient)); Gradient* gradient = malloc(sizeof(Gradient));
// Fetch the &l length parameter. // Fetch the &l length parameter.
// Interpret as a positive integer number of points on the gradient. // Interpret as a positive integer number of points on the gradient.

View File

@ -26,7 +26,7 @@ void TEST_leds() {
// TEST: after a delay, set the leds to a gradient of red - black // TEST: after a delay, set the leds to a gradient of red - black
sleep(1); sleep(1);
union Led led = { Led led = {
.components = { .components = {
.red = 0, .red = 0,
.green = 255, .green = 255,
@ -42,12 +42,12 @@ void TEST_leds() {
sleep(1); sleep(1);
struct Gradient gradient; Gradient gradient;
gradient.points_len = 4; gradient.points_len = 4;
gradient.points[0].offset = 0; gradient.points[0].offset = 0;
gradient.points[0].movement = 0; gradient.points[0].movement = 0;
gradient.points[0].led.components = (struct LedComponents) { gradient.points[0].led.components = (LedComponents) {
.global = GLOBAL(0), .global = GLOBAL(0),
.red = 0, .red = 0,
.green = 0, .green = 0,
@ -56,7 +56,7 @@ void TEST_leds() {
gradient.points[1].offset = 59; gradient.points[1].offset = 59;
gradient.points[1].movement = -1; gradient.points[1].movement = -1;
gradient.points[1].led.components = (struct LedComponents){ gradient.points[1].led.components = (LedComponents){
.global = GLOBAL(10), .global = GLOBAL(10),
.red = 40, .red = 40,
.green = 200, .green = 200,
@ -64,7 +64,7 @@ void TEST_leds() {
}; };
gradient.points[2].offset = 61; gradient.points[2].offset = 61;
gradient.points[2].movement = 1; gradient.points[2].movement = 1;
gradient.points[2].led.components = (struct LedComponents){ gradient.points[2].led.components = (LedComponents){
.global = GLOBAL(10), .global = GLOBAL(10),
.red = 40, .red = 40,
.green = 200, .green = 200,
@ -72,7 +72,7 @@ void TEST_leds() {
}; };
gradient.points[3].offset = 120; gradient.points[3].offset = 120;
gradient.points[3].movement = 0; gradient.points[3].movement = 0;
gradient.points[3].led.components = (struct LedComponents){ gradient.points[3].led.components = (LedComponents){
.global = GLOBAL(0), .global = GLOBAL(0),
.red = 0, .red = 0,
.green = 0, .green = 0,

View File

@ -16,12 +16,12 @@ static httpd_handle_t g_http_server = NULL;
// convert a (valid) request as described in api-doc.txt to a gradient. // convert a (valid) request as described in api-doc.txt to a gradient.
static static
struct result_t request_to_gradient(httpd_req_t* request) { Result request_to_gradient(httpd_req_t* request) {
// buffer for query string // buffer for query string
char* query_buffer; char* query_buffer;
size_t query_length = httpd_req_get_url_query_len(request) + 1; size_t query_length = httpd_req_get_url_query_len(request) + 1;
struct result_t result = { .error = NULL }; Result result = { .error = NULL };
if(query_length > 1) { if(query_length > 1) {
query_buffer = malloc(query_length * sizeof(char)); query_buffer = malloc(query_length * sizeof(char));
@ -41,7 +41,7 @@ esp_err_t on_http_get_root(httpd_req_t* request) {
const char* response_msg = http_response_ok; const char* response_msg = http_response_ok;
LOGLN("GET received on '/next'."); LOGLN("GET received on '/next'.");
// convert the request url to a gradient // convert the request url to a gradient
struct result_t result = request_to_gradient(request); Result result = request_to_gradient(request);
// an error was returned, pass it on to the API caller // an error was returned, pass it on to the API caller
if(!result.is_ok) { if(!result.is_ok) {
httpd_resp_set_status(request, "400 Bad Request"); httpd_resp_set_status(request, "400 Bad Request");
@ -49,8 +49,8 @@ esp_err_t on_http_get_root(httpd_req_t* request) {
} else { } else {
// grab a lock on the leds data // grab a lock on the leds data
xSemaphoreTake(g_led_mutex, portMAX_DELAY); xSemaphoreTake(g_led_mutex, portMAX_DELAY);
// modify leds data // modify leds data, defer sending for the leds thread to take care of
leds_set_current_gradient(result.ok, 0); leds_set_current_gradient(result.ok, 1);
// release lock // release lock
xSemaphoreGive(g_led_mutex); xSemaphoreGive(g_led_mutex);
// request to gradient allocates the gradient on the heap, // request to gradient allocates the gradient on the heap,
@ -73,7 +73,7 @@ esp_err_t on_http_get_default(httpd_req_t* request) {
const char* response_msg = http_response_ok; const char* response_msg = http_response_ok;
LOGLN("GET received on '/default'."); LOGLN("GET received on '/default'.");
// convert the request to a gradient object // convert the request to a gradient object
struct result_t result = request_to_gradient(request); Result result = request_to_gradient(request);
// handle invalid query // handle invalid query
if(!result.is_ok) { if(!result.is_ok) {
httpd_resp_set_status(request, "400 Bad Request"); httpd_resp_set_status(request, "400 Bad Request");

View File

@ -33,18 +33,15 @@ int clamp(int x, int mi, int ma) {
#define GLOBAL(__a) (uint8_t)(__a|0xE0) #define GLOBAL(__a) (uint8_t)(__a|0xE0)
struct result_t { typedef struct Result {
uint8_t is_ok; uint8_t is_ok;
union { union {
void* ok; void* ok;
const char* error; const char* error;
}; };
}; } Result;
typedef struct result_t Result;
#define PARSE_ERR(__err) (Result){.is_ok=0,.error=__err} #define PARSE_ERR(__err) (Result){.is_ok=0,.error=__err}
#define PARSE_OK(__result) (Result){.is_ok=1,.ok=__result} #define PARSE_OK(__result) (Result){.is_ok=1,.ok=__result}
#endif // !_shared_h #endif // !_shared_h