// analog regs PGA
#define rega_aud_ctrl 0x86
enum {
FLDA_AUD_PWDN_LEFT = BIT(0),
FLDA_AUD_PWDN_RIGHT = BIT(1),
FLDA_AUD_MUTE_RIGHT = BIT(2),
FLDA_AUD_MUTE_LEFT = BIT(3),
FLDA_AUD_PRE_GAIN_RIGHT = BIT_RNG(4,5),
FLDA_AUD_PRE_GAIN_LEFT = BIT_RNG(6,7),
};
#define rega_aud_ctrl2 0x87
enum {
FLDA_AUD_PST_GAIN_RIGHT = BIT_RNG(0,3),
FLDA_AUD_PST_GAIN_LEFT = BIT_RNG(4,7),
};
// Структура конфигурации опроса и инициализации устройства ADC
// Выходной пакет непрерывного опроса формируется по данному описанию
// CMD_DEV_CAD Get/Set CFG/ini ADC & Start measure
typedef struct __attribute__((packed)) _dev_adc_cfg_t {
uint8_t pktcnt; // минимальное кол-во передаваемых значений ADC в одном пакете передачи (автоподстройка до мах SMPS_BLK_CNT)
uint8_t chnl; // Channel
uint16_t sps; // период adc chl0
uint8_t pga20db;
uint8_t pga2db5;
} dev_adc_cfg_t; // [7]
extern dev_adc_cfg_t cfg_adc; // store in eep
#define ADC_DFIFO_SIZE 512 // dfifo size: 64,128,256,512...
u16 dfifo_rd_ptr;
s16 dfifo[ADC_DFIFO_SIZE];
#define SOFT_OUT_SCALE 1 // 1, 2, 4
#if (MCU_CORE_TYPE == MCU_CORE_8266)
// 8266 Hardware parameters :
#define ADC_DFIFO_FCLK 16000000 // CLK FIFO
#define MAX_DFIFO_SCALE 8 // DFIFO decimation max
#define MIN_DFIFO_SCALE 1 // DFIFO decimation min
#define MAX_PERIOD_CH0 4095 // Max ADC auto channel 0 (Misc) period max (adc_period_chn0 * system clocks)
#define MIN_PERIOD_CH0 77 // channel ADC period (adc_period_chn0 * system clocks)
#define MAX_PERIOD_CH1 255 // ADC auto channel 1 (L)& 2 period max (adc_period_chn12 * 16 system clocks)
#define MIN_PERIOD_CH1 15 // ADC auto channel 1 (L)& 2 period min (adc_period_chn12 * 16 system clocks)
#define MIN_OUT_SPS (ADC_DFIFO_FCLK/(MAX_DFIFO_SCALE*SOFT_OUT_SCALE)/(MAX_PERIOD_CH0 + MAX_PERIOD_CH1*16))
#define MAX_OUT_SPS_D1 (ADC_DFIFO_FCLK/(1*SOFT_OUT_SCALE)/(MIN_PERIOD_CH0 + MIN_PERIOD_CH1*16))
#define MAX_OUT_SPS_D2 (ADC_DFIFO_FCLK/(2*SOFT_OUT_SCALE)/(MIN_PERIOD_CH0 + MIN_PERIOD_CH1*16))
#define MAX_OUT_SPS_D4 (ADC_DFIFO_FCLK/(4*SOFT_OUT_SCALE)/(MIN_PERIOD_CH0 + MIN_PERIOD_CH1*16))
#define MAX_OUT_SPS_D8 (ADC_DFIFO_FCLK/(8*SOFT_OUT_SCALE)/(MIN_PERIOD_CH0 + MIN_PERIOD_CH1*16))
/**
* @brief This function initializes ADC in sps
* @param sps = (245..50473)/SOFT_OUT_SCALE, x1 -> 245..50473 sps
* @return <= 0 - error
*/
int init_adc_dfifo(dev_adc_cfg_t * p) {
u32 sps = p->sps;
u8 chnl = p->chnl;
u32 per, per12;
if(sps < MIN_OUT_SPS
|| sps > MAX_OUT_SPS_D1)
return 0;
/** adc stop**/
reg_adc_ctrl = 0;
/** dfifo stop**/
reg_dfifo_ana_in = 0;
/**enable adc clock**/
reg_rst_clk0 |= FLD_CLK_ADC_EN;
/**set adc clock **/
adc_SetClkFreq(ADC_CLK_4M);
WriteAnalogReg(0x88,0x0f); // select 192M clk output
WriteAnalogReg(0x05,0x60); // power on pll
WriteAnalogReg(0x06,0xfe); // power on sar
// set sample rate
if(sps > MAX_OUT_SPS_D2) {
per = ADC_DFIFO_FCLK/SOFT_OUT_SCALE;
reg_dfifo_scale = 0x00; // DFIFO decimation 1
reg_aud_alc_vol = 40;
}
else if(sps > MAX_OUT_SPS_D4) {
per = (ADC_DFIFO_FCLK/SOFT_OUT_SCALE)>>1;
reg_dfifo_scale = 0x11; // DFIFO decimation 2
reg_aud_alc_vol = 28;
}
else if(sps > MAX_OUT_SPS_D8) {
per = (ADC_DFIFO_FCLK/SOFT_OUT_SCALE)>>2;
reg_dfifo_scale = 0x33; // DFIFO decimation 4
reg_aud_alc_vol = 16;
}
else {
per = (ADC_DFIFO_FCLK/SOFT_OUT_SCALE)>>3;
reg_dfifo_scale = 0x77; // DFIFO decimation 8
reg_aud_alc_vol = 4;
}
per /= sps;
per12 = (per - MIN_PERIOD_CH0) >> 4;
if(per12 > 255)
per12 = 255;
reg_adc_period_chn12 = per12;
per -= per12<<4;
reg_adc_period_chn0 = per;
// dfifo mode
reg_aud_hpf_alc = 11 | FLD_AUD_IN_HPF_BYPASS; // | FLD_AUD_IN_ALC_BYPASS;
// PGA on ?
if((chnl&0x1f) == FLD_ADC_CHN_PGA_R || (chnl&0x1f) == FLD_ADC_CHN_PGA_L) {
// PGA on
reg_clk_en2 |= FLD_CLK2_DIFIO_EN | FLD_CLK2_AUD_EN;
WriteAnalogReg(rega_aud_ctrl, cfg_adc.pga20db); //(PGA_GAIN_PREAMP << 6));
WriteAnalogReg(rega_aud_ctrl2,cfg_adc.pga2db5);// (PGA_GAIN_POSTAMP << 4));
// select the input channel
// PGA set left channel ANA_C<1> and right channel ANA_C<2>
reg_adc_pga_sel_l = 0x21;
} else {
// PGA off
reg_clk_en2 |= FLD_CLK2_DIFIO_EN;
reg_adc_pga_sel_l = 0;
}
reg_adc_pga_sel_m = 0;
// reg_adc_pga_sel_r = 0; // none 8266?
/// set the adc's mode && channels
// adc_AnaChSet(chnl); // reg_adc_chn_m_sel
// adc_AnaModeSet(SINGLEEND); // reg_adc_chn_m_sel
REG_ADDR32(0x002c) = 0 // chnl GPIO_PC4
| (ADC_CHN_GND) // reg_adc_chn_m_sel
| ((chnl | 0x80) << 8) // reg_adc_chn_l_sel
| (ADC_CHN_GND << 16) // reg_adc_chn_r_sel
| ADC_SAMPLING_RES_14BIT << 24; // reg_adc_res_lr
/// set the reference voltage
// adc_RefVoltageSet(ADC_REF_VOL_1V3); // ADC_REF_VOL_1V3, ADC_REF_VOL_AVDD
reg_adc_ref = MASK_VAL(FLD_ADC_REF_M, ADC_REF_VOL_AVDD) // adc_RefVoltageSet(RV_1P428);
| MASK_VAL(FLD_ADC_REF_L, ADC_REF_VOL_1V3) // !!! // RV_1P428, RV_AVDD, RV_1P224
| MASK_VAL(FLD_ADC_REF_R, ADC_REF_VOL_AVDD);
/// set resolution, sample cycle
// adc_ResSet(ADC_SAMPLING_RES_14BIT); // reg_adc_samp_res
// adc_SampleTimeSet(ADC_SAMPLING_CYCLE_12);// ADC_SAMPLING_CYCLE_6); reg_adc_samp_res
reg_adc_samp_res = MASK_VAL(FLD_ADC_CHNM_SAMP_RESOL, ADC_SAMPLING_RES_14BIT)
| MASK_VAL(FLD_ADC_CHNM_SAMP_CYCLE, ADC_SAMPLING_CYCLE_12)
| MASK_VAL(FLD_ADC_CHNLR_SAMP_CYCLE, 0);
// set dfifo buf
reg_dfifo0_addr = (u16) ((u32)&dfifo);
reg_dfifo0_size = (ADC_DFIFO_SIZE>>3)-1;
// start dfifo
// Bit[3]: disable D-MIC channel
reg_dfifo_ana_in = BIT(3) | FLD_DFIFO_MIC_ADC_IN | FLD_DFIFO_AUD_INPUT_MONO | FLD_DFIFO_WPTR_CLR;
dfifo_rd_ptr = 0;
reg_dfifo_ana_in = BIT(3) | FLD_DFIFO_MIC_ADC_IN | FLD_DFIFO_AUD_INPUT_MONO;
// start adc
reg_adc_ctrl = FLD_ADC_CHNL_AUTO_EN | FLD_ADC_AUD_DATAPATH_EN | MASK_VAL(FLD_ADC_AUD_MODE, 1); //= 0x15; 0: no audio; 1: mono; 2: stereo;
return 1;
}
void deinit_adc(void) {
reg_adc_ctrl = 0;
reg_dfifo_ana_in = 0; // dfifo disable
reg_clk_en2 &= ~(FLD_CLK2_DIFIO_EN | FLD_CLK2_AUD_EN );
WriteAnalogReg(rega_aud_ctrl, FLDA_AUD_PWDN_LEFT | FLDA_AUD_PWDN_RIGHT); //(PGA_GAIN_PREAMP << 6));
REG_ADDR32(0x002c) = 0 // chnl GPIO_PC4
| (ADC_CHN_GND) // reg_adc_chn_m_sel
| (ADC_CHN_GND << 8) // reg_adc_chn_l_sel
| (ADC_CHN_GND << 16) // reg_adc_chn_r_sel
| ADC_SAMPLING_RES_14BIT << 24; // reg_adc_res_lr
ADC_MODULE_CLOSED;
reg_rst_clk0 &= ~FLD_CLK_ADC_EN;
}
...
#if SOFT_OUT_SCALE == 1
unsigned int get_adc_dfifo_len(void) {
return((reg_audio_wr_ptr - dfifo_rd_ptr) & (ADC_DFIFO_SIZE - 1)) >> 1;
}
// В dfifo пишется по 2 семпла! (L и R канал)
// Для выборки семпла надо делать 2 шага, через один семпл.
int get_adc_dfifo(u16 * pbuf, unsigned int cnt) {
int i = 0;
unsigned int cur_size = ((reg_audio_wr_ptr - dfifo_rd_ptr) & (ADC_DFIFO_SIZE - 1)) >> 1;
if (cur_size > cnt) {
do {
dfifo_rd_ptr &= ADC_DFIFO_SIZE - 1;
u16 * p = (u16 *)&dfifo[dfifo_rd_ptr];
dfifo_rd_ptr += 2;
#if 0
pbuf[i++] = *p + 0x8000;
#else
s32 x = p[0] + p[1];
pbuf[i++] = (x >> 1) + 0x8000;
#endif
} while(i < cnt);
}
return i;
}
unsigned int get_adc_dfifo_len(void) {
return((reg_audio_wr_ptr - dfifo_rd_ptr) & (ADC_DFIFO_SIZE - 1)) >> 1;
}