diff --git a/main/leds.c b/main/leds.c index 35962d5..5e7a809 100644 --- a/main/leds.c +++ b/main/leds.c @@ -10,17 +10,17 @@ #include "driver/gpio.h" 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; -struct Gradient g_current_gradient; +Gradient g_default_gradient; +Gradient g_current_gradient; 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 // use for all global data defined in this header -struct LedThreadData g_led_thread_data = { +LedThreadData g_led_thread_data = { .task = 0, .func = &leds_thread }; @@ -40,7 +40,7 @@ uint8_t lerp_uint8(uint8_t a, uint8_t b, float t) { } 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.green = lerp_uint8(from->components.green, to->components.green, 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 -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; float t = 0.f; 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) { 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; } -void leds_set_current_gradient(const struct Gradient* gradient, int defer_send) { - struct GradientPoint from = gradient->points[0]; - struct GradientPoint to; +void leds_set_current_gradient(const Gradient* gradient, int defer_send) { + GradientPoint from = gradient->points[0]; + GradientPoint to; 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); @@ -159,7 +159,7 @@ void memswap(void* d, void* s, size_t n) { void leds_animate() { for(size_t i = 0; i < g_current_gradient.points_len; ++i) { // The gradient point at i - struct GradientPoint* point = g_current_gradient.points + i; + GradientPoint* point = g_current_gradient.points + i; // move towards end if(point->movement > 0) { // without moving past it @@ -167,7 +167,7 @@ void leds_animate() { // swap with next point if we pass it if(point->offset > (point+1)->offset) { - memswap(point, point+1, sizeof(struct GradientPoint)); + memswap(point, point+1, sizeof(GradientPoint)); } // move towards start } else if(point->movement < 0) { @@ -176,7 +176,7 @@ void leds_animate() { // swap with previous point if we fall below it 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, // giving FreeRTOS time to run other tasks vTaskDelay(10 / portTICK_RATE_MS); + // tick timer by 10ms + timer += 0.01; xSemaphoreTake(g_led_mutex, portMAX_DELAY); { send_leds(); leds_animate(); + // reset gradient, defer send until next frame if(timer > g_current_gradient.duration) { timer = 0.f; - leds_set_current_gradient(&g_default_gradient, 0); + leds_reset_gradient(1); } } xSemaphoreGive(g_led_mutex); @@ -208,8 +211,8 @@ void leds_init() { g_serial_out_buffer[0] = 0u; g_serial_out_buffer[61] = ~0u; set_led_range(0, 120, - (union Led){.components = - (struct LedComponents) { + (Led){.components = + (LedComponents) { .red = 0, .green = 0, .blue = 0, diff --git a/main/leds.h b/main/leds.h index f871feb..e415b38 100644 --- a/main/leds.h +++ b/main/leds.h @@ -12,66 +12,66 @@ #include #include "esp_system.h" -enum LedsSendStatus { +typedef enum LedsSendStatus { LEDS_SEND_WAITING, LEDS_SEND_REQUESTED, LEDS_SENDING, -}; +} LedsSendStatus; // pack the struct to match exactly 8 * 4 = 32bits -struct __attribute__((__packed__)) LedComponents { +typedef struct __attribute__((__packed__)) LedComponents { // RGB component values uint8_t red; uint8_t green; uint8_t blue; uint8_t global; // global baseline brightness, highest 3 bits should always be ones -}; +} LedComponents; // union of components and their representation as a u32 // allows for easier sending of data over serial -union Led { +typedef union Led { struct LedComponents components; uint32_t bits; -}; +} Led; // point on a gradient -struct GradientPoint { +typedef struct GradientPoint { union Led led; // value of the led at this point size_t offset; // offset (measured in leds) from the beginning 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 size_t points_len; // number of used gradient points 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 -}; +} Gradient; -struct LedThreadData { +typedef struct LedThreadData { TaskHandle_t task; TaskFunction_t func; -}; +} LedThreadData; // buffer that will be written out to the led strip over serial extern uint32_t g_serial_out_buffer[122]; // 120-long slice of the out buffer that represents the first few leds -extern union Led* g_leds; -extern struct Gradient g_default_gradient; -extern struct Gradient g_current_gradient; +extern Led* g_leds; +extern Gradient g_default_gradient; +extern Gradient g_current_gradient; extern int g_leds_are_default; extern enum LedsSendStatus g_leds_send_state; extern SemaphoreHandle_t g_led_mutex; -extern struct LedThreadData g_led_thread_data; +extern LedThreadData g_led_thread_data; #define CLOCK 4 #define DATA 5 extern void send_leds(); -extern void set_led_range(int start, int end, union Led value); -extern void leds_set_default_gradient(const struct Gradient* gradient); -extern void leds_set_current_gradient(const struct Gradient* gradient, int defer_send); +extern void set_led_range(int start, int end, Led value); +extern void leds_set_default_gradient(const Gradient* gradient); +extern void leds_set_current_gradient(const Gradient* gradient, int defer_send); extern void leds_reset_gradient(int defer_send); extern void leds_thread(); diff --git a/main/parse.c b/main/parse.c index 8cee177..5dff69c 100644 --- a/main/parse.c +++ b/main/parse.c @@ -5,10 +5,10 @@ // 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. -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_key[3]; - struct Gradient* gradient = malloc(sizeof(struct Gradient)); + Gradient* gradient = malloc(sizeof(Gradient)); // Fetch the &l length parameter. // Interpret as a positive integer number of points on the gradient. diff --git a/main/potion_party.c b/main/potion_party.c index a8eb4f6..64c2c46 100644 --- a/main/potion_party.c +++ b/main/potion_party.c @@ -26,7 +26,7 @@ void TEST_leds() { // TEST: after a delay, set the leds to a gradient of red - black sleep(1); - union Led led = { + Led led = { .components = { .red = 0, .green = 255, @@ -42,12 +42,12 @@ void TEST_leds() { sleep(1); - struct Gradient gradient; + Gradient gradient; gradient.points_len = 4; gradient.points[0].offset = 0; gradient.points[0].movement = 0; - gradient.points[0].led.components = (struct LedComponents) { + gradient.points[0].led.components = (LedComponents) { .global = GLOBAL(0), .red = 0, .green = 0, @@ -56,7 +56,7 @@ void TEST_leds() { gradient.points[1].offset = 59; gradient.points[1].movement = -1; - gradient.points[1].led.components = (struct LedComponents){ + gradient.points[1].led.components = (LedComponents){ .global = GLOBAL(10), .red = 40, .green = 200, @@ -64,7 +64,7 @@ void TEST_leds() { }; gradient.points[2].offset = 61; gradient.points[2].movement = 1; - gradient.points[2].led.components = (struct LedComponents){ + gradient.points[2].led.components = (LedComponents){ .global = GLOBAL(10), .red = 40, .green = 200, @@ -72,7 +72,7 @@ void TEST_leds() { }; gradient.points[3].offset = 120; gradient.points[3].movement = 0; - gradient.points[3].led.components = (struct LedComponents){ + gradient.points[3].led.components = (LedComponents){ .global = GLOBAL(0), .red = 0, .green = 0, diff --git a/main/server.c b/main/server.c index 174063c..8748847 100644 --- a/main/server.c +++ b/main/server.c @@ -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. static -struct result_t request_to_gradient(httpd_req_t* request) { +Result request_to_gradient(httpd_req_t* request) { // buffer for query string char* query_buffer; 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) { 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; LOGLN("GET received on '/next'."); // 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 if(!result.is_ok) { httpd_resp_set_status(request, "400 Bad Request"); @@ -49,8 +49,8 @@ esp_err_t on_http_get_root(httpd_req_t* request) { } else { // grab a lock on the leds data xSemaphoreTake(g_led_mutex, portMAX_DELAY); - // modify leds data - leds_set_current_gradient(result.ok, 0); + // modify leds data, defer sending for the leds thread to take care of + leds_set_current_gradient(result.ok, 1); // release lock xSemaphoreGive(g_led_mutex); // 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; LOGLN("GET received on '/default'."); // convert the request to a gradient object - struct result_t result = request_to_gradient(request); + Result result = request_to_gradient(request); // handle invalid query if(!result.is_ok) { httpd_resp_set_status(request, "400 Bad Request"); diff --git a/main/shared.h b/main/shared.h index d72ab9b..369d7a2 100644 --- a/main/shared.h +++ b/main/shared.h @@ -33,18 +33,15 @@ int clamp(int x, int mi, int ma) { #define GLOBAL(__a) (uint8_t)(__a|0xE0) -struct result_t { +typedef struct Result { uint8_t is_ok; union { void* ok; const char* error; }; -}; - -typedef struct result_t Result; +} Result; #define PARSE_ERR(__err) (Result){.is_ok=0,.error=__err} #define PARSE_OK(__result) (Result){.is_ok=1,.ok=__result} - #endif // !_shared_h