Skip to content

Commit ea64892

Browse files
committed
Added logic to decide if we run fallback or dynamic apps.
1 parent dcc28e3 commit ea64892

File tree

3 files changed

+247
-41
lines changed

3 files changed

+247
-41
lines changed

websocket/dynamic_js.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// dynamic_js.cpp
2+
3+
#include <Arduino.h>
4+
#include <WiFi.h>
5+
#include <FS.h>
6+
#include <SD_MMC.h>
7+
#include "pins_config.h"
8+
#include "rm67162.h"
9+
#include "lvgl_elk.h"
10+
11+
// A flag or state variable to indicate setup success or not.
12+
static bool dynamicJsSetupDone = false;
13+
static unsigned long lastRetryAttempt = 0; // If you want a timed retry
14+
15+
void dynamic_js_setup() {
16+
Serial.println("DYNAMIC_JS: Setting up Elk + script.js scenario...");
17+
18+
// 0) Remount SD card
19+
SD_MMC.setPins(PIN_SD_CLK, PIN_SD_CMD, PIN_SD_D0);
20+
if(!SD_MMC.begin("/sdcard", true, false, 20)) {
21+
Serial.println("Card Mount Failed => dynamic setup fails");
22+
dynamicJsSetupDone = false; // Mark as failed
23+
return;
24+
}
25+
26+
// 1) Wi-Fi (station mode)
27+
WiFi.mode(WIFI_STA);
28+
29+
// 2) LVGL display
30+
init_lvgl_display();
31+
32+
// 3) 'S' driver for normal SD usage
33+
init_lv_fs();
34+
35+
// 4) 'M' driver for memory usage (GIF)
36+
init_mem_fs();
37+
38+
// 5) Init memory storage for RamImage
39+
for (int i = 0; i < MAX_RAM_IMAGES; i++) {
40+
g_ram_images[i].used = false;
41+
g_ram_images[i].buffer = NULL;
42+
g_ram_images[i].size = 0;
43+
}
44+
45+
// 6) Create the Elk task
46+
xTaskCreatePinnedToCore(
47+
elk_task, // function pointer
48+
"ElkTask", // name of the task
49+
16384, // stack size in bytes (16KB)
50+
NULL, // parameter
51+
1, // priority
52+
NULL, // task handle
53+
1 // pin to core 1 (or 0 if you want)
54+
);
55+
56+
// If we reach here, assume success
57+
dynamicJsSetupDone = true;
58+
Serial.println("DYNAMIC_JS: setup done!");
59+
}
60+
61+
void dynamic_js_loop() {
62+
// If setup not done, try to do it (or re-do it)
63+
if(!dynamicJsSetupDone) {
64+
// Optionally limit how often we retry
65+
unsigned long now = millis();
66+
if(now - lastRetryAttempt > 5000) {
67+
lastRetryAttempt = now;
68+
Serial.println("DYNAMIC_JS: Trying dynamic_js_setup() again...");
69+
dynamic_js_setup();
70+
}
71+
}
72+
73+
// Otherwise, if setup *did* succeed, just wait or do minimal tasks
74+
delay(1000);
75+
}

websocket/fallback.cpp

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// fallback.cpp
2+
#include <Arduino.h>
3+
#include "lvgl.h"
4+
#include "rm67162.h"
5+
#include "notification.h" // Contains 'extern const lv_img_dsc_t notification;'
6+
7+
// External objects
8+
extern lv_disp_draw_buf_t draw_buf; // or create local if you prefer
9+
extern lv_color_t *buf; // or create local
10+
extern bool fallbackActive; // Exposed globally for your main
11+
12+
// The GIF from notification.h
13+
extern const lv_img_dsc_t notification;
14+
15+
// We'll keep these static to avoid collisions
16+
static lv_obj_t *label = nullptr;
17+
static lv_obj_t *gif = nullptr;
18+
19+
static void my_disp_flush_fallback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
20+
// Display flush provided by rm67162 or your custom driver
21+
// e.g.:
22+
uint32_t w = (area->x2 - area->x1 + 1);
23+
uint32_t h = (area->y2 - area->y1 + 1);
24+
lcd_PushColors(area->x1, area->y1, w, h, (uint16_t *)&color_p->full);
25+
lv_disp_flush_ready(disp);
26+
}
27+
28+
static void scroll_anim_cb(void *var, int32_t v) {
29+
lv_obj_set_y((lv_obj_t *)var, v);
30+
}
31+
32+
static void create_scroll_animation(lv_obj_t *obj, int32_t start, int32_t end, uint32_t duration) {
33+
lv_anim_t a;
34+
lv_anim_init(&a);
35+
lv_anim_set_var(&a, obj);
36+
lv_anim_set_values(&a, start, end);
37+
lv_anim_set_time(&a, duration);
38+
lv_anim_set_exec_cb(&a, scroll_anim_cb);
39+
lv_anim_set_path_cb(&a, lv_anim_path_ease_in_out);
40+
lv_anim_set_repeat_count(&a, 2); // Repeat twice
41+
42+
// When animation finishes, hide label, show GIF
43+
lv_anim_set_ready_cb(&a, [](lv_anim_t *anim) {
44+
lv_obj_t *obj = static_cast<lv_obj_t *>(anim->var);
45+
lv_obj_add_flag(obj, LV_OBJ_FLAG_HIDDEN); // Hide text
46+
lv_obj_clear_flag(gif, LV_OBJ_FLAG_HIDDEN);// Show GIF
47+
});
48+
lv_anim_start(&a);
49+
}
50+
51+
// ------------------------------------------------------------------
52+
// Fallback setup
53+
// ------------------------------------------------------------------
54+
void fallback_setup() {
55+
Serial.println("FALLBACK: Setting up LVGL + scrolling label + GIF...");
56+
57+
// 1) Minimal LVGL init if not already done
58+
lv_init();
59+
// 2) Screen on
60+
pinMode(PIN_LED, OUTPUT);
61+
digitalWrite(PIN_LED, HIGH);
62+
63+
// 3) Init your AMOLED driver, set rotation
64+
rm67162_init();
65+
lcd_setRotation(1);
66+
67+
// 4) Allocate buffer
68+
buf = (lv_color_t *)ps_malloc(sizeof(lv_color_t) * LVGL_LCD_BUF_SIZE);
69+
if(!buf) {
70+
Serial.println("FALLBACK: Buffer alloc failed");
71+
return;
72+
}
73+
74+
// 5) Initialize draw buffer
75+
lv_disp_draw_buf_init(&draw_buf, buf, NULL, LVGL_LCD_BUF_SIZE);
76+
77+
// 6) Register display driver
78+
static lv_disp_drv_t disp_drv;
79+
lv_disp_drv_init(&disp_drv);
80+
disp_drv.hor_res = 536;
81+
disp_drv.ver_res = 240;
82+
disp_drv.flush_cb = my_disp_flush_fallback;
83+
disp_drv.draw_buf = &draw_buf;
84+
lv_disp_drv_register(&disp_drv);
85+
86+
// 7) Style
87+
static lv_style_t style;
88+
lv_style_init(&style);
89+
lv_style_set_text_font(&style, &lv_font_montserrat_40);
90+
lv_style_set_text_color(&style, lv_color_white());
91+
lv_style_set_bg_color(&style, lv_color_black());
92+
lv_style_set_pad_all(&style, 5);
93+
lv_style_set_text_align(&style, LV_TEXT_ALIGN_CENTER);
94+
95+
// 8) Create label
96+
label = lv_label_create(lv_scr_act());
97+
lv_obj_add_style(label, &style, 0);
98+
lv_label_set_text(label,
99+
"This is fallback: a long text that will scroll automatically.\n"
100+
"Add more text to test scrolling.\n"
101+
"Eventually it shows a GIF afterwards."
102+
);
103+
lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP);
104+
lv_obj_set_width(label, 525);
105+
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
106+
107+
// 9) Create scroll animation (10 seconds for a full scroll)
108+
create_scroll_animation(label, 240, -lv_obj_get_height(label), 10000);
109+
110+
// 10) Create the GIF
111+
gif = lv_gif_create(lv_scr_act());
112+
lv_gif_set_src(gif, &notification);
113+
lv_obj_align(gif, LV_ALIGN_CENTER, 0, 0);
114+
115+
// Initially hide label, show GIF
116+
lv_obj_add_flag(label, LV_OBJ_FLAG_HIDDEN);
117+
lv_obj_clear_flag(gif, LV_OBJ_FLAG_HIDDEN);
118+
119+
Serial.println("FALLBACK: Setup complete");
120+
}
121+
122+
// ------------------------------------------------------------------
123+
// Fallback loop
124+
// ------------------------------------------------------------------
125+
void fallback_loop() {
126+
lv_timer_handler();
127+
128+
// If there's serial input, re-animate the label with new text
129+
if (Serial.available()) {
130+
String received = Serial.readStringUntil('\n');
131+
lv_label_set_text(label, received.c_str());
132+
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
133+
lv_obj_clear_flag(label, LV_OBJ_FLAG_HIDDEN);
134+
lv_obj_add_flag(gif, LV_OBJ_FLAG_HIDDEN);
135+
136+
create_scroll_animation(label, 240, -lv_obj_get_height(label), 10000);
137+
}
138+
}

websocket/websocket.ino

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,56 @@
11
#include <Arduino.h>
2+
#include <lvgl.h>
23
#include <WiFi.h>
34
#include <FS.h>
45
#include <SD_MMC.h>
56
#include <stdio.h>
6-
7-
// 1) Pin definitions + config
87
#include "pins_config.h"
98

10-
// 2) LVGL + display driver
11-
#include "rm67162.h" // Your custom display driver
12-
#include "lvgl_elk.h"
9+
// Include fallback & dynamic
10+
extern void fallback_setup();
11+
extern void fallback_loop();
12+
extern void dynamic_js_setup();
13+
extern void dynamic_js_loop();
1314

15+
// We'll share these with fallback.cpp
16+
lv_disp_draw_buf_t draw_buf;
17+
lv_color_t *buf = nullptr;
18+
bool fallbackActive = false;
1419

15-
/******************************************************************************
16-
* K) Arduino setup() & loop()
17-
******************************************************************************/
1820
void setup() {
1921
Serial.begin(115200);
2022
delay(2000);
2123

22-
// 1) Mount SD card
24+
// Try mounting SD
2325
SD_MMC.setPins(PIN_SD_CLK, PIN_SD_CMD, PIN_SD_D0);
24-
if(!SD_MMC.begin("/sdcard", true, false, 1000000)) {
25-
Serial.println("Card Mount Failed");
26+
bool cardMounted = SD_MMC.begin("/sdcard", true, false, 1000000);
27+
28+
if (!cardMounted) {
29+
// Fallback
30+
fallbackActive = true;
31+
fallback_setup();
2632
return;
2733
}
2834

29-
// 2) Wi-Fi (station mode)
30-
WiFi.mode(WIFI_STA);
31-
32-
// 3) Initialize LVGL display
33-
init_lvgl_display();
34-
35-
// 4) 'S' driver for normal SD usage
36-
init_lv_fs();
37-
38-
// 4b) 'M' driver for memory usage (GIF)
39-
init_mem_fs();
40-
41-
// 4c) Init Memory storage
42-
for (int i = 0; i < MAX_RAM_IMAGES; i++) {
43-
g_ram_images[i].used = false;
44-
g_ram_images[i].buffer = NULL;
45-
g_ram_images[i].size = 0;
35+
// Check if /script.js exists
36+
File f = SD_MMC.open("/script.js");
37+
if (!f) {
38+
// Fallback
39+
fallbackActive = true;
40+
f.close();
41+
fallback_setup();
42+
} else {
43+
// Use dynamic JS
44+
fallbackActive = false;
45+
f.close();
46+
dynamic_js_setup();
4647
}
47-
48-
// ***** Instead of calling Elk creation + script here,
49-
// ***** we spawn a new FreeRTOS task with a larger stack:
50-
xTaskCreatePinnedToCore(
51-
elk_task, // function pointer
52-
"ElkTask", // name of the task
53-
16384, // stack size in bytes (16KB)
54-
NULL, // parameter
55-
1, // priority
56-
NULL, // task handle
57-
1 // pin to core 1 (or 0 if you want)
58-
);
5948
}
6049

6150
void loop() {
62-
delay(1000);
51+
if (fallbackActive) {
52+
fallback_loop();
53+
} else {
54+
dynamic_js_loop();
55+
}
6356
}

0 commit comments

Comments
 (0)