fix qor mailboxes + all is in place for audio with thread, dma and irq

This commit is contained in:
Anthony Rabine 2023-07-25 22:06:12 +02:00
parent 51b202abfb
commit 3c652a3bde
11 changed files with 195 additions and 343 deletions

View file

@ -36,6 +36,7 @@
"numbers": "c",
"systick.h": "c",
"critical_section.h": "c",
"serializers.h": "c"
"serializers.h": "c",
"cstring": "c"
}
}

View file

@ -1,4 +1,9 @@
// C library
#include <string.h>
#include <stdlib.h>
// OST common files
#include "ost_hal.h"
#include "debug.h"
@ -22,33 +27,10 @@
#include "audio_player.h"
#include "pico_i2s.h"
static volatile uint32_t msTicks = 0;
static audio_ctx_t audio_ctx;
// ===========================================================================================================
// CONSTANTS / DEFINES
// ===========================================================================================================
void __isr __time_critical_func(audio_i2s_dma_irq_handler)();
// ----------------------------------------------------------------------------
// SYSTEM HAL
// ----------------------------------------------------------------------------
#define UART_ID uart0
#define BAUD_RATE 115200
// We are using pins 0 and 1, but see the GPIO function select table in the
// datasheet for information on which other pins can be used.
#define UART_TX_PIN 0
#define UART_RX_PIN 1
static struct repeating_timer sys_timer;
// static audio_i2s_config_t i2s_config = {28, 26, 0};
static __attribute__((aligned(8))) pio_i2s i2s;
void ost_system_delay_ms(uint32_t delay)
{
busy_wait_ms(delay);
}
const uint8_t LED_PIN = 14; // GP 14
const uint8_t LCD_DC = 8;
@ -66,18 +48,36 @@ const uint8_t ROTARY_BUTTON = 3;
const uint8_t SD_CARD_CS = 17;
const uint8_t SD_CARD_PRESENCE = 24;
static bool sys_timer_callback(struct repeating_timer *t)
{
msTicks++;
#define UART_ID uart0
#define BAUD_RATE 115200
// qor_switch_context();
// We are using pins 0 and 1, but see the GPIO function select table in the
// datasheet for information on which other pins can be used.
#define UART_TX_PIN 0
#define UART_RX_PIN 1
return true;
}
// ===========================================================================================================
// GLOBAL VARIABLES
// ===========================================================================================================
static __attribute__((aligned(8))) pio_i2s i2s;
static volatile uint32_t msTicks = 0;
static audio_ctx_t audio_ctx;
// ===========================================================================================================
// PROTOTYPES
// ===========================================================================================================
extern void init_spi(void);
void dma_init();
void __isr __time_critical_func(audio_i2s_dma_irq_handler)();
// ===========================================================================================================
// OST HAL IMPLEMENTATION
// ===========================================================================================================
void ost_system_delay_ms(uint32_t delay)
{
busy_wait_ms(delay);
}
void gpio_callback(uint gpio, uint32_t events)
{
@ -167,15 +167,10 @@ void ost_system_initialize()
.data_pin = 28,
.clock_pin_base = 26};
// i2s_program_start_synched(pio0, audio_i2s_dma_irq_handler, &i2s, &config);
// pico_i2s_setup(&config);
i2s_program_setup(pio0, audio_i2s_dma_irq_handler, &i2s, &config);
audio_init(&audio_ctx);
//------------------- System timer (1ms)
// add_repeating_timer_ms(1, sys_timer_callback, NULL, &sys_timer);
// ------------ Everything is initialized, print stuff here
debug_printf("System Clock: %lu\n", clock_get_hz(clk_sys));
}
@ -304,21 +299,20 @@ void ost_display_transfer_multi(uint8_t *buff, uint32_t btr)
// AUDIO HAL
// ----------------------------------------------------------------------------
// extern shared_state_t shared_state;
// #include "pico/critical_section.h"
// critical_section_t acrit;
void ost_audio_play(const char *filename)
{
audio_play(&audio_ctx, filename);
// audio_i2s_set_enabled(true);
// audio_process(&audio_ctx);
i2s.buffer_index = 0;
// audio_step = 1;
// On appelle une première fois le process pour récupérer et initialiser le premier buffer...
audio_process(&audio_ctx);
// Puis le deuxième ... (pour avoir un buffer d'avance)
audio_process(&audio_ctx);
// On lance les DMA
i2s_start(&i2s);
}
int ost_audio_process()
@ -326,39 +320,39 @@ int ost_audio_process()
return audio_process(&audio_ctx);
}
static ost_audio_callback_t AudioCallBack = NULL;
void ost_audio_register_callback(ost_audio_callback_t cb)
{
AudioCallBack = cb;
}
void ost_hal_audio_frame_end()
void ost_hal_audio_new_frame(const void *buff, int dma_trans_number)
{
if (dma_trans_number > STEREO_BUFFER_SIZE)
{
// Problème
return;
}
memcpy(i2s.out_ctrl_blocks[i2s.buffer_index], buff, dma_trans_number * sizeof(uint32_t));
i2s.buffer_index = 1 - i2s.buffer_index;
// uint dma_channel = shared_state.dma_channel;
// if (dma_irqn_get_channel_status(PICO_AUDIO_I2S_DMA_IRQ, dma_channel))
// {
// dma_irqn_acknowledge_channel(PICO_AUDIO_I2S_DMA_IRQ, dma_channel);
// }
}
void ost_hal_audio_frame_start(const volatile void *buff, int dma_trans_number)
{
//
// dma_channel_transfer_from_buffer_now(shared_state.dma_channel, buff, dma_trans_number);
// dma_channel_start(shared_state.dma_channel);
dma_hw->ints0 = 1u << i2s.dma_ch_out_data; // clear the IRQ
// dma_hw->ints0 = 1u << i2s.dma_ch_out_data; // clear the IRQ
}
void __isr __time_critical_func(audio_i2s_dma_irq_handler)()
{
/*
uint dma_channel = shared_state.dma_channel;
if (dma_irqn_get_channel_status(PICO_AUDIO_I2S_DMA_IRQ, dma_channel))
{
dma_irqn_acknowledge_channel(PICO_AUDIO_I2S_DMA_IRQ, dma_channel);
}
dma_hw->ints0 = 1u << i2s.dma_ch_out_data; // clear the IRQ
audio_process(&audio_ctx);
*/
// Warn the application layer that we have done on that channel
if (AudioCallBack != NULL)
{
AudioCallBack();
}
}
#if 0 // legacy audio test

View file

@ -16,10 +16,10 @@
#include "debug.h"
void pico_i2s_set_frequency(const audio_i2s_config_t *config)
void pico_i2s_set_frequency(const pio_i2s *i2s, const audio_i2s_config_t *config)
{
float bitClk = config->freq * config->bps * 2.0 /* channels */ * 2.0 /* edges per clock */;
// pio_sm_set_clkdiv(audio_pio, shared_state.pio_sm, (float)clock_get_hz(clk_sys) / bitClk);
pio_sm_set_clkdiv(i2s->pio, i2s->sm_dout, (float)clock_get_hz(clk_sys) / bitClk);
}
#if 0
@ -64,7 +64,7 @@ void audio_i2s_set_enabled(bool enabled)
//---------------------------------------------------------------------------------------------------------------------------
static void dma_double_buffer_init(pio_i2s *i2s, void (*dma_handler)(void))
static void dma_double_buffer_init(pio_i2s *i2s)
{
i2s->dma_ch_out_ctrl = dma_claim_unused_channel(true);
i2s->dma_ch_out_data = dma_claim_unused_channel(true);
@ -75,14 +75,25 @@ static void dma_double_buffer_init(pio_i2s *i2s, void (*dma_handler)(void))
dma_channel_config c = dma_channel_get_default_config(i2s->dma_ch_out_ctrl);
channel_config_set_read_increment(&c, true);
channel_config_set_write_increment(&c, false);
// i2s->out_ctrl_blocks pointe sur deux emplacements, 4 octets par emplacement (qui est une adresse)
// A chaque fois que le DMA de contrôle sera activé, l'adresse va s'incrémenter de 4 octets (DMA_SIZE_32)
// Dès lors :
// - On commence à l'index 0
// - Puis l'index 1
// On va revenir à l'index 0 tous les ... 8 octets, donc on programme ce décalage (3 bits)
channel_config_set_ring(&c, false, 3);
channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
dma_channel_configure(i2s->dma_ch_out_ctrl, &c, &dma_hw->ch[i2s->dma_ch_out_data].al3_read_addr_trig, i2s->out_ctrl_blocks, 1, false);
// la destination est l'alias al3_read_addr_trig qui va donc modifier l'adresse de début du transfer DMA et enclencher le démarrage
// Nous avons deux actions, c'est pour cela que c'est un alias
c = dma_channel_get_default_config(i2s->dma_ch_out_data);
channel_config_set_read_increment(&c, true);
channel_config_set_write_increment(&c, false);
channel_config_set_chain_to(&c, i2s->dma_ch_out_ctrl);
channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
channel_config_set_chain_to(&c, i2s->dma_ch_out_ctrl); // On va chaîner ce DMA au contrôle: lorsque le DMA est terminé, le DMA de contrôle va s'activer... et ainsi de suite
channel_config_set_dreq(&c, pio_get_dreq(i2s->pio, i2s->sm_dout, true));
dma_channel_configure(i2s->dma_ch_out_data,
@ -91,15 +102,9 @@ static void dma_double_buffer_init(pio_i2s *i2s, void (*dma_handler)(void))
NULL,
STEREO_BUFFER_SIZE,
false);
dma_channel_set_irq0_enabled(i2s->dma_ch_out_data, true);
irq_set_exclusive_handler(DMA_IRQ_0, dma_handler);
irq_set_enabled(DMA_IRQ_0, true);
dma_channel_start(i2s->dma_ch_out_ctrl);
}
static void i2s_sync_program_init(PIO pio, pio_i2s *i2s, audio_i2s_config_t *config)
static void i2s_sync_program_init(PIO pio, pio_i2s *i2s, const audio_i2s_config_t *config)
{
uint offset = 0;
i2s->pio = pio;
@ -110,13 +115,46 @@ static void i2s_sync_program_init(PIO pio, pio_i2s *i2s, audio_i2s_config_t *con
offset = pio_add_program(pio0, &i2s_out_master_program);
// 4th argument is bit depth, 5th dout, 6th bclk pin base (lrclk is bclk pin + 1)
i2s_out_master_program_init(pio, i2s->sm_dout, offset, config->bps, config->data_pin, config->clock_pin_base);
// pio_sm_set_clkdiv(pio, i2s->sm_dout, 89); // Approximately 11KHz audio
}
void i2s_program_start_synched(PIO pio, void (*dma_handler)(void), pio_i2s *i2s, audio_i2s_config_t *config)
void i2s_program_setup(PIO pio, void (*dma_handler)(void), pio_i2s *i2s, const audio_i2s_config_t *config)
{
// i2s_sync_program_init(pio, i2s);
pico_i2s_set_frequency(config);
dma_double_buffer_init(i2s, dma_handler);
if (((uint32_t)i2s & 0x7) != 0)
{
debug_printf("pio_i2s argument must be 8-byte aligned!\r\n");
}
i2s_sync_program_init(pio, i2s, config);
pico_i2s_set_frequency(i2s, config); // call after PIO configuration
dma_double_buffer_init(i2s);
irq_set_exclusive_handler(DMA_IRQ_0, dma_handler);
pio_enable_sm_mask_in_sync(i2s->pio, i2s->sm_mask);
}
void i2s_start(pio_i2s *i2s)
{
// D'abord on va paramétrer les diverses interruptions
dma_channel_set_irq0_enabled(i2s->dma_ch_out_data, true);
irq_set_enabled(DMA_IRQ_0, true);
// YAAAAAAA on lance!
dma_channel_start(i2s->dma_ch_out_ctrl);
}
static void pico_gracefully_stop_dma(uint channel)
{
// See errata sheet to avoid spurious interrupts
// disable the channel on IRQ0
dma_channel_set_irq0_enabled(channel, false);
// abort the channel
dma_channel_abort(channel);
// clear the spurious IRQ (if there was one)
dma_channel_acknowledge_irq0(channel);
}
void i2s_stop(pio_i2s *i2s)
{
pico_gracefully_stop_dma(i2s->dma_ch_out_ctrl);
pico_gracefully_stop_dma(i2s->dma_ch_out_data);
irq_set_enabled(DMA_IRQ_0, false);
}

View file

@ -13,158 +13,15 @@
#include "hardware/irq.h"
#include "hardware/pio.h"
#include "audio_player.h"
#ifdef __cplusplus
extern "C"
{
#endif
#if 0
/** \file audio_i2s.h
* \defgroup pico_audio_i2s pico_audio_i2s
* I2S audio output using the PIO
*
* This library uses the \ref hardware_pio system to implement a I2S audio interface
*
* \todo Must be more we need to say here.
* \todo certainly need an example
*
*/
#ifndef PICO_AUDIO_I2S_DMA_IRQ
#ifdef PICO_AUDIO_DMA_IRQ
#define PICO_AUDIO_I2S_DMA_IRQ PICO_AUDIO_DMA_IRQ
#else
#define PICO_AUDIO_I2S_DMA_IRQ 0
#endif
#endif
#ifndef PICO_AUDIO_I2S_PIO
#ifdef PICO_AUDIO_PIO
#define PICO_AUDIO_I2S_PIO PICO_AUDIO_PIO
#else
#define PICO_AUDIO_I2S_PIO 0
#endif
#endif
#if !(PICO_AUDIO_I2S_DMA_IRQ == 0 || PICO_AUDIO_I2S_DMA_IRQ == 1)
#error PICO_AUDIO_I2S_DMA_IRQ must be 0 or 1
#endif
#if !(PICO_AUDIO_I2S_PIO == 0 || PICO_AUDIO_I2S_PIO == 1)
#error PICO_AUDIO_I2S_PIO ust be 0 or 1
#endif
#ifndef PICO_AUDIO_I2S_MAX_CHANNELS
#ifdef PICO_AUDIO_MAX_CHANNELS
#define PICO_AUDIO_I2S_MAX_CHANNELS PICO_AUDIO_MAX_CHANNELS
#else
#define PICO_AUDIO_I2S_MAX_CHANNELS 2u
#endif
#endif
#ifndef PICO_AUDIO_I2S_BUFFERS_PER_CHANNEL
#ifdef PICO_AUDIO_BUFFERS_PER_CHANNEL
#define PICO_AUDIO_I2S_BUFFERS_PER_CHANNEL PICO_AUDIO_BUFFERS_PER_CHANNEL
#else
#define PICO_AUDIO_I2S_BUFFERS_PER_CHANNEL 3u
#endif
#endif
#ifndef PICO_AUDIO_I2S_BUFFER_SAMPLE_LENGTH
#ifdef PICO_AUDIO_BUFFER_SAMPLE_LENGTH
#define PICO_AUDIO_I2S_BUFFER_SAMPLE_LENGTH PICO_AUDIO_BUFFER_SAMPLE_LENGTH
#else
#define PICO_AUDIO_I2S_BUFFER_SAMPLE_LENGTH 576u
#endif
#endif
#ifndef PICO_AUDIO_I2S_SILENCE_BUFFER_SAMPLE_LENGTH
#ifdef PICO_AUDIO_I2S_SILENCE_BUFFER_SAMPLE_LENGTH
#define PICO_AUDIO_I2S_SILENCE_BUFFER_SAMPLE_LENGTH PICO_AUDIO_SILENCE_BUFFER_SAMPLE_LENGTH
#else
#define PICO_AUDIO_I2S_SILENCE_BUFFER_SAMPLE_LENGTH 256u
#endif
#endif
// Allow use of pico_audio driver without actually doing anything much
#ifndef PICO_AUDIO_I2S_NOOP
#ifdef PICO_AUDIO_NOOP
#define PICO_AUDIO_I2S_NOOP PICO_AUDIO_NOOP
#else
#define PICO_AUDIO_I2S_NOOP 0
#endif
#endif
#ifndef PICO_AUDIO_I2S_MONO_INPUT
#define PICO_AUDIO_I2S_MONO_INPUT 0
#endif
#ifndef PICO_AUDIO_I2S_MONO_OUTPUT
#define PICO_AUDIO_I2S_MONO_OUTPUT 0
#endif
#ifndef PICO_AUDIO_I2S_DATA_PIN
// #warning PICO_AUDIO_I2S_DATA_PIN should be defined when using AUDIO_I2S
#define PICO_AUDIO_I2S_DATA_PIN 28
#endif
#ifndef PICO_AUDIO_I2S_CLOCK_PIN_BASE
// #warning PICO_AUDIO_I2S_CLOCK_PIN_BASE should be defined when using AUDIO_I2S
#define PICO_AUDIO_I2S_CLOCK_PIN_BASE 26
#endif
/** \brief Base configuration structure used when setting up
* \ingroup pico_audio_i2s
*/
typedef struct
{
uint32_t freq;
uint32_t bps;
uint8_t data_pin;
uint8_t clock_pin_base;
} audio_i2s_config_t;
typedef struct
{
uint32_t freq;
uint8_t pio_sm;
uint8_t dma_channel;
} shared_state_t;
typedef struct audio_format
{
uint32_t sample_freq; ///< Sample frequency in Hz
uint16_t format; ///< Audio format \ref audio_formats
uint16_t channel_count; ///< Number of channels
} audio_format_t;
/** \brief Set up system to output I2S audio
* \ingroup pico_audio_i2s
*
* \param intended_audio_format \todo
* \param config The configuration to apply.
*/
void pico_i2s_setup(const audio_i2s_config_t *config);
/** \brief Set up system to output I2S audio
* \ingroup pico_audio_i2s
*
* \param enable true to enable I2S audio, false to disable.
*/
void audio_i2s_set_enabled(bool enabled);
void audio_start_dma_transfer(const int32_t *bytes, uint32_t count);
#endif
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
//----------------------------------------------------------------------------------
#define AUDIO_BUFFER_FRAMES 48
#define STEREO_BUFFER_SIZE AUDIO_BUFFER_FRAMES * 2
#define AUDIO_BUFFER_FRAMES SIZE_OF_SAMPLES
#define STEREO_BUFFER_SIZE AUDIO_BUFFER_FRAMES * 2 // for left + right
typedef struct
{
@ -177,16 +34,22 @@ extern "C"
typedef struct pio_i2s
{
int32_t output_buffer[STEREO_BUFFER_SIZE * 2]; // double buffering, so x2
int32_t *out_ctrl_blocks[2];
PIO pio;
uint8_t sm_mask;
uint8_t sm_dout;
uint dma_ch_out_ctrl;
uint dma_ch_out_data;
int32_t *out_ctrl_blocks[2];
int32_t output_buffer[STEREO_BUFFER_SIZE * 2];
int buffer_index;
} pio_i2s;
void i2s_program_start_synched(PIO pio, void (*dma_handler)(void), pio_i2s *i2s, audio_i2s_config_t *config);
void i2s_program_setup(PIO pio, void (*dma_handler)(void), pio_i2s *i2s, const audio_i2s_config_t *config);
void i2s_start(pio_i2s *i2s);
void i2s_stop(pio_i2s *i2s);
#ifdef __cplusplus
}

View file

@ -10,10 +10,8 @@
#include "ost_hal.h"
#include "serializers.h"
#define SIZE_OF_SAMPLES (128) // in bytes
// Audio Double Buffer for DMA transfer
int32_t audio_buf[2][SIZE_OF_SAMPLES];
int32_t audio_buf[SIZE_OF_SAMPLES];
// int16_t audio_buf16[2][SIZE_OF_SAMPLES];
// Audio Buffer for File Read
@ -64,14 +62,10 @@ void audio_init(audio_ctx_t *ctx)
for (int i = 0; i < SIZE_OF_SAMPLES; i++)
{
audio_buf[0][i] = DAC_ZERO_VALUE;
audio_buf[1][i] = DAC_ZERO_VALUE;
// audio_buf16[0][i] = DAC_ZERO_VALUE;
// audio_buf16[1][i] = DAC_ZERO_VALUE;
audio_buf[i] = DAC_ZERO_VALUE;
}
ctx->dma_trans_number = SIZE_OF_SAMPLES / 4;
ctx->transfer_size = SIZE_OF_SAMPLES / 4;
}
static int list_chunk_is_info_type(audio_ctx_t *ctx)
@ -188,7 +182,7 @@ static int get_audio_buf(audio_ctx_t *ctx, int32_t *buf_32b)
{
debug_printf("ERROR: f_read %d, data_offset = %d\n\r", (int)fr, (int)ctx->audio_info.data_offset);
f_close(&ctx->fil);
ctx->dma_trans_number = number / 4;
ctx->transfer_size = number / 4;
return 1;
}
if (ctx->audio_info.data_size <= ctx->audio_info.data_offset)
@ -232,40 +226,31 @@ static int get_audio_buf(audio_ctx_t *ctx, int32_t *buf_32b)
*/
// ctx->audio_info.lvl_l = get_level(lvl_l / (number / 4));
// ctx->audio_info.lvl_r = get_level(lvl_r / (number / 4));
ctx->dma_trans_number = (number / 4); // 32 bytes tranfers
ctx->transfer_size = (number / 4); // 32 bytes tranfers
return _next_is_end;
}
int audio_process(audio_ctx_t *ctx)
{
int nxt1 = (ctx->count & 0x1) ^ 0x1;
int nxt2 = 1 - nxt1;
// dma_flag_clear(DMA1, DMA_CH1, DMA_FLAG_FTF);
// dma_channel_disable(DMA1, DMA_CH1);
ost_hal_audio_frame_end();
if (ctx->next_is_end)
{
ctx->playing = 0;
ctx->pausing = 0;
}
// init_dma_i2s2(audio_buf[nxt1], dma_trans_number);
// dma_channel_enable(DMA1, DMA_CH1);
ost_hal_audio_frame_start(audio_buf[nxt1], ctx->dma_trans_number);
if (ctx->playing && !ctx->pausing)
{
ctx->next_is_end = get_audio_buf(ctx, audio_buf[nxt2]);
// Récupération du buffer audio à partir du disque
ctx->next_is_end = get_audio_buf(ctx, &audio_buf[0]);
ost_hal_audio_new_frame(&audio_buf[0], ctx->transfer_size);
}
else
{
for (int i = 0; i < SIZE_OF_SAMPLES; i++)
{
audio_buf[nxt2][i] = DAC_ZERO_VALUE;
audio_buf[i] = DAC_ZERO_VALUE;
}
ctx->dma_trans_number = SIZE_OF_SAMPLES / 4;
ctx->transfer_size = SIZE_OF_SAMPLES / 4;
}
ctx->count++;

View file

@ -6,6 +6,7 @@
#include <ff.h>
#define SIZE_OF_SAMPLES (128) // in bytes
#define FILENAME_MAX_SIZE 260
typedef struct
@ -29,7 +30,7 @@ typedef struct
{
FIL fil;
audio_info_type_t audio_info;
int32_t dma_trans_number;
int32_t transfer_size;
uint16_t idx_play;
int next_is_end;
int playing;

View file

@ -120,30 +120,6 @@ void UserTask_1(void *args)
}
}
void UserTask_2(void *args)
{
static ost_event_t wake_up;
wake_up.ev = 34;
while (1)
{
for (int i = 0; i < 65500; i++)
{
for (int j = 0; j < 300; j++)
;
}
debug_printf("X\n");
for (int i = 0; i < 65500; i++)
{
for (int j = 0; j < 100; j++)
;
}
qor_mbox_notify(&b, (void **)&wake_up, 1);
}
}
// ===========================================================================================================
// SD CARD TASK
// ===========================================================================================================
@ -152,6 +128,8 @@ static uint32_t AudioStack[4096];
static qor_mbox_t AudioMailBox;
static ost_event_t wake_up;
typedef struct
{
uint8_t ev;
@ -162,6 +140,8 @@ ost_audio_event_t audio_queue[10];
// End of DMA transfer callback
static void audio_callback(void)
{
qor_mbox_notify(&b, (void **)&wake_up, QOR_MBOX_OPTION_SEND_BACK);
gpio_xor_mask(1 << 1);
}
void AudioTask(void *args)
@ -169,6 +149,8 @@ void AudioTask(void *args)
picture_show("example.bmp");
// ost_audio_play("out2.wav");
wake_up.ev = 34;
qor_mbox_init(&AudioMailBox, (void **)&audio_queue, 10);
ost_audio_register_callback(audio_callback);
@ -182,37 +164,54 @@ void AudioTask(void *args)
while (1)
{
// Benchmark code
#if 0
if (onetime)
{
onetime = false;
gpio_put(1, 1);
ost_audio_play("out2.wav");
gpio_put(1, 0);
int isPlaying = 0;
int count = 0;
do
{
gpio_put(1, 1);
isPlaying = ost_audio_process();
gpio_put(1, 0);
count++;
} while (isPlaying);
debug_printf("Packets: %d\r\n", count);
}
#endif
// ost_event_t *e = NULL;
// uint32_t res = qor_mbox_wait(&b, (void **)&e, 30);
ost_audio_play("out2.wav");
// if (res == QOR_MBOX_OK)
// {
// }
ost_event_t *e = NULL;
ost_hal_gpio_set(OST_GPIO_DEBUG_LED, 0);
qor_sleep(500);
ost_hal_gpio_set(OST_GPIO_DEBUG_LED, 1);
qor_sleep(500);
int isPlaying = 0;
int count = 0;
do
{
uint32_t res = qor_mbox_wait(&AudioMailBox, (void **)&e, 30); // On devrait recevoir un message toutes les 3ms (durée d'envoi d'un buffer I2S)
if (res == QOR_MBOX_OK)
{
isPlaying = ost_audio_process();
}
count++;
} while (isPlaying);
for (;;)
{
ost_hal_gpio_set(OST_GPIO_DEBUG_LED, 0);
qor_sleep(500);
ost_hal_gpio_set(OST_GPIO_DEBUG_LED, 1);
qor_sleep(500);
}
}
}

View file

@ -107,8 +107,7 @@ extern "C"
// ----------------------------------------------------------------------------
// AUDIO HAL
// ----------------------------------------------------------------------------
void ost_hal_audio_frame_end();
void ost_hal_audio_frame_start(const volatile void *, int dma_trans_number);
void ost_hal_audio_new_frame(const void *buffer, int size);
#ifdef __cplusplus
}

View file

@ -221,7 +221,6 @@ void qor_create_thread(qor_tcb_t *tcb, thread_func_t task, uint32_t *stack, uint
tcb->state = qor_tcb_state_active;
tcb->wait_time = 0;
tcb->state = qor_tcb_state_active;
tcb->priority = priority;
tcb->name = name;
tcb->next = NULL;
@ -341,7 +340,10 @@ void qor_scheduler(void)
}
else if (best_sleeping != NULL)
{
// On va réveiller un endormi, car son temps d'attente est dépassé (ok ou timeout, ça dépend si c'est un sleep volontaire ou attente de mailbox dépassée)
RunPt = best_sleeping;
RunPt->state = qor_tcb_state_active; // devient actif
RunPt->ts = 0; // means timeout
}
else
{
@ -382,6 +384,7 @@ void qor_mbox_init(qor_mbox_t *mbox, void **msgBuffer, uint32_t maxCount)
mbox->read = 0;
mbox->read = 0;
mbox->head = NULL;
mbox->count = 0;
}
uint32_t qor_mbox_wait(qor_mbox_t *mbox, void **msg, uint32_t wait_ms)
@ -396,6 +399,13 @@ uint32_t qor_mbox_wait(qor_mbox_t *mbox, void **msg, uint32_t wait_ms)
RunPt->mbox = mbox;
mbox->head = RunPt;
qor_sleep(wait_ms);
disable_irq();
if (RunPt->ts == 0)
{
enable_irq();
return QOR_MBOX_TIMEOUT;
}
}
else
{
@ -445,11 +455,12 @@ uint32_t qor_mbox_notify(qor_mbox_t *mbox, void *msg, uint32_t notifyOption)
}
mbox->count++;
// We warn all waiting threads that a new message is available
// We warn waiting thread that a new message is available
qor_tcb_t *t = mbox->head;
if (t != NULL)
{
t->wait_time = 0;
t->state = qor_tcb_state_active; // force wake up
}
enable_irq();

View file

@ -84,8 +84,9 @@ typedef struct
} mbox_stats_t;
#define QOR_MBOX_OK 1
#define QOR_MBOX_ERROR 2
#define QOR_MBOX_FULL 3
#define QOR_MBOX_TIMEOUT 2
#define QOR_MBOX_ERROR 3
#define QOR_MBOX_FULL 4
void qor_mbox_init(qor_mbox_t *mbox, void **msgBuffer, uint32_t maxCount);
uint32_t qor_mbox_wait(qor_mbox_t *mbox, void **msg, uint32_t wait_ms);

View file

@ -20,46 +20,6 @@
@ The Cortex-M0 is limited on the thumb number of instructionss
@ the context restore is therefore a bit more complex that M3 or M4 CPU
@ One limitation is the POP instruction that cannot access to the HI registers (registers after R7)
@
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@ | |
@ -------------
@
@
@
@
qor_go: