DIS10/dis10_lab2.1A/config.c
2024-02-22 11:29:05 +01:00

290 lines
9.8 KiB
C

/*
* Configure functions to use the TI TLV320AIC3254 codec on the
* CC3200AUDBOOST board with the CC3220S-LAUNCHXL board
* without using DMA.
*
* Copyright (C) 2018, Hogeschool Rotterdam, Harry Broeders
* All rights reserved.
*
* Based on Driver for TI TLV320AIC3110 CODEC
* Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*/
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <ti/devices/cc32xx/inc/hw_common_reg.h>
#include <ti/devices/cc32xx/inc/hw_i2c.h>
#include <ti/devices/cc32xx/inc/hw_ints.h>
#include <ti/devices/cc32xx/inc/hw_memmap.h>
#include <ti/devices/cc32xx/inc/hw_types.h>
#include <ti/devices/cc32xx/driverlib/rom.h>
#include <ti/devices/cc32xx/driverlib/rom_map.h>
#include <ti/devices/cc32xx/driverlib/i2c.h>
#include <ti/devices/cc32xx/driverlib/i2s.h>
#include <ti/devices/cc32xx/driverlib/pin.h>
#include <ti/devices/cc32xx/driverlib/prcm.h>
#include <ti/devices/cc32xx/driverlib/utils.h>
#include <ti/drivers/I2C.h>
#include <ti/drivers/power/PowerCC32XX.h>
#include "config.h"
// Configure an I2C connection using the TI I2C driver.
I2C_Handle ConfigureI2C(uint_least8_t index, I2C_BitRate bitRate)
{
I2C_Handle i2cHandle;
I2C_Params i2cParams;
I2C_init();
I2C_Params_init(&i2cParams);
i2cParams.bitRate = bitRate;
i2cHandle = I2C_open(index, &i2cParams);
if (i2cHandle == NULL) {
// Error initializing I2C.
while (1);
}
return i2cHandle;
}
// Configure an I2S connection which is use to send/receive samples to/from the codec.
void ConfigureI2S(unsigned long peripheral, unsigned long base, unsigned int samplingFrequency)
{
// Register power dependency. Keeps the I2S clock running in SLP and DSLP modes.
int_fast16_t ret = Power_setDependency(PowerCC32XX_PERIPH_I2S);
if (ret != Power_SOK) {
// Error setting power dependency.
while (1);
}
// There is no TI I2S driver (without DMA) available so the TI driverlib API is used.
PRCMPeripheralReset(peripheral);
I2SEnable(base, I2S_MODE_TX_RX_SYNC);
unsigned int bitClock = samplingFrequency * 16 * 2;
PRCMI2SClockFreqSet(bitClock);
I2SConfigSetExpClk(base, bitClock, bitClock, I2S_MODE_MASTER | I2S_SLOT_SIZE_16 | I2S_PORT_CPU);
I2SSerializerConfig(base, I2S_DATA_LINE_0, I2S_SER_MODE_TX, I2S_INACT_LOW_LEVEL);
I2SSerializerConfig(base, I2S_DATA_LINE_1, I2S_SER_MODE_RX, I2S_INACT_LOW_LEVEL);
// Configure I2S pins in pin mux
PinTypeI2S(PIN_64, PIN_MODE_7); // xr0Pin = I2S SDout (CC3220S-LAUNCHXL) = DIN_J3 (CC3200AUDBOOST)
PinTypeI2S(PIN_50, PIN_MODE_6); // xr1Pin = I2S SDin (CC3220S-LAUNCHXL) = DOUT_J3 (CC3200AUDBOOST)
PinTypeI2S(PIN_53, PIN_MODE_2); // clkPin = I2S SCLK (CC3220S-LAUNCHXL) = BCLK_J3 (CC3200AUDBOOST)
PinTypeI2S(PIN_63, PIN_MODE_7); // fsxPin = I2S WC (CC3220S-LAUNCHXL) = FSYNC_J3 (CC3200AUDBOOST)
PRCMPeripheralClkEnable(peripheral, PRCM_RUN_MODE_CLK);
}
#define CODEC_I2C_SLAVE_ADDR ((0x30 >> 1))
static uint8_t CodecRegRead(I2C_Handle i2cHandle, uint8_t regAddr)
{
I2C_Transaction i2cTransaction;
uint8_t data;
i2cTransaction.slaveAddress = CODEC_I2C_SLAVE_ADDR;
i2cTransaction.writeBuf = &regAddr;
i2cTransaction.writeCount = 1;
i2cTransaction.readBuf = &data;
i2cTransaction.readCount = 1;
if (!I2C_transfer(i2cHandle, &i2cTransaction))
{
// I2C transfer failed
while (1);
}
return data;
}
static void CodecRegWrite(I2C_Handle i2cHandle, uint8_t regAddr, uint8_t regValue)
{
uint8_t data[2];
I2C_Transaction i2cTransaction;
data[0] = regAddr;
data[1] = regValue;
i2cTransaction.slaveAddress = CODEC_I2C_SLAVE_ADDR;
i2cTransaction.writeBuf = &data[0];
i2cTransaction.writeCount = 2;
i2cTransaction.readBuf = NULL;
i2cTransaction.readCount = 0;
if (!I2C_transfer(i2cHandle, &i2cTransaction))
{
// I2C transfer failed
while (1);
}
}
static void CodecPageSelect(I2C_Handle i2cHandle, unsigned long pageAddress)
{
CodecRegWrite(i2cHandle, 0, pageAddress);
}
static void CodecReset(I2C_Handle i2cHandle)
{
// Select page 0.
CodecPageSelect(i2cHandle, 0);
// Soft RESET.
CodecRegWrite(i2cHandle, 1, 0x01);
// Wait for 27000 * 3 = 81000 clock cycles @ 80 MHz ~ 1 ms.
UtilsDelay(27000);
}
// volume: 0 -> 0 bB (Highest) to 116 -> -72.3 dB (Lowest)
void AudioVolumeControl(I2C_Handle i2cHandle, signed char volume)
{
// Select page 1
CodecPageSelect(i2cHandle, 1);
// Enable HPL output analog volume
CodecRegWrite(i2cHandle, 22, volume);
CodecRegWrite(i2cHandle, 23, volume);
}
void CodecMute(I2C_Handle i2cHandle)
{
// Select page 0.
CodecPageSelect(i2cHandle, 0);
// Mute.
CodecRegWrite(i2cHandle, 64, 0x0C);
}
void CodecUnmute(I2C_Handle i2cHandle)
{
// Select page 0.
CodecPageSelect(i2cHandle, 0);
// Unmute.
CodecRegWrite(i2cHandle, 64, 0x00);
}
// Codec configure:
// PGA (Programmable Gain Amplifier) = 0 dB.
// Headphone Output = enabled.
// Line outputs (to class D amplifier) = disabled.
// ADC gain = 0 dB.
// AGC (Automatic Gain Control) = disabled.
// ADC processing block = PRB_R1 (default).
// Microphone = disabled.
// DAC processing block = PRB_P1 (default).
// DRC (Dynamic Gain Compression) = disabled.
void ConfigureAudioCodec(I2C_Handle i2cHandle, unsigned int samplingFrequency)
{
// Check parameter.
if (samplingFrequency < 8000 || samplingFrequency > 48000 || samplingFrequency % 4000 != 0)
{
while(1);
// Wrong value for sampling frequency.
}
size_t sampleIndex = (samplingFrequency / 4000) - 2;
// values for DOSR, MDAC, NDAC, NADC and J in steps of 4 kHz starting from 8 kHz to 48 kHz.
// 8 12 16 20 24 28 32 36 40 44 48
int DOSR[] = {512, 512, 384, 304, 256, 208, 192, 160, 144, 128, 128};
int MDAC[] = { 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2};
int NDAC[] = { 1, 1, 2, 16, 8, 8, 8, 8, 8, 8, 8};
int NADC[] = { 2, 2, 3, 19, 16, 13, 12, 10, 9, 8, 8};
int J[] = { 4, 4, 6, 38, 32, 26, 24, 20, 18, 16, 16};
// Reset code for startup.
CodecReset(i2cHandle);
// Select page 0.
CodecPageSelect(i2cHandle, 0);
// Set I2S Mode and Word Length = 16 bits, BCLK and WCLK are inputs to the device.
CodecRegWrite(i2cHandle, 27, 0x00);
// Clock settings chip
CodecRegWrite(i2cHandle, 4, 0x03); // PLL CLock is CODEC_CLKIN
CodecRegWrite(i2cHandle, 5, 0x94); // PLL enabled, P = 1, R = 4
CodecRegWrite(i2cHandle, 6, J[sampleIndex]); // PLL J
CodecRegWrite(i2cHandle, 7, 0); // PLL D = 0
CodecRegWrite(i2cHandle, 8, 0); // PLL D = 0
// PLL_CLK = PLL_CLKIN * R * J.D / P = PLL_CLKIN * 4 * J = (Fs * 32) * 4 * J
// Clock settings DAC.
CodecRegWrite(i2cHandle, 11, 0x80 + NDAC[sampleIndex]); // NDAC is powered up
CodecRegWrite(i2cHandle, 12, 0x80 + MDAC[sampleIndex]); // MDAC is powered up
CodecRegWrite(i2cHandle, 13, DOSR[sampleIndex] / 256); // DOSR
CodecRegWrite(i2cHandle, 14, DOSR[sampleIndex] % 256);
// DAC_fs = CODEC_CLKIN / (NDAC * MDAC * DOSR)
// Clock settings ADC.
CodecRegWrite(i2cHandle, 18, 0x80 + NADC[sampleIndex]); // NADC is powered up, NADC = 2
CodecRegWrite(i2cHandle, 19, 0x80 + 2); // MADC is powered up, MADC = 2
CodecRegWrite(i2cHandle, 20, 128); // AOSR = 128
// ADC_fs = CODEC_CLKIN / (NADC * MADC * AOSR)
// Configure power supplies.
CodecPageSelect(i2cHandle, 1);
CodecRegWrite(i2cHandle, 1, 0x08); // AVdd and DVdd are connected
CodecRegWrite(i2cHandle, 2, 0x01); // LDO enabled AVDD LDO output = 1.72 V
CodecRegWrite(i2cHandle, 71, 0x32); // Aanalog input powerup = 6.4 ms
CodecRegWrite(i2cHandle, 123, 0x01); // Reference powered up in 40 ms
// Configure ADC channel.
// Route IN1L to Left MICPGA with 10K input impedance.
CodecRegWrite(i2cHandle, 52, 0x40);
// Route CM to Left MICPGA with 10K input impedance.
CodecRegWrite(i2cHandle, 54, 0x40);
// Route IN1R to Right MICPGA with 10K input impedance.
CodecRegWrite(i2cHandle, 55, 0x40);
// Route CM to Right MICPGA with 10K input impedance.
CodecRegWrite(i2cHandle, 57,0x40);
// Floating IN1L.
CodecRegWrite(i2cHandle, 58, 0xC0);
// Select Page 0.
CodecPageSelect(i2cHandle, 0);
// Power up LADC/RADC.
CodecRegWrite(i2cHandle, 81, 0xC0);
// Unmute LADC/RADC.
CodecRegWrite(i2cHandle, 82, 0x00);
// Configure DAC channel.
// Select Page 1.
CodecPageSelect(i2cHandle, 1);
// De-pop: soft stepping disabled, N = 5, Rpop = 6k. See SLAA408A page 11,12,13.
CodecRegWrite(i2cHandle, 20, 0x25);
// Route LDAC/RDAC to HPL/HPR.
CodecRegWrite(i2cHandle, 12, 0x08);
CodecRegWrite(i2cHandle, 13, 0x08);
// Power up HPL/HPR drivers.
CodecRegWrite(i2cHandle, 9, 0x30);
// Unmute HPL/HPR driver, 0dB Gain.
CodecRegWrite(i2cHandle, 16, 0x00);
CodecRegWrite(i2cHandle, 17, 0x00);
// Select Page 0.
CodecPageSelect(i2cHandle, 0);
// Unmute DAC, 0dB Gain.
CodecRegWrite(i2cHandle, 65, 0x00);
CodecRegWrite(i2cHandle, 66, 0x00);
// Select Page 1.
CodecPageSelect(i2cHandle, 1);
while (CodecRegRead(i2cHandle, 63) & 0x11000000 != 0x11000000)
{
UtilsDelay(27000); // delay 27000 * 3 = 81000 clock cycles @ 80 MHz ~ 1 ms.
}
// Select Page 0.
CodecPageSelect(i2cHandle, 0);
// Power up LDAC/RDAC.
CodecRegWrite(i2cHandle, 63, 0xd4);
// Unmute LDAC/RDAC.
CodecRegWrite(i2cHandle, 64, 0x00);
}