i2s: add DMA

This commit is contained in:
Daniel Fekete 2017-06-09 19:56:07 +02:00
parent 9c5f9ec7b2
commit b9410d7bfd
2 changed files with 69 additions and 14 deletions

View File

@ -1,6 +1,8 @@
#include "I2S.h"
#include "stm32_gpio_af.h"
#include "stm32_dma.h"
#include "Arduino.h"
I2SClass::I2SClass(SPI_TypeDef *instance) {
@ -22,7 +24,19 @@ I2SClass::I2SClass(SPI_TypeDef *instance, uint8_t sd, uint8_t ws, uint8_t ck, ui
stm32SetMCK(mck);
}
void I2SClass::setBuffer(uint16_t *buffer, int bufferSize) {
this->doubleBuffer = buffer;
this->halfBufferSize = bufferSize / 2;
}
int I2SClass::getBufferSize() {
return halfBufferSize * 2;
}
uint8_t I2SClass::begin(i2s_mode_t mode, uint32_t sampleRate, uint8_t bitsPerSample) {
static uint16_t static_buffer[2048];
setBuffer((uint16_t*)&static_buffer, 2048);
#ifdef SPI1
if (handle.Instance == SPI1) __HAL_RCC_SPI1_CLK_ENABLE();
@ -100,23 +114,53 @@ uint8_t I2SClass::begin(i2s_mode_t mode, uint32_t sampleRate, uint8_t bitsPerSam
return false;
}
__HAL_RCC_DMA1_CLK_ENABLE();
if (!stm32DmaAcquire(&dmaHandle, SPI_TX, (void*)handle.Instance, true)) {
return false;
}
dmaHandle.Init.Direction = DMA_MEMORY_TO_PERIPH;
dmaHandle.Init.PeriphInc = DMA_PINC_DISABLE;
dmaHandle.Init.MemInc = DMA_MINC_ENABLE;
dmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
dmaHandle.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
dmaHandle.Init.Mode = DMA_NORMAL;
dmaHandle.Init.Priority = DMA_PRIORITY_LOW;
dmaHandle.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&dmaHandle);
__HAL_LINKDMA(&handle,hdmatx,dmaHandle);
return HAL_I2S_Init(&handle) == HAL_OK;
}
void I2SClass::write(uint16_t data) {
HAL_I2S_Transmit(&handle, &data, 1, 1000);
I2SClass *i2sDma;
extern "C" void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) {
i2sDma->dmaDone = true;
}
void I2SClass::write32(uint32_t data) {
HAL_I2S_Transmit(&handle, (uint16_t*)&data, 1, 1000);
void I2SClass::write(int16_t data) {
doubleBuffer[dataIndex + bufferIndex * halfBufferSize] = data;
dataIndex++;
if (dataIndex == halfBufferSize) {
while(!dmaDone);
i2sDma = this;
dmaDone = false;
HAL_I2S_Transmit_DMA(&handle, doubleBuffer + bufferIndex * halfBufferSize, halfBufferSize);
dataIndex = 0;
bufferIndex++;
bufferIndex %= 2;
}
}
void I2SClass::write(uint16_t *data, uint16_t size) {
HAL_I2S_Transmit(&handle, data, size, 1000);
}
void I2SClass::write32(uint32_t *data, uint16_t size) {
HAL_I2S_Transmit(&handle, (uint16_t*)data, size, 1000);
void I2SClass::write(int16_t *data, uint16_t size) {
for(int i=0; i<size; i++) {
write(data[i]);
}
}
void I2SClass::stm32SetSD(uint8_t sd) {

View File

@ -19,11 +19,13 @@ class I2SClass {
uint8_t begin(i2s_mode_t mode, uint32_t sampleRate, uint8_t bitsPerSample);
void write(uint16_t data);
void write32(uint32_t data);
void setBuffer(uint16_t *buffer, int bufferSize);
void write(uint16_t *data, uint16_t size);
void write32(uint32_t *data, uint16_t size);
int getBufferSize();
void write(int16_t data);
void write(int16_t *data, uint16_t size);
void stm32SetSD(uint8_t sd);
void stm32SetWS(uint8_t ws);
@ -42,6 +44,15 @@ class I2SClass {
uint32_t ckPin = 0;
GPIO_TypeDef *mckPort = NULL;
uint32_t mckPin = 0;
DMA_HandleTypeDef dmaHandle;
int halfBufferSize;
uint16_t *doubleBuffer;
volatile uint16_t dataIndex, bufferIndex;
volatile bool dmaDone = true;
};
#endif