|
|
@ -26,10 +26,12 @@ |
|
|
|
|
|
|
|
#define SAMPLE_PER_CYCLE (SAMPLE_RATE/WAVE_FREQ_HZ) |
|
|
|
|
|
|
|
#define EXIT_BIT 0x01 |
|
|
|
|
|
|
|
using namespace std; |
|
|
|
|
|
|
|
SemaphoreHandle_t xPlayingSemaphore = NULL; |
|
|
|
static TaskHandle_t xTaskToNotify = NULL; |
|
|
|
|
|
|
|
Sound::Sound() { |
|
|
|
xPlayingSemaphore = xSemaphoreCreateMutex(); |
|
|
@ -88,18 +90,32 @@ void Sound::end() { |
|
|
|
i2s_driver_uninstall(i2s_num); //stop & destroy i2s driver
|
|
|
|
} |
|
|
|
|
|
|
|
void Sound::play(const char* path) { |
|
|
|
if (xTaskToNotify != NULL) { |
|
|
|
xTaskNotify( xTaskToNotify, |
|
|
|
EXIT_BIT, |
|
|
|
eSetBits); |
|
|
|
taskYIELD(); |
|
|
|
} |
|
|
|
|
|
|
|
xTaskCreate(&(Sound::play_task), "play_task", 3072, (void*)path, 5, &xTaskSound); |
|
|
|
} |
|
|
|
|
|
|
|
void Sound::play_task(void *pvParameter) { |
|
|
|
// Serial.print("initial free stack: "); Serial.println(uxTaskGetStackHighWaterMark( NULL ), DEC); // DEBUG
|
|
|
|
char *path = (char *) pvParameter; |
|
|
|
Serial.println("sound task: playing"); |
|
|
|
if ( xPlayingSemaphore == NULL || xSemaphoreTake( xPlayingSemaphore, (TickType_t) 10) != pdTRUE ) { |
|
|
|
if ( xPlayingSemaphore == NULL || xSemaphoreTake( xPlayingSemaphore, 42 / portTICK_PERIOD_MS) != pdTRUE ) { |
|
|
|
Serial.println("Sound task: could not obtain semaphore"); |
|
|
|
vTaskDelete( NULL ); |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
xTaskToNotify = xTaskGetCurrentTaskHandle(); |
|
|
|
|
|
|
|
File file = SDCard::open(path); |
|
|
|
if (!file) { |
|
|
|
xTaskToNotify = NULL; |
|
|
|
Serial.print("Failed to open file: "); Serial.println(path); |
|
|
|
vTaskDelete( NULL ); |
|
|
|
return; |
|
|
@ -133,6 +149,19 @@ void Sound::play_task(void *pvParameter) { |
|
|
|
buf_pos += num_pushed_bytes; |
|
|
|
} |
|
|
|
// Buffer now empty
|
|
|
|
|
|
|
|
uint32_t ulNotifiedValue; |
|
|
|
BaseType_t xResult = xTaskNotifyWait( pdFALSE, /* Don't clear bits on entry. */ |
|
|
|
ULONG_MAX, /* Clear all bits on exit. */ |
|
|
|
&ulNotifiedValue, /* Stores the notified value. */ |
|
|
|
0 ); /* xMaxBlockTime */ |
|
|
|
if( xResult == pdPASS ) { /* A notification was received */ |
|
|
|
if( ( ulNotifiedValue & EXIT_BIT ) != 0 ) { /* the EXIT BIT was set */ |
|
|
|
Serial.println("play_task: got notify. exiting."); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
//TickType_t delay = 10 / portTICK_PERIOD_MS; // max delay: 10ms instead of portMAX_DELAY
|
|
|
|
vTaskDelay(20 / portTICK_PERIOD_MS); |
|
|
|
} |
|
|
@ -140,8 +169,9 @@ void Sound::play_task(void *pvParameter) { |
|
|
|
SDCard::close(file); |
|
|
|
i2s_stop(i2s_num); |
|
|
|
delete[] buf; |
|
|
|
xSemaphoreGive( xPlayingSemaphore ); |
|
|
|
Serial.println("task exiting"); |
|
|
|
xTaskToNotify = NULL; |
|
|
|
xSemaphoreGive( xPlayingSemaphore ); |
|
|
|
vTaskDelete( NULL ); |
|
|
|
} |
|
|
|
|
|
|
|