//=============================================================================
// PWMIn.c 20160401 CHG
//
//=============================================================================
//
//-----------------------------------------------------------------------------
#include "chip.h"
#include "System.h"
#include "PWMIn.h"
#define TIMOUT_PWM_DETECTED 10 // Number of 10 mSec ticks where PWM must be seen before channel is set to "failsafe"
int capture[4];// PWM value in uSec
// Status for each channel, set to TRUE if channel in failsafe (no signal detected, or signal out of bounds)
static int inFailsafe[4]= {FALSE, FALSE, FALSE, FALSE};
// Timers for each PWM input, if decremented to 0, channel is in failsafe (no signal detected)
static int pwmInChange[4]={TIMOUT_PWM_DETECTED, TIMOUT_PWM_DETECTED, TIMOUT_PWM_DETECTED, TIMOUT_PWM_DETECTED};
//---------------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------------
int getFailsafePWMIn(int channel) {
return inFailsafe[channel-1];
}
//---------------------------------------------------------------------------------------
// Get PWM value for servo input (in uSec)
//---------------------------------------------------------------------------------------
int getValuePWMIn(int channel) {
if (getFailsafePWMIn(channel))
return 1520;
return capture[channel-1];
}
/*
for (int i=0; i<4; i++) {
if (pwmInChange) {
pwmInChange--;
if (pwmInChange==0) {
inFailsafe=TRUE;
inuSec=0;
}
}
*/
//---------------------------------------------------------------------------------------
// Interrupt handler for SCT3 events.
// We catch event 3,4 and 5. These occurs when SCT detects a falling edge on PWM1, PWM2 or PWM3
// Event 0,1 and 2 are rising edge on the 3 PWM inputs. We don't get an interrupt on these events
// as they only copy the current counter value to CAP[0/1/2] when rising edge occurs
//---------------------------------------------------------------------------------------
void SCT3_IRQHandler(void) {
// PWM 1 falling
if(LPC_SCT3->EVFLAG & SCT_EVT_3) {
// If we have a wraparound on the counter between the rising and falling edge detection, correct the value
if (LPC_SCT3->CAP[3].U < LPC_SCT3->CAP[0].U)
capture[0]=0xFFFFFFFF + LPC_SCT3->CAP[3].U - LPC_SCT3->CAP[0].U;
else
capture[0] = LPC_SCT3->CAP[3].U- LPC_SCT3->CAP[0].U;
// Set timeout for change detected
pwmInChange[0]=TIMOUT_PWM_DETECTED;
LPC_SCT3->EVFLAG = SCT_EVT_3;
}
// PWM 2 falling
if(LPC_SCT3->EVFLAG & SCT_EVT_4) {
// If we have a wraparound on the counter between the rising and falling edge detection, correct the value
if (LPC_SCT3->CAP[3].U < LPC_SCT3->CAP[0].U)
capture[1]=0xFFFFFFFF + LPC_SCT3->CAP[4].U - LPC_SCT3->CAP[1].U;
else
capture[1] = LPC_SCT3->CAP[4].U- LPC_SCT3->CAP[1].U;
// Set timeout for change detected
pwmInChange[1]=TIMOUT_PWM_DETECTED;
LPC_SCT3->EVFLAG = SCT_EVT_4;
}
// PWM 3 falling
if(LPC_SCT3->EVFLAG & SCT_EVT_5) {
// If we have a wraparound on the counter between the rising and falling edge detection, correct the value
if (LPC_SCT3->CAP[5].U < LPC_SCT3->CAP[2].U)
capture[2]=0xFFFFFFFF + LPC_SCT3->CAP[5].U - LPC_SCT3->CAP[2].U;
else
capture[2] = LPC_SCT3->CAP[5].U- LPC_SCT3->CAP[2].U;
// Set timeout for change detected
pwmInChange[2]=TIMOUT_PWM_DETECTED;
LPC_SCT3->EVFLAG = SCT_EVT_5;
}
}
//---------------------------------------------------------------------------------------
// Initialize PWMIn module
//---------------------------------------------------------------------------------------
void initPWMIn(void) {
// Input capture on SCT3/SCT2:
// P0.07=PWMIN1 (SCT3)
// P1.11=PWMIN2 (SCT3)
// P1.21=PWMIN3 (SCT3)
// P1.19=PWMIN4 (SCT2)
// Enable pulldown on all 4 PWM inputs
Chip_IOCON_PinMuxSet(LPC_IOCON, 0, 7, (IOCON_MODE_PULLDOWN));
Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 11, (IOCON_MODE_PULLDOWN));
Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 21, (IOCON_MODE_PULLDOWN));
Chip_IOCON_PinMuxSet(LPC_IOCON, 1, 19, (IOCON_MODE_PULLDOWN));
Chip_SCT_Init(LPC_SCT3);
//unified 32bit counter, SYNC all inputs, enable prescaler in CTRL register
LPC_SCT3->CONFIG = SCT_CONFIG_32BIT_COUNTER | (1<<9) | (1<<10) | (1<<11);
//set prescaler 72 to count µs
Chip_SCT_SetControl(LPC_SCT3, SCT_CTRL_PRE_L(72-1));
//input capture setting
LPC_INMUX->SCT3_INMUX[0] = 0;// SCT3_IN0 = P0.07
LPC_INMUX->SCT3_INMUX[1] = 1;// SCT3_IN1 = P1.11
LPC_INMUX->SCT3_INMUX[2] = 2;// SCT3_IN2 = P1.21
LPC_SCT3->REGMODE = (SCT_EVT_0)| (SCT_EVT_1) | (SCT_EVT_2)| (SCT_EVT_3)| (SCT_EVT_4)| (SCT_EVT_5);//set capture register(s)
// Set event for each capture register
// Rising capture:
LPC_SCT3->CAPCTRL[0].U = (SCT_EVT_0);
LPC_SCT3->CAPCTRL[1].U = (SCT_EVT_1);
LPC_SCT3->CAPCTRL[2].U = (SCT_EVT_2);
// Falling capture:
LPC_SCT3->CAPCTRL[3].U = (SCT_EVT_3);
LPC_SCT3->CAPCTRL[4].U = (SCT_EVT_4);
LPC_SCT3->CAPCTRL[5].U = (SCT_EVT_5);
//---------------------------------------------------------------------------------------
// Define 6 events for the 3 inputs.
// Event 0,1 and 2 are for the rising edge on each input
// When one of these events occurs, SCT will store the current counter value in the CAP[0/1/2] regsiter
// Event 4,5 and 6 are for the falling edge on each input
// When one of these events occurs, SCT will store the current counter value in the CAP[3/4/5] regsiter and generate an interrupt
//
//---------------------------------------------------------------------------------------
// Event 0: capture rising, only used for capture, no interrupt
LPC_SCT3->EVENT[0].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[0].CTRL = (0) | // capture, not used
(0 << 5) | // OUTSEL[5] = selects input
(0 << 6) | // IOSEL[9:6] = 0 select SCT3_IN0
(1 << 10) | // IOCOND[11:10] = 1 rising
(2 << 12) | // COMBMODE[13:12] = IO condition
(1 << 14) | // STATELD[14] = STATEV is loaded
(1 << 15); // STATEV[19:15] = new state 1
// Event 1: capture rising, only used for capture, no interrupt
LPC_SCT3->EVENT[1].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[1].CTRL = (0) | // capture, not used
(0 << 5) | // OUTSEL[5] = selects input
(1 << 6) | // IOSEL[9:6] = 0 select SCT3_IN0
(1 << 10) | // IOCOND[11:10] = 1 rising
(2 << 12) | // COMBMODE[13:12] = IO condition
(1 << 14) | // STATELD[14] = STATEV is loaded
(1 << 15); // STATEV[19:15] = new state 1
// Event 2: capture rising, only used for capture, no interrupt
LPC_SCT3->EVENT[2].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[2].CTRL = (0) | // capture, not used
(0 << 5) | // OUTSEL[5] = selects input
(2 << 6) | // IOSEL[9:6] = 0 select SCT3_IN0
(1 << 10) | // IOCOND[11:10] = 1 rising
(2 << 12) | // COMBMODE[13:12] = IO condition
(1 << 14) | // STATELD[14] = STATEV is loaded
(1 << 15); // STATEV[19:15] = new state 1
//---------------------------------------------------------------------------------------
// Event 3: capture falling, used for capture and generates an interrupt
LPC_SCT3->EVENT[3].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[3].CTRL = (0) | // capture, not used
(0 << 5) | // OUTSEL[5] = selects input
(0 << 6) | // IOSEL[9:6] = 0 select SCT3_IN0
(2 << 10) | // IOCOND[11:10] = 1 falling
(2 << 12) | // COMBMODE[13:12] = IO condition
(1 << 14) | // STATELD[14] = STATEV is loaded
(1 << 15); // STATEV[19:15] = new state 1
// Event 4: capture falling, used for capture and generates an interrupt
LPC_SCT3->EVENT[4].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[4].CTRL = (0) | // capture, not used
(0 << 5) | // OUTSEL[5] = selects input
(1 << 6) | // IOSEL[9:6] = 0 select SCT3_IN0
(2 << 10) | // IOCOND[11:10] = 1 falling
(2 << 12) | // COMBMODE[13:12] = IO condition
(1 << 14) | // STATELD[14] = STATEV is loaded
(1 << 15); // STATEV[19:15] = new state 1
// Event 5: capture falling, used for capture and generates an interrupt
LPC_SCT3->EVENT[5].STATE = (SCT_EVT_1); // event happens in state
LPC_SCT3->EVENT[5].CTRL = (0) | // capture, not used
(0 << 5) | // OUTSEL[5] = selects input
(2 << 6) | // IOSEL[9:6] = 0 select SCT3_IN0
(2 << 10) | // IOCOND[11:10] = 1 falling
(2 << 12) | // COMBMODE[13:12] = IO condition
(1 << 14) | // STATELD[14] = STATEV is loaded
(1 << 15); // STATEV[19:15] = new state 1
LPC_SCT3->STATE = 1;//start state
//---------------------------------------------------------------------------------------
// Only generate interrupts on the falling edge events (event 3,4 and 5)
//---------------------------------------------------------------------------------------
LPC_SCT3->EVFLAG = (SCT_EVT_3)| (SCT_EVT_4)| (SCT_EVT_5); //reset flags
LPC_SCT3->EVEN = (SCT_EVT_3)| (SCT_EVT_4)| (SCT_EVT_5); //enable interrupts
NVIC_SetPriority(SCT3_IRQn, 0);//set priority
NVIC_EnableIRQ(SCT3_IRQn);
Chip_SCT_ClearControl(LPC_SCT3, SCT_CTRL_HALT_L | SCT_CTRL_HALT_H);//and start
}
|