added edge action argument
parent
afb521f7a8
commit
46011ea8d9
17
api-doc.txt
17
api-doc.txt
|
@ -1,8 +1,21 @@
|
|||
The server listens on '/' for GET queries with a url query format like
|
||||
?l=*&r0=*&g0=*&b0=*&a0=*&t0=* ... &rl=*&gl=*&bl=*&al=*&tl=*
|
||||
|
||||
Where l is the number of points on a gradient. And each point of the gradient has a r* g* b* a* and t* where * is the index.
|
||||
|
||||
r g and b are the red green and blue 8-bit colour components of a point on the gradient. A is the 5-bit global component of the led at that point.
|
||||
t is the offset from the start measured in leds.
|
||||
|
||||
Each point also has an optional &m 'movement' argument. &m should be either -1, +1 or 0 and represents the movement per frame or the point.
|
||||
A point on the gradient can have an &m parameter, and has to have a &r, &g, &b, &a, and &t.
|
||||
The whole gradient can have a duration &d parameter and must have a length &l
|
||||
When no movement is set, 0 (no movement) is implied.
|
||||
|
||||
When movement is set, a &e 'edge' component can also be set for that point. &e defines what the point will do once it reaches an end of the strip.
|
||||
Edge should be one of
|
||||
w to wrap to the opposite end of the strip.
|
||||
r to reverse direction
|
||||
s to stop
|
||||
|
||||
If no &e is specified, s is implied.
|
||||
|
||||
A point on the gradient may have a movement &m and edge &e parameter, and has to have a &r, &g, &b, &a, and &t.
|
||||
The whole gradient may have a duration &d parameter and must have a length &l
|
||||
|
|
32
main/leds.c
32
main/leds.c
|
@ -156,23 +156,49 @@ void memswap(void* d, void* s, size_t n) {
|
|||
free(tmp);
|
||||
}
|
||||
|
||||
static
|
||||
void led_check_edge(GradientPoint* point) {
|
||||
int offset = clamp(point->offset, 0, 120);
|
||||
switch(point->edge_action) {
|
||||
default:
|
||||
case LEDS_EDGE_WRAP:
|
||||
if(point->offset < 0) {
|
||||
point->offset += 120;
|
||||
} else if(point->offset >= 120) {
|
||||
point->offset %= 120;
|
||||
}
|
||||
break;
|
||||
case LEDS_EDGE_REVERSE: {
|
||||
if(offset != point->offset) {
|
||||
point->offset = offset;
|
||||
point->movement *= -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LEDS_EDGE_STOP:
|
||||
point->offset = clamp(point->offset, 0, 120);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void leds_animate() {
|
||||
for(size_t i = 0; i < g_current_gradient.points_len; ++i) {
|
||||
// The gradient point at i
|
||||
GradientPoint* point = g_current_gradient.points + i;
|
||||
// move towards end
|
||||
if(point->movement > 0) {
|
||||
++point->offset;
|
||||
// without moving past it
|
||||
point->offset = min(point->offset + 1, 120);
|
||||
|
||||
led_check_edge(point);
|
||||
// swap with next point if we pass it
|
||||
if(point->offset > (point+1)->offset) {
|
||||
memswap(point, point+1, sizeof(GradientPoint));
|
||||
}
|
||||
// move towards start
|
||||
} else if(point->movement < 0) {
|
||||
++point->offset;
|
||||
// without passing it
|
||||
point->offset = max(0, point->offset - 1);
|
||||
led_check_edge(point);
|
||||
|
||||
// swap with previous point if we fall below it
|
||||
if(point->offset < (point-1)->offset) {
|
||||
|
|
|
@ -18,6 +18,12 @@ typedef enum LedsSendStatus {
|
|||
LEDS_SENDING,
|
||||
} LedsSendStatus;
|
||||
|
||||
typedef enum MoveEdgeAction {
|
||||
LEDS_EDGE_WRAP,
|
||||
LEDS_EDGE_REVERSE,
|
||||
LEDS_EDGE_STOP
|
||||
} MoveEdgeAction;
|
||||
|
||||
// pack the struct to match exactly 8 * 4 = 32bits
|
||||
typedef struct __attribute__((__packed__)) LedComponents {
|
||||
// RGB component values
|
||||
|
@ -37,8 +43,9 @@ typedef union Led {
|
|||
// point on a gradient
|
||||
typedef struct GradientPoint {
|
||||
union Led led; // value of the led at this point
|
||||
size_t offset; // offset (measured in leds) from the beginning
|
||||
int offset; // offset (measured in leds) from the beginning
|
||||
short movement; // direction of movement over time
|
||||
MoveEdgeAction edge_action; // what to do when movement hits an end of the strip
|
||||
} GradientPoint;
|
||||
|
||||
typedef struct Gradient {
|
||||
|
|
18
main/parse.c
18
main/parse.c
|
@ -3,6 +3,16 @@
|
|||
#include <string.h>
|
||||
#include <esp_http_server.h>
|
||||
|
||||
MoveEdgeAction strtoea(const char* str) {
|
||||
if(strcmp(str, "w")) {
|
||||
return LEDS_EDGE_WRAP;
|
||||
} else if(strcmp(str, "r")) {
|
||||
return LEDS_EDGE_REVERSE;
|
||||
} else {
|
||||
return LEDS_EDGE_STOP;
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
Result parse_leds_query(char* query_string, size_t query_size) {
|
||||
|
@ -75,11 +85,17 @@ Result parse_leds_query(char* query_string, size_t query_size) {
|
|||
// Get the movement variable &m.
|
||||
// Interpreted as an integer number from -1 to +1
|
||||
sprintf(query_key, "m%d", point);
|
||||
if(gradient->duration > 0 && httpd_query_key_value(query_string, query_key, query_value, sizeof(query_value)) == ESP_OK) {
|
||||
if(httpd_query_key_value(query_string, query_key, query_value, sizeof(query_value)) == ESP_OK) {
|
||||
gradient->points[point].movement = clamp(-1, +1, atoi(query_value));
|
||||
} else {
|
||||
gradient->points[point].movement = 0;
|
||||
}
|
||||
sprintf(query_key, "e%d", point);
|
||||
if(httpd_query_key_value(query_string, query_key, query_value, sizeof(query_value)) == ESP_OK) {
|
||||
gradient->points[point].edge_action = strtoea(query_value);
|
||||
} else {
|
||||
gradient->points[point].edge_action = LEDS_EDGE_STOP;
|
||||
}
|
||||
|
||||
// Log fetched fields
|
||||
LOGLN("led[%d]:", point);
|
||||
|
|
Loading…
Reference in New Issue