diff --git a/components/squeezelite/display.c b/components/squeezelite/display.c
index 58f377b5..442f3470 100644
--- a/components/squeezelite/display.c
+++ b/components/squeezelite/display.c
@@ -56,16 +56,32 @@ struct grfg_packet {
#pragma pack(pop)
static struct scroller_s {
- TaskHandle_t task;
- bool active;
+ // copy of grfs content
u8_t screen, direction;
u32_t pause, speed;
- u16_t by, mode, width, scroll_width;
+ u16_t by, mode, full_width, window_width;
u16_t max, size;
+ // scroller management & sharing between grfg and scrolling task
+ TaskHandle_t task;
u8_t *scroll_frame, *back_frame;
+ bool active, updated;
+ u8_t *scroll_ptr;
+ int scroll_len, scroll_step;
} scroller;
+/*
+ ANIM_SCREEN_1 => end of first scroll on screen 1
+ ANIM_SCREEN_2 => end of first scroll on screen 2
+ ANIM_SCROLL_ONCE | ANIM_SCREEN_1 => end of scroll once on screen 1
+ ANIM_SCROLL_ONCE | ANIM_SCREEN_2 => end of scroll once on screen 2
+*/
+#define ANIM_TRANSITION 0x01 // A transition animation has finished
+#define ANIM_SCROLL_ONCE 0x02
+#define ANIM_SCREEN_1 0x04
+#define ANIM_SCREEN_2 0x08
+
#define SCROLL_STACK_SIZE 2048
+
#define LINELEN 40
#define HEIGHT 32
@@ -98,12 +114,18 @@ static void scroll_task(void* arg);
grfd
W: screen number
W: width of scrollable area in pixels
-
-ANIC flags
-ANIM_TRANSITION 0x01 # A transition animation has finished
-ANIM_SCROLL_ONCE 0x02 # A scrollonce has finished
-ANIM_SCREEN_1 0x04 # For scrollonce only, screen 1 was scrolling
-ANIM_SCREEN_2 0x08 # For scrollonce only, screen 2 was scrolling
+ anic ( two versions, don't know what to chose)
+ B: flag
+ ANIM_TRANSITION (0x01) - transition animation has finished (previous use of ANIC)
+ ANIM_SCREEN_1 (0x04) - end of first scroll on screen 1
+ ANIM_SCREEN_2 (0x08) - end of first scroll on screen 2
+ ANIM_SCROLL_ONCE (0x02) | ANIM_SCREEN_1 (0x04) - end of scroll once on screen 1
+ ANIM_SCROLL_ONCE (0x02) | ANIM_SCREEN_2 (0x08) - end of scroll once on screen 2
+ - or -
+ ANIM_TRANSITION 0x01 # A transition animation has finished
+ ANIM_SCROLL_ONCE 0x02 # A scrollonce has finished
+ ANIM_SCREEN_1 0x04 # For scrollonce only, screen 1 was scrolling
+ ANIM_SCREEN_2 0x08 # For scrollonce only, screen 2 was scrolling
*/
/****************************************************************************************
@@ -282,10 +304,14 @@ static void vfdc_handler( u8_t *_data, int bytes_read) {
* Process graphic display data
*/
static void grfe_handler( u8_t *data, int len) {
- scroller.active = false;
xSemaphoreTake(display_sem, portMAX_DELAY);
+
+ scroller.active = false;
display->draw_cbr(data + sizeof(struct grfe_packet), HEIGHT);
+
xSemaphoreGive(display_sem);
+
+ LOG_DEBUG("grfe frame %u", len);
}
/****************************************************************************************
@@ -323,21 +349,30 @@ static void grfs_handler(u8_t *data, int len) {
htons(pkt->width), // total width of animation
htons(pkt->offset) // offset if multiple packets are sent
);
+
+ // new grfs frame, build scroller info
+ if (!offset) {
+ // use the display as a general lock
+ xSemaphoreTake(display_sem, portMAX_DELAY);
- // copy scroll parameters
- scroller.screen = pkt->screen;
- scroller.direction = pkt->direction;
- scroller.pause = htonl(pkt->pause);
- scroller.speed = htonl(pkt->speed);
- scroller.by = htons(pkt->by);
- scroller.mode = htons(pkt->mode);
- scroller.width = htons(pkt->width);
+ // copy & set scroll parameters
+ scroller.screen = pkt->screen;
+ scroller.direction = pkt->direction;
+ scroller.pause = htonl(pkt->pause);
+ scroller.speed = htonl(pkt->speed);
+ scroller.by = htons(pkt->by);
+ scroller.mode = htons(pkt->mode);
+ scroller.full_width = htons(pkt->width);
+ scroller.updated = scroller.active = true;
- // copy scroll frame data
+ xSemaphoreGive(display_sem);
+ }
+
+ // copy scroll frame data (no semaphore needed)
if (scroller.size + size < scroller.max) {
memcpy(scroller.scroll_frame + offset, data + sizeof(struct grfs_packet), size);
scroller.size = offset + size;
- LOG_INFO("scroller size now %u", scroller.size);
+ LOG_INFO("scroller current size %u", scroller.size);
} else {
LOG_INFO("scroller too larger %u/%u", scroller.size + size, scroller.max);
}
@@ -349,76 +384,112 @@ static void grfs_handler(u8_t *data, int len) {
static void grfg_handler(u8_t *data, int len) {
struct grfg_packet *pkt = (struct grfg_packet*) data;
- memcpy(scroller.back_frame, data + sizeof(struct grfg_packet), len - sizeof(struct grfg_packet));
- scroller.scroll_width = htons(pkt->width);
- scroller.active = true;
- vTaskResume(scroller.task);
-
LOG_INFO("gfrg s:%hu w:%hu (len:%u)", htons(pkt->screen), htons(pkt->width), len);
+
+ memcpy(scroller.back_frame, data + sizeof(struct grfg_packet), len - sizeof(struct grfg_packet));
+ scroller.window_width = htons(pkt->width);
+
+ xSemaphoreTake(display_sem, portMAX_DELAY);
+
+ // can't be in grfs as we need full size & scroll_width
+ if (scroller.updated) {
+ scroller.scroll_len = display->width * display->height / 8 - (display->width - scroller.window_width) * display->height / 8;
+ if (scroller.direction == 1) {
+ scroller.scroll_ptr = scroller.scroll_frame;
+ scroller.scroll_step = scroller.by * display->height / 8;
+ } else {
+ scroller.scroll_ptr = scroller.scroll_frame + scroller.size - scroller.scroll_len;
+ scroller.scroll_step = -scroller.by * display->height / 8;
+ }
+
+ scroller.updated = false;
+ }
+
+ if (!scroller.active) {
+ // this is a background update and scroller has been finished, so need to update here
+ u8_t *frame = malloc(display->width * display->height / 8);
+ memcpy(frame, scroller.back_frame, display->width * display->height / 8);
+ for (int i = 0; i < scroller.scroll_len; i++) frame[i] |= scroller.scroll_ptr[i];
+ display->draw_cbr(frame, HEIGHT);
+ free(frame);
+ LOG_DEBUG("direct drawing");
+ }
+ else {
+ // if we just got a content update, let the scroller manage the screen
+ LOG_INFO("resuming scrolling task");
+ vTaskResume(scroller.task);
+ }
+
+ xSemaphoreGive(display_sem);
}
/****************************************************************************************
* Scroll task
*/
static void scroll_task(void *args) {
- u8_t *scroll_ptr, *frame;
- bool active = false;
+ u8_t *frame = NULL;
int len = display->width * display->height / 8;
- int scroll_len, scroll_step;
-
+
while (1) {
- if (!active) vTaskSuspend(NULL);
-
- // restart at the beginning - I don't know what right scrolling means ...
- scroll_len = len - (display->width - scroller.scroll_width) * display->height / 8;
- if (scroller.direction == 1) {
- scroll_ptr = scroller.scroll_frame;
- scroll_step = scroller.by * display->height / 8;
- } else {
- scroll_ptr = scroller.scroll_frame + scroller.size - scroll_len;
- scroll_step = -scroller.by * display->height / 8;
- }
-
- frame = malloc(display->width * display->height / 8);
-
- // scroll required amount of columns (within the window)
- while (scroller.direction == 1 ? (scroll_ptr <= scroller.scroll_frame + scroller.size - scroll_step - len) :
- (scroll_ptr + scroll_step >= scroller.scroll_frame) ) {
- // build a combined frame
- memcpy(frame, scroller.back_frame, len);
- for (int i = 0; i < scroll_len; i++) frame[i] |= scroll_ptr[i];
- scroll_ptr += scroll_step;
-
+ xSemaphoreTake(display_sem, portMAX_DELAY);
+
+ // suspend ourselves if nothing to do, grfg will wake us up
+ if (!scroller.active) {
+ xSemaphoreGive(display_sem);
+ vTaskSuspend(NULL);
xSemaphoreTake(display_sem, portMAX_DELAY);
- active = scroller.active;
-
- if (!active) {
- LOG_INFO("scrolling interrupted");
- xSemaphoreGive(display_sem);
- break;
- }
+ }
+
+ // lock screen & active status
+ frame = malloc(display->width * display->height / 8);
+
+ // scroll required amount of columns (within the window)
+ while (scroller.direction == 1 ? (scroller.scroll_ptr <= scroller.scroll_frame + scroller.size - scroller.scroll_step - len) :
+ (scroller.scroll_ptr + scroller.scroll_step >= scroller.scroll_frame) ) {
+ // don't do anything if we have aborted
+ if (!scroller.active) break;
+
+ // scroll required amount of columns (within the window)
+ memcpy(frame, scroller.back_frame, display->width * display->height / 8);
+ for (int i = 0; i < scroller.scroll_len; i++) frame[i] |= scroller.scroll_ptr[i];
+ scroller.scroll_ptr += scroller.scroll_step;
display->draw_cbr(frame, HEIGHT);
+
xSemaphoreGive(display_sem);
usleep(scroller.speed * 1000);
+ xSemaphoreTake(display_sem, portMAX_DELAY);
}
- if (active) {
- // build default screen
+ // done with scrolling cycle reset scroller ptr
+ scroller.scroll_ptr = scroller.scroll_frame + (scroller.direction == 2 ? scroller.size - scroller.scroll_len : 0);
+
+ // scrolling done, update screen and see if we need to continue
+ if (scroller.active) {
memcpy(frame, scroller.back_frame, len);
- for (int i = 0; i < scroll_len; i++) frame[i] |= scroller.scroll_frame[i];
- xSemaphoreTake(display_sem, portMAX_DELAY);
- display->draw_cbr(frame, HEIGHT);
+ for (int i = 0; i < scroller.scroll_len; i++) frame[i] |= scroller.scroll_ptr[i];
+ display->draw_cbr(frame, HEIGHT);
+ free(frame);
+
+ // see if we need to pause or if we are done
+ if (scroller.mode) {
+ scroller.active = false;
+ xSemaphoreGive(display_sem);
+ //sendANIC(ANIM_SCROLL_ONCE | ANIM_SCREEN_1);
+ LOG_INFO("scroll-once terminated");
+ } else {
+ xSemaphoreGive(display_sem);
+ usleep(scroller.pause * 1000);
+ LOG_DEBUG("scroll cycle done, pausing for %u (ms)", scroller.pause);
+ }
+ } else {
+ free(frame);
xSemaphoreGive(display_sem);
-
- // pause for required time and continue (or not)
- usleep(scroller.pause * 1000);
- active = (scroller.mode == 0);
+ LOG_INFO("scroll aborted");
}
-
- free(frame);
}
}
+
diff --git a/plugin/SqueezeESP32.zip b/plugin/SqueezeESP32.zip
index d9a21459..0a05ba23 100644
Binary files a/plugin/SqueezeESP32.zip and b/plugin/SqueezeESP32.zip differ
diff --git a/plugin/SqueezeESP32/SqueezeESP32.zip b/plugin/SqueezeESP32/SqueezeESP32.zip
new file mode 100644
index 00000000..0a05ba23
Binary files /dev/null and b/plugin/SqueezeESP32/SqueezeESP32.zip differ
diff --git a/plugin/SqueezeESP32/install.xml b/plugin/SqueezeESP32/install.xml
index 755b1edd..f0689582 100644
--- a/plugin/SqueezeESP32/install.xml
+++ b/plugin/SqueezeESP32/install.xml
@@ -3,8 +3,8 @@
enabled
philippe_44@outlook.com
- *
- *.*
+ 7.5
+ *
SlimServer
PLUGIN_SQUEEZEESP32
diff --git a/plugin/repo.xml b/plugin/repo.xml
index 65171627..a98a12ce 100644
--- a/plugin/repo.xml
+++ b/plugin/repo.xml
@@ -1,10 +1,10 @@
-
+
https://github.com/sle118/squeezelite-esp32
Philippe
- a1d676e7a3a2d241d17a39aff05bcb8377565a76
+ 0d5d5101edf534a6eaac8e42cec88532011976a5
philippe_44@outlook.com
SqueezeESP32 additional player id (100)
http://github.com/sle118/squeezelite-esp32/raw/master/plugin/SqueezeESP32.zip