Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
274 lines (235 sloc) 9.05 KB
#include "ak4556.h"
#include "debug_hw.h"
#include "debug_usart.h"
#include <stm32f7xx_hal.h>
#include "bootloader.h"
// private structs & vars
SAI_HandleTypeDef SaiHandle;
SAI_HandleTypeDef SaiHandle2;
DMA_HandleTypeDef hSaiDma;
DMA_HandleTypeDef hSaiDma2;
// AUDIO_DrvTypeDef *audio_drv;
// audio buffers for codec DMA
// prefer to malloc these in the Init fn?
__IO uint32_t inBuff[AUDIO_BUFF_SIZE];
__IO uint32_t outBuff[AUDIO_BUFF_SIZE];
// exported fns
void ak4556_Init( uint32_t s_rate )
{
RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct;
// Configure PLLSAI prescalers
// PLLSAI_VCO: VCO_429M
// SAI_CLK(first level) = PLLSAI_VCO/PLLSAIQ = 429/2 = 214.5 Mhz
// SAI_CLK_x = SAI_CLK(first level)/PLLSAIDIVQ = 214.5/19 = 11.289 Mhz
// nb: this uses SAI2 pll clock?!
RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
RCC_PeriphCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI;
// 48kHz; 44k 24k
RCC_PeriphCLKInitStruct.PLLSAI.PLLSAIN = 344; // 429 344
RCC_PeriphCLKInitStruct.PLLSAI.PLLSAIQ = 7; // 2 7
RCC_PeriphCLKInitStruct.PLLSAIDivQ = 1; // 19 2
HAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);
// Initialize SAI
__HAL_SAI_RESET_HANDLE_STATE(&SaiHandle);
__HAL_SAI_RESET_HANDLE_STATE(&SaiHandle2);
// DAC
SaiHandle.Instance = AUDIO_SAI_A;
__HAL_SAI_DISABLE(&SaiHandle);
SaiHandle.Init.AudioMode = SAI_MODEMASTER_TX;
SaiHandle.Init.Synchro = SAI_ASYNCHRONOUS;
SaiHandle.Init.SynchroExt = SAI_SYNCEXT_OUTBLOCKA_ENABLE;
SaiHandle.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
SaiHandle.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
SaiHandle.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; //HF instead of 1QF?
SaiHandle.Init.AudioFrequency = s_rate;
SaiHandle.Init.Protocol = SAI_FREE_PROTOCOL;
SaiHandle.Init.DataSize = SAI_DATASIZE_24;
SaiHandle.Init.FirstBit = SAI_FIRSTBIT_MSB;
SaiHandle.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; // unsure?
SaiHandle.FrameInit.FrameLength = 64;
SaiHandle.FrameInit.ActiveFrameLength = 32;
SaiHandle.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
SaiHandle.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
SaiHandle.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
SaiHandle.SlotInit.FirstBitOffset = 0;
SaiHandle.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
SaiHandle.SlotInit.SlotNumber = 2;
SaiHandle.SlotInit.SlotActive = SAI_SLOTACTIVE_0;
if( HAL_OK != HAL_SAI_Init(&SaiHandle) ){
Debug_USART_printf("SAI failed init");
}
// ADC
SaiHandle2.Instance = AUDIO_SAI_B;
__HAL_SAI_DISABLE(&SaiHandle2);
SaiHandle2.Init.AudioMode = SAI_MODESLAVE_RX;
SaiHandle2.Init.Synchro = SAI_SYNCHRONOUS; // lock to other block
SaiHandle2.Init.SynchroExt = SAI_SYNCEXT_OUTBLOCKA_ENABLE;
SaiHandle2.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
SaiHandle2.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
SaiHandle2.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
SaiHandle2.Init.AudioFrequency = s_rate;
SaiHandle2.Init.Protocol = SAI_FREE_PROTOCOL;
SaiHandle2.Init.DataSize = SAI_DATASIZE_24;
SaiHandle2.Init.FirstBit = SAI_FIRSTBIT_MSB;
SaiHandle2.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; // unsure?
SaiHandle2.FrameInit.FrameLength = 64;
SaiHandle2.FrameInit.ActiveFrameLength = 32;
SaiHandle2.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
SaiHandle2.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
SaiHandle2.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
SaiHandle2.SlotInit.FirstBitOffset = 0;
SaiHandle2.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
SaiHandle2.SlotInit.SlotNumber = 2;
SaiHandle2.SlotInit.SlotActive = SAI_SLOTACTIVE_0;
if( HAL_OK != HAL_SAI_Init(&SaiHandle2) ){
Debug_USART_printf("SAI failed init");
}
// Enable SAI to generate clock used by audio driver
__HAL_SAI_ENABLE(&SaiHandle2); // adc before dac
__HAL_SAI_ENABLE(&SaiHandle);
// Reset codec
HAL_GPIO_WritePin(AUDIO_SAI_RESET_GPIO_PORT, AUDIO_SAI_RESET_PIN, GPIO_PIN_RESET);
register unsigned int i; // wait a little while
for( i = 0; i < 1000; ++i ){
__asm__ __volatile__ ("nop\n\t":::"memory");
}
HAL_GPIO_WritePin(AUDIO_SAI_RESET_GPIO_PORT, AUDIO_SAI_RESET_PIN, GPIO_PIN_SET);
}
void ak4556_Start( void )
{
// Zero the output buffer
for( uint16_t i=0; i<AUDIO_BUFF_SIZE; i++ ){
inBuff[i] = 0;
outBuff[i] = 0x77777777;
}
// Enable DAC output
if( HAL_OK != HAL_SAI_Transmit_DMA(&SaiHandle, (uint8_t *)outBuff, AUDIO_BUFF_SIZE) ){
Debug_USART_printf("failed to transmit sai dma");
}
// Enable ADC audio input
if( HAL_OK != HAL_SAI_Receive_DMA(&SaiHandle2, (uint8_t *)inBuff, AUDIO_BUFF_SIZE) ){
Debug_USART_printf("failed to receive sai dma");
}
}
void ak4556_Stop( void )
{
HAL_SAI_DMAStop( &SaiHandle );
HAL_SAI_DMAStop( &SaiHandle2 );
}
void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
{
GPIO_InitTypeDef GPIO_Init;
GPIO_Init.Mode = GPIO_MODE_AF_PP;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
__HAL_RCC_DMA2_CLK_ENABLE();
if(hsai == &SaiHandle){
AUDIO_SAI_A_CLK_ENABLE(); // RCC
AUDIO_SAI_A_MCLK_ENABLE();
AUDIO_SAI_A_SCK_ENABLE();
AUDIO_SAI_A_FS_ENABLE();
AUDIO_SAI_A_SD_ENABLE();
GPIO_Init.Alternate = AUDIO_SAI_A_FS_AF;
GPIO_Init.Pin = AUDIO_SAI_A_FS_PIN;
HAL_GPIO_Init(AUDIO_SAI_A_FS_GPIO_PORT, &GPIO_Init);
GPIO_Init.Alternate = AUDIO_SAI_A_SCK_AF;
GPIO_Init.Pin = AUDIO_SAI_A_SCK_PIN;
HAL_GPIO_Init(AUDIO_SAI_A_SCK_GPIO_PORT, &GPIO_Init);
GPIO_Init.Alternate = AUDIO_SAI_A_SD_AF;
GPIO_Init.Pin = AUDIO_SAI_A_SD_PIN;
HAL_GPIO_Init(AUDIO_SAI_A_SD_GPIO_PORT, &GPIO_Init);
GPIO_Init.Alternate = AUDIO_SAI_A_MCLK_AF;
GPIO_Init.Pin = AUDIO_SAI_A_MCLK_PIN;
HAL_GPIO_Init(AUDIO_SAI_A_MCLK_GPIO_PORT, &GPIO_Init);
AUDIO_SAI_RESET_ENABLE();
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_PULLUP;
GPIO_Init.Pin = AUDIO_SAI_RESET_PIN;
HAL_GPIO_Init(AUDIO_SAI_RESET_GPIO_PORT, &GPIO_Init);
// Configure DMA used for SAI_A
// st3, ch0
hSaiDma.Init.Channel = DMA_CHANNEL_0;
hSaiDma.Init.Direction = DMA_MEMORY_TO_PERIPH;
hSaiDma.Init.PeriphInc = DMA_PINC_DISABLE;
hSaiDma.Init.MemInc = DMA_MINC_ENABLE;
hSaiDma.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hSaiDma.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hSaiDma.Init.Mode = DMA_CIRCULAR;
hSaiDma.Init.Priority = DMA_PRIORITY_HIGH;
hSaiDma.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hSaiDma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hSaiDma.Init.MemBurst = DMA_MBURST_SINGLE;
hSaiDma.Init.PeriphBurst = DMA_PBURST_SINGLE;
// Select the DMA instance to be used for the transfer : DMA2_Stream6
hSaiDma.Instance = DMA2_Stream1;
// Associate the DMA handle
__HAL_LINKDMA(hsai, hdmatx, hSaiDma);
// Deinitialize the Stream for new transfer
HAL_DMA_DeInit(&hSaiDma);
// Configure the DMA Stream
if( HAL_OK != HAL_DMA_Init(&hSaiDma) ){
Debug_USART_printf("dma1 failed to init");
}
} else { // BLOCK B
AUDIO_SAI_B_CLK_ENABLE(); // RCC
AUDIO_SAI_B_SD_ENABLE();
GPIO_Init.Alternate = AUDIO_SAI_B_SD_AF;
GPIO_Init.Pin = AUDIO_SAI_B_SD_PIN;
HAL_GPIO_Init(AUDIO_SAI_B_SD_GPIO_PORT, &GPIO_Init);
// Configure DMA used for SAI_B
// st5, ch0
hSaiDma2.Init.Channel = DMA_CHANNEL_0;
hSaiDma2.Init.Direction = DMA_PERIPH_TO_MEMORY;
hSaiDma2.Init.PeriphInc = DMA_PINC_DISABLE;
hSaiDma2.Init.MemInc = DMA_MINC_ENABLE;
hSaiDma2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
hSaiDma2.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
hSaiDma2.Init.Mode = DMA_CIRCULAR;
hSaiDma2.Init.Priority = DMA_PRIORITY_HIGH;
hSaiDma2.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hSaiDma2.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hSaiDma2.Init.MemBurst = DMA_MBURST_SINGLE;
hSaiDma2.Init.PeriphBurst = DMA_PBURST_SINGLE;
// Select the DMA instance to be used for the transfer : DMA2_Stream6
hSaiDma2.Instance = DMA2_Stream5;
// Associate the DMA handle
__HAL_LINKDMA(hsai, hdmarx, hSaiDma2);
// Deinitialize the Stream for new transfer
HAL_DMA_DeInit(&hSaiDma2);
// Configure the DMA Stream
if( HAL_OK != HAL_DMA_Init(&hSaiDma2) ){
Debug_USART_printf("dma2 failed to init");
}
// Codec request triggers transfer & new frame calc
HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 0x02, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
}
}
// DMA triggered by codec requesting more ADC!
void DMA2_Stream5_IRQHandler(void)
{
// essentially triggers below callbacks
HAL_DMA_IRQHandler(SaiHandle2.hdmarx);
}
void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
{
Debug_HW_set(bm_1, 1);
Debug_HW_set(led_x, 1);
DSP_Block_Process(&inBuff[0], &outBuff[0], DSP_BLOCK_SIZE);
Debug_HW_set(led_x, 0);
Debug_HW_set(bm_1, 0);
}
void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
{
Debug_HW_set(bm_1, 1);
Debug_HW_set(led_x, 1);
DSP_Block_Process(&inBuff[DSP_BLOCK_SIZE], &outBuff[DSP_BLOCK_SIZE], DSP_BLOCK_SIZE);
Debug_HW_set(led_x, 0);
Debug_HW_set(bm_1, 0);
}
void dsp_clear_buffer( void )
{
for( uint16_t i=0; i<DSP_BLOCK_SIZE*2; i++ ){
outBuff[i] = 0;
}
}