#ifndef TAS5720_H
#define TAS5720_H

#include "driver/i2c.h"

#define TAS5720_I2C_SPEED 100000

#define TAS5720_ADDRESS_DEVICE_IDENTIFICATION               0x00
#define TAS5720_ADDRESS_POWER_CONTROL                       0x01
#define TAS5720_ADDRESS_DIGITAL_CONTROL                     0x02
#define TAS5720_ADDRESS_VOLUME_CONTROL_CONFIGURATION        0x03
#define TAS5720_ADDRESS_VOLUME_CONTROL_LEFT                 0x04
#define TAS5720_ADDRESS_VOLUME_CONTROL_RIGHT                0x05
#define TAS5720_ADDRESS_ANALOG_CONTROL                      0x06
#define TAS5720_ADDRESS_FAULT_CONFIGURATION_ERROR_STATUS    0x08
#define TAS5720_ADDRESS_DIGITAL_CLIPPER_2                   0x10
#define TAS5720_ADDRESS_DIGITAL_CLIPPER_1                   0x11

typedef enum {
    SAI_24_BITS_RIGHT_JUSTIFIED = 0,
    SAI_20_BITS_LEFT_JUSTIFIED = 1,
    SAI_18_BITS_RIGHT_JUSTIFIED = 2,
    SAI_16_BITS_LEFT_JUSTIFIED = 3,
    SAI_I2S = 4,
    SAI_16_24_BITS_LEFT_JUSTIFIED = 5,
} SAIFormat;

typedef enum {
    DIGITAL_BOOST_0DB = 0,
    DIGITAL_BOOST_6DB = 1,
    DIGITAL_BOOST_12DB = 2,
    DIGITAL_BOOST_18DB = 3
} DigitalBoost;

typedef enum {
    RIGHT = 0,
    LEFT = 1
} ChannelSelection;

typedef enum {
    GAIN_19_2_DBV = 0,
    GAIN_22_6_DBV = 1,
    GAIN_25_DBV = 2
} AnalogGain;

typedef enum {
    RATE_6_LRCK = 0,
    RATE_8_LRCK = 1,
    RATE_10_LRCK = 2,
    RATE_12_LRCK = 3,
    RATE_14_LRCK = 4,
    RATE_16_LRCK = 5,
    RATE_20_LRCK = 6,
    RATE_24_LRCK = 7
} PWMRate;

typedef enum {
    OCE_DEFAULT = 0,
    OCE_REDUCE_75_PERCENT = 1,
    OCE_REDUCE_50_PERCENT = 2,
    OCE_REDUCE_25_PERCENT = 3
} OCEThreshold;

typedef struct {
    i2c_port_t i2c_num;
    uint8_t address;
    bool debug;
    uint8_t rx_data;
    uint8_t volumeLeft;
    uint8_t volumeRight;
} TAS5720_t;

void TAS5720_init(TAS5720_t *tas, i2c_port_t i2c_num, uint8_t address, bool debug);
void TAS5720_write(TAS5720_t *tas, uint8_t reg, uint8_t data);
uint8_t TAS5720_read(TAS5720_t *tas, uint8_t reg);
uint8_t TAS5720_getDeviceIdentification(TAS5720_t *tas);
bool TAS5720_getSleepMode(TAS5720_t *tas);
void TAS5720_setSleepMode(TAS5720_t *tas, bool sleep);
bool TAS5720_getShutdown(TAS5720_t *tas);
void TAS5720_setShutdown(TAS5720_t *tas, bool shutdown);
SAIFormat TAS5720_getSerialAudioInterfaceFormat(TAS5720_t *tas);
void TAS5720_setSerialAudioInterfaceFormat(TAS5720_t *tas, SAIFormat format);
bool TAS5720_getSpeed(TAS5720_t *tas);
void TAS5720_setSpeed(TAS5720_t *tas, bool doubleSpeed);
DigitalBoost TAS5720_getDigitalBoost(TAS5720_t *tas);
void TAS5720_setDigitalBoost(TAS5720_t *tas, DigitalBoost boost);
bool TAS5720_getHighPassFilterMode(TAS5720_t *tas);
void TAS5720_setHighPassFilterMode(TAS5720_t *tas, bool bypass);
void TAS5720_muteLeft(TAS5720_t *tas, bool mute);
void TAS5720_muteRight(TAS5720_t *tas, bool mute);
void TAS5720_mute(TAS5720_t *tas, bool mute);
void TAS5720_setFade(TAS5720_t *tas, bool fade);
void TAS5720_getVolume(TAS5720_t *tas);
void TAS5720_setVolume(TAS5720_t *tas, uint8_t left, uint8_t right);
void TAS5720_setVolumeBoth(TAS5720_t *tas, uint8_t volume);
ChannelSelection TAS5720_getChannelSelection(TAS5720_t *tas);
void TAS5720_setChannelSelection(TAS5720_t *tas, ChannelSelection channel);
AnalogGain TAS5720_getAnalogGain(TAS5720_t *tas);
void TAS5720_setAnalogGain(TAS5720_t *tas, AnalogGain gain);
PWMRate TAS5720_getPWMRate(TAS5720_t *tas);
void TAS5720_setPWMRate(TAS5720_t *tas, PWMRate rate);
bool TAS5720_getOverTemperatureErrorStatus(TAS5720_t *tas);
bool TAS5720_getOutputDCErrorStatus(TAS5720_t *tas);
bool TAS5720_getOverCurrentErrorStatus(TAS5720_t *tas);
bool TAS5720_getClockErrorStatus(TAS5720_t *tas);
bool TAS5720_getErrorStatus(TAS5720_t *tas);
OCEThreshold TAS5720_getOCEThreshold(TAS5720_t *tas);
void TAS5720_setOCEThreshold(TAS5720_t *tas, OCEThreshold threshold);
uint32_t TAS5720_getDigitalClipper(TAS5720_t *tas);
void TAS5720_setDigitalClipper(TAS5720_t *tas, uint32_t clipper);

#endif // TAS5720_H
