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 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()

View file

@ -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);

View file

@ -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

View file

@ -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;

View file

@ -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);

View file

@ -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);
}

View file

@ -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

View file

@ -72,8 +72,13 @@ void StoryProject::SaveStory(const std::vector<uint8_t> &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)