From c2d3a0ae67e44b3ea7042cce879dbc8898eb42cd Mon Sep 17 00:00:00 2001 From: Anthony Rabine Date: Wed, 2 Aug 2023 15:43:42 +0200 Subject: [PATCH] fix: mailbox buffer type, load story, button events (WIP) --- .../raspberry-pico-w/pico_hal_wrapper.c | 50 +++++++--- software/system/fs_task.c | 81 +++++++++------ software/system/fs_task.h | 2 + software/system/hmi_task.c | 2 +- software/system/ost_hal.h | 26 +++-- software/system/vm_task.c | 99 ++++++++++++++++--- software/system/vm_task.h | 2 +- story-editor/src/story_project.cpp | 9 +- 8 files changed, 197 insertions(+), 74 deletions(-) diff --git a/software/platform/raspberry-pico-w/pico_hal_wrapper.c b/software/platform/raspberry-pico-w/pico_hal_wrapper.c index 00935c1..e7fe221 100644 --- a/software/platform/raspberry-pico-w/pico_hal_wrapper.c +++ b/software/platform/raspberry-pico-w/pico_hal_wrapper.c @@ -62,6 +62,7 @@ const uint8_t SD_CARD_PRESENCE = 24; static __attribute__((aligned(8))) pio_i2s i2s; static volatile uint32_t msTicks = 0; static audio_ctx_t audio_ctx; +static ost_button_callback_t ButtonCallback = NULL; // =========================================================================================================== // PROTOTYPES @@ -79,15 +80,38 @@ void ost_system_delay_ms(uint32_t delay) busy_wait_ms(delay); } +static uint32_t DebounceTs = 0; +static bool IsDebouncing = false; +static uint32_t ButtonsState = 0; +static uint32_t ButtonsStatePrev = 0; + void gpio_callback(uint gpio, uint32_t events) { static bool one_time = true; - // if (one_time) + if (events & GPIO_IRQ_EDGE_FALL) { - one_time = false; - // debouncer - debug_printf("G\n"); + DebounceTs = time_us_32() / 1000; + IsDebouncing = true; + } + else if (IsDebouncing) + { + IsDebouncing = false; + uint32_t current = time_us_32() / 1000; + if (current - DebounceTs > 50) + { + if (gpio_get(ROTARY_BUTTON)) + { + ButtonsState |= OST_BUTTON_OK; + } + + if ((ButtonsStatePrev != ButtonsState) && (ButtonCallback != NULL)) + { + ButtonCallback(ButtonsState); + } + + ButtonsStatePrev = ButtonsState; + } } } @@ -146,7 +170,7 @@ void ost_system_initialize() gpio_set_dir(ROTARY_BUTTON, GPIO_IN); gpio_disable_pulls(ROTARY_BUTTON); - gpio_set_irq_enabled_with_callback(ROTARY_BUTTON, GPIO_IRQ_EDGE_FALL, true, &gpio_callback); + gpio_set_irq_enabled_with_callback(ROTARY_BUTTON, GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE, true, &gpio_callback); //------------------- Init SDCARD gpio_init(SD_CARD_CS); @@ -203,16 +227,16 @@ uint32_t ost_system_stopwatch_stop() return (stopwatch_end_time - stopwatch_start_time); } +void ost_button_register_callback(ost_button_callback_t cb) +{ + ButtonCallback = cb; +} + int ost_hal_gpio_get(ost_hal_gpio_t gpio) { int value = 0; switch (gpio) { - case OST_GPIO_ROTARY_A: - value = gpio_get(ROTARY_A); - break; - case OST_GPIO_ROTARY_B: - value = gpio_get(ROTARY_B); break; default: break; @@ -231,10 +255,6 @@ void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value) case OST_GPIO_DEBUG_PIN: gpio_put(DEBUG_PIN, value); break; - - // Nothing to do for these inputes - case OST_GPIO_ROTARY_A: - case OST_GPIO_ROTARY_B: default: break; } @@ -245,7 +265,7 @@ void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value) // ---------------------------------------------------------------------------- void ost_hal_sdcard_set_slow_clock() { - spi_set_baudrate(spi0, 10000); + spi_set_baudrate(spi0, 1000000UL); } void ost_hal_sdcard_set_fast_clock() diff --git a/software/system/fs_task.c b/software/system/fs_task.c index b70e2a6..65f92b8 100644 --- a/software/system/fs_task.c +++ b/software/system/fs_task.c @@ -45,7 +45,9 @@ typedef struct { fs_state_t ev; uint8_t *mem; - char *filename; + ost_button_t button; + char *image; + char *sound; } ost_fs_event_t; // =========================================================================================================== @@ -58,7 +60,7 @@ static qor_mbox_t AudioMailBox; static ost_audio_event_t wake_up; -static ost_audio_event_t AudioQueue[10]; +static ost_audio_event_t *AudioQueue[10]; static int dbg_state = 0; @@ -66,7 +68,7 @@ static fs_state_t FsState = FS_WAIT_FOR_EVENT; static qor_mbox_t FsMailBox; -static ost_fs_event_t FsEventQueue[10]; +static ost_fs_event_t *FsEventQueue[10]; static ost_context_t OstContext; @@ -81,7 +83,7 @@ static void audio_callback(void) qor_mbox_notify(&AudioMailBox, (void **)&wake_up, QOR_MBOX_OPTION_SEND_BACK); } -void show_duration(uint32_t millisecondes) +static void show_duration(uint32_t millisecondes) { uint32_t minutes, secondes, reste; @@ -95,9 +97,9 @@ void show_duration(uint32_t millisecondes) debug_printf("Temps : %d minutes, %d secondes, %d millisecondes\r\n", minutes, secondes, reste); } -void play_sound_file(const char *filename) +static void play_sound_file(const char *filename) { - debug_printf("\r\n-------------------------------------------------------\r\nPlaying: out2.wav\r\n"); + debug_printf("\r\n-------------------------------------------------------\r\nPlaying: %s\r\n", filename); ost_system_stopwatch_start(); ost_audio_play(filename); @@ -148,18 +150,26 @@ void FsTask(void *args) switch (FsState) { case FS_PLAY_SOUND: - ScratchFile[STORY_DIR_OFFSET] = 0; - strcat(ScratchFile, SoundsDir); - strcat(ScratchFile, OstContext.sound); - play_sound_file(ScratchFile); + if (OstContext.sound != NULL) + { + ScratchFile[STORY_DIR_OFFSET] = 0; + strcat(ScratchFile, SoundsDir); + strcat(ScratchFile, OstContext.sound); + play_sound_file(ScratchFile); + } FsState = FS_WAIT_FOR_EVENT; break; case FS_DISPLAY_IMAGE: - ScratchFile[STORY_DIR_OFFSET] = 0; - strcat(ScratchFile, ImagesDir); - strcat(ScratchFile, OstContext.image); - filesystem_display_image(ScratchFile); + if (OstContext.image != NULL) + { + ScratchFile[STORY_DIR_OFFSET] = 0; + strcat(ScratchFile, ImagesDir); + strcat(ScratchFile, OstContext.image); + + filesystem_display_image(ScratchFile); + } + if (OstContext.sound != NULL) { FsState = FS_PLAY_SOUND; @@ -180,19 +190,7 @@ void FsTask(void *args) memcpy(&ScratchFile[1], OstContext.uuid, UUID_SIZE); ScratchFile[1 + UUID_SIZE] = 0; - // first, display image, then sound - if (OstContext.image != NULL) - { - FsState = FS_DISPLAY_IMAGE; - } - else if (OstContext.sound != NULL) - { - FsState = FS_PLAY_SOUND; - } - else - { - FsState = FS_WAIT_FOR_EVENT; - } + FsState = FS_DISPLAY_IMAGE; // Always display image (then sound), if there is one } else { @@ -200,8 +198,11 @@ void FsTask(void *args) } break; case FS_LOAD_STORY: - filesystem_load_rom(fs_ev->mem, fs_ev->filename); + ScratchFile[STORY_DIR_OFFSET] = 0; + strcat(ScratchFile, "/story.c32"); + filesystem_load_rom(fs_ev->mem, ScratchFile); // ROM loaded, execute story + vm_task_start_story(); FsState = FS_WAIT_FOR_EVENT; break; @@ -212,6 +213,8 @@ void FsTask(void *args) { // valid event, accept it FsState = fs_ev->ev; + OstContext.image = fs_ev->image; + OstContext.sound = fs_ev->sound; } else { @@ -226,12 +229,30 @@ void FsTask(void *args) void fs_task_scan_index() { static ost_fs_event_t ScanIndexEv = { - .ev = FS_LOAD_INDEX, - .filename = NULL}; + .ev = FS_LOAD_INDEX}; qor_mbox_notify(&FsMailBox, (void **)&ScanIndexEv, QOR_MBOX_OPTION_SEND_BACK); } +void fs_task_load_story(uint8_t *mem) +{ + static ost_fs_event_t LoadRomxEv = { + .ev = FS_LOAD_STORY}; + + LoadRomxEv.mem = mem; + qor_mbox_notify(&FsMailBox, (void **)&LoadRomxEv, QOR_MBOX_OPTION_SEND_BACK); +} + +void fs_task_media_start(char *image, char *sound) +{ + static ost_fs_event_t MediaStartEv = { + .ev = FS_DISPLAY_IMAGE}; + + MediaStartEv.image = image; + MediaStartEv.sound = sound; + qor_mbox_notify(&FsMailBox, (void **)&MediaStartEv, QOR_MBOX_OPTION_SEND_BACK); +} + void fs_task_initialize() { qor_mbox_init(&AudioMailBox, (void **)&AudioQueue, 10); diff --git a/software/system/fs_task.h b/software/system/fs_task.h index 7da90c8..5a116f4 100644 --- a/software/system/fs_task.h +++ b/software/system/fs_task.h @@ -3,5 +3,7 @@ void fs_task_scan_index(); void fs_task_initialize(); +void fs_task_load_story(uint8_t *mem); +void fs_task_media_start(char *image, char *sound); #endif // FS_TASK_H diff --git a/software/system/hmi_task.c b/software/system/hmi_task.c index aef4a76..f20c3dc 100644 --- a/software/system/hmi_task.c +++ b/software/system/hmi_task.c @@ -49,7 +49,7 @@ static qor_mbox_t HmiMailBox; static ost_hmi_event_t HmiEvent; -static ost_hmi_event_t HmiQueue[10]; +static ost_hmi_event_t *HmiQueue[10]; static ost_system_state_t OstState = OST_SYS_WAIT_INDEX; diff --git a/software/system/ost_hal.h b/software/system/ost_hal.h index 4a68e84..13a63d8 100644 --- a/software/system/ost_hal.h +++ b/software/system/ost_hal.h @@ -10,11 +10,6 @@ extern "C" #define OST_ID_SPI_FOR_SDCARD 0 -#define portDISABLE_INTERRUPTS() __asm volatile("csrc mstatus, 8") -#define portENABLE_INTERRUPTS() __asm volatile("csrs mstatus, 8") - -#define portNOP() __asm volatile(" nop ") - // ---------------------------------------------------------------------------- // SHARED TYPES // ---------------------------------------------------------------------------- @@ -35,31 +30,44 @@ extern "C" typedef enum { - OST_GPIO_ROTARY_A, - OST_GPIO_ROTARY_B, OST_GPIO_DEBUG_LED, - OST_GPIO_DEBUG_PIN, + OST_GPIO_DEBUG_PIN } ost_hal_gpio_t; + typedef enum + { + OST_BUTTON_OK = 0x01, + OST_BUTTON_HOME = 0x02, + OST_BUTTON_PAUSE = 0x04, + OST_BUTTON_VOLUME_UP = 0x08, + OST_BUTTON_VOLUME_DOWN = 0x10 + } ost_button_t; + // ---------------------------------------------------------------------------- // HIGH LEVEL API // ---------------------------------------------------------------------------- + // System API void ost_system_initialize(); void system_putc(char ch); void ost_system_delay_ms(uint32_t delay); - void ost_system_stopwatch_start(); uint32_t ost_system_stopwatch_stop(); + // Audio API void ost_audio_play(const char *filename); void ost_audio_stop(); int ost_audio_process(); typedef void (*ost_audio_callback_t)(void); void ost_audio_register_callback(ost_audio_callback_t cb); + // Buttons APU + typedef void (*ost_button_callback_t)(uint32_t flags); + void ost_button_register_callback(ost_button_callback_t cb); + // ---------------------------------------------------------------------------- // GPIO HAL // ---------------------------------------------------------------------------- + int ost_hal_gpio_get(ost_hal_gpio_t gpio); void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value); diff --git a/software/system/vm_task.c b/software/system/vm_task.c index bbbd1b1..b875500 100644 --- a/software/system/vm_task.c +++ b/software/system/vm_task.c @@ -15,24 +15,35 @@ // =========================================================================================================== // DEFINITIONS // =========================================================================================================== -#define VM_EV_NO_EVENT 0 -#define VM_EV_START_STORY_EVENT 0xA1 +typedef enum +{ + VM_EV_NO_EVENT = 0, + VM_EV_START_STORY_EVENT = 0xA1, + VM_EV_BUTTON_EVENT = 0x88 +} ost_vm_ev_type_t; typedef struct { - uint8_t ev; + ost_vm_ev_type_t ev; const char *story_dir; + uint32_t button_mask; } ost_vm_event_t; +typedef enum +{ + OST_VM_STATE_WAIT_EVENT, + OST_VM_STATE_HOME, + OST_VM_STATE_RUN_STORY, +} ost_vm_state_t; + // =========================================================================================================== // PRIVATE GLOBAL VARIABLES // =========================================================================================================== static qor_tcb_t VmTcb; static uint32_t VmStack[4096]; static qor_mbox_t VmMailBox; -static ost_vm_event_t VmQueue[10]; +static ost_vm_event_t *VmQueue[10]; -static ost_vm_event_t VmStartEvent; static uint8_t m_rom_data[16 * 1024]; static uint8_t m_ram_data[16 * 1024]; static chip32_ctx_t m_chip32_ctx; @@ -40,6 +51,8 @@ static char CurrentStory[260]; // Current story path static char ImageFile[260]; static char SoundFile[260]; +static ost_vm_state_t VmState = OST_VM_STATE_WAIT_EVENT; + // =========================================================================================================== // VIRTUAL MACHINE TASK // =========================================================================================================== @@ -67,11 +80,15 @@ uint8_t vm_syscall(chip32_ctx_t *ctx, uint8_t code) // Media if (code == 1) // Execute media { + char *image_ptr = NULL; + char *sound_ptr = NULL; if (m_chip32_ctx.registers[R0] != 0) { // image file name address is in R0 // QString imageFile = m_model.BuildFullImagePath(GetFileNameFromMemory(m_chip32_ctx.registers[R0])); // m_ostHmiDock->SetImage(imageFile); + get_file_from_memory(ImageFile, m_chip32_ctx.registers[R0]); + image_ptr = ImageFile; } else { @@ -84,7 +101,10 @@ uint8_t vm_syscall(chip32_ctx_t *ctx, uint8_t code) // QString soundFile = m_model.BuildFullSoundPath(GetFileNameFromMemory(m_chip32_ctx.registers[R1])); // qDebug() << ", Sound: " << soundFile; // m_model.PlaySoundFile(soundFile); + get_file_from_memory(SoundFile, m_chip32_ctx.registers[R1]); + sound_ptr = SoundFile; } + fs_task_media_start(image_ptr, sound_ptr); retCode = SYSCALL_RET_WAIT_EV; // set the VM in pause } // WAIT EVENT bits: @@ -105,6 +125,16 @@ uint8_t vm_syscall(chip32_ctx_t *ctx, uint8_t code) return retCode; } +static void button_callback(uint32_t flags) +{ + static ost_vm_event_t ButtonEv = { + .ev = VM_EV_BUTTON_EVENT, + .story_dir = NULL}; + + ButtonEv.button_mask = flags; + qor_mbox_notify(&VmMailBox, (void **)&ButtonEv, QOR_MBOX_OPTION_SEND_BACK); +} + void VmTask(void *args) { // VM Initialize @@ -122,36 +152,73 @@ void VmTask(void *args) chip32_result_t run_result; ost_vm_event_t *e = NULL; + uint32_t res = 0; + bool isHome = true; while (1) { - uint32_t res = qor_mbox_wait(&VmMailBox, (void **)&e, 300); // On devrait recevoir un message toutes les 3ms (durée d'envoi d'un buffer I2S) - if (res == QOR_MBOX_OK) + switch (VmState) { - if (VmStartEvent.ev == VM_EV_START_STORY_EVENT) + case OST_VM_STATE_RUN_STORY: + do { - // Launch the execution of a story - chip32_initialize(&m_chip32_ctx); + run_result = chip32_step(&m_chip32_ctx); - do + } while (run_result == VM_OK); + + // pour le moment, dans tous les cas on attend un événement + // Que ce soit par erreur, ou l'attente un appui boutton... + VmState = OST_VM_STATE_WAIT_EVENT; + break; + + case OST_VM_STATE_WAIT_EVENT: + default: + res = qor_mbox_wait(&VmMailBox, (void **)&e, 300); // On devrait recevoir un message toutes les 3ms (durée d'envoi d'un buffer I2S) + + if (res == QOR_MBOX_OK) + { + + if (isHome) { - run_result = chip32_step(&m_chip32_ctx); - } while (run_result != VM_OK); + if (e->ev == VM_EV_BUTTON_EVENT) + { + if ((e->button_mask & OST_BUTTON_OK) == OST_BUTTON_OK) + { + // Load story from disk + debug_printf("Clicked OK\r\n"); + fs_task_load_story(m_rom_data); + } + } + else if (e->ev == VM_EV_START_STORY_EVENT) + { + // Launch the execution of a story + chip32_initialize(&m_chip32_ctx); + VmState = OST_VM_STATE_RUN_STORY; + } + } + else + { + } } + break; } } } -void vm_task_start_story(const char *story_directory) +void vm_task_start_story() { - VmStartEvent.story_dir = story_directory; + static ost_vm_event_t VmStartEvent; + VmStartEvent.ev = VM_EV_START_STORY_EVENT; qor_mbox_notify(&VmMailBox, (void **)&VmStartEvent, QOR_MBOX_OPTION_SEND_BACK); } void vm_task_initialize() { - VmStartEvent.ev = VM_EV_START_STORY_EVENT; + VmState = OST_VM_STATE_WAIT_EVENT; + qor_mbox_init(&VmMailBox, (void **)&VmQueue, 10); qor_create_thread(&VmTcb, VmTask, VmStack, sizeof(VmStack) / sizeof(VmStack[0]), VM_TASK_PRIORITY, "VmTask"); + + ost_button_register_callback(button_callback); } diff --git a/software/system/vm_task.h b/software/system/vm_task.h index c1d470e..4201702 100644 --- a/software/system/vm_task.h +++ b/software/system/vm_task.h @@ -1,7 +1,7 @@ #ifndef VM_TASK_H #define VM_TASK_H -void vm_task_start_story(const char *story_directory); +void vm_task_start_story(); void vm_task_initialize(); #endif // VM_TASK_H diff --git a/story-editor/src/story_project.cpp b/story-editor/src/story_project.cpp index a744e7b..2f7e0fb 100644 --- a/story-editor/src/story_project.cpp +++ b/story-editor/src/story_project.cpp @@ -72,8 +72,13 @@ void StoryProject::SaveStory(const std::vector &m_program) tlv.add_object(3); tlv.add_string(m_uuid.c_str(), m_uuid.size()); // uuid - tlv.add_string(m_titleImage.c_str(), m_titleImage.size()); // title image - tlv.add_string(m_titleSound.c_str(), m_titleSound.size()); // title sound + + // Title image + std::string image = RemoveFileExtension(m_titleImage) + ".qoi"; + tlv.add_string(image.c_str(), image.size()); + + std::string sound = RemoveFileExtension(m_titleSound) + ".wav"; + tlv.add_string(sound.c_str(), sound.size()); // title sound } void StoryProject::Initialize(const std::string &file_path)