Sei sulla pagina 1di 6

/****************************************************************************

Module
ReloadSensor.c
Revision
1.0.1
Description
This is a template file for implementing a simple service under the
Gen2 Events and Services Framework.
Notes
History
When Who
--------------------
****************************************************************************/
/*----------------------------- Include Files -----------------------------*/
/* include header files for this state machine as well as any machines at the
next lower level in the hierarchy that are sub-machines to this machine
*/
#include <stdio.h>
#include "ES_Configure.h"
#include "ES_Framework.h"
#include "ES_Port.h"
#include "ES_DeferRecall.h"
#include "ES_Timers.h"
#include "termio.h"
#include "BITDEFS.h" // standard bit definitions to make things more readable

// the headers to access the GPIO subsystem


#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_sysctl.h"
#include "inc/hw_pwm.h"
#include "inc/hw_timer.h"
#include "inc/hw_nvic.h"

// the headers to access the TivaWare Library


#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h"
#include "driverlib/gpio.h"
#include "driverlib/timer.h"
#include "driverlib/interrupt.h"

// headers from service files


//#include "SPISerice.h"
//#include "DCMotorService.h"
#include "ReloadSensor.h"
#include "GameMasterSM.h"

/*----------------------------- Module Defines ----------------------------*/


#define BitsPerNibble 4

//Time define
#define TicksPerMS 40000 //use system clock
#define USperMS 1000
#define OneShotTimeout 100*TicksPerMS //100ms oneshot timeout
//The reload emitter freq is between 500Hz-1000Hz, period is between 1 ms-2ms
#define PeriodMinTicks 1*TicksPerMS
#define PeriodMaxTicks 2*TicksPerMS

//PWM definition
//#define ALL_BITS (0xff<<2)
// 40,000 ticks per mS assumes a 40Mhz clock, we will use SysClk/32 for PWM
#define PWMTicksPerMS 40000/32
//IR Emitter is PE4: M1PWM2 (M1PWM1GENA)
// program generator A to go to 1 at rising comare A, 0 on falling compare A
#define GenA_Normal (PWM_1_GENA_ACTCMPAU_ONE | PWM_1_GENA_ACTCMPAD_ZERO )
// program generator B to go to 1 at rising comare B, 0 on falling compare B
#define GenB_Normal (PWM_1_GENB_ACTCMPBU_ONE | PWM_1_GENB_ACTCMPBD_ZERO )
// for convenience to write data to registers
#define BitsPerNibble 4
//Reload emitter sensor is PC6 WT1CCP0
/*---------------------------- Module Functions ---------------------------*/
/* prototypes for private functions for this service.They should be functions
relevant to the behavior of this service
*/

/*---------------------------- Module Variables ---------------------------*/


// with the introduction of Gen2, we need a module level Priority variable
static uint8_t EdgeCounter = 0;
static uint32_t OneShotCount = 0;
static uint32_t LastEdgeTime = 0;
static uint32_t AvgSignalPeriod = 0;
static float P_Emit = 0; //P_Emit is in ms. The period of our signal should be 1/2
of the IREmitter on the reload station
static uint32_t P_EmitTicks = 0;
/*------------------------------ Module Code ------------------------------*/
/****************************************************************************
Function
InitEdgeCapturePeriod
This function is for capture the beacon periods
Parameters
****************************************************************************/
void InitReloadCapture(void){
// start by enabling the clock to the timer (Wide Timer 1)
HWREG(SYSCTL_RCGCWTIMER) |= SYSCTL_RCGCWTIMER_R1;
// enable the clock to Port C
HWREG(SYSCTL_RCGCGPIO) |= SYSCTL_RCGCGPIO_R2;
// since we added this Port C clock init, we can immediately start
// into configuring the timer, no need for further delay
// make sure that timer (Timer A) is disabled before configuring
HWREG(WTIMER1_BASE+TIMER_O_CTL) &= ~TIMER_CTL_TAEN;
// set it up in 32bit wide (individual, not concatenated) mode
// the constant name derives from the 16/32 bit timer, but this is a 32/64
// bit timer so we are setting the 32bit mode
HWREG(WTIMER1_BASE+TIMER_O_CFG) = TIMER_CFG_16_BIT;
// we want to use the full 32 bit count, so initialize the Interval Load
// register to 0xffffffff (its default value)
HWREG(WTIMER1_BASE+TIMER_O_TAILR) = 0xffffffff;
// set up timer A in capture mode (TAMR=3, TAAMS = 0),
// for edge time (TACMR = 1) and up-counting (TACDIR = 1)
HWREG(WTIMER1_BASE+TIMER_O_TAMR) =
(HWREG(WTIMER1_BASE+TIMER_O_TAMR) & ~TIMER_TAMR_TAAMS) |
(TIMER_TAMR_TACDIR | TIMER_TAMR_TACMR | TIMER_TAMR_TAMR_CAP);
// To set the event to rising edge, we need to modify the TAEVENT bits
// in GPTMCTL. Rising edges = 00, so we set the TAEVENT bits
HWREG(WTIMER1_BASE+TIMER_O_CTL) &= ~TIMER_CTL_TAEVENT_M;
// Now Set up the port to do the capture (clock was enabled earlier)
// start by setting the alternate function for Port C bit 6 (WT1CCP0)
HWREG(GPIO_PORTC_BASE+GPIO_O_AFSEL) |= BIT6HI;
// Then, map bit 6's alternate function to WT1CCP0
// 7 is the mux value to select WT1CCP0, 16 to shift it over to the
// right nibble for bit 6 (4 bits/nibble * 6 bits)
HWREG(GPIO_PORTC_BASE+GPIO_O_PCTL) = (HWREG(GPIO_PORTC_BASE+GPIO_O_PCTL) &
0xf0ffffff) + (7<<24);
// Enable pin on Port C for digital I/O
HWREG(GPIO_PORTC_BASE+GPIO_O_DEN) |= BIT6HI;
// make pin 4 on Port C into an input
HWREG(GPIO_PORTC_BASE+GPIO_O_DIR) &= BIT6LO;
// back to the timer to enable a local capture interrupt
HWREG(WTIMER1_BASE+TIMER_O_IMR) |= TIMER_IMR_CAEIM;
// enable the Timer A in Wide Timer 1 interrupt in the NVIC
// it is interrupt number 96 so appears in EN3 at bit 0
HWREG(NVIC_EN3) |= BIT0HI;
// make sure interrupts are enabled globally
__enable_irq();
// Start the input capture timer later when needed
}

void StartReloadCapture(void){ //goes into header


// now kick the InputCaptureTimer off by enabling it and
//enabling the timer to stall while stopped by the debugger
HWREG(WTIMER1_BASE+TIMER_O_CTL) |= (TIMER_CTL_TAEN | TIMER_CTL_TASTALL);
}

void StopReloadCapture(void){ //goes into header


// now kick the InputCaptureTimer off by enabling it and
//enabling the timer to stall while stopped by the debugger
HWREG(WTIMER1_BASE+TIMER_O_CTL) &= ~(TIMER_CTL_TAEN);
}

void ReloadCaptureResponse( void ){


// start by clearing the source of the interrupt, the input capture event
HWREG(WTIMER1_BASE+TIMER_O_ICR) = TIMER_ICR_CAECINT;

uint32_t ThisEdgeTime;
uint32_t SignalPeriod;
//grab ThisEdgeTime from timer register
ThisEdgeTime = HWREG(WTIMER1_BASE+TIMER_O_TAR);
//calculate SignalPeriod using ThisEdgeTime and LastEdgeTime
SignalPeriod = ThisEdgeTime - LastEdgeTime;

//increment EdgeCounter
EdgeCounter ++;
//calculate AvgSignalPeriod by caiculating the average period during the whole
EdgeCCounter time
AvgSignalPeriod = (AvgSignalPeriod * (EdgeCounter - 1) + SignalPeriod) /
EdgeCounter;

//if EdgeCounter is large enough (to exclude noise)


if (EdgeCounter == 20){
//if AvgSignalPeriod is within a proper range (to exlcude noise)
if((AvgSignalPeriod >= PeriodMinTicks) && (AvgSignalPeriod <=
PeriodMaxTicks))
{
// P_Emit = 0.5*(PWMTicksPerMS*AvgSignalPeriod)/TicksPerMS;
//calculate the period that we need to emit to get the ball
P_Emit = 0.5*AvgSignalPeriod/32;
P_EmitTicks = P_Emit;
//post an event to GameMaster with the event type as EV_EMITTER_DETECTED
and event paramete as the period of the reload emitter
ES_Event_t ThisEvent;
ThisEvent.EventType = EV_EMITTER_DETECTED;
float temp = AvgSignalPeriod*USperMS/TicksPerMS; //temp is in us
uint16_t periodposted = temp;
ThisEvent.EventParam = periodposted; //period posted is in us

//restart one shot timer so that it doesn't time out


HWREG(WTIMER1_BASE+TIMER_O_TBILR) = OneShotTimeout;
PostGameMasterSM(ThisEvent);
//clear EdgeCounter
EdgeCounter = 0;
}
else
{
// Clear EdgeCounter and AvgSignalPeriod
EdgeCounter = 0;
AvgSignalPeriod = 0;
}
}
//update LastEdgeTime with ThisEdgeTime
LastEdgeTime = ThisEdgeTime;
}

/*******************************************************************************
*****************************/
void InitReloadOneShot( void ){
// start by enabling the clock to the timer (Wide Timer 1)
HWREG(SYSCTL_RCGCWTIMER) |= SYSCTL_RCGCWTIMER_R1;
// kill a few cycles to let the clock get going
while((HWREG(SYSCTL_PRWTIMER) & SYSCTL_PRWTIMER_R1) != SYSCTL_PRWTIMER_R1);
// make sure that timer (Timer B) is disabled before configuring
HWREG(WTIMER1_BASE+TIMER_O_CTL) &= ~TIMER_CTL_TBEN; //TBEN = Bit0
// set it up in 32bit wide (individual, not concatenated) mode
// the constant name derives from the 16/32 bit timer, but this is a 32/64
// bit timer so we are setting the 32bit mode
HWREG(WTIMER1_BASE+TIMER_O_CFG) = TIMER_CFG_16_BIT; //bits 0-2 = 0x04
// set up timer B in 1-shot mode so that it disables timer on timeouts
// first mask off the TBMR field (bits 0:1) then set the value for
// 1-shot mode = 0x01
HWREG(WTIMER1_BASE+TIMER_O_TBMR) =
(HWREG(WTIMER1_BASE+TIMER_O_TBMR)& ~TIMER_TBMR_TBMR_M)|
TIMER_TBMR_TBMR_1_SHOT;
// set up timer B DOWN-counting (TBCDIR = 0)
// so that rewrting the OneShotTimeout will restart timerB
HWREG(WTIMER1_BASE+TIMER_O_TBMR) &= ~TIMER_TBMR_TBCDIR;
// set timeout
HWREG(WTIMER1_BASE+TIMER_O_TBILR) = OneShotTimeout;
// enable a local timeout interrupt. TBTOIM = bit 0
HWREG(WTIMER1_BASE+TIMER_O_IMR) |= TIMER_IMR_TBTOIM; // bit0
// enable the Timer B in Wide Timer 1 interrupt in the NVIC
// it is interrupt number 97 so appears in EN3 at bit 1
HWREG(NVIC_EN3) |= BIT1HI;
// make sure interrupts are enabled globally
__enable_irq();
}

void StartReloadOneShot( void ){


// now kick the timer off by enabling it and enabling the timer to
// stall while stopped by the debugger
HWREG(WTIMER1_BASE+TIMER_O_CTL) |= (TIMER_CTL_TBEN | TIMER_CTL_TBSTALL);
}

void StopReloadOneShot( void ){


// now kick the timer off by enabling it and enabling the timer to
// stall while stopped by the debugger
HWREG(WTIMER1_BASE+TIMER_O_CTL) &= ~TIMER_CTL_TBEN;
}

void ReloadOneShotIntResponse( void ){


//start by clearing the source of the interrupt
HWREG(WTIMER1_BASE+TIMER_O_ICR) = TIMER_ICR_TBTOCINT;
//increment our counter so that we can tell this is running
OneShotCount++;
//clear accumulated noise on counts
EdgeCounter = 0;
AvgSignalPeriod = 0;
//OneShotTimer timing out means the no beacon pulses detected
//post an event to GameMasterSM with event type as EV_EMITTER_MISSED
ES_Event_t ThisEvent;
ThisEvent.EventType = EV_EMITTER_MISSED;
PostGameMasterSM(ThisEvent);
}

/*******************************************************************************
***********************************/
void InitIRPWM(void){
//IR output is PE4 M1PWM2
// start by enabling the clock to the PWM Module (PWM1)
HWREG(SYSCTL_RCGCPWM) |= SYSCTL_RCGCPWM_R1;

// enable the clock to Port E


HWREG(SYSCTL_RCGCGPIO) |= BIT4HI;

// Select the PWM clock as System Clock/32


HWREG(SYSCTL_RCC) = (HWREG(SYSCTL_RCC) & ~SYSCTL_RCC_PWMDIV_M) |
(SYSCTL_RCC_USEPWMDIV | SYSCTL_RCC_PWMDIV_32);

// make sure that the PWM module clock has gotten going
while ((HWREG(SYSCTL_PRPWM) & SYSCTL_PRPWM_R1) != SYSCTL_PRPWM_R1)
;

// disable the PWM while initializing


HWREG( PWM1_BASE+PWM_O_1_CTL ) = 0;

// program generators to go to 1 at rising compare A/B, 0 on falling compare A/B


// GenA_Normal = (PWM_1_GENA_ACTCMPAU_ONE | PWM_1_GENA_ACTCMPAD_ZERO )
HWREG( PWM1_BASE+PWM_O_1_GENA) = GenA_Normal;
// GenB_Normal = (PWM_1_GENB_ACTCMPBU_ONE | PWM_1_GENB_ACTCMPBD_ZERO )
HWREG( PWM1_BASE+PWM_O_1_GENB) = GenB_Normal;

// Set the PWM period. Since we are counting both up & down, we initialize
// the load register to 1/2 the desired total period. We will also program
// the match compare registers to 1/2 the desired high time
HWREG( PWM1_BASE+PWM_O_1_LOAD) = (P_EmitTicks)>>1;

// Set the initial Duty cycle on A to 50% by programming the compare value
// to 1/2 the period to count up (or down). Technically, the value to program
// should be Period/2 - DesiredHighTime/2, but since the desired high time is
1/2
// the period, we can skip the subtract
HWREG( PWM1_BASE+PWM_O_1_CMPA) = HWREG( PWM1_BASE+PWM_O_1_LOAD)>>1; // Left
Motor Duty cycle 50%

// Set the initial Duty cycle on B to 0%


//HWREG( PWM1_BASE+PWM_O_0_CMPB) = HWREG( PWM1_BASE+PWM_O_0_LOAD)>>1; //Right
Motor Duty cycle 50%

// enable the PWM outputs


HWREG( PWM1_BASE+PWM_O_ENABLE) |= PWM_ENABLE_PWM2EN;

// now configure the Port E pins to be PWM outputs


// start by selecting the alternate function for PB6 & PB7
HWREG(GPIO_PORTE_BASE+GPIO_O_AFSEL) |= BIT4HI;

// now choose to map PWM to those pins, this is a mux value of 5 that we
// want to use for specifying the function on bits 4
HWREG(GPIO_PORTE_BASE+GPIO_O_PCTL) =
(HWREG(GPIO_PORTE_BASE+GPIO_O_PCTL) & 0xfff0ffff) +
(5<<(4*BitsPerNibble));
// Enable pins 4 Port E for digital I/O
HWREG(GPIO_PORTE_BASE+GPIO_O_DEN) |= BIT4HI;

// make pins 4 on Port E into outputs


HWREG(GPIO_PORTE_BASE+GPIO_O_DIR) |= BIT4HI;

// set the up/down count mode, enable the PWM generator and make
// both generator updates locally synchronized to zero count
HWREG(PWM1_BASE+ PWM_O_1_CTL) = (PWM_1_CTL_MODE | PWM_1_CTL_ENABLE |
PWM_1_CTL_GENAUPD_LS |
PWM_1_CTL_GENBUPD_LS);
}
/*------------------------------- Footnotes -------------------------------*/
/*------------------------------ End of file ------------------------------*/

Potrebbero piacerti anche