From 770ad2240b048625a700a5e23f87922a9ef51c57 Mon Sep 17 00:00:00 2001 From: Chip Audette Date: Fri, 10 Feb 2017 13:15:11 -0500 Subject: [PATCH] Add Control_TLV for Teensy Audio Board! --- OpenAudio_ArduinoLibrary.h | 1 + control_tlv320aic3206.h | 48 ++ control_tlv320aic_3206.cpp | 472 ++++++++++++++++++ .../Tympan_TLV320AIC/Tympan_TLV320AIC.ino | 65 +++ keywords.txt | 8 +- 5 files changed, 593 insertions(+), 1 deletion(-) create mode 100644 control_tlv320aic3206.h create mode 100644 control_tlv320aic_3206.cpp create mode 100644 examples/Tympan_TLV320AIC/Tympan_TLV320AIC.ino diff --git a/OpenAudio_ArduinoLibrary.h b/OpenAudio_ArduinoLibrary.h index d3b2361..dbcf340 100644 --- a/OpenAudio_ArduinoLibrary.h +++ b/OpenAudio_ArduinoLibrary.h @@ -1,6 +1,7 @@ #include #include +#include #include #include #include diff --git a/control_tlv320aic3206.h b/control_tlv320aic3206.h new file mode 100644 index 0000000..621cae4 --- /dev/null +++ b/control_tlv320aic3206.h @@ -0,0 +1,48 @@ +/* Extension control files for TLV320AIC3206 + * Copyright (c) 2016, Creare, bpf@creare.com + * + * + */ + +#ifndef control_tlv320_h_ +#define control_tlv320_h_ + +#include "AudioControl.h" + +class AudioControlTLV320AIC3206: public AudioControl +{ +public: + bool enable(void); + bool disable(void); + bool volume(float n); + bool inputLevel(float n); + bool inputSelect(int n); + bool micGain(float n); + bool setMicBias(int n); + +private: + void aic_reset(void); + void aic_init(void); + void aic_initDAC(void); + void aic_initADC(void); + unsigned int aic_readPage(uint8_t page, uint8_t reg); + bool aic_writePage(uint8_t page, uint8_t reg, uint8_t val); + bool aic_writeAddress(uint16_t address, uint8_t val); + bool aic_goToPage(uint8_t page); +}; + +#define TYMPAN_OUTPUT_HEADPHONE_JACK_OUT 1 + +#define TYMPAN_INPUT_LINE_IN 0 +#define TYMPAN_INPUT_JACK_AS_MIC 1 +#define TYMPAN_INPUT_JACK_AS_LINEIN 2 +#define TYMPAN_INPUT_ON_BOARD_MIC 3 + +#define TYMPAN_MIC_BIAS_OFF 0 +#define TYMPAN_MIC_BIAS_1_25 1 +#define TYMPAN_MIC_BIAS_1_7 2 +#define TYMPAN_MIC_BIAS_2_5 3 +#define TYMPAN_MIC_BIAS_VSUPPLY 4 +#define TYMPAN_DEFAULT_MIC_BIAS TYMPAN_MIC_BIAS_2_5 + +#endif diff --git a/control_tlv320aic_3206.cpp b/control_tlv320aic_3206.cpp new file mode 100644 index 0000000..6d6313b --- /dev/null +++ b/control_tlv320aic_3206.cpp @@ -0,0 +1,472 @@ +/* Extension control files for TLV320AIC3206 + * Copyright (c) 2016, Creare, bpf@creare.com + * + * + */ + +#include "control_tlv320aic3206.h" +#include + +//******************************** Constants *******************************// + +#define AIC3206_I2C_ADDR 0x18 + + +#ifndef AIC_FS +# define AIC_FS 44100UL +#endif + +#define AIC_BITS 16 + +#define AIC_I2S_SLAVE 1 +#if AIC_I2S_SLAVE +// Direction of BCLK and WCLK (reg 27) is input if a slave: +# define AIC_CLK_DIR 0 +#else +// If master, make outputs: +# define AIC_CLK_DIR 0x0C +#endif + +//#ifndef AIC_CODEC_CLKIN_BCLK +//# define AIC_CODEC_CLKIN_BCLK 0 +//#endif + +//**************************** Clock Setup **********************************// + +//********************************** 44100 *********************************// +#if AIC_FS == 44100 + +// MCLK = 180000000 * 16 / 255 = 11.294117 MHz // FROM TEENSY, FIXED + +// PLL setup. PLL_OUT = MCLK * R * J.D / P +//// J.D = 7.5264, P = 1, R = 1 => 90.32 MHz // FROM 12MHz CHA AND WHF // +// J.D = 7.9968, P = 1, R = 1 => 90.3168 MHz // For 44.1kHz exact +// J.D = 8.0000000002, P = 1, R = 1 => 9.35294117888MHz // for TEENSY 44.11764706kHz +#define PLL_J 8 +#define PLL_D 0 + +// Bitclock divisor. +// BCLK = DAC_CLK/N = PLL_OUT/NDAC/N = 32*fs or 16*fs +// PLL_OUT = fs*NDAC*MDAC*DOSR +// BLCK = 32*fs = 1411200 = PLL +#if AIC_BITS == 16 +#define BCLK_N 8 +#elif AIC_BITS == 32 +#define BCLK_N 4 +#endif + +// ADC/DAC FS setup. +// ADC_MOD_CLK = CODEC_CLKIN / (NADC * MADC) +// DAC_MOD_CLK = CODEC_CLKIN / (NDAC * MDAC) +// ADC_FS = PLL_OUT / (NADC*MADC*AOSR) +// DAC_FS = PLL_OUT / (NDAC*MDAC*DOSR) +// FS = 90.3168MHz / (8*2*128) = 44100 Hz. +// MOD = 90.3168MHz / (8*2) = 5644800 Hz + +// Actual from Teensy: 44117.64706Hz * 128 => 5647058.82368Hz * 8*2 => 90352941.17888Hz + +// DAC clock config. +// Note: MDAC*DOSR/32 >= RC, where RC is 8 for the default filter. +// See Table 2-21 +// http://www.ti.com/lit/an/slaa463b/slaa463b.pdf +// PB1 - RC = 8. Use M8, N2 +// PB25 - RC = 12. Use M8, N2 + +#define DOSR 128 +#define NDAC 2 +#define MDAC 8 + +#define AOSR 128 +#define NADC 2 +#define MADC 8 + +// Signal Processing Modes, Playback and Recording. +#define PRB_P 1 +#define PRB_R 1 + +#endif // end fs if block + +//**************************** Chip Setup **********************************// + +//******************* INPUT DEFINITIONS *****************************// +// MIC routing registers +#define TYMPAN_MICPGA_LEFT_POSITIVE_REG 0x0134 // page 1 register 52 +#define TYMPAN_MICPGA_LEFT_NEGATIVE_REG 0x0136 // page 1 register 54 +#define TYMPAN_MICPGA_RIGHT_POSITIVE_REG 0x0137 // page 1 register 55 +#define TYMPAN_MICPGA_RIGHT_NEGATIVE_REG 0x0139 // page 1 register 57 + +#define TYMPAN_MIC_ROUTING_POSITIVE_IN1 0b11000000 // +#define TYMPAN_MIC_ROUTING_POSITIVE_IN2 0b00110000 // +#define TYMPAN_MIC_ROUTING_POSITIVE_IN3 0b00001100 // +#define TYMPAN_MIC_ROUTING_POSITIVE_REVERSE 0b00000011 // + +#define TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L 0b11000000 // +#define TYMPAN_MIC_ROUTING_NEGATIVE_IN2_REVERSE 0b00110000 // +#define TYMPAN_MIC_ROUTING_NEGATIVE_IN3_REVERSE 0b00001100 // +#define TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM2L 0b00000011 // + +#define TYMPAN_MIC_ROUTING_RESISTANCE_10k 0b01010101 +#define TYMPAN_MIC_ROUTING_RESISTANCE_20k 0b10101010 +#define TYMPAN_MIC_ROUTING_RESISTANCE_40k 0b11111111 +#define TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT TYMPAN_MIC_ROUTING_RESISTANCE_10k + +#define TYMPAN_MICPGA_LEFT_VOLUME_REG 0x013B // page 1 register 59 // 0 to 47.5dB in 0.5dB steps +#define TYMPAN_MICPGA_RIGHT_VOLUME_REG 0x013C // page 1 register 60 // 0 to 47.5dB in 0.5dB steps + +#define TYMPAN_MICPGA_VOLUME_ENABLE 0x00 // default is 0b11000000 - clear to 0 to enable + +#define TYMPAN_MIC_BIAS_REG 0x0133 // page 1 reg 51 +#define TYMPAN_MIC_BIAS_POWER_ON 0x40 +#define TYMPAN_MIC_BIAS_POWER_OFF 0x00 +#define TYMPAN_MIC_BIAS_OUTPUT_VOLTAGE_1_25 0x00 +#define TYMPAN_MIC_BIAS_OUTPUT_VOLTAGE_1_7 0x01 +#define TYMPAN_MIC_BIAS_OUTPUT_VOLTAGE_2_5 0x10 +#define TYMPAN_MIC_BIAS_OUTPUT_VOLTAGE_VSUPPLY 0x11 + +#define TYMPAN_ADC_PROCESSING_BLOCK_REG 0x003d // page 0 register 61 + +#define TYMPAN_ADC_CHANNEL_POWER_REG 0x0051 // page 0 register81 +#define TYMPAN_ADC_CHANNELS_ON 0b11000000 // power up left and right + +#define TYMPAN_ADC_MUTE_REG 0x0052 // page 0, register 82 +#define TYMPAN_ADC_UNMUTE 0x00 + +bool AudioControlTLV320AIC3206::enable(void) +{ + delay(100); + + // Setup for Master mode, pins 18/19, external pullups, 400kHz, 200ms default timeout + Wire.begin(); + delay(5); + + aic_reset(); delay(100); + aic_init(); delay(100); + aic_initADC(); delay(100); + aic_initDAC(); delay(100); + + aic_readPage(0, 27); // check a specific register - a register read test + + Serial.println("TLV320 enable done"); + + return true; + +} + +bool AudioControlTLV320AIC3206::disable(void) { + return true; +} + +bool AudioControlTLV320AIC3206::inputLevel(float volume) { + return false; +} + +bool AudioControlTLV320AIC3206::inputSelect(int n) { + if (n == TYMPAN_INPUT_LINE_IN) { + // USE LINE IN SOLDER PADS + aic_writeAddress(TYMPAN_MICPGA_LEFT_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN1 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_LEFT_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_RIGHT_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN1 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_RIGHT_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + // BIAS OFF + setMicBias(TYMPAN_MIC_BIAS_OFF); + + Serial.println("Set Audio Input to Line In"); + return true; + } else if (n == TYMPAN_INPUT_JACK_AS_MIC) { + // mic-jack = IN3 + aic_writeAddress(TYMPAN_MICPGA_LEFT_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN3 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_LEFT_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_RIGHT_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN3 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_RIGHT_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + // BIAS on, using default + setMicBias(TYMPAN_DEFAULT_MIC_BIAS); + + Serial.println("Set Audio Input to JACK AS MIC, BIAS SET TO DEFAULT 2.5V"); + return true; + } else if (n == TYMPAN_INPUT_JACK_AS_LINEIN) { + // 1 + // mic-jack = IN3 + aic_writeAddress(TYMPAN_MICPGA_LEFT_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN3 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_LEFT_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_RIGHT_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN3 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_RIGHT_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + // BIAS Off + setMicBias(TYMPAN_MIC_BIAS_OFF); + + Serial.println("Set Audio Input to JACK AS LINEIN, BIAS OFF"); + return true; + } else if (n == TYMPAN_INPUT_ON_BOARD_MIC) { + // on-board = IN2 + aic_writeAddress(TYMPAN_MICPGA_LEFT_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN2 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_LEFT_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_RIGHT_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN2 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_RIGHT_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + // BIAS Off + setMicBias(TYMPAN_MIC_BIAS_OFF); + Serial.println("Set Audio Input to Tympan On-Board MIC, BIAS OFF"); + + return true; + } + Serial.print("ERROR: Unable to Select Input - Value not supported: "); + Serial.println(n); + return false; +} + +bool AudioControlTLV320AIC3206::setMicBias(int n) { + if (n == TYMPAN_MIC_BIAS_1_25) { + aic_writeAddress(TYMPAN_MIC_BIAS_REG, TYMPAN_MIC_BIAS_POWER_ON | TYMPAN_MIC_BIAS_OUTPUT_VOLTAGE_1_25); // power up mic bias + return true; + } else if (n == TYMPAN_MIC_BIAS_1_7) { + aic_writeAddress(TYMPAN_MIC_BIAS_REG, TYMPAN_MIC_BIAS_POWER_ON | TYMPAN_MIC_BIAS_OUTPUT_VOLTAGE_1_7); // power up mic bias + return true; + } else if (n == TYMPAN_MIC_BIAS_2_5) { + aic_writeAddress(TYMPAN_MIC_BIAS_REG, TYMPAN_MIC_BIAS_POWER_ON | TYMPAN_MIC_BIAS_OUTPUT_VOLTAGE_2_5); // power up mic bias + return true; + } else if (n == TYMPAN_MIC_BIAS_VSUPPLY) { + aic_writeAddress(TYMPAN_MIC_BIAS_REG, TYMPAN_MIC_BIAS_POWER_ON | TYMPAN_MIC_BIAS_OUTPUT_VOLTAGE_VSUPPLY); // power up mic bias + return true; + } else if (n == TYMPAN_MIC_BIAS_OFF) { + aic_writeAddress(TYMPAN_MIC_BIAS_REG, TYMPAN_MIC_BIAS_POWER_OFF); // power up mic bias + return true; + } + Serial.print("ERROR: Unable to set MIC BIAS - Value not supported: "); + Serial.println(n); + return false; +} + +void AudioControlTLV320AIC3206::aic_reset() { + Serial.println("INFO: Reseting AIC"); + aic_writePage(0x00, 0x01, 0x01); + // aic_writeAddress(0x0001, 0x01); + + delay(10); +} + + +// example - turn on IN3 - mic jack, with negatives routed to CM1L and with 10k resistance +// aic_writeAddress(TYMPAN_LEFT_MICPGA_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN3 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); +// aic_writeAddress(TYMPAN_LEFT_MICPGA_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); +// aic_writeAddress(TYMPAN_RIGHT_MICPGA_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN3 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); +// aic_writeAddress(TYMPAN_RIGHT_MICPGA_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + +void AudioControlTLV320AIC3206::aic_initADC() { + Serial.println("INFO: Initializing AIC ADC"); + aic_writeAddress(TYMPAN_ADC_PROCESSING_BLOCK_REG, PRB_R); // processing blocks - ADC + aic_writePage(1, 61, 0); // 0x3D // Select ADC PTM_R4 Power Tune? + aic_writePage(1, 71, 0b00110001); // 0x47 // Set MicPGA startup delay to 3.1ms + aic_writeAddress(TYMPAN_MIC_BIAS_REG, TYMPAN_MIC_BIAS_POWER_ON | TYMPAN_MIC_BIAS_2_5); // power up mic bias + + aic_writeAddress(TYMPAN_MICPGA_LEFT_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN2 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_LEFT_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_RIGHT_POSITIVE_REG, TYMPAN_MIC_ROUTING_POSITIVE_IN2 & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + aic_writeAddress(TYMPAN_MICPGA_RIGHT_NEGATIVE_REG, TYMPAN_MIC_ROUTING_NEGATIVE_CM_TO_CM1L & TYMPAN_MIC_ROUTING_RESISTANCE_DEFAULT); + + aic_writeAddress(TYMPAN_MICPGA_LEFT_VOLUME_REG, TYMPAN_MICPGA_VOLUME_ENABLE); // enable Left MicPGA, set gain to 0 dB + aic_writeAddress(TYMPAN_MICPGA_RIGHT_VOLUME_REG, TYMPAN_MICPGA_VOLUME_ENABLE); // enable Right MicPGA, set gain to 0 dB + + aic_writeAddress(TYMPAN_ADC_MUTE_REG, TYMPAN_ADC_UNMUTE); // Unmute Left and Right ADC Digital Volume Control + aic_writeAddress(TYMPAN_ADC_CHANNEL_POWER_REG, TYMPAN_ADC_CHANNELS_ON); // Unmute Left and Right ADC Digital Volume Control +} + +// set MICPGA volume, 0-47.5dB in 0.5dB setps +bool AudioControlTLV320AIC3206::micGain(float volume) { + if (volume < 0.0) { + volume = 0.0; // 0.0 dB + Serial.println("WARNING: Attempting to set MIC volume outside range"); + } + if (volume > 47.5) { + volume = 47.5; // 47.5 dB + Serial.println("WARNING: Attempting to set MIC volume outside range"); + } + + Serial.print("INFO: Setting MIC volume to "); + Serial.print(volume, 1); + + volume = volume * 2.0; // convert to value map (0.5 dB steps) + int8_t volume_int = (int8_t) (round(volume)); // round + + Serial.print(". Converted to volume map => "); + Serial.println(volume_int); + + aic_writeAddress(TYMPAN_MICPGA_LEFT_VOLUME_REG, TYMPAN_MICPGA_VOLUME_ENABLE | volume_int); // enable Left MicPGA, set gain to 0 dB + aic_writeAddress(TYMPAN_MICPGA_RIGHT_VOLUME_REG, TYMPAN_MICPGA_VOLUME_ENABLE | volume_int); // enable Right MicPGA, set gain to 0 dB + return true; +} + +//******************* OUTPUT DEFINITIONS *****************************// +#define TYMPAN_DAC_PROCESSING_BLOCK_REG 0x003c // page 0 register 60 +#define TYMPAN_DAC_VOLUME_LEFT_REG 0x0041 // page 0 reg 65 +#define TYMPAN_DAC_VOLUME_RIGHT_REG 0x0042 // page 0 reg 66 + +// -63.6 to +24 dB in 0.5dB steps. uses signed 8-bit +bool AudioControlTLV320AIC3206::volume(float volume) { + + // Constrain to limits + if (volume > 24.0) { + volume = 24.0; + Serial.println("WARNING: Attempting to set DAC Volume outside range"); + } + if (volume < -63.5) { + volume = -63.5; + Serial.println("WARNING: Attempting to set DAC Volume outside range"); + } + + Serial.print("INFO: Setting DAC volume to "); + Serial.print(volume, 1); + + volume = volume * 2.0; // convert to value map (0.5 dB steps) + int8_t volume_int = (int8_t) (round(volume)); // round + + Serial.print(". Converted to volume map => "); + Serial.println(volume_int); + + aic_writeAddress(TYMPAN_DAC_VOLUME_RIGHT_REG, volume_int); + aic_writeAddress(TYMPAN_DAC_VOLUME_LEFT_REG, volume_int); + return true; +} + +void AudioControlTLV320AIC3206::aic_initDAC() { + Serial.println("INFO: Initializing AIC DAC"); + // PLAYBACK SETUP + + aic_writeAddress(TYMPAN_DAC_PROCESSING_BLOCK_REG, PRB_P); // processing blocks - DAC + + //aic_writePage(1, 20, 0x25); // 0x14 De-Pop + aic_writePage(1, 12, 8); // route LDAC/RDAC to HPL/HPR + aic_writePage(1, 13, 8); // route LDAC/RDAC to HPL/HPR + aic_writePage(0, 63, 0xD6); // 0x3F // Power up LDAC/RDAC +// aic_writePage(1, 14, 8); // route LDAC/RDAC to LOL/LOR +// aic_writePage(1, 15, 8); // route LDAC/RDAC to LOL/LOR + aic_writePage(1, 16, 0); // unmute HPL Driver, 0 gain + aic_writePage(1, 17, 0); // unmute HPR Driver, 0 gain +// aic_writePage(1, 18, 0); // unmute LOL Driver, 0 gain +// aic_writePage(1, 19, 0); // unmute LOR Driver, 0 gain + aic_writePage(1, 9, 0x30); // Power up HPL/HPR and LOL/LOR drivers + delay(100); + aic_writeAddress(TYMPAN_DAC_VOLUME_LEFT_REG, 0); // default to 0 dB + aic_writeAddress(TYMPAN_DAC_VOLUME_RIGHT_REG, 0); // default to 0 dB + aic_writePage(0, 64, 0); // 0x40 // Unmute LDAC/RDAC +} + +void AudioControlTLV320AIC3206::aic_init() { + Serial.println("INFO: Initializing AIC"); + + // PLL + aic_writePage(0, 4, 3); // 0x04 low PLL clock range, MCLK is PLL input, PLL_OUT is CODEC_CLKIN + aic_writePage(0, 5, (PLL_J != 0 ? 0x91 : 0x11)); + aic_writePage(0, 6, PLL_J); + aic_writePage(0, 7, PLL_D >> 8); + aic_writePage(0, 8, PLL_D &0xFF); + + // CLOCKS + aic_writePage(0, 11, 0x80 | NDAC); // 0x0B + aic_writePage(0, 12, 0x80 | MDAC); // 0x0C + aic_writePage(0, 13, 0); // 0x0D + aic_writePage(0, 14, DOSR); // 0x0E + // aic_writePage(0, 18, 0); // 0x12 // powered down, ADC_CLK same as DAC_CLK + // aic_writePage(0, 19, 0); // 0x13 // powered down, ADC_MOD_CLK same as DAC_MOD_CLK + aic_writePage(0, 18, 0x80 | NADC); // 0x12 + aic_writePage(0, 19, 0x80 | MADC); // 0x13 + aic_writePage(0, 20, AOSR); + aic_writePage(0, 30, 0x80 | BCLK_N); // power up BLCK N Divider, default is 128 + + // POWER + aic_writePage(1, 1, 8); // 0x01 + aic_writePage(1, 2, 0); // 0x02 Enable Master Analog Power Control + aic_writePage(1, 10, 0); // common mode 0.9 for full chip, HP, LO // from WHF/CHA + aic_writePage(1, 71, 0x31); // 0x47 Set input power-up time to 3.1ms (for ADC) + aic_writePage(1, 123, 1); // 0x7B Set reference to power up in 40ms when analog blocks are powered up + //aic_writePage(1, 124, 6); // 0x7D Charge Pump + aic_writePage(1, 125, 0x53); // Enable ground-centered mode, DC offset correction // from WHF/CHA + + // !!!!!!!!! The below writes are from WHF/CHA - probably don't need? + // aic_writePage(1, 1, 10); // 0x01 // Charge pump + aic_writePage(0, 27, 0x01 | AIC_CLK_DIR | (AIC_BITS == 32 ? 0x30 : 0)); // 0x1B + // aic_writePage(0, 28, 0); // 0x1C +} + +unsigned int AudioControlTLV320AIC3206::aic_readPage(uint8_t page, uint8_t reg) +{ + unsigned int val; + if (aic_goToPage(page)) { + Wire.beginTransmission(AIC3206_I2C_ADDR); + Wire.write(reg); + unsigned int result = Wire.endTransmission(); + if (result != 0) { + Serial.print("ERROR: Read Page. Page: ");Serial.print(page); + Serial.print(" Reg: ");Serial.print(reg); + Serial.print(". Received Error During Read Page: "); + Serial.println(result); + val = 300 + result; + return val; + } + if (Wire.requestFrom(AIC3206_I2C_ADDR, 1) < 1) { + Serial.print("ERROR: Read Page. Page: ");Serial.print(page); + Serial.print(" Reg: ");Serial.print(reg); + Serial.println(". Nothing to return"); + val = 400; + return val; + } + if (Wire.available() >= 1) { + uint16_t val = Wire.read(); + Serial.print("INFO: Read Page. Page: ");Serial.print(page); + Serial.print(" Reg: ");Serial.print(reg); + Serial.print(". Received: "); + Serial.println(val, HEX); + return val; + } + } else { + Serial.print("INFO: Read Page. Page: ");Serial.print(page); + Serial.print(" Reg: ");Serial.print(reg); + Serial.println(". Failed to go to read page. Could not go there"); + val = 500; + return val; + } + val = 600; + return val; +} + +bool AudioControlTLV320AIC3206::aic_writeAddress(uint16_t address, uint8_t val) { + uint8_t reg = (uint8_t) (address & 0xFF); + uint8_t page = (uint8_t) ((address >> 8) & 0xFF); + + return aic_writePage(page, reg, val); +} + +bool AudioControlTLV320AIC3206::aic_writePage(uint8_t page, uint8_t reg, uint8_t val) { + Serial.print("INFO: Write Page. Page: ");Serial.print(page); + Serial.print(" Reg: ");Serial.print(reg); + Serial.print(" Val: ");Serial.println(val); + if (aic_goToPage(page)) { + Wire.beginTransmission(AIC3206_I2C_ADDR); + Wire.write(reg);delay(10); + Wire.write(val);delay(10); + uint8_t result = Wire.endTransmission(); + if (result == 0) return true; + else { + Serial.print("ERROR: Received Error During Write Page: "); + Serial.println(result); + } + } + return false; +} + +bool AudioControlTLV320AIC3206::aic_goToPage(byte page) { + Wire.beginTransmission(AIC3206_I2C_ADDR); + Wire.write(0x00); delay(10);// page register + Wire.write(page); delay(10);// go to page + byte result = Wire.endTransmission(); + if (result != 0) { + Serial.print("ERROR: Received Error During GoTo Page: "); + Serial.println(result); + if (result == 2) { + // failed to transmit address + //return aic_goToPage(page); + } else if (result == 3) { + // failed to transmit data + //return aic_goToPage(page); + } + return false; + } + return true; +} diff --git a/examples/Tympan_TLV320AIC/Tympan_TLV320AIC.ino b/examples/Tympan_TLV320AIC/Tympan_TLV320AIC.ino new file mode 100644 index 0000000..bded1fc --- /dev/null +++ b/examples/Tympan_TLV320AIC/Tympan_TLV320AIC.ino @@ -0,0 +1,65 @@ +/* + * Tympan_TLV320AIC.ino + * + * Created: BPF and WEA, Creare LLC, Jan/Feb 2017 + * Purpose: Demonstrate basic audio pass-thru using the Tympan Audio Board, + * which is based on the TI TLV320AIC3206 + * + * License: MIT License, Use At Your Own Risk + * + */ + +#include +#include +#include +#include +#include +#include //AudioControlTLV320AIC3206 lives here + +// define audio classes and connections +AudioControlTLV320AIC3206 tlv320aic3206_1; +AudioInputI2S audioInput; +AudioOutputI2S audioOutput; +AudioConnection patchCord1(audioInput, 0, audioOutput, 0); +AudioConnection patchCord2(audioInput, 1, audioOutput, 1); + +// define the setup +void setup(void) +{ + //allocate the audio memory first + AudioMemory(160); //big number to accomodate the delay effect + + //begin the serial comms + Serial.begin(115200); + delay(500); + Serial.println("Tympan_TLV320AIC: starting..."); + + // Setup the TLV320 + tlv320aic3206_1.enable(); // activate AIC + + // Choose the desired input + tlv320aic3206_1.inputSelect(TYMPAN_INPUT_ON_BOARD_MIC); // use the on board microphones // default + // tlv320aic3206_1.inputSelect(TYMPAN_INPUT_JACK_AS_MIC); // use the microphone jack - defaults to mic bias 2.5V + // tlv320aic3206_1.inputSelect(TYMPAN_INPUT_JACK_AS_LINEIN); // use the microphone jack - defaults to mic bias OFF + // tlv320aic3206_1.inputSelect(TYMPAN_INPUT_LINE_IN); // use the line in pads on the TYMPAN board - defaults to mic bias OFF + + //Adjust the MIC bias, if using TYMPAN_INPUT_JACK_AS_MIC + // tlv320aic3206_1.setMicBias(TYMPAN_MIC_BIAS_OFF); // Turn mic bias off + // tlv320aic3206_1.setMicBias(TYMPAN_MIC_BIAS_2_5); // set mic bias to 2.5 // default + // tlv320aic3206_1.setMicBias(TYMPAN_MIC_BIAS_1_7); // set mic bias to 1.7 + // tlv320aic3206_1.setMicBias(TYMPAN_MIC_BIAS_1_25); // set mic bias to 1.25 + // tlv320aic3206_1.setMicBias(TYMPAN_MIC_BIAS_VSUPPLY); // set mic bias to supply voltage + + // VOLUMES + tlv320aic3206_1.volume(10); // -63.6 to +24 dB in 0.5dB steps. uses float + tlv320aic3206_1.micGain(10); // set MICPGA volume, 0-47.5dB in 0.5dB setps + + Serial.println("Done"); +} + +void loop(void) +{ + // Nothing to do - just looping input to output + delay(2000); + Serial.println("Running..."); +} diff --git a/keywords.txt b/keywords.txt index 1524630..9fdefdc 100644 --- a/keywords.txt +++ b/keywords.txt @@ -20,5 +20,11 @@ AudioMixer4_F32 KEYWORD1 AudioMultiply_F32 KEYWORD1 AudioSynthWaveform_F32 KEYWORD1 +AudioControlTLV320AIC3206 KEYWORD1 +inputSelect KEYWORD2 +setMicBias KEYWORD2 +volume KEYWORD2 +micGain KEYWORD2 + AudioControlSGTL5000_Extended KEYWORD1 -micBiasEnable KEYWORD2 \ No newline at end of file +micBiasEnable KEYWORD2