/***************************************************************************//** * @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; }