Adafruit_TLV320_I2S/Adafruit_TLV320DAC3100.h
2025-03-27 15:40:01 -04:00

278 lines
13 KiB
C++

/*!
* @file Adafruit_TLV320DAC3100.h
*
* Arduino library for the TI TLV320DAC3100 stereo DAC with headphone amplifier
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Written by Limor Fried for Adafruit Industries.
*
* MIT license, all text here must be included in any redistribution.
*/
#ifndef _ADAFRUIT_TLV320DAC3100_H
#define _ADAFRUIT_TLV320DAC3100_H
#include "Adafruit_TLV320DAC3100_typedefs.h"
#include <Adafruit_BusIO_Register.h>
#include <Adafruit_I2CDevice.h>
#include <Arduino.h>
#include <Wire.h>
#define TLV320DAC3100_I2CADDR_DEFAULT 0x18 ///< Default I2C address
#define TLV320DAC3100_REG_PAGE_SELECT 0x00 ///< Page select register
#define TLV320DAC3100_REG_RESET 0x01 ///< Reset register
#define TLV320DAC3100_REG_OT_FLAG 0x03 ///< Over-temperature flag register
#define TLV320DAC3100_REG_CLOCK_MUX1 0x04 ///< Clock muxing control register 1
#define TLV320DAC3100_REG_PLL_PROG_PR 0x05 ///< PLL P and R values
#define TLV320DAC3100_REG_PLL_PROG_J 0x06 ///< PLL J value
#define TLV320DAC3100_REG_PLL_PROG_D_MSB 0x07 ///< PLL D value MSB
#define TLV320DAC3100_REG_PLL_PROG_D_LSB 0x08 ///< PLL D value LSB
#define TLV320DAC3100_REG_NDAC 0x0B ///< NDAC divider value
#define TLV320DAC3100_REG_MDAC 0x0C ///< MDAC divider value
#define TLV320DAC3100_REG_DOSR 0x0D ///< DOSR divider value MSB/LSB
#define TLV320DAC3100_REG_DOSR_MSB 0x0D ///< DOSR divider value MSB
#define TLV320DAC3100_REG_DOSR_LSB 0x0E ///< DOSR divider value LSB
#define TLV320DAC3100_REG_CLKOUT_MUX 0x19 ///< CLKOUT MUX register
#define TLV320DAC3100_REG_CLKOUT_M 0x1A ///< CLKOUT M divider value
#define TLV320DAC3100_REG_CODEC_IF_CTRL1 0x1B ///< Codec Interface Control 1
#define TLV320DAC3100_REG_DATA_SLOT_OFFSET 0x1C ///< Data-slot offset register
#define TLV320DAC3100_REG_BCLK_N 0x1E ///< BCLK N divider value
#define TLV320DAC3100_REG_DAC_FLAG 0x25 ///< DAC Flag register
#define TLV320DAC3100_REG_DAC_FLAG2 0x26 ///< DAC Flag register 2
#define TLV320DAC3100_REG_INT1_CTRL 0x30 ///< INT1 Control Register
#define TLV320DAC3100_REG_INT2_CTRL 0x31 ///< INT2 Control Register
#define TLV320DAC3100_REG_GPIO1_CTRL 0x33 ///< GPIO1 In/Out Pin Control Register
#define TLV320DAC3100_REG_DIN_CTRL 0x36 ///< DIN Pin Control Register
#define TLV320DAC3100_REG_DAC_PRB \
0x3C ///< DAC Processing Block Selection Register
#define TLV320DAC3100_REG_DAC_DATAPATH 0x3F ///< DAC Data-Path Setup Register
#define TLV320DAC3100_REG_DAC_VOL_CTRL 0x40 ///< DAC Volume Control Register
#define TLV320DAC3100_REG_DAC_LVOL 0x41 ///< DAC Left Volume Control Register
#define TLV320DAC3100_REG_DAC_RVOL 0x42 ///< DAC Right Volume Control Register
#define TLV320DAC3100_REG_HEADSET_DETECT 0x43 ///< Headset Detection Register
#define TLV320DAC3100_REG_BEEP_L 0x47 ///< Left Beep Generator Register
#define TLV320DAC3100_REG_BEEP_R 0x48 ///< Right Beep Generator Register
#define TLV320DAC3100_REG_BEEP_LEN_MSB 0x49 ///< Beep Length MSB Register
#define TLV320DAC3100_REG_BEEP_LEN_MID \
0x4A ///< Beep Length Middle Bits Register
#define TLV320DAC3100_REG_BEEP_LEN_LSB 0x4B ///< Beep Length LSB Register
#define TLV320DAC3100_REG_BEEP_SIN_MSB 0x4C ///< Beep Sin(x) MSB Register
#define TLV320DAC3100_REG_BEEP_SIN_LSB 0x4D ///< Beep Sin(x) LSB Register
#define TLV320DAC3100_REG_BEEP_COS_MSB 0x4E ///< Beep Cos(x) MSB Register
#define TLV320DAC3100_REG_BEEP_COS_LSB 0x4F ///< Beep Cos(x) LSB Register
#define TLV320DAC3100_REG_VOL_ADC_CTRL \
0x74 ///< VOL/MICDET-Pin SAR ADC Control Register
#define TLV320DAC3100_REG_VOL_ADC_READ 0x75 ///< VOL/MICDET-Pin Gain Register
// Page 1
#define TLV320DAC3100_REG_BCLK_CTRL2 0x1D ///< BCLK Control Register 2
#define TLV320DAC3100_REG_HP_SPK_ERR_CTL \
0x1E ///< Headphone and Speaker Error Control Register
#define TLV320DAC3100_REG_HP_DRIVERS 0x1F ///< Headphone Drivers Register
#define TLV320DAC3100_REG_SPK_AMP 0x20 ///< Class-D Speaker Amplifier Register
#define TLV320DAC3100_REG_HP_POP \
0x21 ///< HP Output Drivers POP Removal Settings Register
#define TLV320DAC3100_REG_PGA_RAMP \
0x22 ///< Output Driver PGA Ramp-Down Period Control Register
#define TLV320DAC3100_REG_OUT_ROUTING \
0x23 ///< DAC Output Mixer Routing Register
#define TLV320DAC3100_REG_HPL_VOL 0x24 ///< Left Analog Volume to HPL Register
#define TLV320DAC3100_REG_HPR_VOL 0x25 ///< Right Analog Volume to HPR Register
#define TLV320DAC3100_REG_SPK_VOL 0x26 ///< Left Analog Volume to SPK Register
#define TLV320DAC3100_REG_HPL_DRIVER 0x28 ///< HPL Driver Register
#define TLV320DAC3100_REG_HPR_DRIVER 0x29 ///< HPR Driver Register
#define TLV320DAC3100_REG_SPK_DRIVER 0x2A ///< Class-D Speaker Driver Register
#define TLV320DAC3100_REG_HP_DRIVER_CTRL 0x2C ///< HP Driver Control Register
#define TLV320DAC3100_REG_MICBIAS 0x2E ///< MICBIAS Configuration Register
#define TLV320DAC3100_REG_INPUT_CM 0x32 ///< Input Common Mode Settings Register
#define TLV320DAC3100_REG_TIMER_MCLK_DIV \
0x10 ///< Timer Clock MCLK Divider Register
#define TLV320DAC3100_REG_IRQ_FLAGS_STICKY \
0x2C ///< Interrupt Flags - Sticky Register
#define TLV320DAC3100_REG_IRQ_FLAGS 0x2E ///< Interrupt Flags - DAC Register
// IRQ Flag bits
#define TLV320DAC3100_IRQ_HPL_SHORT \
0x80 ///< Short circuit detected at HPL / left class-D driver
#define TLV320DAC3100_IRQ_HPR_SHORT \
0x40 ///< Short circuit detected at HPR / right class-D driver
#define TLV320DAC3100_IRQ_BUTTON_PRESS 0x20 ///< Headset button pressed
#define TLV320DAC3100_IRQ_HEADSET_DETECT \
0x10 ///< Headset insertion detected (1) or removal detected (0)
#define TLV320DAC3100_IRQ_LEFT_DRC \
0x08 ///< Left DAC signal power greater than DRC threshold
#define TLV320DAC3100_IRQ_RIGHT_DRC \
0x04 ///< Right DAC signal power greater than DRC threshold
/*!
* @brief Class to interact with TLV320DAC3100 DAC
*/
class Adafruit_TLV320DAC3100 {
public:
Adafruit_TLV320DAC3100();
bool begin(uint8_t i2c_addr = TLV320DAC3100_I2CADDR_DEFAULT,
TwoWire *wire = &Wire);
bool reset(void);
bool isOvertemperature(void);
bool setPLLClockInput(tlv320dac3100_pll_clkin_t clkin);
tlv320dac3100_pll_clkin_t getPLLClockInput(void);
bool setCodecClockInput(tlv320dac3100_codec_clkin_t clkin);
tlv320dac3100_codec_clkin_t getCodecClockInput(void);
bool setClockDividerInput(tlv320dac3100_cdiv_clkin_t clkin);
tlv320dac3100_cdiv_clkin_t getClockDividerInput(void);
bool powerPLL(bool on);
bool isPLLpowered(void);
bool setPLLValues(uint8_t P, uint8_t R, uint8_t J, uint16_t D);
bool getPLLValues(uint8_t *P, uint8_t *R, uint8_t *J, uint16_t *D);
bool getDACFlags(bool *left_dac_powered, bool *hpl_powered,
bool *left_classd_powered, bool *right_dac_powered,
bool *hpr_powered, bool *right_classd_powered,
bool *left_pga_gain_ok, bool *right_pga_gain_ok);
bool setNDAC(bool enable, uint8_t val);
bool getNDAC(bool *enabled, uint8_t *val);
bool setMDAC(bool enable, uint8_t val);
bool getMDAC(bool *enabled, uint8_t *val);
bool setDOSR(uint16_t val);
bool getDOSR(uint16_t *val);
bool setCLKOUT_M(bool enable, uint8_t val);
bool getCLKOUT_M(bool *enabled, uint8_t *val);
bool setBCLKoffset(uint8_t offset);
bool getBCLKoffset(uint8_t *offset);
bool setBCLK_N(bool enable, uint8_t val);
bool getBCLK_N(bool *enabled, uint8_t *val);
bool setBCLKConfig(bool invert_bclk, bool active_when_powered_down,
tlv320dac3100_bclk_src_t source);
bool getBCLKConfig(bool *invert_bclk, bool *active_when_powered_down,
tlv320dac3100_bclk_src_t *source);
bool validatePLLConfig(uint8_t P, uint8_t R, uint8_t J, uint16_t D,
float pll_clkin);
bool setCodecInterface(tlv320dac3100_format_t format,
tlv320dac3100_data_len_t len, bool bclk_out = false,
bool wclk_out = false);
bool getCodecInterface(tlv320dac3100_format_t *format,
tlv320dac3100_data_len_t *len, bool *bclk_out,
bool *wclk_out);
bool setInt1Source(bool headset_detect, bool button_press, bool dac_drc,
bool agc_noise, bool over_current, bool multiple_pulse);
bool setInt2Source(bool headset_detect, bool button_press, bool dac_drc,
bool agc_noise, bool over_current, bool multiple_pulse);
bool setGPIO1Mode(tlv320_gpio1_mode_t mode);
tlv320_gpio1_mode_t getGPIO1Mode(void);
bool setGPIO1Output(bool value);
bool getGPIO1Input(void);
bool setDINMode(tlv320_din_mode_t mode);
tlv320_din_mode_t getDINMode(void);
bool getDINInput(void);
bool setDACProcessingBlock(uint8_t block_number);
uint8_t getDACProcessingBlock(void);
bool
setDACDataPath(bool left_dac_on, bool right_dac_on,
tlv320_dac_path_t left_path = TLV320_DAC_PATH_NORMAL,
tlv320_dac_path_t right_path = TLV320_DAC_PATH_NORMAL,
tlv320_volume_step_t volume_step = TLV320_VOLUME_STEP_1SAMPLE);
bool getDACDataPath(bool *left_dac_on, bool *right_dac_on,
tlv320_dac_path_t *left_path,
tlv320_dac_path_t *right_path,
tlv320_volume_step_t *volume_step);
bool
setDACVolumeControl(bool left_mute, bool right_mute,
tlv320_vol_control_t control = TLV320_VOL_INDEPENDENT);
bool getDACVolumeControl(bool *left_mute, bool *right_mute,
tlv320_vol_control_t *control);
bool setChannelVolume(bool right_channel, float dB);
float getChannelVolume(bool right_channel);
bool setHeadsetDetect(
bool enable,
tlv320_detect_debounce_t detect_debounce = TLV320_DEBOUNCE_16MS,
tlv320_button_debounce_t button_debounce = TLV320_BTN_DEBOUNCE_0MS);
tlv320_headset_status_t getHeadsetStatus(void);
bool isBeeping(void);
bool enableBeep(bool enable);
bool setBeepVolume(int8_t left_dB,
int8_t right_dB = -100); // -100 is sentinel value
bool setBeepLength(uint32_t samples);
bool setBeepSinCos(uint16_t sin_val, uint16_t cos_val);
bool configureBeepTone(float frequency, uint32_t duration_ms,
uint32_t sample_rate);
bool configVolADC(bool pin_control, bool use_mclk,
tlv320_vol_hyst_t hysteresis, tlv320_vol_rate_t rate);
float readVolADCdB(void);
bool resetSpeakerOnSCD(bool reset);
bool resetHeadphoneOnSCD(bool reset);
bool
configureHeadphoneDriver(bool left_powered, bool right_powered,
tlv320_hp_common_t common = TLV320_HP_COMMON_1_35V,
bool powerDownOnSCD = false);
/*!
* @brief Check if headphone outputs have detected a short circuit
* @return true if short circuit detected, false if not
*/
bool isHeadphoneShorted(void);
bool enableSpeaker(bool en);
bool speakerEnabled(void);
bool isSpeakerShorted(void);
bool
configureHeadphonePop(bool wait_for_powerdown = true,
tlv320_hp_time_t powerup_time = TLV320_HP_TIME_304MS,
tlv320_ramp_time_t ramp_time = TLV320_RAMP_4MS);
bool setSpeakerWaitTime(tlv320_spk_wait_t wait_time = TLV320_SPK_WAIT_0MS);
bool
configureAnalogInputs(tlv320_dac_route_t left_dac = TLV320_DAC_ROUTE_NONE,
tlv320_dac_route_t right_dac = TLV320_DAC_ROUTE_NONE,
bool left_ain1 = false, bool left_ain2 = false,
bool right_ain2 = false,
bool hpl_routed_to_hpr = false);
bool setHPLVolume(bool route_enabled, uint8_t gain = 0x7F);
bool setHPRVolume(bool route_enabled, uint8_t gain = 0x7F);
bool setSPKVolume(bool route_enabled, uint8_t gain = 0x7F);
bool configureHPL_PGA(uint8_t gain_db = 0, bool unmute = true);
bool configureHPR_PGA(uint8_t gain_db = 0, bool unmute = true);
bool configureSPK_PGA(tlv320_spk_gain_t gain = TLV320_SPK_GAIN_6DB,
bool unmute = true);
bool isHPLGainApplied(void);
bool isHPRGainApplied(void);
bool isSPKGainApplied(void);
bool headphoneLineout(bool left, bool right);
bool configMicBias(bool power_down = false, bool always_on = false,
tlv320_micbias_volt_t voltage = TLV320_MICBIAS_OFF);
bool setInputCommonMode(bool ain1_cm, bool ain2_cm);
bool configDelayDivider(bool use_mclk = true, uint8_t divider = 1);
bool configurePLL(uint32_t mclk_freq, uint32_t desired_freq,
float max_error = 0.001);
uint8_t readIRQflags(bool sticky = false);
uint8_t readRegister(uint8_t page, uint8_t reg);
private:
bool setPage(uint8_t page);
uint8_t getPage(void);
Adafruit_I2CDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface
};
#endif