static int32_t ADC_Read()

in IndustrialDeviceController/Software/MT3620_IDC_RTApp/lib/ADC.c [118:230]


static int32_t ADC_Read(
    AdcContext *handle, void (*callback)(int32_t status),
    uint32_t dmaFifoSize, ADC_Data *data,
    uint32_t *rawData, uint16_t channel,
    bool periodic, uint32_t frequency,
    uint16_t referenceVoltage)
{
    handle->callback = callback;
    handle->fifoSize = dmaFifoSize;
    handle->rawData = rawData;
    handle->data = data;

    mt3620_adc_ctl3_t ctl3 = { .mask = mt3620_adc->adc_ctl3 };
    ctl3.comp_time_delay = 1;
    ctl3.comp_preamp_current = 1;
    ctl3.comp_preamp_en = 1;
    ctl3.dither_en = 1;
    ctl3.dither_step_size = 2;
    ctl3.auxadc_in_mux_en = 1;
    ctl3.vcm_gen_en = 1;
    ctl3.auxadc_clk_gen_en = 1;
    ctl3.auxadc_pmu_clk_inv = 0;
    ctl3.auxadc_clk_src = 0;
    if (referenceVoltage > ADC_VREF_1V8_MIN && referenceVoltage < ADC_VREF_1V8_MAX) {
        ctl3.vcm_azure_en = 1;
    }
    else if (referenceVoltage > ADC_VREF_2V5_MIN && referenceVoltage < ADC_VREF_2V5_MAX) {
        ctl3.vcm_azure_en = 0;
    }
    else if (referenceVoltage > ADC_VREF_1V8_MAX && referenceVoltage < ADC_VREF_2V5_MIN) {
        ctl3.vcm_azure_en = ADC_VCM_AZURE_EN_DEF;
    } else {
        return ERROR_ADC_VREF_UNSUPPORTED;
    };
    mt3620_adc->adc_ctl3 = ctl3.mask;

    mt3620_adc_ctl0_t ctl0 = { .mask = mt3620_adc->adc_ctl0 };
    ctl0.adc_fsm_en = 0;
    ctl0.reg_avg_mode = 0;
    ctl0.reg_t_ch = 8;
    ctl0.pmode_en = 0;
    ctl0.reg_t_init = 20;
    ctl0.reg_ch_map = 0;
    mt3620_adc->adc_ctl0 = ctl0.mask;

#ifdef ADC_FIFO_CLEAR
    while (true) {
        mt3620_adc_fifo_debug16_t debug16 = (mt3620_adc_fifo_debug16_t)mt3620_adc->adc_fifo_debug16;
        if (debug16.read_ptr == debug16.write_ptr) {
            break;
        }
        (void)mt3620_adc->adc_fifo_rbr;
    }
#endif

    /* Wait for time specified in datasheet */
    GPT *timer = GPT_Open(MT3620_UNIT_GPT3, MT3620_GPT_3_LOW_SPEED, GPT_MODE_NONE);
    GPT_WaitTimer_Blocking(timer, 50, GPT_UNITS_MICROSEC);
    GPT_Close(timer);

    /* Set trigger level based on number of channels selected */
    uint8_t numChannels = ADC_CountChannels(channel);

    handle->channelsCount = numChannels;

    //Check fifo size is at least as great as the number of channels
    if (handle->fifoSize < numChannels) {
        return ERROR_ADC_FIFO_INVALID;
    }

    //Set DMA registers
    mt3620_dma_global->ch_en_set = (1 << MT3620_ADC_DMA_CHANNEL);

    MT3620_DMA_FIELD_WRITE(MT3620_ADC_DMA_CHANNEL, start, str, false);
    mt3620_dma[MT3620_ADC_DMA_CHANNEL].pgmaddr = handle->rawData;
    mt3620_dma[MT3620_ADC_DMA_CHANNEL].ffsize  = handle->fifoSize;
    if (handle->fifoSize == 1) {
        mt3620_dma[MT3620_ADC_DMA_CHANNEL].count = 1;
    } else {
        mt3620_dma[MT3620_ADC_DMA_CHANNEL].count   = ((3 * mt3620_dma[MT3620_ADC_DMA_CHANNEL].ffsize) / 4);
    }
    mt3620_dma[MT3620_ADC_DMA_CHANNEL].fixaddr = (void*)&mt3620_adc->adc_fifo_rbr;
    mt3620_dma[MT3620_ADC_DMA_CHANNEL].swptr   = 0;

    MT3620_DMA_FIELD_WRITE(MT3620_ADC_DMA_CHANNEL, ackint, ack, 1);

    MT3620_ADC_FIELD_WRITE(adc_fifo_dma_en, rx_dma_en, 1);

    mt3620_dma_con_t con = { .mask = mt3620_dma[MT3620_ADC_DMA_CHANNEL].con };
    con.size = 2;
    con.dir = 1;
    con.dreq = true;
    con.iten = true;
    con.toen = false;
    mt3620_dma[MT3620_ADC_DMA_CHANNEL].con = con.mask;

    MT3620_DMA_FIELD_WRITE(MT3620_ADC_DMA_CHANNEL, start, str, true);

    /* Select ADC channel and enable ADC finite state machine */
    ctl0.mask = mt3620_adc->adc_ctl0;
    if (periodic) {
        if (frequency > ADC_CLK_FREQUENCY) {
            return ERROR_ADC_FREQUENCY_UNSUPPORTED;
        }
        mt3620_adc->reg_period = (ADC_CLK_FREQUENCY / frequency) - 1;
        ctl0.pmode_en = periodic;
    }
    ctl0.reg_ch_map = channel;
    ctl0.adc_fsm_en = 1;
    mt3620_adc->adc_ctl0 = ctl0.mask;

    return ERROR_NONE;
}