243 lines
7.5 KiB
C
243 lines
7.5 KiB
C
/*
|
|
* pwm.c
|
|
*
|
|
* Created on: Jul 25, 2023
|
|
* Author: Keith.Lloyd
|
|
*/
|
|
|
|
|
|
#include "pin_mux.h"
|
|
#include "board.h"
|
|
#include "fsl_sctimer.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.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);
|
|
}
|
|
|
|
|
|
|