diff --git a/source/Core/BSP/Pinecilv2/IRQ.cpp b/source/Core/BSP/Pinecilv2/IRQ.cpp index 31431e99..e57433c2 100644 --- a/source/Core/BSP/Pinecilv2/IRQ.cpp +++ b/source/Core/BSP/Pinecilv2/IRQ.cpp @@ -24,21 +24,34 @@ history ADC_Vin; history ADC_Temp; history ADC_Tip; -// IRQ is called at the end of the 8 set readings, pop these from the FIFO and send to filters -void adc_fifo_irq(void) { - if (ADC_GetIntStatus(ADC_INT_FIFO_READY) == SET) { - // Read out all entries in the fifo - while (ADC_Get_FIFO_Count()) { - uint32_t reading = ADC_Read_FIFO(); - ADC_Result_Type parsed = {0, 0, 0}; - ADC_Parse_Result(&reading, 1, &parsed); +void read_adc_fifo(void) { + // Read out all entries in the fifo + uint8_t pending_readings = ADC_Get_FIFO_Count(); + + // There _should_ always be 8 readings here. If there are not, it means that the adc didnt start when we wanted and timing slipped + // So if there isn't 8 readings, we throw them out + if (pending_readings != 8) { + MSG((char *)"Discarding out of sync adc %d\r\n", pending_readings); + } else { + MSG((char *)"FIFO Count %d\r\n", pending_readings); + while (pending_readings) { + pending_readings--; + uint32_t raw_reading = ADC_Read_FIFO(); + ADC_Result_Type parsed = {0, 0, 0}; + ADC_Parse_Result(&raw_reading, 1, &parsed); + switch (parsed.posChan) { case TMP36_ADC_CHANNEL: ADC_Temp.update(parsed.value << 2); break; - case TIP_TEMP_ADC_CHANNEL: + case TIP_TEMP_ADC_CHANNEL: { + int32_t avg = ADC_Tip.average(); + int32_t delta = (int32_t)parsed.value - (avg >> 2); + if (delta > 4000) { + MSG((char *)"ADC Chan %d -> %d -> %d\r\n", pending_readings, parsed.value, delta); + } ADC_Tip.update(parsed.value << 2); - break; + } break; case VIN_ADC_CHANNEL: ADC_Vin.update(parsed.value << 2); break; @@ -46,17 +59,16 @@ void adc_fifo_irq(void) { break; } } - // unblock the PID controller thread - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if (pidTaskNotification) { - vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); - } + } + ADC_FIFO_Clear(); + // unblock the PID controller thread + if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + BaseType_t xHigherPriorityTaskWoken = pdFALSE; + if (pidTaskNotification) { + vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } } - // Clear IRQ - ADC_IntClr(ADC_INT_ALL); } volatile bool inFastPWMMode = false; @@ -68,8 +80,23 @@ volatile uint16_t PWMSafetyTimer = 0; volatile uint8_t pendingPWM = 0; volatile bool pendingNextPeriodIsFast = false; -inline void start_PWM_output(void) { +void timer0_comp0_callback(void) { + // Trigged at end of output cycle; turn off the tip PWM + PWM_Channel_Disable(PWM_Channel); + TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_0); +} + +// Timer 0 is used to co-ordinate the ADC and the output PWM +void timer0_comp1_callback(void) { + ADC_Start(); + TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_1); +} +void timer0_comp2_callback(void) { + // Triggered at end of timer cycle; re-start the tip driver + ADC_Stop(); TIMER_Disable(TIMER_CH0); + // Read the ADC data _now_. So that if things have gone out of sync, we know about it + read_adc_fifo(); if (PWMSafetyTimer) { PWMSafetyTimer--; @@ -86,62 +113,24 @@ inline void start_PWM_output(void) { // Turn on output PWM_Channel_Enable(PWM_Channel); } else { - TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_0, 255 - 1); - // Leave output off PWM_Channel_Disable(PWM_Channel); } } else { PWM_Channel_Disable(PWM_Channel); - switchToFastPWM(); } TIMER_Enable(TIMER_CH0); -} - -void timer0_comp0_callback(void) { - // Trigged at end of output cycle; turn off the tip PWM - PWM_Channel_Disable(PWM_Channel); - TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_0); -} - -// Timer 0 is used to co-ordinate the ADC and the output PWM -void timer0_comp1_callback(void) { - if (PWM_Channel_Is_Enabled(PWM_Channel)) { - ADC_FIFO_Clear(); - // So there appears to be a bug _somewhere_ where sometimes the comparator doesn't fire - // Its not re-occurring with specific values, so suspect its a weird bug - // For now, we just skip the cycle and throw away the ADC readings. Its a waste but - // It stops stupid glitches in readings, i'd take slight instability from the time jump - // Over the readings we get that are borked as the heater is left on - // - PWM_Channel_Disable(PWM_Channel); - // Trigger the PID now instead - if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { - BaseType_t xHigherPriorityTaskWoken = pdFALSE; - if (pidTaskNotification) { - vTaskNotifyGiveFromISR(pidTaskNotification, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); - } - } - } else { - ADC_Start(); - } - TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_1); -} -void timer0_comp2_callback(void) { - // Triggered at end of timer cycle; re-start the tip driver TIMER_ClearIntStatus(TIMER_CH0, TIMER_COMP_ID_2); - start_PWM_output(); } + void switchToFastPWM(void) { inFastPWMMode = true; holdoffTicks = 10; tempMeasureTicks = 10; totalPWM = powerPWM + tempMeasureTicks + holdoffTicks; - TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_2, totalPWM); - // ~10Hz TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_1, powerPWM + holdoffTicks); + TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_2, totalPWM); // Set divider to 10 ~= 10.5Hz uint32_t tmpVal = BL_RD_REG(TIMER_BASE, TIMER_TCDR); @@ -157,10 +146,10 @@ void switchToSlowPWM(void) { tempMeasureTicks = 5; totalPWM = powerPWM + tempMeasureTicks + holdoffTicks; - TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_2, totalPWM); // Adjust ADC TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_1, powerPWM + holdoffTicks); + TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_2, totalPWM); // Set divider for ~ 5Hz uint32_t tmpVal = BL_RD_REG(TIMER_BASE, TIMER_TCDR); @@ -169,9 +158,11 @@ void switchToSlowPWM(void) { BL_WR_REG(TIMER_BASE, TIMER_TCDR, tmpVal); } + void setTipPWM(const uint8_t pulse, const bool shouldUseFastModePWM) { - PWMSafetyTimer = 10; // This is decremented in the handler for PWM so that the tip pwm is - // disabled if the PID task is not scheduled often enough. + PWMSafetyTimer = 10; + // This is decremented in the handler for PWM so that the tip pwm is + // disabled if the PID task is not scheduled often enough. pendingPWM = pulse; pendingNextPeriodIsFast = shouldUseFastModePWM; } diff --git a/source/Core/BSP/Pinecilv2/IRQ.h b/source/Core/BSP/Pinecilv2/IRQ.h index 4f6d6814..bc7dca72 100644 --- a/source/Core/BSP/Pinecilv2/IRQ.h +++ b/source/Core/BSP/Pinecilv2/IRQ.h @@ -19,7 +19,6 @@ extern "C" { void timer0_comp0_callback(void); void timer0_comp1_callback(void); void timer0_comp2_callback(void); -void adc_fifo_irq(void); void GPIO_IRQHandler(void); #ifdef __cplusplus } diff --git a/source/Core/BSP/Pinecilv2/Setup.cpp b/source/Core/BSP/Pinecilv2/Setup.cpp index c44aaf6f..89496166 100644 --- a/source/Core/BSP/Pinecilv2/Setup.cpp +++ b/source/Core/BSP/Pinecilv2/Setup.cpp @@ -66,7 +66,7 @@ void hardware_init() { // Note on I2C clock rate @ 100Khz the screen update == 20ms which is too long for USB-PD to work // 200kHz and above works I2C_ClockSet(I2C0_ID, 300000); // Sets clock to around 25 kHz less than set here - TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_1, 0); + TIMER_SetCompValue(TIMER_CH0, TIMER_COMP_ID_0, 0); } void setup_pwm(void) { // Setup PWM we use for driving the tip @@ -96,10 +96,6 @@ void setup_adc(void) { ADC_CFG_Type adc_cfg = {}; ADC_FIFO_Cfg_Type adc_fifo_cfg = {}; - CPU_Interrupt_Disable(GPADC_DMA_IRQn); - - ADC_IntMask(ADC_INT_ALL, MASK); - // Please also see PR #1529 for even more context /* @@ -178,16 +174,11 @@ void setup_adc(void) { #endif adc_fifo_cfg.dmaEn = DISABLE; - adc_fifo_cfg.fifoThreshold = ADC_FIFO_THRESHOLD_8; // Triger FIFO when all 8 measurements are done + adc_fifo_cfg.fifoThreshold = ADC_FIFO_THRESHOLD_1; ADC_FIFO_Cfg(&adc_fifo_cfg); ADC_MIC_Bias_Disable(); ADC_Tsen_Disable(); ADC_Gain_Trim(); - - // Enable FiFo IRQ - Interrupt_Handler_Register(GPADC_DMA_IRQn, adc_fifo_irq); - ADC_IntMask(ADC_INT_FIFO_READY, UNMASK); - CPU_Interrupt_Enable(GPADC_DMA_IRQn); ADC_Stop(); ADC_FIFO_Clear(); ADC_Scan_Channel_Config(adc_tip_pos_chans, adc_tip_neg_chans, sizeof(adc_tip_pos_chans) / sizeof(ADC_Chan_Type), DISABLE);