diff --git a/Core/Inc/tlv320aic3104_ctrl.h b/Core/Inc/tlv320aic3104_ctrl.h new file mode 100644 index 0000000..e75c1d5 --- /dev/null +++ b/Core/Inc/tlv320aic3104_ctrl.h @@ -0,0 +1,22 @@ +#ifndef __TLV320AIC3104_CTRL_H__ +#define __TLV320AIC3104_CTRL_H__ + +#include + + +typedef enum CODEC_SELECT_en { + CODEC_A = 0, + CODEC_B = 1, +} CODEC_SELECT; + +typedef enum TLV_PAGE_SELECT_en { + TLV_PAGE_0 = 0, + TLV_PAGE_1 = 1, +} TLV_PAGE_SELECT; + +extern int16_t TlvPageSelect(CODEC_SELECT codec, TLV_PAGE_SELECT page); +extern int16_t TlvReadReg(CODEC_SELECT codec, TLV_PAGE_SELECT page, uint8_t reg); +extern int16_t TlvWriteReg(CODEC_SELECT codec, TLV_PAGE_SELECT page, uint8_t reg, uint8_t val); + + +#endif diff --git a/Core/Src/tlv320aic3104_ctrl.c b/Core/Src/tlv320aic3104_ctrl.c new file mode 100644 index 0000000..fa7ba36 --- /dev/null +++ b/Core/Src/tlv320aic3104_ctrl.c @@ -0,0 +1,90 @@ +/***************************************************************************//** +* @file tlv320aic3104_ctrl.c +* @brief Control functions for TLV320AIC3104 audio codec using I2C +*//****************************************************************************/ + +//------------------------------C library--------------------------------------- +#include +//----------------------------user includes------------------------------------- +#include "tlv320aic3104_ctrl.h" +#include "i2c_master.h" +#include "main.h" +//------------------------------------------------------------------------------ + + +/* Private macros ------------------------------------------------------------*/ + +// Codecs on different I2C buses +#define I2C_CODEC_A I2C1 +#define I2C_CODEC_B I2C3 + +#define CODEC_I2C_ADDR 0x30 // left-aligned 7-bit slave address + +/* Private variables ---------------------------------------------------------*/ +static uint8_t PageSelect[2] = {0xFF, 0xFF}; // current page selected for each codec, to optimize page switching + +/* Functions -----------------------------------------------------------------*/ + + +/***************************************************************************//** +* @brief Read register value from codec +* @param codec: codec select (0 for CODEC_A, 1 for CODEC_B) +* @param page: page select (0 or 1) +* @param reg: register address (0-127) +* @return register value (0-255) on success, negative error code on failure +*//****************************************************************************/ +int16_t TlvReadReg(CODEC_SELECT codec, TLV_PAGE_SELECT page, uint8_t reg) { + if (page != PageSelect[codec]) { + int err = TlvPageSelect(codec, page); + if (err < 0) return err; + } + if (reg) reg--; // workaround: reading gives regaddr+1 positions back at (datasheet is wrong...) + uint8_t val = 0; + int err = I2C_ReadReg((codec == CODEC_A) ? I2C_CODEC_A : I2C_CODEC_B, + CODEC_I2C_ADDR, + ®, 1, + &val, 1); + if (err < 0) return err; + return val; +} + +/***************************************************************************//** +* @brief Write register value to codec +* @param codec: codec select (0 for CODEC_A, 1 for CODEC_B) +* @param reg: register address (0-127) +* @param val: register value to write (0-255) +* @return 0 on success, negative error code on failure +*//****************************************************************************/ +int16_t TlvWriteReg(CODEC_SELECT codec, TLV_PAGE_SELECT page, uint8_t reg, uint8_t val) { + if (page != PageSelect[codec]) { + int err = TlvPageSelect(codec, page); + if (err < 0) return err; + } + uint8_t data[2] = {reg, val}; + int err = I2C_Write((codec == CODEC_A) ? I2C_CODEC_A : I2C_CODEC_B, + CODEC_I2C_ADDR, + data, 2); + return err; +} + +/***************************************************************************//** +* @brief Write register value to codec +* @param codec: codec select (0 for CODEC_A, 1 for CODEC_B) +* @param reg: register address (0-127) +* @param val: register value to write (0-255) +* @return 0 on success, negative error code on failure +*//****************************************************************************/ +int16_t TlvPageSelect(CODEC_SELECT codec, TLV_PAGE_SELECT page) { + if (codec > CODEC_B) codec = CODEC_B; // clamp codec select + PageSelect[codec] = page; // update current page for the codec + uint8_t reg = 0; // page select register address is 0 + uint8_t data[2] = {reg, page}; + int err = I2C_Write((codec == CODEC_A) ? I2C_CODEC_A : I2C_CODEC_B, + CODEC_I2C_ADDR, + data, 2); + return err; +} + + + +