#include "api_rt_pwm.h" #include "api_rt_dbg.h" #include "api_rt_timer.h" #include "board_config.h" #include "gd32f30x.h" #include #include "api_rt_adc.h" #include "classB.h" ApiRtPwm_Handle Pwms[1]; /* ========================================================================== */ /* ============================ Api RT Functions ============================ */ /* ========================================================================== */ void iRtPwm_Init() { Pwms[0].PwmBase = TIMER0; for (int i = 0; i < 6; i++) { Pwms[0].CompareValues[i] = HW_INIT_HHPWM_PERIOD; Pwms[0].ActiveCompareValues[i] = HW_INIT_HHPWM_PERIOD; } Pwms[0].CountZeroISR.Enable = 0; Pwms[0].CountZeroISR.Action = 0; Pwms[0].CountMaxISR.Enable = 0; Pwms[0].CountMaxISR.Action = 0; Pwms[0].BreakISR.Enable = 0; Pwms[0].BreakISR.Action = 0; Pwms[0].OutputEnable = 0; for (int i = 0; i < 4; i++) { Pwms[0].ChannelISR[i].Enable = 0; Pwms[0].ChannelISR[i].Action = 0; // Pwms[0].ChannelOutputEnable[i] = 0; } #if API_FUNCTION_PWM_SYNC_MULTI_SAMPLING Pwms[0].SyncSamplingEnable = 1; Pwms[0].SyncSamplingUpTickCount = 1; Pwms[0].SyncSamplingUpTick[0] = HW_INIT_HHPWM_PERIOD; Pwms[0].SyncSamplingDownTickCount = 1; Pwms[0].SyncSamplingDownTick[0] = HW_SAMPLE_BEFORE_UPDATE_CNTS; #endif } void iRtPwm_CountZeroIsr(uint8_t devIndex) { if (Pwms[devIndex].CountZeroISR.Enable) { if (Pwms[devIndex].CountZeroISR.Action != 0) { Pwms[devIndex].CountZeroISR.Action(); } } } void iRtPwm_CountMaxIsr(uint8_t devIndex) { if (Pwms[devIndex].CountMaxISR.Enable) { if (Pwms[devIndex].CountMaxISR.Action != 0) { Pwms[devIndex].CountMaxISR.Action(); } } } void iRtPwm_UpdateIsr(uint8_t devIndex) { uint32_t base = Pwms[devIndex].PwmBase; uint32_t ulOvTimeCnt = 0; if(TIMER_INTF(base) & TIMER_INT_FLAG_UP) { if((TIMER_CTL0(base) & TIMER_CTL0_DIR) == 0) // When Counting Up { /* TBC Up interrupt */ iRtPwm_CountZeroIsr(devIndex); } else { /* Reset Timer6 counts*/ iTimer_Reset(HW_TBC_HALF_UPDATE_TIMER); /* TBC Down interrupt */ iRtPwm_CountMaxIsr(devIndex); /* Timing management, refer to the Software design description for details */ while ((iTimer_GetCount(HW_TBC_HALF_UPDATE_TIMER) < HW_INIT_PWM_PERIOD) && (ulOvTimeCnt < 10000)) { ulOvTimeCnt++; }; /* ADC0 trigger set */ iPwm_SetCompareValueImmediate(0,3,Pwms[0].SyncSamplingUpTick[1]); /* ADC Enable*/ iAdc_Enable(0); /* Software trigger for regular sampling*/ iAdc_Convert(0); /* Compara value load */ iRtPwm_ActivateCompareValues(0); timer_dma_enable(base,TIMER_DMA_UPD); dma_channel_enable(DMA0,DMA_CH4); } } /* Timer0 update interrupt flag clear */ TIMER_INTF(base) = ~(uint32_t)TIMER_INT_FLAG_UP; } void iRtPwm_SyncSamplingAdcIsr(uint8_t devIndex) { if (ADC_STAT(ADC0) & ADC_INT_FLAG_EOIC) { Adcs[1].Results[HW_ADC_IA_CH] = ADC_IDATA0(ADC0); Adcs[1].Results[HW_ADC_IB_CH] = ADC_IDATA1(ADC0); Adcs[1].Results[HW_ADC_IC_CH] = ADC_IDATA2(ADC0); /* ADC0 disable */ ADC_CTL1(ADC0) &= ~((uint32_t)ADC_CTL1_ADCON); /* ADC1 trigger set */ iPwm_SetCompareValueImmediate(0,3,Pwms[0].SyncSamplingUpTick[0]); /* ADC1 enable */ ADC_CTL1(ADC1) |= (uint32_t)ADC_CTL1_ADCON; /* ADC0 interrupt flag clear */ ADC_STAT(ADC0) &= ~((uint32_t)ADC_INT_FLAG_EOIC); } else if (ADC_STAT(ADC1) & ADC_INT_FLAG_EOIC) { if (Pwms[0].SyncSamplingUpTick[0] != HW_INIT_HHHPWM_PERIOD) { Adcs[2].Results[HW_ADC_IDC_CH] = ADC_IDATA0(ADC1); } /* ADC1 disable */ ADC_CTL1(ADC1) &= ~((uint32_t)ADC_CTL1_ADCON); /* ADC1 interrupt flag clear */ ADC_STAT(ADC1) &= ~((uint32_t)ADC_INT_FLAG_EOIC); } else { //do noting } } void iRtPwm_ActivateCompareValues(uint8_t devIndex) { ASSERT_LESS(devIndex, 1); for (int i = 0; i < 6; i++) { Pwms[devIndex].ActiveCompareValues[i] = Pwms[devIndex].CompareValues[i]; } } /* ========================================================================== */ /* ============================== API Functions ============================= */ /* ========================================================================== */ uint32_t iPwm_GetClock(uint8_t devIndex) { return HW_TIM_CLOCK_HZ; } void iPwm_EnableCount(uint8_t devIndex) { uint32_t base = Pwms[devIndex].PwmBase; TIMER_CTL0(base) |= (uint32_t)BIT(0); } void iPwm_DisableCount(uint8_t devIndex) { uint32_t base = Pwms[devIndex].PwmBase; TIMER_CTL0(base) &= ~(uint32_t)BIT(0); } uint32_t iPwm_GetCountMax(uint8_t devIndex) { uint32_t base = Pwms[devIndex].PwmBase; uint32_t count_value = 0U; count_value = TIMER_CAR(base); return count_value; } void iPwm_SetCountMax(uint8_t devIndex, uint32_t countMax) { uint32_t base = Pwms[devIndex].PwmBase; TIMER_CAR(base)= countMax; } uint32_t iPwm_GetCount(uint8_t devIndex) { uint32_t base = Pwms[devIndex].PwmBase; uint32_t count_value = 0U; count_value = TIMER_CNT(base); return count_value; } void iPwm_SetCount(uint8_t devIndex, uint32_t count) { uint32_t base = Pwms[devIndex].PwmBase; TIMER_CNT(base)= count; } ApiPwm_CountMode iPwm_GetCountMode(uint8_t devIndex) { uint32_t base = Pwms[devIndex].PwmBase; ApiPwm_CountMode mode = ApiPwm_CountUp; if ((TIMER_CTL0(base) & (uint16_t)0x0060) == (uint16_t)0x0000) { if ((TIMER_CTL0(base) & (uint16_t)0x0010) != 0) { mode = ApiPwm_CountUp; } #if API_FUNCTION_PWM_COUNTDOWN == SUPPORT else { mode = ApiPwm_CountDown; } #endif } else { mode = ApiPwm_CountUpDown; } return mode; } void iPwm_SetCountMode(uint8_t devIndex, ApiPwm_CountMode mode) { uint32_t base = Pwms[devIndex].PwmBase; switch (mode) { case ApiPwm_CountUp: TIMER_CTL0(base) &= ~((uint16_t)0x0060); TIMER_CTL0(base) &= ~(uint16_t)0x0010; break; #if FUNCTION_PWM_COUNTDOWN == SUPPORT case ApiPwm_CountDown: TIMER_CTL0(base) &= ~((uint16_t)0x0060); TIMER_CTL0(base) |= (uint16_t)0x0010; break; #endif case ApiPwm_CountUpDown: TIMER_CTL0(base) |= ((uint16_t)0x0060); break; default: break; } } ApiPwm_CompareMode iPwm_GetCompareMode(uint8_t devIndex, uint8_t channelIndex) { uint32_t base = Pwms[devIndex].PwmBase; uint8_t conf = 0; switch (channelIndex) { case 0: conf = TIMER_CHCTL0(base) & (uint32_t)0x000000F0UL; break; case 1: conf = (TIMER_CHCTL0(base) & (uint32_t)0x0000F000UL) >> 16; break; case 2: conf = TIMER_CHCTL1(base) & (uint32_t)0x000000F0UL; break; case 3: conf = (TIMER_CHCTL1(base) & (uint32_t)0x0000F000UL) >> 16; break; default: break; } ApiPwm_CompareMode mode = ApiPwm_NoAction; switch (conf >> 4) { case 0x00: mode = ApiPwm_NoAction; break; case 0x01: mode = ApiPwm_UpMatchSet; #if FUNCTION_PWM_COUNTDOWN if (iPwm_GetCountMode(devIndex) == Pwm_CountDown) mode = ApiPwm_DownMatchSet; #endif break; case 0x02: mode = ApiPwm_UpMatchClear; #if FUNCTION_PWM_COUNTDOWN if (iPwm_GetCountMode(devIndex) == Pwm_CountDown) mode = ApiPwm_DownMatchClear; #endif break; case 0x03: mode = ApiPwm_UpMatchToggle; #if FUNCTION_PWM_COUNTDOWN if (iPwm_GetCountMode(devIndex) == Pwm_CountDown) mode = ApiPwm_DownMatchToggle; #endif break; case 0x04: mode = ApiPwm_ForceClear; break; case 0x05: mode = ApiPwm_ForceSet; break; case 0x06: mode = ApiPwm_HigherClear; break; case 0x07: mode = ApiPwm_HigherSet; break; default: mode = ApiPwm_NoAction; break; } return mode; } void iPwm_SetCompareMode(uint8_t devIndex, uint8_t channelIndex, ApiPwm_CompareMode mode) { uint32_t base = Pwms[devIndex].PwmBase; uint8_t conf = 0; switch (mode) { case ApiPwm_NoAction: conf = 0x00; break; case ApiPwm_UpMatchSet: conf = 0x01; break; case ApiPwm_UpMatchClear: conf = 0x02; break; case ApiPwm_UpMatchToggle: conf = 0x03; break; case ApiPwm_ForceClear: conf = 0x04; break; case ApiPwm_ForceSet: conf = 0x05; break; case ApiPwm_HigherClear: conf = 0x06; break; case ApiPwm_HigherSet: conf = 0x07; break; default: break; } #if API_FUNCTION_PWM_COUNTDOWN if (iPwm_GetCountMode(devIndex) == ApiPwm_CountDown) { switch (mode) { case ApiPwm_DownMatchSet: conf = 0x01; break; case ApiPwm_DownMatchClear: conf = 0x02; break; case ApiPwm_DownMatchToggle: conf = 0x03; break; } } #endif switch (channelIndex) { case 0: TIMER_CHCTL0(base) &= ~((uint32_t)0x000000F0UL); TIMER_CHCTL0(base) |= (((uint32_t)conf) << 4); break; case 1: TIMER_CHCTL0(base) &= ~((uint32_t)0x0000F000UL); TIMER_CHCTL0(base) |= (((uint32_t)conf) << (4 + 8)); break; case 2: TIMER_CHCTL0(base) &= ~((uint32_t)0x000000F0UL); TIMER_CHCTL0(base) |= (((uint32_t)conf) << 4); break; case 3: TIMER_CHCTL0(base) &= ~((uint32_t)0x0000F000UL); TIMER_CHCTL0(base) |= (((uint32_t)conf) << (4 + 8)); break; } } uint32_t iPwm_GetCompareValue(uint8_t devIndex, uint8_t channelIndex) { uint32_t base = Pwms[devIndex].PwmBase; uint32_t value = 0; switch (channelIndex) { case 0: value = TIMER_CH0CV(base); break; case 1: value = TIMER_CH1CV(base); break; case 2: value = TIMER_CH2CV(base); break; case 3: value = TIMER_CH3CV(base); break; default: break; } return value; } void iPwm_SetCompareValue(uint8_t devIndex, uint8_t channelIndex, uint32_t value) { ASSERT_LESS(devIndex, 1); ASSERT_LESS(channelIndex, 3); Pwms[devIndex].CompareValues[channelIndex] = value; } void iPwm_SetCompareValueDelay(uint8_t devIndex, uint8_t channelIndex, uint32_t value) { ASSERT_LESS(devIndex, 1); ASSERT_LESS(channelIndex, 3); Pwms[devIndex].CompareValues[channelIndex + 3] = value; } void iPwm_SetCompareGroupValues16(uint8_t devIndex, uint16_t* values) { for (int i = 0; i < 6; i++) { Pwms[devIndex].CompareValues[i] = values[i]; } } void iPwm_SetCompareValueImmediate(uint8_t devIndex, uint8_t channelIndex, uint32_t value) { ASSERT_LESS(devIndex, 1); ASSERT_LESS(channelIndex, 4); uint32_t base = Pwms[devIndex].PwmBase; switch (channelIndex) { case 0: TIMER_CH0CV(base) = value; break; case 1: TIMER_CH1CV(base) = value; break; case 2: TIMER_CH2CV(base) = value; break; case 3: TIMER_CH3CV(base) = value; break; default: break; } } int8_t iPwm_GetEnableState(uint8_t devIndex) { ASSERT_LESS(devIndex, 1); return Pwms[devIndex].OutputEnable; } void iPwm_EnableOutput(uint8_t devIndex) { ASSERT_LESS(devIndex, 1); uint32_t base = Pwms[devIndex].PwmBase; TIMER_CCHP(base) |= (uint32_t)0x00008000UL; Pwms[devIndex].OutputEnable = 1; } void iPwm_DisableOutput(uint8_t devIndex) { ASSERT_LESS(devIndex, 1); uint32_t base = Pwms[devIndex].PwmBase; TIMER_CCHP(base) &= ~((uint32_t)0x00008000UL); Pwms[devIndex].OutputEnable = 0; } // // int8_t Pwm_GetChannelEnableState(uint8_t devIndex, uint8_t channelIndex) // // { // // } // // void Pwm_EnableChannelOutput(uint8_t devIndex, uint8_t channelIndex) // // { // // ASSERT_LESS(devIndex, 1); // // ASSERT_LESS(channelIndex, 4); // // TIM_TypeDef *base = Pwms[devIndex].PwmBase; // // if (channelIndex < 64) // // { // // base->CCER |= ((uint32_t)0x01) << (channelIndex * 4); // // } // // else // // { // // base->CCER |= ((uint32_t)0x04) << ((channelIndex - 64) * 4); // // } // // } // // void Pwm_DisableChannelOutput(uint8_t devIndex, uint8_t channelIndex) // // { // // ASSERT_LESS(devIndex, 1); // // ASSERT_LESS(channelIndex, 4); // // TIM_TypeDef *base = Pwms[devIndex].PwmBase; // // if (channelIndex < 64) // // { // // base->CCER &= ~(((uint32_t)0x01) << (channelIndex * 4)); // // } // // else // // { // // base->CCER &= ~(((uint32_t)0x04) << ((channelIndex - 64) * 4)); // // } // // } void iPwm_EnableDeviceInterrupt(uint8_t devIndex, ApiPwm_DeviceInterrupt interrupt) { ASSERT_LESS(devIndex, 1); switch (interrupt) { case ApiPwm_CountZeroInt: Pwms[devIndex].CountZeroISR.Enable = 1; break; case ApiPwm_CountMaxInt: Pwms[devIndex].CountMaxISR.Enable = 1; break; case ApiPwm_BreakInt: Pwms[devIndex].BreakISR.Enable = 1; break; default: break; } } void iPwm_DisableDeviceInterrupt(uint8_t devIndex, ApiPwm_DeviceInterrupt interrupt) { ASSERT_LESS(devIndex, 1); switch (interrupt) { case ApiPwm_CountZeroInt: Pwms[devIndex].CountZeroISR.Enable = 0; break; case ApiPwm_CountMaxInt: Pwms[devIndex].CountMaxISR.Enable = 0; break; case ApiPwm_BreakInt: Pwms[devIndex].BreakISR.Enable = 0; break; default: break; } } void iPwm_EnableChannelInterrupt(uint8_t devIndex, uint8_t channelIndex, ApiPwm_ChannelInterrupt interrupt) { ASSERT_LESS(devIndex, 1); ASSERT_LESS(channelIndex, 4); Pwms[devIndex].ChannelISR[channelIndex].Enable = 1; } void iPwm_DisableChannelInterrupt(uint8_t devIndex, uint8_t channelIndex, ApiPwm_ChannelInterrupt interrupt) { ASSERT_LESS(devIndex, 1); ASSERT_LESS(channelIndex, 4); Pwms[devIndex].ChannelISR[channelIndex].Enable = 0; } void iPwm_BindDeviceInterrupt(uint8_t devIndex, ApiPwm_DeviceInterrupt interrupt, void (*action)()) { ASSERT_LESS(devIndex, 1); switch (interrupt) { case ApiPwm_CountZeroInt: Pwms[devIndex].CountZeroISR.Action = action; break; case ApiPwm_CountMaxInt: Pwms[devIndex].CountMaxISR.Action = action; break; case ApiPwm_BreakInt: Pwms[devIndex].BreakISR.Action = action; break; default: break; } } void iPwm_BindChannelInterrupt(uint8_t devIndex, uint8_t channelIndex, ApiPwm_DeviceInterrupt interrupt, void (*action)()) { ASSERT_LESS(devIndex, 1); ASSERT_LESS(channelIndex, 4); Pwms[devIndex].ChannelISR[channelIndex].Action = action; } int8_t iPwm_GetBreakState(uint8_t devIndex) { ASSERT_LESS(devIndex, 1); uint32_t base = Pwms[devIndex].PwmBase; return (TIMER_INTF(base) & ((uint32_t)0x00000080UL)) ? 1 : 0; } void iPwm_ClearBreak(uint8_t devIndex) { ASSERT_LESS(devIndex, 1); uint32_t base = Pwms[devIndex].PwmBase; TIMER_INTF(base) &= ~((uint32_t)0x00000080UL); } #if API_FUNCTION_PWM_SYNC_MULTI_SAMPLING void iPwm_EnableSyncMultiSampling(uint8_t devIndex) { Pwms[devIndex].SyncSamplingEnable = 1; } void iPwm_DisableSyncMultiSampling(uint8_t devIndex) { Pwms[devIndex].SyncSamplingEnable = 0; Pwms[devIndex].SyncSamplingUpTickCount = 1; Pwms[devIndex].SyncSamplingUpTick[0] = TIMER_CAR(Pwms[devIndex].PwmBase)>> 1; Pwms[devIndex].SyncSamplingDownTickCount = 1; Pwms[devIndex].SyncSamplingDownTick[0] = TIMER_CAR(Pwms[devIndex].PwmBase)>> 1; } void iPwm_SyncMultiSamplingCountUp(uint8_t devIndex, uint32_t samplingTicks[], uint8_t samplingCounts) { if (Pwms[devIndex].SyncSamplingEnable == 1) { Pwms[devIndex].SyncSamplingUpTickCount = samplingCounts; for (int i = 0; i < samplingCounts; i++) { Pwms[devIndex].SyncSamplingUpTick[i] = samplingTicks[i]; } } } void iPwm_SyncMultiSamplingCountDown(uint8_t devIndex, uint32_t samplingTicks[], uint8_t samplingCounts) { if (Pwms[devIndex].SyncSamplingEnable == 1) { Pwms[devIndex].SyncSamplingDownTickCount = samplingCounts; for (int i = 0; i < samplingCounts; i++) { Pwms[devIndex].SyncSamplingDownTick[i] = samplingTicks[i]; } } } #endif