Add I2S implementation

This commit is contained in:
Daniel Fekete 2017-04-25 21:39:00 +02:00
parent c3fff6c080
commit 4760f3dead
7 changed files with 174 additions and 1 deletions

View File

@ -51,6 +51,16 @@ void stm32AfSPIInit(const SPI_TypeDef *instance,
}
void stm32AfI2SInit(const SPI_TypeDef *instance,
GPIO_TypeDef *sdPort, uint32_t sdPin,
GPIO_TypeDef *wsPort, uint32_t wsPin,
GPIO_TypeDef *ckPort, uint32_t ckPin) {
stm32AfInit(chip_af_i2s_sd, sizeof(chip_af_i2s_sd) / sizeof(chip_af_i2s_sd[0]), instance, sdPort, sdPin, GPIO_MODE_AF_PP, GPIO_NOPULL);
stm32AfInit(chip_af_i2s_ws, sizeof(chip_af_i2s_ws) / sizeof(chip_af_i2s_ws[0]), instance, wsPort, wsPin, GPIO_MODE_AF_PP, GPIO_NOPULL);
stm32AfInit(chip_af_i2s_ck, sizeof(chip_af_i2s_ck) / sizeof(chip_af_i2s_ck[0]), instance, ckPort, ckPin, GPIO_MODE_AF_PP, GPIO_NOPULL);
}
void stm32AfI2CInit(const I2C_TypeDef *instance,
GPIO_TypeDef *sdaPort, uint32_t sdaPin,
GPIO_TypeDef *sclPort, uint32_t sclPin) {

View File

@ -51,6 +51,11 @@ void stm32AfSPIInit(const SPI_TypeDef *instance,
GPIO_TypeDef *misoPort, uint32_t misoPin,
GPIO_TypeDef *sckPort, uint32_t sckPin);
void stm32AfI2SInit(const SPI_TypeDef *instance,
GPIO_TypeDef *sdPort, uint32_t sdPin,
GPIO_TypeDef *wsPort, uint32_t wsPin,
GPIO_TypeDef *ckPort, uint32_t ckPin);
void stm32AfI2CInit(const I2C_TypeDef *instance,
GPIO_TypeDef *sdaPort, uint32_t sdaPin,
GPIO_TypeDef *sclPort, uint32_t sclPin);

View File

@ -0,0 +1,104 @@
#include "I2S.h"
#include "stm32_gpio_af.h"
I2SClass::I2SClass(SPI_TypeDef *instance) {
handle.Instance = instance;
}
I2SClass::I2SClass(SPI_TypeDef *instance, uint8_t sd, uint8_t ws, uint8_t ck) {
handle.Instance = instance;
this->sdPort = variant_pin_list[sd].port;
this->sdPin = variant_pin_list[sd].pin_mask;
this->wsPort = variant_pin_list[ws].port;
this->wsPin = variant_pin_list[ws].pin_mask;
this->ckPort = variant_pin_list[ck].port;
this->ckPin = variant_pin_list[ck].pin_mask;
}
uint8_t I2SClass::begin(i2s_mode_t mode, uint32_t sampleRate, uint8_t bitsPerSample) {
#ifdef SPI1
if (handle.Instance == SPI1) __HAL_RCC_SPI1_CLK_ENABLE();
#endif
#ifdef SPI2
if (handle.Instance == SPI2) __HAL_RCC_SPI2_CLK_ENABLE();
#endif
#ifdef SPI3
if (handle.Instance == SPI3) __HAL_RCC_SPI3_CLK_ENABLE();
#endif
#ifdef SPI4
if (handle.Instance == SPI4) __HAL_RCC_SPI4_CLK_ENABLE();
#endif
#ifdef SPI5
if (handle.Instance == SPI5) __HAL_RCC_SPI5_CLK_ENABLE();
#endif
#ifdef SPI6
if (handle.Instance == SPI6) __HAL_RCC_SPI6_CLK_ENABLE();
#endif
stm32AfI2SInit(handle.Instance, sdPort, sdPin, wsPort, wsPin, ckPort, ckPin);
if (mode == I2S_PHILIPS_MODE) {
handle.Init.Standard = I2S_STANDARD_PHILIPS;
} else if (mode == I2S_LEFT_JUSTIFIED_MODE) {
handle.Init.Standard = I2S_STANDARD_LSB;
} else if (mode == I2S_RIGHT_JUSTIFIED_MODE) {
handle.Init.Standard = I2S_STANDARD_MSB;
} else {
return false;
}
handle.Init.Mode = I2S_MODE_MASTER_TX;
handle.Init.MCLKOutput = I2S_MCLKOUTPUT_DISABLE;
handle.Init.AudioFreq = I2S_AUDIOFREQ_44K;
handle.Init.CPOL = I2S_CPOL_LOW;
handle.Init.ClockSource = I2S_CLOCK_PLL;
handle.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE;
if (sampleRate >= 96000) {
handle.Init.AudioFreq = I2S_AUDIOFREQ_96K;
} else if (sampleRate >= 48000) {
handle.Init.AudioFreq = I2S_AUDIOFREQ_48K;
} else if (sampleRate >= 44000) {
handle.Init.AudioFreq = I2S_AUDIOFREQ_44K;
} else if (sampleRate >= 32000) {
handle.Init.AudioFreq = I2S_AUDIOFREQ_32K;
} else if (sampleRate >= 22000) {
handle.Init.AudioFreq = I2S_AUDIOFREQ_22K;
} else if (sampleRate >= 16000) {
handle.Init.AudioFreq = I2S_AUDIOFREQ_16K;
} else if (sampleRate >= 11000) {
handle.Init.AudioFreq = I2S_AUDIOFREQ_11K;
} else {
handle.Init.AudioFreq = I2S_AUDIOFREQ_8K;
}
if (bitsPerSample == 16) {
handle.Init.DataFormat = I2S_DATAFORMAT_16B;
} else if (bitsPerSample == 24) {
handle.Init.DataFormat = I2S_DATAFORMAT_24B;
} else if (bitsPerSample == 32) {
handle.Init.DataFormat = I2S_DATAFORMAT_32B;
} else {
return false;
}
return HAL_I2S_Init(&handle) == HAL_OK;
}
void I2SClass::write(uint16_t data) {
HAL_I2S_Transmit(&handle, &data, 1, 1000);
}
void I2SClass::write32(uint32_t data) {
HAL_I2S_Transmit(&handle, (uint16_t*)&data, 1, 1000);
}
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);
}

View File

@ -1 +1,36 @@
// TODO implement https://www.arduino.cc/en/Reference/I2S using HAL_I2S_xxx
#ifndef _I2S_H
#define _I2S_H
#include "stm32_def.h"
typedef enum {
I2S_PHILIPS_MODE,
I2S_RIGHT_JUSTIFIED_MODE,
I2S_LEFT_JUSTIFIED_MODE
} i2s_mode_t;
class I2SClass {
public:
I2SClass(SPI_TypeDef *instance);
I2SClass(SPI_TypeDef *instance, uint8_t sd, uint8_t ws, uint8_t ck);
uint8_t begin(i2s_mode_t mode, uint32_t sampleRate, uint8_t bitsPerSample);
void write(uint16_t data);
void write32(uint32_t data);
void write(uint16_t *data, uint16_t size);
void write32(uint32_t *data, uint16_t size);
I2S_HandleTypeDef handle;
GPIO_TypeDef *sdPort = NULL;
uint32_t sdPin = 0;
GPIO_TypeDef *wsPort = NULL;
uint32_t wsPin = 0;
GPIO_TypeDef *ckPort = NULL;
uint32_t ckPin = 0;
};
#endif

View File

@ -4,6 +4,7 @@
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();
@ -33,6 +34,14 @@ void SystemClock_Config(void) {
Error_Handler();
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

View File

@ -4,6 +4,7 @@
void SystemClock_Config(void) {
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
__HAL_RCC_PWR_CLK_ENABLE();
@ -33,6 +34,15 @@ void SystemClock_Config(void) {
Error_Handler();
}
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
PeriphClkInitStruct.PLLI2S.PLLI2SN = 192;
PeriphClkInitStruct.PLLI2S.PLLI2SR = 2;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);