1
0
Fork 0

Part 6: Audio

This commit is contained in:
Austin Morlan 2020-05-25 16:32:31 -07:00
parent e525a823dc
commit 8f17172aa3
Signed by: austin
GPG Key ID: FD6B27654AF5E348
4 changed files with 132 additions and 0 deletions

View File

@ -1,6 +1,7 @@
idf_component_register(
SRCS
"main.c"
"odroid/audio.c"
"odroid/battery.c"
"odroid/display.c"
"odroid/input.c"

View File

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

85
src/odroid/audio.c Normal file
View File

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

8
src/odroid/audio.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include <stdint.h>
void Odroid_InitializeAudio(void);
void Odroid_PlayAudio(uint16_t* buffer, int length);