Add I2S implementation
This commit is contained in:
parent
c3fff6c080
commit
4760f3dead
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue