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
|
The server listens on '/' for GET queries with a url query format like
|
||||||
?l=*&r0=*&g0=*&b0=*&a0=*&t0=* ... &rl=*&gl=*&bl=*&al=*&tl=*
|
?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.
|
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.
|
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.
|
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.
|
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.
|
When no movement is set, 0 (no movement) is implied.
|
||||||
The whole gradient can have a duration &d parameter and must have a length &l
|
|
||||||
|
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);
|
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() {
|
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
|
||||||
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) {
|
||||||
|
++point->offset;
|
||||||
// without moving past it
|
// without moving past it
|
||||||
point->offset = min(point->offset + 1, 120);
|
led_check_edge(point);
|
||||||
|
|
||||||
// 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(GradientPoint));
|
memswap(point, point+1, sizeof(GradientPoint));
|
||||||
}
|
}
|
||||||
// move towards start
|
// move towards start
|
||||||
} else if(point->movement < 0) {
|
} else if(point->movement < 0) {
|
||||||
|
++point->offset;
|
||||||
// without passing it
|
// without passing it
|
||||||
point->offset = max(0, point->offset - 1);
|
led_check_edge(point);
|
||||||
|
|
||||||
// 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) {
|
||||||
|
|
|
@ -18,6 +18,12 @@ typedef enum LedsSendStatus {
|
||||||
LEDS_SENDING,
|
LEDS_SENDING,
|
||||||
} LedsSendStatus;
|
} LedsSendStatus;
|
||||||
|
|
||||||
|
typedef enum MoveEdgeAction {
|
||||||
|
LEDS_EDGE_WRAP,
|
||||||
|
LEDS_EDGE_REVERSE,
|
||||||
|
LEDS_EDGE_STOP
|
||||||
|
} MoveEdgeAction;
|
||||||
|
|
||||||
// pack the struct to match exactly 8 * 4 = 32bits
|
// pack the struct to match exactly 8 * 4 = 32bits
|
||||||
typedef struct __attribute__((__packed__)) LedComponents {
|
typedef struct __attribute__((__packed__)) LedComponents {
|
||||||
// RGB component values
|
// RGB component values
|
||||||
|
@ -37,8 +43,9 @@ typedef union Led {
|
||||||
// point on a gradient
|
// point on a gradient
|
||||||
typedef 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
|
int offset; // offset (measured in leds) from the beginning
|
||||||
short movement; // direction of movement over time
|
short movement; // direction of movement over time
|
||||||
|
MoveEdgeAction edge_action; // what to do when movement hits an end of the strip
|
||||||
} GradientPoint;
|
} GradientPoint;
|
||||||
|
|
||||||
typedef struct Gradient {
|
typedef struct Gradient {
|
||||||
|
|
18
main/parse.c
18
main/parse.c
|
@ -3,6 +3,16 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <esp_http_server.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.
|
// 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.
|
||||||
Result parse_leds_query(char* query_string, size_t query_size) {
|
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.
|
// Get the movement variable &m.
|
||||||
// Interpreted as an integer number from -1 to +1
|
// Interpreted as an integer number from -1 to +1
|
||||||
sprintf(query_key, "m%d", point);
|
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));
|
gradient->points[point].movement = clamp(-1, +1, atoi(query_value));
|
||||||
} else {
|
} else {
|
||||||
gradient->points[point].movement = 0;
|
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
|
// Log fetched fields
|
||||||
LOGLN("led[%d]:", point);
|
LOGLN("led[%d]:", point);
|
||||||
|
|
Loading…
Reference in New Issue