i2s: improve performance, add extra methods

This commit is contained in:
Daniel Fekete 2017-06-15 21:34:18 +02:00
parent 1373c95224
commit 63b8c33205
2 changed files with 43 additions and 23 deletions

View File

@ -24,19 +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) {
void I2SClass::setBuffer(int16_t *buffer, int bufferSize) {
this->doubleBuffer = buffer;
this->halfBufferSize = bufferSize / 2;
this->bufferSize = bufferSize;
}
int I2SClass::getBufferSize() {
return halfBufferSize * 2;
return bufferSize;
}
uint8_t I2SClass::begin(i2s_mode_t mode, uint32_t sampleRate, uint8_t bitsPerSample) {
static uint16_t static_buffer[2048];
static int16_t static_buffer[2048];
setBuffer((uint16_t*)&static_buffer, 2048);
setBuffer(static_buffer, 2048);
#ifdef SPI1
if (handle.Instance == SPI1) __HAL_RCC_SPI1_CLK_ENABLE();
@ -139,28 +139,42 @@ uint8_t I2SClass::begin(i2s_mode_t mode, uint32_t sampleRate, uint8_t bitsPerSam
I2SClass *i2sDma;
extern "C" void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) {
i2sDma->dmaDone = true;
i2sDma->tail += i2sDma->dmaSendSize;
if ((uint32_t)(i2sDma->head - i2sDma->tail) > i2sDma->dmaSendSize) {
HAL_I2S_Transmit_DMA(hi2s, (uint16_t*)(i2sDma->doubleBuffer + (i2sDma->tail % i2sDma->bufferSize)), i2sDma->dmaSendSize);
} else {
i2sDma->dmaDone = true;
}
}
void I2SClass::write(int16_t data) {
doubleBuffer[dataIndex + bufferIndex * halfBufferSize] = data;
dataIndex++;
while((head + 1) % bufferSize == tail % bufferSize);
if (dataIndex == halfBufferSize) {
while(!dmaDone);
doubleBuffer[head % bufferSize] = data;
head++;
if (dmaDone && (uint32_t)(head - tail) > dmaSendSize) {
i2sDma = this;
dmaDone = false;
HAL_I2S_Transmit_DMA(&handle, doubleBuffer + bufferIndex * halfBufferSize, halfBufferSize);
dataIndex = 0;
bufferIndex++;
bufferIndex %= 2;
HAL_I2S_Transmit_DMA(&handle, (uint16_t*)(doubleBuffer + (tail % bufferSize)), dmaSendSize);
}
}
void I2SClass::write(int16_t *data, size_t samples) {
for(size_t i=0; i<samples; i++) {
write(data[i]);
}
}
void I2SClass::write(int16_t *data, uint16_t size) {
for(int i=0; i<size; i++) {
write(data[i]);
}
uint32_t I2SClass::availableForWrite() {
return bufferSize - (head - tail);
}
uint32_t I2SClass::getDelay() {
return dmaSendSize;
}
void I2SClass::stm32SetSD(uint8_t sd) {

View File

@ -19,13 +19,17 @@ class I2SClass {
uint8_t begin(i2s_mode_t mode, uint32_t sampleRate, uint8_t bitsPerSample);
void setBuffer(uint16_t *buffer, int bufferSize);
void setBuffer(int16_t *buffer, int bufferSize);
int getBufferSize();
uint32_t getDelay();
uint32_t availableForWrite();
void write(int16_t data);
void write(int16_t *data, uint16_t size);
void write(int16_t *data, size_t size);
void stm32SetSD(uint8_t sd);
void stm32SetWS(uint8_t ws);
@ -47,9 +51,11 @@ class I2SClass {
DMA_HandleTypeDef dmaHandle;
int halfBufferSize;
uint16_t *doubleBuffer;
volatile uint16_t dataIndex, bufferIndex;
uint32_t bufferSize;
int16_t *doubleBuffer;
uint16_t dmaSendSize = 512;
volatile uint32_t head = 0, tail = 0;
volatile bool dmaDone = true;