#include #include #include #include #include #include #include #include #include #include #include #include "battery.h" #include "job.h" #include "term.h" #include "ui.h" #include "vfs/vfs.h" #include "wren_utils.h" static int tick_ctr = 0; static int shift_state = 0; static int alpha_state = 0; static int off_state = 0; static volatile int must_redraw; static int timer_redraw; static int callback_redraw(void) { must_redraw = 1; return TIMER_CONTINUE; } volatile int must_yield; jmp_buf sched_ctxbuf; static int timer_sched; static int callback_sched(void) { must_yield = 1; return TIMER_CONTINUE; } static void check_keyevents(void) { static uint16_t backlight_save; key_event_t kev = pollevent(); if (kev.type != KEYEV_DOWN) return; if (off_state) { if (kev.key != KEY_ACON) return; off_state = 0; // reset backlight r61524_set(0x5a1, backlight_save & 0x00ff); timer_start(timer_redraw); } term_kprintf("key event: key=0x%x mod=%d shift=%d alpha=%d", kev.key, kev.mod, kev.shift, kev.alpha); if (kev.key == KEY_SHIFT) shift_state = !shift_state; if (kev.key == KEY_ALPHA) alpha_state = !alpha_state; if (kev.key == KEY_ACON && shift_state) { timer_pause(timer_redraw); off_state = 1; // save, then turn backlight level off: // force to display something dclear(C_WHITE); dupdate(); // store the backlight pwm backlight_save = r61524_get(0x5a1) & 0x00ff; // force vram clear dclear(C_BLACK); dupdate(); dclear(C_BLACK); dupdate(); // force backlight pwm to 0 r61524_set(0x5a1, 0); shift_state = 0; alpha_state = 0; return; } if (kev.key == KEY_MENU && !shift_state && !alpha_state) { // TODO: print pause menu gint_osmenu(); } } __attribute__((noreturn)) static void halt(void) { term_kprint("SYSTEM HALTED"); set_statusbar(tick_ctr, shift_state, alpha_state, get_battery_voltage()); set_menubar(); dclear(C_BLACK); tgrid_display(); dupdate(); while (1) { getkey(); } } int main(int isappli, int optnum) { term_kprintf("main(%d, %d)", isappli, optnum); vfs_init(); halt(); timer_sched = timer_configure(TIMER_ANY, 10 * 1000, GINT_CALL(callback_sched)); // 100 Hz <=> 10 ms timer_redraw = timer_configure(TIMER_ANY, 31250, GINT_CALL(callback_redraw)); // 32 Hz timer_start(timer_redraw); // start a few jobs job_start("test_job_1", "System.print(\"inner start\")\n" "var i = 0\n" "while (i < 30000) {\n" " if ((i % 500) == 0) {\n" " System.write(\"vm 1: i=%(i)\\n\")\n" " }\n" " i = i + 1\n" "}\n" "System.print(\"inner end\")\n"); job_start("test_job_2", "System.print(\"inner start\")\n" "var i = 0\n" "while (i < 30000) {\n" " if ((i % 500) == 0) {\n" " System.write(\"vm 2: i=%(i)\\n\")\n" " }\n" " i = i + 1\n" "}\n" "System.print(\"inner end\")\n"); job_start("test_job_3", "System.print(\"inner start\")\n" "var i = 0\n" "while (i < 30000) {\n" " if ((i % 500) == 0) {\n" " System.write(\"vm 3: i=%(i)\\n\")\n" " }\n" " i = i + 1\n" "}\n" "System.print(\"inner end\")\n"); while (1) { // system routine check_keyevents(); if (off_state) { sleep(); continue; } tick_ctr++; if (must_redraw) { set_statusbar(tick_ctr, shift_state, alpha_state, get_battery_voltage()); set_menubar(); dclear(C_BLACK); tgrid_display(); dupdate(); must_redraw = 0; } // scheduler routine next_job(); if (current_job_id < 0) { term_kprint("all jobs ended"); break; } // first, backup current scheduler context const int ret = setjmp(sched_ctxbuf); switch (ret) { case 0: // resume job timer_start(timer_sched); must_yield = 0; job_resume(current_job_id); break; case 1: // term_kprintf("job(%d) yield", current_job_id); // pause timer during sheduler operations, we restart it before resuming a job timer_pause(timer_sched); // force garbage collect after each cycle job_GC(current_job_id); continue; break; case 2: term_kprintf("job(%d) exit", current_job_id); job_free(current_job_id); break; default: __builtin_unreachable(); term_kprint("SHOULD NOT BE REACHED!!!"); halt(); } } halt(); return 1; }