/** * adc.c * * Initialization and communication for the Analog to Digital Converter (ADC) hardware. * * Copyright (c) 2022 Bigscreen, Inc. */ #include #include "adc.h" #include "displayboard.h" #include "temp_sense.h" void adc_end_conversion(void); // callback function to clear interrupt by reading ADC data void usbcpd_update_adc_values(uint16_t val1, uint16_t val2); void init_adc(void) { struct adc_config adc_cfg; pmc_enable_periph_clk(ID_ADC); adc_select_clock_source_mck(ADC); adc_get_config_defaults(&adc_cfg); adc_init(ADC, &adc_cfg); // Prescaler set to max makes the temp sense channel settle down. // For some reason, if it's not maxed out the resulting ADC conversion is super jumpy ADC->ADC_MR &= ~(ADC_MR_PRESCAL_Msk); ADC->ADC_MR |= ADC_MR_PRESCAL(0xFF); // TODO: check if all three channels are converted // with a single trigger adc_channel_enable(ADC, USBC_ADC_CC1_CH); adc_channel_enable(ADC, USBC_ADC_CC2_CH); adc_channel_enable(ADC, TEMP_SENSE_ADC_CH); adc_set_trigger(ADC, ADC_TRIG_SW); adc_set_callback(ADC, ADC_INTERRUPT_EOC_3, adc_end_conversion, 1); adc_set_resolution(ADC, ADC_12_BITS); adc_start_calibration(ADC); NVIC_EnableIRQ(ADC_IRQn); NVIC_SetPriority(ADC_IRQn, ADC_INTERRUPT_PRIO); } void trig_adc(void) { adc_start_software_conversion(ADC); } void adc_end_conversion(void) { // Retrieve results of ADC conversions temp_sense_update_adc_value(ADC->ADC_CDR[TEMP_SENSE_ADC_CH]); usbcpd_update_adc_values(ADC->ADC_CDR[USBC_ADC_CC1_CH], ADC->ADC_CDR[USBC_ADC_CC2_CH]); } uint16_t cc1val = UINT16_MAX; uint16_t cc2val = UINT16_MAX; void usbcpd_update_adc_values(uint16_t val1, uint16_t val2) { cc1val = val1; cc2val = val2; } uint16_t get_cc1_val() { return cc1val; } uint16_t get_cc2_val() { return cc2val; } USB_Flip_State_t get_flip_status() { USB_Flip_State_t retval = Flip_Undefined; #if 0 // Unitialized? Check if cc1 or cc2 is still at the UINT16_MAX if((cc1val == UINT16_MAX) || (cc2val == UINT16_MAX)) { retval = Flip_Undefined; } // CC1 active, CC2 low - cable is inserted "unflipped", with CC = CC1 else if((CC_ACTIVE_THRESH_LOW <= cc1val) && (cc1val <= CC_ACTIVE_THRESH_HIGH) && (cc2val <= CC_INACTIVE_THRESH)) { retval = Flip_CC1; } // CC2 active, CC1 low - cable is inserted "flipped", with CC = CC2 else if((CC_ACTIVE_THRESH_LOW <= cc2val) && (cc2val <= CC_ACTIVE_THRESH_HIGH) && (cc1val <= CC_INACTIVE_THRESH)) { retval = Flip_CC2; } // If the CC1 or CC2 value is above the "wrong way" threshhold, then the junction box cable end is inserted the wrong way else if((cc1val >= CC_WRONG_WAY_THRESH) && (cc2val <= CC_INACTIVE_THRESH)) { retval = Flip_CC1_JcnBoxWrongWay; } else if((cc2val >= CC_WRONG_WAY_THRESH) && (cc1val <= CC_INACTIVE_THRESH)) { retval = Flip_CC2_JcnBoxWrongWay; } #endif if((cc1val >= CC_WRONG_WAY_THRESH) && (cc2val <= CC_INACTIVE_THRESH)) { retval = Flip_CC1_JcnBoxWrongWay; } else if((cc2val >= CC_WRONG_WAY_THRESH) && (cc1val <= CC_INACTIVE_THRESH)) { retval = Flip_CC2_JcnBoxWrongWay; } else if(cc1val > cc2val) { retval = Flip_CC1; } else { retval = Flip_CC2; } return retval; }