You are on page 1of 9

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

Module
LightsService.c
Revision
1.0.1
Description
This is the first service for the Lights Service under the
Gen2 Events and Services Framework. (a simple service)
Notes
History
When
Who
-------------- --11/15/16 21:12 lbh

What/Why
-------ME218A Project

****************************************************************************/
/*----------------------------- Include Files -----------------------------*/
/* include header files for the framework and this service
*/
#include "ES_Configure.h"
#include "ES_Framework.h"
#include "ES_DeferRecall.h"
#include "ES_ShortTimer.h"
#include
#include
#include
#include

"LightsService.h"
"Audio.h"
"PWM10Tiva.h"
"string.h"

#include
#include
#include
#include
#include
#include
#include

"inc/hw_memmap.h"
"inc/hw_types.h"
"inc/hw_gpio.h"
"inc/hw_sysctl.h"
"driverlib/sysctl.h"
"driverlib/pin_map.h"
"driverlib/gpio.h"

// Define PART_TM4C123GH6PM in project

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


// these times assume a 1.000mS/tick timing
#define ONE_SEC 976
#define HALF_SEC (ONE_SEC/2)
#define TIMESTEP (HALF_SEC)
//channel numbers
#define YellowBackground 0
#define RedBackground 1
#define WhiteBackground 2
#define BlueBackground 3
//Rename front light pins
#define FrontLightPin GPIO_PIN_6
//These are for controlling light levels at each phase of the day
//Dawn (Morning)
#define StartRedDawn 0
#define StartBlueDawn 99
#define StartWhiteDawn 0
#define StartYellowDawn 0
#define EndRedDawn 30
#define EndBlueDawn 20

#define EndWhiteDawn 5
#define EndYellowDawn 20
//SunRising (Afternoon)
#define StartRedSunRising 30
#define StartBlueSunRising 20
#define StartWhiteSunRising 5
#define StartYellowSunRising 20
#define EndRedSunRising 15
#define EndBlueSunRising 3
#define EndWhiteSunRising 60
#define EndYellowSunRising 99
//SunSetting (Evening)
#define StartRedSunSetting 15
#define StartBlueSunSetting 3
#define StartWhiteSunSetting 60
#define StartYellowSunSetting 99
#define EndRedSunSetting 66
#define EndBlueSunSetting 33
#define EndWhiteSunSetting 10
#define EndYellowSunSetting 66
//Dusk (Twilight)
#define StartRedDusk 66
#define StartBlueDusk 33
#define StartWhiteDusk 10
#define StartYellowDusk 66
#define EndRedDusk 20
#define EndBlueDusk 66
#define EndWhiteDusk 5
#define EndYellowDusk 10
//Night (Night)
#define StartRedNight 20
#define StartBlueNight 66
#define StartWhiteNight 5
#define StartYellowNight 10
#define EndRedNight 0
#define EndBlueNight 99
#define EndWhiteNight 0
#define EndYellowNight 0
//Number of gradations desired in each period of day. 1 step = 1 timestep
(1/20s)
#define DawnSteps 8
#define SunRisingSteps 24
#define SunSettingSteps 24
#define DuskSteps 8
#define NightSteps 32
/*---------------------------- 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
/* create new macro to always access all 8 bits */
#define ALL_BITS (0xff<<2)
//Data private to the module:
static uint8_t MyPriority;
static LightsState_t CurrentState;
// add a deferral queue for up to 3 pending deferrals +1 to allow for overhead

static ES_Event DeferralQueue[3+1];


//Counter reflects how far through each period of day we are. Initialised to
zero
static int DawnCounter = 0;
static int SunRisingCounter = 0;
static int SunSettingCounter = 0;
static int DuskCounter = 0;
static int NightCounter = 0;
/*------------------------------ Module Code ------------------------------*/
/****************************************************************************
Function
InitLightsService
Parameters
uint8_t : the priorty of this service
Returns
bool, false if error in initialization, true otherwise
Description
Saves away the priority, and does any
other required initialization for this service
Notes
Author
Latifah Hamzah, 15 Nov 2016
****************************************************************************/
bool InitLightsService (uint8_t Priority)
{
// initialize deferral queue for testing Deferral function
ES_InitDeferralQueueWith( DeferralQueue, ARRAY_SIZE(DeferralQueue) );
//Initialize the MyPriority variable with the passed in parameter.
MyPriority = Priority;
//Enable Port C (clock)
HWREG(SYSCTL_RCGCGPIO) |= SYSCTL_RCGCGPIO_R2;
//waits for clock to be ready
while ((HWREG(SYSCTL_PRGPIO) & SYSCTL_PRGPIO_R2) != SYSCTL_PRGPIO_R2);
//assigns bit 6, Port C as a digital I/O line
HWREG(GPIO_PORTC_BASE+GPIO_O_DEN) |= FrontLightPin;
//sets bit 6, Port C as an output - it controls the front lights
HWREG(GPIO_PORTC_BASE+GPIO_O_DIR) |= FrontLightPin;
//start with front lights off
HWREG(GPIO_PORTC_BASE+(GPIO_O_DATA+ALL_BITS)) &= ~FrontLightPin;
//background lights (Port B, pins 4-7) initialised elsewhere as PWM
//Sets Frequency of yellow and red LEDs (group 0, channels 0 and 1) to
2000

PWM_TIVA_SetFreq(2000,0);
//Sets Frequency of blue and background white LEDs (group 1, channels 2
and 3) to 2000
PWM_TIVA_SetFreq(2000,1);
//sets up timer for lightning
void _HW_Timer_Init(TimerRate_t Rate);
uint16_t ES_Timer_GetTime(void);
return true;
}
/****************************************************************************
Function

PostLightsService
Parameters
ES_Event ThisEvent ,the event to post to the queue
Returns
bool false if the Enqueue operation failed, true otherwise
Description
Posts an event to this state machine's queue
Notes
Author
Latifah Hamzah, 15 Nov 2016
****************************************************************************/
bool PostLightsService( ES_Event ThisEvent )
{
return ES_PostToService(MyPriority, ThisEvent);
}
/****************************************************************************
Function
RunLightsService
Parameters
ES_Event : the event to process
Returns
ES_Event, ES_NO_EVENT if no error ES_ERROR otherwise
Description
add your description here
Notes
Author
Latifah Hamzah, 15 Nov 2016
****************************************************************************/
ES_Event RunLightsService(ES_Event ThisEvent){
//EventType is one of: ES_RESET, ES_OPEN, ES_WIND, ES_WELCOME
//Parameter will be the strength of the wind. Other parameters ignored / not
used.
ES_Event ReturnEvent;
ReturnEvent.EventType = ES_NO_EVENT; // assume no errors
//Local Variables: NextState
LightsState_t NextState;
//Set NextState to CurrentState
NextState = CurrentState;
switch(CurrentState){
case Idle:
if (ThisEvent.EventType == ES_WELCOME){
//turn front lights on
HWREG(GPIO_PORTC_BASE+(GPIO_O_DATA+ALL_BITS)) |=
GPIO_PIN_6;

//nextState is Dawn
NextState = Dawn;

}
//If ThisEvent is ES_RESET
if (ThisEvent.EventType == ES_RESET){
//set all counters to zero
DawnCounter = 0;

SunRisingCounter = 0;
SunSettingCounter = 0;
DuskCounter = 0;
NightCounter = 0;
//turn all lights off
//front lights off
HWREG(GPIO_PORTC_BASE+(GPIO_O_DATA+ALL_BITS)) &=

~GPIO_PIN_6;

//lightning off
HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS)) &=
~GPIO_PIN_3;

//all background lights off


PWM_TIVA_SetDuty(0,YellowBackground);
PWM_TIVA_SetDuty(0,RedBackground);
PWM_TIVA_SetDuty(0,WhiteBackground);
PWM_TIVA_SetDuty(0,BlueBackground);
//nextState is Idle
NextState = Idle;
}

break;

case Dawn:
//doesn't do anything until get an ES_OPEN event
if (ThisEvent.EventType == ES_OPEN){
//increment DawnCounter by 1
DawnCounter ++;
//turns background lights on to minimum dawn settings
PWM_TIVA_SetDuty(StartYellowDawn,YellowBackground);
PWM_TIVA_SetDuty(StartRedDawn,RedBackground);
PWM_TIVA_SetDuty(StartWhiteDawn,WhiteBackground);
PWM_TIVA_SetDuty(StartBlueDawn,BlueBackground);
//starts circadian timer
ES_Timer_InitTimer(CircadianClock, TIMESTEP); //half an
hour is half a sec
}
//if event type is ES_TIMEOUT & posting clock was circadian clock
if (ThisEvent.EventType == ES_TIMEOUT && ThisEvent.EventParam
== CircadianClock) {
//increment DawnCounter by 1
DawnCounter ++ ;
//sets pwm of lights
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartRedDawn+((DawnCounter-1)*(EndRedDawn-StartRedDawn)/
(DawnSteps-1)))),RedBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartYellowDawn+((DawnCounter-1)*(EndYellowDawnStartYellowDawn)/(DawnSteps-1)))),YellowBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartBlueDawn+((DawnCounter-1)*(EndBlueDawn-StartBlueDawn)/
(DawnSteps-1)))),BlueBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartWhiteDawn+((DawnCounter-1)*(EndWhiteDawnStartWhiteDawn)/(DawnSteps-1)))),WhiteBackground);
//starts circadian timer
ES_Timer_InitTimer(CircadianClock, TIMESTEP);
if(DawnSteps == DawnCounter){ //Dawn is ending
NextState = SunRising;
//reset DawnCounter for next time dawn starts
DawnCounter = 0;
}
}
//If ThisEvent is ES_RESET
if (ThisEvent.EventType == ES_RESET){
//set all counters to zero

DawnCounter = 0;
SunRisingCounter = 0;
SunSettingCounter = 0;
DuskCounter = 0;
NightCounter = 0;
//turn all lights off
//front lights off
HWREG(GPIO_PORTC_BASE+(GPIO_O_DATA+ALL_BITS)) &=
~GPIO_PIN_6;

//lightning off
HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS)) &=

~GPIO_PIN_3;

//all background lights off


PWM_TIVA_SetDuty(0,YellowBackground);
PWM_TIVA_SetDuty(0,RedBackground);
PWM_TIVA_SetDuty(0,WhiteBackground);
PWM_TIVA_SetDuty(0,BlueBackground);
//nextState is Idle
NextState = Idle;
}
break;
case SunRising:
//if event type is ES_TIMEOUT & posting clock was circadian
clock

if (ThisEvent.EventType == ES_TIMEOUT && ThisEvent.EventParam


== CircadianClock) {
//increment SunRisingCounter by 1
SunRisingCounter ++ ;
//sets pwm of lights
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartRedSunRising+((SunRisingCounter-1)*(EndRedSunRisingStartRedSunRising)/(SunRisingSteps-1)))),RedBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartYellowSunRising+((SunRisingCounter1)*(EndYellowSunRising-StartYellowSunRising)/(SunRisingSteps1)))),YellowBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartBlueSunRising+((SunRisingCounter-1)*(EndBlueSunRisingStartBlueSunRising)/(SunRisingSteps-1)))),BlueBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartWhiteSunRising+((SunRisingCounter-1)*(EndWhiteSunRisingStartWhiteSunRising)/(SunRisingSteps-1)))),WhiteBackground);
//starts circadian timer
ES_Timer_InitTimer(CircadianClock, TIMESTEP);
if(SunRisingSteps == SunRisingCounter){ //Sun Rising is
ending, ie at midday
NextState = SunSetting;
//reset SunRisingCounter for next time sun rising
starts
SunRisingCounter = 0;
}
}
//If ThisEvent is ES_RESET
if (ThisEvent.EventType == ES_RESET){
//set all counters to zero
DawnCounter = 0;
SunRisingCounter = 0;
SunSettingCounter = 0;
DuskCounter = 0;
NightCounter = 0;
//turn all lights off
//front lights off
HWREG(GPIO_PORTC_BASE+(GPIO_O_DATA+ALL_BITS)) &=

~GPIO_PIN_6;

//lightning off
HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS)) &=

~GPIO_PIN_3;

//all background lights off


PWM_TIVA_SetDuty(0,YellowBackground);
PWM_TIVA_SetDuty(0,RedBackground);
PWM_TIVA_SetDuty(0,WhiteBackground);
PWM_TIVA_SetDuty(0,BlueBackground);
//nextState is Idle
NextState = Idle;
}
break;
case SunSetting:
//if event type is ES_TIMEOUT & posting clock was circadian
clock

if (ThisEvent.EventType == ES_TIMEOUT && ThisEvent.EventParam


== CircadianClock) {
//increment SunSettingCounter by 1
SunSettingCounter ++;
//sets pwm of lights (red and blue brightening, white
and yellow dimming)
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartRedSunSetting+((SunSettingCounter-1)*(EndRedSunSettingStartRedSunSetting)/(SunSettingSteps-1)))),RedBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartYellowSunSetting+((SunSettingCounter1)*(EndYellowSunSetting-StartYellowSunSetting)/(SunSettingSteps1)))),YellowBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartBlueSunSetting+((SunSettingCounter1)*(EndBlueSunSetting-StartBlueSunSetting)/(SunSettingSteps1)))),BlueBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartWhiteSunSetting+((SunSettingCounter1)*(EndWhiteSunSetting-StartWhiteSunSetting)/(SunSettingSteps1)))),WhiteBackground);
//starts circadian timer
ES_Timer_InitTimer(CircadianClock, TIMESTEP);
if(SunSettingSteps == SunSettingCounter) {//Sun has
finished setting
NextState = Dusk;
//reset SunSettingCounter for next time sun
setting starts
SunSettingCounter = 0;
}
}
//If ThisEvent is ES_RESET
if (ThisEvent.EventType == ES_RESET){
//set all counters to zero
DawnCounter = 0;
SunRisingCounter = 0;
SunSettingCounter = 0;
DuskCounter = 0;
NightCounter = 0;
//turn all lights off
//front lights off
HWREG(GPIO_PORTC_BASE+(GPIO_O_DATA+ALL_BITS)) &=
~GPIO_PIN_6;
//lightning off
HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS)) &=
~GPIO_PIN_3;
//all background lights off

PWM_TIVA_SetDuty(0,YellowBackground);
PWM_TIVA_SetDuty(0,RedBackground);
PWM_TIVA_SetDuty(0,WhiteBackground);
PWM_TIVA_SetDuty(0,BlueBackground);
//nextState is Idle
NextState = Idle;
}

break;

clock

case Dusk:
//if event type is ES_TIMEOUT & posting clock was circadian

if (ThisEvent.EventType == ES_TIMEOUT && ThisEvent.EventParam


== CircadianClock) {
//increment DuskCounter by 1
DuskCounter ++;
//sets pwm of lights
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartRedDusk+((DuskCounter-1)*(EndRedDusk-StartRedDusk)/
(DuskSteps-1)))),RedBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartYellowDusk+((DuskCounter-1)*(EndYellowDuskStartYellowDusk)/(DuskSteps-1)))),YellowBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartBlueDusk+((DuskCounter-1)*(EndBlueDusk-StartBlueDusk)/
(DuskSteps-1)))),BlueBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartWhiteDusk+((DuskCounter-1)*(EndWhiteDuskStartWhiteDusk)/(DuskSteps-1)))),WhiteBackground);
//starts circadian timer
ES_Timer_InitTimer(CircadianClock, TIMESTEP);
if(DuskSteps == DuskCounter) {//Dusk has ended
NextState = Night;
//reset DuskCounter for next time dusk starts

has fallen

DuskCounter = 0;
ES_Event nightFallen; //create an event indicating night
nightFallen.EventType = ES_NIGHTFALL;
PostAudioService(nightFallen); //notify audio that night

has fallen

~GPIO_PIN_6;
~GPIO_PIN_3;

}
}
//If ThisEvent is ES_RESET
if (ThisEvent.EventType == ES_RESET){
//set all counters to zero
DawnCounter = 0;
SunRisingCounter = 0;
SunSettingCounter = 0;
DuskCounter = 0;
NightCounter = 0;
//turn all lights off
//front lights off
HWREG(GPIO_PORTC_BASE+(GPIO_O_DATA+ALL_BITS)) &=
//lightning off
HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS)) &=
//all background lights off
PWM_TIVA_SetDuty(0,YellowBackground);
PWM_TIVA_SetDuty(0,RedBackground);
PWM_TIVA_SetDuty(0,WhiteBackground);
PWM_TIVA_SetDuty(0,BlueBackground);
//nextState is Idle

NextState = Idle;

break;
case Night:
//if event type is ES_TIMEOUT & posting clock was circadian
clock

if (ThisEvent.EventType == ES_TIMEOUT && ThisEvent.EventParam


== CircadianClock) {
//increment NightCounter by 1
NightCounter ++;
//sets pwm of lights (blue brightening, everything else
dimming)
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartRedNight+((NightCounter-1)*(EndRedNight-StartRedNight)/
(NightSteps-1)))),RedBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartYellowNight+((NightCounter-1)*(EndYellowNightStartYellowNight)/(NightSteps-1)))),YellowBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartBlueNight+((NightCounter-1)*(EndBlueNightStartBlueNight)/(NightSteps-1)))),BlueBackground);
PWM_TIVA_SetDuty((uint8_t)
(WeatherModulator*(StartWhiteNight+((NightCounter-1)*(EndWhiteNightStartWhiteNight)/(NightSteps-1)))),WhiteBackground);
//starts circadian timer
ES_Timer_InitTimer(CircadianClock, HALF_SEC);
if(NightSteps == NightCounter) {//Night has ended
NextState = Dawn;
//reset NightCounter for next time dusk starts
NightCounter = 0;
}

~GPIO_PIN_6;

}
//If ThisEvent is ES_RESET
if (ThisEvent.EventType == ES_RESET){
//set all counters to zero
DawnCounter = 0;
SunRisingCounter = 0;
SunSettingCounter = 0;
DuskCounter = 0;
NightCounter = 0;
//turn all lights off
//front lights off
HWREG(GPIO_PORTC_BASE+(GPIO_O_DATA+ALL_BITS)) &=
//lightning off
HWREG(GPIO_PORTB_BASE+(GPIO_O_DATA+ALL_BITS)) &=

~GPIO_PIN_3;

//all background lights off


PWM_TIVA_SetDuty(0,YellowBackground);
PWM_TIVA_SetDuty(0,RedBackground);
PWM_TIVA_SetDuty(0,WhiteBackground);
PWM_TIVA_SetDuty(0,BlueBackground);
//nextState is Idle
NextState = Idle;
}

break;
}
CurrentState = NextState;
return ReturnEvent;