fix: mailbox buffer type, load story, button events (WIP)

This commit is contained in:
Anthony Rabine 2023-08-02 15:43:42 +02:00
parent 5bf26b500b
commit c2d3a0ae67
8 changed files with 197 additions and 74 deletions

View file

@ -62,6 +62,7 @@ const uint8_t SD_CARD_PRESENCE = 24;
static __attribute__((aligned(8))) pio_i2s i2s; static __attribute__((aligned(8))) pio_i2s i2s;
static volatile uint32_t msTicks = 0; static volatile uint32_t msTicks = 0;
static audio_ctx_t audio_ctx; static audio_ctx_t audio_ctx;
static ost_button_callback_t ButtonCallback = NULL;
// =========================================================================================================== // ===========================================================================================================
// PROTOTYPES // PROTOTYPES
@ -79,15 +80,38 @@ void ost_system_delay_ms(uint32_t delay)
busy_wait_ms(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) void gpio_callback(uint gpio, uint32_t events)
{ {
static bool one_time = true; static bool one_time = true;
// if (one_time) if (events & GPIO_IRQ_EDGE_FALL)
{ {
one_time = false; DebounceTs = time_us_32() / 1000;
// debouncer IsDebouncing = true;
debug_printf("G\n"); }
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_set_dir(ROTARY_BUTTON, GPIO_IN);
gpio_disable_pulls(ROTARY_BUTTON); 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 //------------------- Init SDCARD
gpio_init(SD_CARD_CS); gpio_init(SD_CARD_CS);
@ -203,16 +227,16 @@ uint32_t ost_system_stopwatch_stop()
return (stopwatch_end_time - stopwatch_start_time); 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 ost_hal_gpio_get(ost_hal_gpio_t gpio)
{ {
int value = 0; int value = 0;
switch (gpio) switch (gpio)
{ {
case OST_GPIO_ROTARY_A:
value = gpio_get(ROTARY_A);
break;
case OST_GPIO_ROTARY_B:
value = gpio_get(ROTARY_B);
break; break;
default: default:
break; break;
@ -231,10 +255,6 @@ void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value)
case OST_GPIO_DEBUG_PIN: case OST_GPIO_DEBUG_PIN:
gpio_put(DEBUG_PIN, value); gpio_put(DEBUG_PIN, value);
break; break;
// Nothing to do for these inputes
case OST_GPIO_ROTARY_A:
case OST_GPIO_ROTARY_B:
default: default:
break; break;
} }
@ -245,7 +265,7 @@ void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void ost_hal_sdcard_set_slow_clock() void ost_hal_sdcard_set_slow_clock()
{ {
spi_set_baudrate(spi0, 10000); spi_set_baudrate(spi0, 1000000UL);
} }
void ost_hal_sdcard_set_fast_clock() void ost_hal_sdcard_set_fast_clock()

View file

@ -45,7 +45,9 @@ typedef struct
{ {
fs_state_t ev; fs_state_t ev;
uint8_t *mem; uint8_t *mem;
char *filename; ost_button_t button;
char *image;
char *sound;
} ost_fs_event_t; } 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 wake_up;
static ost_audio_event_t AudioQueue[10]; static ost_audio_event_t *AudioQueue[10];
static int dbg_state = 0; static int dbg_state = 0;
@ -66,7 +68,7 @@ static fs_state_t FsState = FS_WAIT_FOR_EVENT;
static qor_mbox_t FsMailBox; static qor_mbox_t FsMailBox;
static ost_fs_event_t FsEventQueue[10]; static ost_fs_event_t *FsEventQueue[10];
static ost_context_t OstContext; 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); 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; 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); 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_system_stopwatch_start();
ost_audio_play(filename); ost_audio_play(filename);
@ -148,18 +150,26 @@ void FsTask(void *args)
switch (FsState) switch (FsState)
{ {
case FS_PLAY_SOUND: case FS_PLAY_SOUND:
ScratchFile[STORY_DIR_OFFSET] = 0; if (OstContext.sound != NULL)
strcat(ScratchFile, SoundsDir); {
strcat(ScratchFile, OstContext.sound); ScratchFile[STORY_DIR_OFFSET] = 0;
play_sound_file(ScratchFile); strcat(ScratchFile, SoundsDir);
strcat(ScratchFile, OstContext.sound);
play_sound_file(ScratchFile);
}
FsState = FS_WAIT_FOR_EVENT; FsState = FS_WAIT_FOR_EVENT;
break; break;
case FS_DISPLAY_IMAGE: 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) if (OstContext.sound != NULL)
{ {
FsState = FS_PLAY_SOUND; FsState = FS_PLAY_SOUND;
@ -180,19 +190,7 @@ void FsTask(void *args)
memcpy(&ScratchFile[1], OstContext.uuid, UUID_SIZE); memcpy(&ScratchFile[1], OstContext.uuid, UUID_SIZE);
ScratchFile[1 + UUID_SIZE] = 0; ScratchFile[1 + UUID_SIZE] = 0;
// first, display image, then sound FsState = FS_DISPLAY_IMAGE; // Always display image (then sound), if there is one
if (OstContext.image != NULL)
{
FsState = FS_DISPLAY_IMAGE;
}
else if (OstContext.sound != NULL)
{
FsState = FS_PLAY_SOUND;
}
else
{
FsState = FS_WAIT_FOR_EVENT;
}
} }
else else
{ {
@ -200,8 +198,11 @@ void FsTask(void *args)
} }
break; break;
case FS_LOAD_STORY: 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 // ROM loaded, execute story
vm_task_start_story();
FsState = FS_WAIT_FOR_EVENT; FsState = FS_WAIT_FOR_EVENT;
break; break;
@ -212,6 +213,8 @@ void FsTask(void *args)
{ {
// valid event, accept it // valid event, accept it
FsState = fs_ev->ev; FsState = fs_ev->ev;
OstContext.image = fs_ev->image;
OstContext.sound = fs_ev->sound;
} }
else else
{ {
@ -226,12 +229,30 @@ void FsTask(void *args)
void fs_task_scan_index() void fs_task_scan_index()
{ {
static ost_fs_event_t ScanIndexEv = { static ost_fs_event_t ScanIndexEv = {
.ev = FS_LOAD_INDEX, .ev = FS_LOAD_INDEX};
.filename = NULL};
qor_mbox_notify(&FsMailBox, (void **)&ScanIndexEv, QOR_MBOX_OPTION_SEND_BACK); 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() void fs_task_initialize()
{ {
qor_mbox_init(&AudioMailBox, (void **)&AudioQueue, 10); qor_mbox_init(&AudioMailBox, (void **)&AudioQueue, 10);

View file

@ -3,5 +3,7 @@
void fs_task_scan_index(); void fs_task_scan_index();
void fs_task_initialize(); 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 #endif // FS_TASK_H

View file

@ -49,7 +49,7 @@ static qor_mbox_t HmiMailBox;
static ost_hmi_event_t HmiEvent; 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; static ost_system_state_t OstState = OST_SYS_WAIT_INDEX;

View file

@ -10,11 +10,6 @@ extern "C"
#define OST_ID_SPI_FOR_SDCARD 0 #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 // SHARED TYPES
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -35,31 +30,44 @@ extern "C"
typedef enum typedef enum
{ {
OST_GPIO_ROTARY_A,
OST_GPIO_ROTARY_B,
OST_GPIO_DEBUG_LED, OST_GPIO_DEBUG_LED,
OST_GPIO_DEBUG_PIN, OST_GPIO_DEBUG_PIN
} ost_hal_gpio_t; } 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 // HIGH LEVEL API
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// System API
void ost_system_initialize(); void ost_system_initialize();
void system_putc(char ch); void system_putc(char ch);
void ost_system_delay_ms(uint32_t delay); void ost_system_delay_ms(uint32_t delay);
void ost_system_stopwatch_start(); void ost_system_stopwatch_start();
uint32_t ost_system_stopwatch_stop(); uint32_t ost_system_stopwatch_stop();
// Audio API
void ost_audio_play(const char *filename); void ost_audio_play(const char *filename);
void ost_audio_stop(); void ost_audio_stop();
int ost_audio_process(); int ost_audio_process();
typedef void (*ost_audio_callback_t)(void); typedef void (*ost_audio_callback_t)(void);
void ost_audio_register_callback(ost_audio_callback_t cb); 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 // GPIO HAL
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
int ost_hal_gpio_get(ost_hal_gpio_t gpio); int ost_hal_gpio_get(ost_hal_gpio_t gpio);
void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value); void ost_hal_gpio_set(ost_hal_gpio_t gpio, int value);

View file

@ -15,24 +15,35 @@
// =========================================================================================================== // ===========================================================================================================
// DEFINITIONS // 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 typedef struct
{ {
uint8_t ev; ost_vm_ev_type_t ev;
const char *story_dir; const char *story_dir;
uint32_t button_mask;
} ost_vm_event_t; } 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 // PRIVATE GLOBAL VARIABLES
// =========================================================================================================== // ===========================================================================================================
static qor_tcb_t VmTcb; static qor_tcb_t VmTcb;
static uint32_t VmStack[4096]; static uint32_t VmStack[4096];
static qor_mbox_t VmMailBox; 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_rom_data[16 * 1024];
static uint8_t m_ram_data[16 * 1024]; static uint8_t m_ram_data[16 * 1024];
static chip32_ctx_t m_chip32_ctx; static chip32_ctx_t m_chip32_ctx;
@ -40,6 +51,8 @@ static char CurrentStory[260]; // Current story path
static char ImageFile[260]; static char ImageFile[260];
static char SoundFile[260]; static char SoundFile[260];
static ost_vm_state_t VmState = OST_VM_STATE_WAIT_EVENT;
// =========================================================================================================== // ===========================================================================================================
// VIRTUAL MACHINE TASK // VIRTUAL MACHINE TASK
// =========================================================================================================== // ===========================================================================================================
@ -67,11 +80,15 @@ uint8_t vm_syscall(chip32_ctx_t *ctx, uint8_t code)
// Media // Media
if (code == 1) // Execute media if (code == 1) // Execute media
{ {
char *image_ptr = NULL;
char *sound_ptr = NULL;
if (m_chip32_ctx.registers[R0] != 0) if (m_chip32_ctx.registers[R0] != 0)
{ {
// image file name address is in R0 // image file name address is in R0
// QString imageFile = m_model.BuildFullImagePath(GetFileNameFromMemory(m_chip32_ctx.registers[R0])); // QString imageFile = m_model.BuildFullImagePath(GetFileNameFromMemory(m_chip32_ctx.registers[R0]));
// m_ostHmiDock->SetImage(imageFile); // m_ostHmiDock->SetImage(imageFile);
get_file_from_memory(ImageFile, m_chip32_ctx.registers[R0]);
image_ptr = ImageFile;
} }
else 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])); // QString soundFile = m_model.BuildFullSoundPath(GetFileNameFromMemory(m_chip32_ctx.registers[R1]));
// qDebug() << ", Sound: " << soundFile; // qDebug() << ", Sound: " << soundFile;
// m_model.PlaySoundFile(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 retCode = SYSCALL_RET_WAIT_EV; // set the VM in pause
} }
// WAIT EVENT bits: // WAIT EVENT bits:
@ -105,6 +125,16 @@ uint8_t vm_syscall(chip32_ctx_t *ctx, uint8_t code)
return retCode; 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) void VmTask(void *args)
{ {
// VM Initialize // VM Initialize
@ -122,36 +152,73 @@ void VmTask(void *args)
chip32_result_t run_result; chip32_result_t run_result;
ost_vm_event_t *e = NULL; ost_vm_event_t *e = NULL;
uint32_t res = 0;
bool isHome = true;
while (1) 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 run_result = chip32_step(&m_chip32_ctx);
chip32_initialize(&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); if (e->ev == VM_EV_BUTTON_EVENT)
} while (run_result != VM_OK); {
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); qor_mbox_notify(&VmMailBox, (void **)&VmStartEvent, QOR_MBOX_OPTION_SEND_BACK);
} }
void vm_task_initialize() 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_mbox_init(&VmMailBox, (void **)&VmQueue, 10);
qor_create_thread(&VmTcb, VmTask, VmStack, sizeof(VmStack) / sizeof(VmStack[0]), VM_TASK_PRIORITY, "VmTask"); qor_create_thread(&VmTcb, VmTask, VmStack, sizeof(VmStack) / sizeof(VmStack[0]), VM_TASK_PRIORITY, "VmTask");
ost_button_register_callback(button_callback);
} }

View file

@ -1,7 +1,7 @@
#ifndef VM_TASK_H #ifndef VM_TASK_H
#define 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(); void vm_task_initialize();
#endif // VM_TASK_H #endif // VM_TASK_H

View file

@ -72,8 +72,13 @@ void StoryProject::SaveStory(const std::vector<uint8_t> &m_program)
tlv.add_object(3); tlv.add_object(3);
tlv.add_string(m_uuid.c_str(), m_uuid.size()); // uuid 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) void StoryProject::Initialize(const std::string &file_path)