typedef'd all structs, unions and enums
parent
f6b5d577e1
commit
afb521f7a8
39
main/leds.c
39
main/leds.c
|
@ -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,
|
||||||
|
|
38
main/leds.h
38
main/leds.h
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue