/* * ADC.c * * Created: Tue Sep 13 2022 19:51:36 * Author Chris */ // ============================================================================================ // Includes #include "Core1_ADC.h" #include "hardware/adc.h" #include "hardware/irq.h" #include "hardware/divider.h" // ============================================================================================ // Defines #define YES true #define NO false #define ANALOG_REFERENCE_mV 3300ul #define ADC_INPUT_PIN 29 // ============================================================================================ // Variables static uint32_t _ADC_Result_Value; static uint32_t _ADC_Result_mV; const uint32_t _ADC_Result_Num = 11; const uint32_t _ADC_Result_Denum = 1; const bool _ADC_Result_LowPass = NO; // ============================================================================================ // Function Declarations void Core1_ADC_Select_Next_MUX_Channel(); void Core1_ADC_Set_Mux(uint channel); void Core1_ADC_Store_ADC_Result(uint16_t adc_value); uint32_t Core1_ADC_Low_Pass_Filter(int current_value, int new_value); /******************************************************************* Interrupt Service Routines *******************************************************************/ bool ISR_ADC() { Core1_ADC_Store_ADC_Result(adc_fifo_get()); } /******************************************************************* Functions *******************************************************************/ void Core1_ADC_Init() { _ADC_Result_Value = 0; _ADC_Result_mV = 0; adc_gpio_init(ADC_INPUT_PIN); adc_init(); adc_select_input(3); adc_fifo_setup( true, // Write each completed conversion to the sample FIFO false, // Enable DMA data request (DREQ) 1, // DREQ (and IRQ) asserted when at least 1 sample present false, // We won't see the ERR bit because of 8 bit reads; disable. false // Shift each sample to 8 bits when pushing to FIFO ); adc_set_clkdiv(5999); // One measurement every 0.125ms -> 8 measurements per 1 ms adc_irq_set_enabled(true); irq_set_exclusive_handler(ADC_IRQ_FIFO, (void *)ISR_ADC); irq_set_enabled(ADC_IRQ_FIFO, true); adc_run(true); } uint16_t Core1_ADC_Get_Result_Value(uint channel) { return _ADC_Result_Value; } uint16_t Core1_ADC_Get_Result_mV(uint channel) { return _ADC_Result_mV; } /******************************************************************* Internal Functions *******************************************************************/ void Core1_ADC_Store_ADC_Result(uint16_t adc_value) { if(_ADC_Result_LowPass == YES) { _ADC_Result_Value = (uint16_t)Core1_ADC_Low_Pass_Filter((float)_ADC_Result_Value, (float)adc_value); } else { _ADC_Result_Value = (uint32_t)adc_value; } _ADC_Result_mV = ((_ADC_Result_Value * ANALOG_REFERENCE_mV * _ADC_Result_Num) / 4096) / _ADC_Result_Denum; } uint32_t Core1_ADC_Low_Pass_Filter(int current_value, int new_value) { // Link: https://kiritchatterjee.wordpress.com/2014/11/10/a-simple-digital-low-pass-filter-in-c/ const int Beta = 6; current_value = (current_value << Beta) - current_value; current_value += new_value; current_value >>= Beta; return (uint32_t)current_value; }