|
@@ -29,7 +29,7 @@
|
|
|
// here we should include all possible drivers
|
|
|
extern struct display_s SSD1306_display;
|
|
|
|
|
|
-struct display_s *display;
|
|
|
+struct display_s *display = NULL;
|
|
|
|
|
|
static const char *TAG = "display";
|
|
|
|
|
@@ -72,6 +72,7 @@ void display_init(char *welcome) {
|
|
|
init = true;
|
|
|
ESP_LOGI(TAG, "Display initialization successful");
|
|
|
} else {
|
|
|
+ display = NULL;
|
|
|
ESP_LOGE(TAG, "Display initialization failed");
|
|
|
}
|
|
|
} else {
|
|
@@ -103,7 +104,7 @@ void display_init(char *welcome) {
|
|
|
}
|
|
|
|
|
|
/****************************************************************************************
|
|
|
- * This is not really thread-safe as displayer_task might be in the middle of line drawing
|
|
|
+ * This is not thread-safe as displayer_task might be in the middle of line drawing
|
|
|
* but it won't crash (I think) and making it thread-safe would be complicated for a
|
|
|
* feature which is secondary (the LMS version of scrolling is thread-safe)
|
|
|
*/
|
|
@@ -128,11 +129,19 @@ static void displayer_task(void *args) {
|
|
|
if (scroll_sleep <= 10) {
|
|
|
// something to scroll (or we'll wake-up every pause ms ... no big deal)
|
|
|
if (*displayer.string && displayer.state == DISPLAYER_ACTIVE) {
|
|
|
- display->line(2, -displayer.offset, DISPLAY_CLEAR | DISPLAY_UPDATE, displayer.string);
|
|
|
xSemaphoreTake(displayer.mutex, portMAX_DELAY);
|
|
|
+
|
|
|
+ // need to work with local copies as we don't want to suspend caller
|
|
|
+ int offset = -displayer.offset;
|
|
|
+ char *string = strdup(displayer.string);
|
|
|
scroll_sleep = displayer.offset ? displayer.speed : displayer.pause;
|
|
|
displayer.offset = displayer.offset >= displayer.boundary ? 0 : (displayer.offset + min(displayer.by, displayer.boundary - displayer.offset));
|
|
|
- xSemaphoreGive(displayer.mutex);
|
|
|
+
|
|
|
+ xSemaphoreGive(displayer.mutex);
|
|
|
+
|
|
|
+ // now display using safe copies, can be lengthy
|
|
|
+ display->line(2, offset, DISPLAY_CLEAR | DISPLAY_UPDATE, string);
|
|
|
+ free(string);
|
|
|
} else {
|
|
|
scroll_sleep = DEFAULT_SLEEP;
|
|
|
}
|
|
@@ -149,8 +158,8 @@ static void displayer_task(void *args) {
|
|
|
displayer.tick = tick;
|
|
|
displayer.elapsed += elapsed / 1000;
|
|
|
xSemaphoreGive(displayer.mutex);
|
|
|
- if (displayer.elapsed < 3600) sprintf(counter, "%2u:%02u", displayer.elapsed / 60, displayer.elapsed % 60);
|
|
|
- else sprintf(counter, "%2u:%2u:%02u", displayer.elapsed / 3600, (displayer.elapsed % 3600) / 60, displayer.elapsed % 60);
|
|
|
+ if (displayer.elapsed < 3600) sprintf(counter, "%5u:%02u", displayer.elapsed / 60, displayer.elapsed % 60);
|
|
|
+ else sprintf(counter, "%2u:%02u:%02u", displayer.elapsed / 3600, (displayer.elapsed % 3600) / 60, displayer.elapsed % 60);
|
|
|
display->line(1, DISPLAY_RIGHT, (DISPLAY_CLEAR | DISPLAY_ONLY_EOL) | DISPLAY_UPDATE, counter);
|
|
|
timer_sleep = 1000;
|
|
|
} else timer_sleep = max(1000 - elapsed, 0);
|
|
@@ -171,6 +180,10 @@ void displayer_metadata(char *artist, char *album, char *title) {
|
|
|
char *string = displayer.string, *p;
|
|
|
int len = SCROLLABLE_SIZE;
|
|
|
|
|
|
+ // need a display!
|
|
|
+ if (!display) return;
|
|
|
+
|
|
|
+ // just do title if there is no config set
|
|
|
if (!displayer.metadata_config) {
|
|
|
strncpy(displayer.string, title ? title : "", SCROLLABLE_SIZE);
|
|
|
return;
|
|
@@ -218,7 +231,7 @@ void displayer_metadata(char *artist, char *album, char *title) {
|
|
|
p = strchr(q + 1, '%');
|
|
|
}
|
|
|
} else {
|
|
|
- string = strdup(title ? title : "");
|
|
|
+ strncpy(string, title ? title : "", SCROLLABLE_SIZE);
|
|
|
}
|
|
|
|
|
|
// get optional scroll speed
|
|
@@ -232,11 +245,13 @@ void displayer_metadata(char *artist, char *album, char *title) {
|
|
|
xSemaphoreGive(displayer.mutex);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/****************************************************************************************
|
|
|
*
|
|
|
*/
|
|
|
void displayer_scroll(char *string, int speed) {
|
|
|
+ // need a display!
|
|
|
+ if (!display) return;
|
|
|
+
|
|
|
xSemaphoreTake(displayer.mutex, portMAX_DELAY);
|
|
|
|
|
|
if (speed) displayer.speed = speed;
|
|
@@ -252,10 +267,13 @@ void displayer_scroll(char *string, int speed) {
|
|
|
*
|
|
|
*/
|
|
|
void displayer_timer(enum displayer_time_e mode, int elapsed, int duration) {
|
|
|
+ // need a display!
|
|
|
+ if (!display) return;
|
|
|
+
|
|
|
xSemaphoreTake(displayer.mutex, portMAX_DELAY);
|
|
|
|
|
|
- if (elapsed >= 0) displayer.elapsed = elapsed;
|
|
|
- if (duration >= 0) displayer.duration = duration;
|
|
|
+ if (elapsed >= 0) displayer.elapsed = elapsed / 1000;
|
|
|
+ if (duration >= 0) displayer.duration = duration / 1000;
|
|
|
if (displayer.timer) displayer.tick = xTaskGetTickCount();
|
|
|
|
|
|
xSemaphoreGive(displayer.mutex);
|
|
@@ -267,6 +285,8 @@ void displayer_timer(enum displayer_time_e mode, int elapsed, int duration) {
|
|
|
void displayer_control(enum displayer_cmd_e cmd, ...) {
|
|
|
va_list args;
|
|
|
|
|
|
+ if (!display) return;
|
|
|
+
|
|
|
va_start(args, cmd);
|
|
|
xSemaphoreTake(displayer.mutex, portMAX_DELAY);
|
|
|
|