Part 6: Audio
This commit is contained in:
parent
e525a823dc
commit
8f17172aa3
|
@ -1,6 +1,7 @@
|
|||
idf_component_register(
|
||||
SRCS
|
||||
"main.c"
|
||||
"odroid/audio.c"
|
||||
"odroid/battery.c"
|
||||
"odroid/display.c"
|
||||
"odroid/input.c"
|
||||
|
|
38
src/main.c
38
src/main.c
|
@ -1,3 +1,4 @@
|
|||
#include "odroid/audio.h"
|
||||
#include "odroid/battery.h"
|
||||
#include "odroid/display.h"
|
||||
#include "odroid/input.h"
|
||||
|
@ -12,12 +13,14 @@
|
|||
static const char* LOG_TAG = "Main";
|
||||
static uint16_t gFramebuffer[LCD_WIDTH * LCD_HEIGHT];
|
||||
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
Odroid_InitializeInput();
|
||||
Odroid_InitializeDisplay();
|
||||
Odroid_InitializeSdcard();
|
||||
Odroid_InitializeBatteryReader();
|
||||
Odroid_InitializeAudio();
|
||||
|
||||
// Load sprite
|
||||
uint16_t* sprite = (uint16_t*)malloc(64 * 64 * sizeof(uint16_t));
|
||||
|
@ -36,6 +39,28 @@ void app_main(void)
|
|||
fclose(spriteFile);
|
||||
}
|
||||
|
||||
// Load sound effect
|
||||
uint16_t* soundBuffer;
|
||||
int soundEffectLength = 1441;
|
||||
{
|
||||
FILE* soundFile = fopen("/sdcard/jump", "r");
|
||||
assert(soundFile);
|
||||
|
||||
uint8_t* soundEffect = malloc(soundEffectLength);
|
||||
assert(soundEffect);
|
||||
|
||||
soundBuffer = malloc(soundEffectLength*2);
|
||||
assert(soundBuffer);
|
||||
|
||||
fread(soundEffect, soundEffectLength, 1, soundFile);
|
||||
|
||||
for (int i = 0; i < soundEffectLength; ++i)
|
||||
{
|
||||
// 16 bits required but only MSB is actually sent to the DAC
|
||||
soundBuffer[i] = (soundEffect[i] << 8u);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ESP_LOGI(LOG_TAG, "Odroid initialization complete - entering main loop");
|
||||
|
||||
|
@ -44,6 +69,8 @@ void app_main(void)
|
|||
|
||||
uint16_t color = 0xffff;
|
||||
|
||||
int lastState = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
memset(gFramebuffer, 0, 320 * 240 * 2);
|
||||
|
@ -61,6 +88,17 @@ void app_main(void)
|
|||
else if (input.start) { color = SWAP_ENDIAN_16(RGB565(0, 0, 0xff)); }
|
||||
else if (input.select) { color = SWAP_ENDIAN_16(RGB565(0xff, 0xff, 0xff)); }
|
||||
|
||||
|
||||
int thisState = input.volume;
|
||||
|
||||
if ((thisState == 1) && (thisState != lastState))
|
||||
{
|
||||
Odroid_PlayAudio(soundBuffer, soundEffectLength*2);
|
||||
}
|
||||
|
||||
lastState = thisState;
|
||||
|
||||
|
||||
int spriteRow = 0;
|
||||
int spriteCol = 0;
|
||||
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
#include "audio.h"
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <driver/i2s.h>
|
||||
|
||||
|
||||
static const gpio_num_t AUDIO_AMP_SD_PIN = GPIO_NUM_25;
|
||||
|
||||
static QueueHandle_t gQueue;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t* buffer;
|
||||
int length;
|
||||
} QueueData;
|
||||
|
||||
|
||||
static void PlayTask(void *arg)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
QueueData data;
|
||||
|
||||
if (xQueueReceive(gQueue, &data, 10))
|
||||
{
|
||||
size_t bytesWritten;
|
||||
i2s_write(I2S_NUM_0, data.buffer, data.length, &bytesWritten, portMAX_DELAY);
|
||||
i2s_zero_dma_buffer(I2S_NUM_0);
|
||||
}
|
||||
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
void Odroid_InitializeAudio(void)
|
||||
{
|
||||
// Configure the amplifier shutdown signal
|
||||
{
|
||||
gpio_config_t gpioConfig = {};
|
||||
|
||||
gpioConfig.mode = GPIO_MODE_OUTPUT;
|
||||
gpioConfig.pin_bit_mask = 1ULL << AUDIO_AMP_SD_PIN;
|
||||
|
||||
ESP_ERROR_CHECK(gpio_config(&gpioConfig));
|
||||
|
||||
gpio_set_level(AUDIO_AMP_SD_PIN, 1);
|
||||
}
|
||||
|
||||
// Configure the I2S driver
|
||||
{
|
||||
i2s_config_t i2sConfig= {};
|
||||
|
||||
i2sConfig.mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN;
|
||||
i2sConfig.sample_rate = 5512;
|
||||
i2sConfig.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT;
|
||||
i2sConfig.communication_format = I2S_COMM_FORMAT_I2S_MSB;
|
||||
i2sConfig.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT;
|
||||
i2sConfig.dma_buf_count = 8;
|
||||
i2sConfig.dma_buf_len = 64;
|
||||
|
||||
ESP_ERROR_CHECK(i2s_driver_install(I2S_NUM_0, &i2sConfig, 0, NULL));
|
||||
ESP_ERROR_CHECK(i2s_set_dac_mode(I2S_DAC_CHANNEL_LEFT_EN));
|
||||
}
|
||||
|
||||
// Create task for playing sounds so that our main task isn't blocked
|
||||
{
|
||||
gQueue = xQueueCreate(1, sizeof(QueueData));
|
||||
assert(gQueue);
|
||||
|
||||
BaseType_t result = xTaskCreatePinnedToCore(&PlayTask, "I2S Task", 1024, NULL, 5, NULL, 1);
|
||||
assert(result == pdPASS);
|
||||
}
|
||||
}
|
||||
|
||||
void Odroid_PlayAudio(uint16_t* buffer, int length)
|
||||
{
|
||||
QueueData data = {};
|
||||
|
||||
data.buffer = buffer;
|
||||
data.length = length;
|
||||
|
||||
xQueueSendToBack(gQueue, &data, portMAX_DELAY);
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void Odroid_InitializeAudio(void);
|
||||
void Odroid_PlayAudio(uint16_t* buffer, int length);
|
||||
|
Loading…
Reference in New Issue