/* * pwm.c * * Created on: Jul 25, 2023 * Author: Keith.Lloyd */ #include "pin_mux.h" #include "board.h" #include "fsl_sctimer.h" #include #include #include "frq.h" #include "pwm.h" #include "ports.h" #include "arm_math.h" #include "timer.h" /******************************************************************************* * Definitions ******************************************************************************/ #define SCTIMER_CLK_FREQ CLOCK_GetFreq(kCLOCK_BusClk) #define DEMO_SCTIMER_OUT kSCTIMER_Out_1 /******************************************************************************* * Prototypes ******************************************************************************/ /******************************************************************************* * Variables ******************************************************************************/ volatile bool sctimerIsrFlag = false; volatile bool brightnessUp = true; /* Indicate LED is brighter or dimmer */ volatile uint8_t BC_Duty_Cycle = 10; uint32_t eventNumberOutput; uint32_t eventNumberOutput2; volatile bool PWM_Update_Flag = false; extern uint8_t Port_State[]; /******************************************************************************* * Code ******************************************************************************/ //OBSOLETE - DO NOT USE void init_PWM(void) { sctimer_config_t sctimerInfo; sctimer_pwm_signal_param_t pwmParam; sctimer_pwm_signal_param_t pwmParam2; //Added this for 2nd output uint32_t sctimerClock; SCTIMER_GetDefaultConfig(&sctimerInfo); #if 0 //Testing_external_clock sctimerClock = 16384000; //SCTIMER_CLK_FREQ; //change SCTimer schtuff here sctimerInfo.clockMode = kSCTIMER_Input_ClockMode; sctimerInfo.clockSelect = kSCTIMER_Clock_On_Rise_Input_0; //Note: 100MHz max external clock #else sctimerClock = SCTIMER_CLK_FREQ; //todo: set sctimerInfo.clockMode and sctimerInfo.clockSelect for internal 144MHz clock - for changing back from external #endif /* Initialize SCTimer module */ SCTIMER_Init(SCT0, &sctimerInfo); status_t status; BC_Duty_Cycle = 10; uint32_t BC_Frequency = 32768; /* Configure PWM params with frequency 24kHZ from output */ pwmParam.output = kSCTIMER_Out_1; //output 1 = pin 43 pwmParam.level = kSCTIMER_HighTrue; pwmParam.dutyCyclePercent = BC_Duty_Cycle; status = SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, BC_Frequency, sctimerClock, &eventNumberOutput); // Configure 2nd PWM output pin pwmParam2.output = kSCTIMER_Out_2; //Output 2 = pin 44 pwmParam2.level = kSCTIMER_LowTrue; //invert polarity pwmParam2.dutyCyclePercent = 100 - BC_Duty_Cycle; status = SCTIMER_SetupPwm(SCT0, &pwmParam2, kSCTIMER_CenterAlignedPwm, BC_Frequency, sctimerClock, &eventNumberOutput2); /* Start the 32-bit unify timer */ SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_U); } /* * Set PWM frequency and duty cycle * Set duty to 0 to disable * Use Flexcomm 0 outputs 1 and 2 */ void PWM_Setup(uint32_t newFreq, uint32_t dutyCycle) { //Error check if(dutyCycle > 49 ) { dutyCycle = 49; } sctimer_config_t sctimerInfo; sctimer_pwm_signal_param_t pwmParam; sctimer_pwm_signal_param_t pwmParam2; //Added this for 2nd output uint32_t sctimerClock; SCTIMER_GetDefaultConfig(&sctimerInfo); #if 0 //New code Selects appropriate external oscillator. SCTIMER_Deinit(SCT0); SCTIMER_GetDefaultConfig(&sctimerInfo); //Set up for correct clock CLOCK_SELECT_t clock = PWM_GetBroadcastFrequencyOK(newFreq); switch(clock) { case CS_EXT1: sctimerClock = PWM_EXT1_FREQ_HZ; sctimerInfo.clockMode = kSCTIMER_Input_ClockMode; sctimerInfo.clockSelect = kSCTIMER_Clock_On_Rise_Input_0; //Note: 100MHz max external clock break; case CS_EXT2: sctimerClock = PWM_EXT2_FREQ_HZ; sctimerInfo.clockMode = kSCTIMER_Input_ClockMode; sctimerInfo.clockSelect = kSCTIMER_Clock_On_Rise_Input_0; break; case CS_INTERNAL: case CS_NUM: default: //Use internal clock. This is default setup for sctimerinfo. sctimerClock = SCTIMER_CLK_FREQ; break; } PWM_SetExternalClockSource(clock); //Set the external clock #else //Functional code using internal clock sctimerClock = SCTIMER_CLK_FREQ; //todo: set sctimerInfo.clockMode and sctimerInfo.clockSelect for internal 144MHz clock - for changing back from external #endif /* Initialize SCTimer module */ SCTIMER_Init(SCT0, &sctimerInfo); status_t status; /* Configure PWM params with frequency 24kHZ from output */ pwmParam.output = kSCTIMER_Out_1; //output 1 = pin 43 pwmParam.level = kSCTIMER_HighTrue; pwmParam.dutyCyclePercent = dutyCycle; status = SCTIMER_SetupPwm(SCT0, &pwmParam, kSCTIMER_CenterAlignedPwm, newFreq, sctimerClock, &eventNumberOutput); // Configure 2nd PWM output pin pwmParam2.output = kSCTIMER_Out_2; //Output 2 = pin 44 pwmParam2.level = kSCTIMER_LowTrue; //invert polarity pwmParam2.dutyCyclePercent = 100 - dutyCycle; status = SCTIMER_SetupPwm(SCT0, &pwmParam2, kSCTIMER_CenterAlignedPwm, newFreq, sctimerClock, &eventNumberOutput2); /* Start the 32-bit unify timer */ SCTIMER_StartTimer(SCT0, kSCTIMER_Counter_U); } /* * Determine whether a frequency will work for broadcast and which clock to use * returns CS_INTERNAL, CS_EXT1, or CS_EXT2 if one of them works * returns the FIRST one that works * returns CS_NUM if none of them work */ CLOCK_SELECT_t PWM_GetBroadcastFrequencyOK(uint32_t newFreq) { uint32_t clockFreq = 0; uint32_t divider = 0; float32_t testFreq = 0; CLOCK_SELECT_t retval = (CS_NUM); //Check internal clock clockFreq = SCTIMER_CLK_FREQ; divider = (uint32_t)(clockFreq / (newFreq * 2.0)); testFreq = clockFreq / (divider * 2.0); if(fabs(testFreq - (float32_t)(newFreq)) <= PWM_MAX_BROADCAST_ERR_HZ) { return CS_INTERNAL; } //Check External 2 clockFreq = PWM_EXT2_FREQ_HZ; divider = (uint32_t)(clockFreq / (newFreq * 2.0)); testFreq = clockFreq / (divider * 2.0); if(fabs(testFreq - (float32_t)(newFreq)) <= PWM_MAX_BROADCAST_ERR_HZ) { return CS_EXT2; } //Check External 1 clockFreq = PWM_EXT1_FREQ_HZ; divider = (uint32_t)(clockFreq / (newFreq * 2.0)); testFreq = clockFreq / (divider * 2.0); if(fabs(testFreq - (float32_t)(newFreq)) <= PWM_MAX_BROADCAST_ERR_HZ) { return CS_EXT1; } return CS_NUM; //return this if none of the options work } void PWM_SetExternalClockSource(CLOCK_SELECT_t clock) { Port_State[TOP_SR] &= CLK_MASK_BITS; //clear external clock select bits switch(clock) { case CS_EXT1: Port_State[TOP_SR] |= MASK_15; //15.61MHz external break; case CS_EXT2: Port_State[TOP_SR] |= MASK_58; //58.98MHz external break; case CS_INTERNAL: Port_State[TOP_SR] |= MASK_144; //external OFF, use 144MHz internal clock break; } SPI0_SendBytes(Port_State, 3, EXPANDER); Delay_Ticks(1); }