//
// Created by ilya on 10.01.24.
//

#ifndef NAU88U10YG_H
#define NAU88U10YG_H

#include "nau88u10yg_enums.h"
#include "nau88u10yg_regs.h"
#include "stdbool.h"
#include "stdint.h"
#include "I2cIO.h"

// Desired Output 11.28960
#define PLL_K_1_MCLK_26MHz_mode1 0x3C
#define PLL_K_2_MCLK_26MHz_mode1 0x145
#define PLL_K_3_MCLK_26MHz_mode1 0x1D4

// Desired Output 12.28800
#define PLL_K_1_MCLK_26MHz_mode2 0x23
#define PLL_K_2_MCLK_26MHz_mode2 0x1EA
#define PLL_K_3_MCLK_26MHz_mode2 0x126

//todo инвертировать данные во всех структурах, аналогично power manager, проверить, нужно ли это на самом деле

typedef union {
    uint16_t raw;
    struct  {
//        uint8_t addr: 7;
        uint16_t data: 9;
        uint8_t addr: 7;
    };
} NAU88U10YG_RegAddrPacket;

typedef union {
    uint8_t raw: 8;
    struct  {
        uint8_t data: 1;
        uint8_t regAddr: 7;
    };
} NAU88U10YG_StartReadingConditionPacket;

///-------------------------------------------- POWER MANAGEMENT -------------------------------------------------------
typedef union {
    uint16_t raw: 9;
    struct {
        eNAU88U10YG_PowerManagement1_REFIMP ReferenceImpedance_Select: 2;
        bool IOBuffer_Enable: 1;
        bool AnalogueAmplifierBiasControl_Enable: 1;
        bool MicrophoneBias_Enable: 1;
        bool PLL_Enable: 1;
        uint8_t : 2;
        bool DCBUF_Enable: 1;
        //
//        bool DCBUF_Enable: 1;
//        uint8_t : 2;
//        bool PLL_Enable: 1;
//        bool MicrophoneBias_Enable: 1;
//        bool AnalogueAmplifierBiasControl_Enable: 1;
//        bool IOBuffer_Enable: 1;
//        eNAU88U10YG_PowerManagement1_REFIMP ReferenceImpedance_Select: 2;
    };
} NAU88U10YG_PowerManagement1;

typedef union {
    uint16_t raw: 9;
    struct {
        bool ADC_Enable: 1;
        uint8_t : 1;
        bool PGA_Enable: 1;
        uint8_t : 1;
        bool InputBoost_Enable: 1;
        uint8_t : 4;
        //
//        uint8_t : 4;
//        bool InputBoost_Enable: 1;
//        uint8_t : 1;
//        bool PGA_Enable: 1;
//        uint8_t : 1;
//        bool ADC_Enable: 1;
    };
} NAU88U10YG_PowerManagement2;

typedef union {
    uint16_t raw: 9;
    struct {
        bool DAC_Enable:1;
        uint8_t : 1;
        bool SpeakerMixer_Enable:1;
        bool MONOMixer_Enable:1;
        uint8_t : 1;
        bool SPKOUT_P_Enable: 1;
        bool SPKOUT_N_Enable: 1;
        bool MOUT_Enable: 1;
        uint8_t : 1;
        //
//        uint8_t : 1;
//        bool MOUT_Enable: 1;
//        bool SPKOUT_N_Enable: 1;
//        bool SPKOUT_P_Enable: 1;
//        uint8_t : 1;
//        bool MONOMixer_Enable:1;
//        bool SpeakerMixer_Enable:1;
//        uint8_t : 1;
//        bool DAC_Enable:1;
    };
} NAU88U10YG_PowerManagement3;

typedef struct {
    NAU88U10YG_PowerManagement1 powerManagement1;
    NAU88U10YG_PowerManagement2 powerManagement2;
    NAU88U10YG_PowerManagement3 powerManagement3;
}NAU88U10YG_PowerManagement_State;


///----------------------------------------------- AUDIO CONTROL -------------------------------------------------------
typedef union {
    uint16_t raw: 9;
    struct {
        bool BCLK_Polarity:1;
        bool FrameClock_Polarity:1;
        eNAU88U10YG_AudioInterface_WLEN WordLength_Selection:2;
        eNAU88U10YG_AudioInterface_AIFMT AudioDataFormat_Select:2;
        bool DACDatePhasesOfFrameClock:1; //0-left 1-right
        bool ADCDatePhasesOfFrameClock:1; //0-left 1-right
        uint8_t : 1;
    };
} NAU88U10YG_AudioInterface;

typedef union {
    uint16_t raw: 9;
    struct {
        uint8_t : 3;
        bool CompandingMode_8bit_Enable:1;
        eNAU88U10YG_CompandingDACCM DACCompanding_Select:2;
        eNAU88U10YG_CompandingADCCM ADCCompanding_Select:2;
        bool ADDAP:1; //  Setting ADDAP[0] bit to HIGH enables the loopback so that the ADC data can be fed directly into the DAC input.
    };
} NAU88U10YG_AudioInterfaceCompanding;

typedef union {
    uint16_t raw: 9;
    struct {
        eNAU88U10YG_ClockControl1_CLKM InternalClock_Sourse:1;
        eNAU88U10YG_ClockControl1_MCLKSEL MasterClock_Selection:3;
        eNAU88U10YG_ClockControl1_BCLKSEL BitClockSelect:3;
        uint8_t : 1;
        eNAU88U10YG_ClockControl1_CLKIOEN FRAMEandBCLk_Mode:1;
    };
} NAU88U10YG_ClockControl;

typedef union {
    uint16_t raw: 9;
    struct {
        uint8_t : 5;
        eNAU88U10YG_ClockControl2_SMPLR SampleRate_Selection:3;
        bool SlowClock_Enable:1;
    };
} NAU88U10YG_AudioSampleRateControl;

typedef union {
    uint16_t raw: 9;
    struct {
        uint8_t : 2;
        bool SoftMute_Enable:1;
        eNAU88U10YG_DAC_CTRL_DEEMP De_emphasis_Select:2;
        eNAU88U10YG_DAC_CTRL_DACOS OverSampleRate:1;
        bool AutoMute_Enable:1;
        uint8_t : 1;
        eNAU88U10YG_DAC_CTRL_DACPL PolarityInvert:1;
    };
} NAU88U10YG_DACControl;

typedef union {
    uint16_t raw: 9;
    struct {
        uint8_t : 1;
        uint8_t DACGain :8;
    };
} NAU88U10YG_DACGainControl;

typedef union {
    uint16_t raw: 9;
     struct {
        bool HighPassFilter_Enable:1;
        eNAU88U10YG_ADC_CTRL_HPFAM AudioOrAplication_Mode:1;
        uint8_t HigtPassFilter:3;
        eNAU88U10YG_ADC_CTRL_ADCOS OverSampleRate:1;
        bool ADCPolarity:1;
    };
} NAU88U10YG_ADCControl;

typedef union {
    uint16_t raw: 9;
    struct {
        uint8_t : 1;
        uint8_t ADCGain :8;
    };
} NAU88U10YG_ADCGainControl;

typedef struct {
    NAU88U10YG_AudioInterface AudioInterface;
    NAU88U10YG_AudioInterfaceCompanding AudioInterfaceCopanding;
    NAU88U10YG_ClockControl ClockControl;
    NAU88U10YG_AudioSampleRateControl AudioSampleRateControl;
    NAU88U10YG_DACControl DACControl;
    NAU88U10YG_DACGainControl DACGainControl;
    NAU88U10YG_ADCControl ADCControl;
    NAU88U10YG_ADCGainControl ADCGainControl;
}NAU88U10YG_AudioControl;


///------------------------------------------------- PLL CONTROL -----------------------------------------------------//
typedef struct {
    uint16_t raw: 9;
    struct {
        uint8_t : 4;
        uint8_t PLLClock :1;
        uint8_t PLLInteger :4;
    };
}NAU88U10YG_PLLControl;

typedef struct {
    uint16_t raw: 9;
    struct {
        uint8_t : 3;
        uint8_t PLLK :6;
    };
}NAU88U10YG_PLLK1;

typedef struct {
    uint16_t raw: 9;
    struct {
        uint16_t PLLK :9;
    };
}NAU88U10YG_PLLK2;

typedef struct {
    uint16_t raw: 9;
    struct {
        uint16_t PLLK :9;
    };
}NAU88U10YG_PLLK3;

typedef struct {
    NAU88U10YG_PLLControl PLL_Control;
    NAU88U10YG_PLLK1 PLLK1;
    NAU88U10YG_PLLK2 PLLK2;
    NAU88U10YG_PLLK3 PLLK3;
}NAU88U10YG_PLL;

////-------------------------------------INPUT, OUTPUT & MIXER CONTROL--------------------------------------------------

typedef struct {
    uint16_t raw: 9;
    struct {
        uint8_t : 1;
        bool MOUTAttenuation :1;
        bool SPKAttenuation :1;
        uint8_t : 6;
    };
}NAU88U10YG_AttenuationControl;

typedef struct {
    uint16_t raw: 9;
    struct {
        eNAU88U10YG_OUTPUT_CTRL_AOUTIMP AnalogOutputResistance :1;
        bool ThermalShutdown_Enable :1;
        eNAU88U10YG_OUTPUT_CTRL_SPKBST SpeakerOutputBoostStage  :1;
        eNAU88U10YG_OUTPUT_CTRL_MOUTBST MONOOutputBoostStage :1;
        uint8_t : 5;
        //
//        uint8_t : 3;
//        uint8_t MONOOutputBoostStage :1;
//        uint8_t SpeakerOutputBoostStage  :1;
//        bool ThermalShutdown_Enable :1;
//        uint8_t AnalogOutputResistance :1;
    };
}NAU88U10YG_OutputCtrl;

typedef struct {
    uint16_t raw: 9;
    struct {
        uint8_t SPKGain : 6;
        bool SPKMuteEnable :1;
        bool SPKZC :1;
        uint8_t : 1;
    };
}NAU88U10YG_SpeakerGainControll;

////--------------------------------------------------------------------------------------------------------------------

bool xAudioCodecReadRegister(tI2cIO *i2c, uint16_t AdrRegQwery, uint16_t *DataRegResult);

bool xAudioCodecWrite_Register8b_Data8b(tI2cIO *i2c, uint8_t reg, uint8_t data);


#endif //NAU88U10YG_H
