Skip to content

Instantly share code, notes, and snippets.

@michaellin
Created December 1, 2015 03:39
Show Gist options
  • Save michaellin/f0c14452f08090d92a42 to your computer and use it in GitHub Desktop.
Save michaellin/f0c14452f08090d92a42 to your computer and use it in GitHub Desktop.
/****************************************************************************
Module
Audio2.c
Description
This service implements a state machine to play audio for player 2
Author
Margaret Coad
Date
11/10/15
****************************************************************************/
/*----------------------------- 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 "Audio2.h"
#include "PWM12Tiva.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
#include "inc/hw_sysctl.h"
#include "driverlib/sysctl.h"
#include "driverlib/pin_map.h" // Define PART_TM4C123GH6PM in project
#include "driverlib/gpio.h"
/*----------------------------- Module Defines ----------------------------*/
/*---------------------------- Module Functions ---------------------------*/
/* prototypes for private functions for this service. They should be functions
relevant to the behavior of this service
*/
/*---------------------------- Module Variables ---------------------------*/
// Data private to the module: MyPriority, CurrentState, inARMedMode, // inPipeOut, inCelebration, various note frequencies, various
// frequency and delay arrays for different tunes
static uint8_t MyPriority;
static Audio2State_t CurrentState;
static uint8_t inARMedMode;
static uint8_t inPipeOut;
static uint8_t inCelebration;
// Frequencies of various musical notes
static const uint16_t E6 = 1319;
static const uint16_t D6 = 1175;
static const uint16_t Cs6 = 1109;
static const uint16_t B5 = 988;
static const uint16_t As5 = 932;
static const uint16_t A5 = 880;
static const uint16_t Gs5 = 831;
static const uint16_t Fs5 = 740;
static const uint16_t E5 = 660;
static const uint16_t Ds5 = 622;
static const uint16_t D5 = 587;
static const uint16_t Cs5 = 554;
static const uint16_t B4 = 494;
static const uint16_t As4 = 466;
static const uint16_t A4 = 440;
static const uint16_t Gs4 = 415;
static const uint16_t Fs4 = 370;
static const uint16_t E4 = 330;
static const uint16_t Ds4 = 311;
static const uint16_t D4 = 294;
static const uint16_t Cs4 = 277;
static const uint16_t C4 = 262;
static const uint16_t B3 = 247;
static const uint16_t A3 = 220;
// Length of a quarter note
static const uint16_t Q = 450;
// Tune arrays holding frequencies and delays for each tune
static const uint16_t ARMedModeFreqs[89] = {E5, Cs5, A4, Cs5, E5, A5, Cs6, B5, A5, Cs5, Ds5, E5, 0, E5, 0, E5, Cs6, B5, A5, Gs5, Fs5, Gs5, A5, 0, A5, E5, Cs5, A4, E5, Cs5, A4, Cs5, E5, A5, Cs6, B5, A5, Cs5, Ds5, E5, 0, E5, 0, E5, Cs6, B5, A5, Gs5, Fs5, Gs5, A5, Cs5, Ds5, E5, 0,
E5, A5, 0, A5, 0, A5, Gs5, Fs5, 0, Fs5, 0, Fs5, B5, D6, Cs6, B5, A5, 0, A5, Gs5, E5, 0, E5, A5, B5, Cs6, D6, E6, A5, B5, Cs6, D6, B5, A5};
static const uint16_t ARMedModeDelays[89] = {0.75*Q, 0.25*Q, Q, Q, Q, 2*Q, 0.75*Q, 0.25*Q, Q, Q, Q, 1.9*Q, 0.1*Q, 0.65*Q, 0.1*Q, 0.25*Q, 1.5*Q, 0.5*Q, Q, 2*Q, 0.75*Q, 0.25*Q, 0.9*Q, 0.1*Q, Q, Q, Q, Q, 0.75*Q, 0.25*Q, Q, Q, Q, 2*Q, 0.75*Q, 0.25*Q, Q, Q, Q, 1.9*Q, 0.1*Q, 0.65*Q, 0.1*Q, 0.25*Q, 1.5*Q, 0.5*Q, Q, 2*Q, 0.75*Q, 0.25*Q, Q, Q, Q, 1.9*Q, 0.1*Q, Q, 0.9*Q, 0.1*Q, 0.9*Q, 0.1*Q, 0.5*Q, 0.5*Q, 0.9*Q, 0.1*Q, 0.9*Q, 0.1*Q, Q, Q, 0.5*Q, 0.5*Q, 0.5*Q, 0.4*Q, 0.1*Q, Q, Q, 0.4*Q, 0.1*Q, 0.5*Q, 1.5*Q, 0.5*Q, 0.5*Q, 0.5*Q, 2*Q, 0.5*Q, 0.5*Q, 1.5*Q, 0.5*Q, Q, 2*Q};
static const uint16_t StartButtonFreqs[3] = {A4, E5, A5};
static const uint16_t StartButtonDelays[3] = {0.25*Q, 0.25*Q, 0.25*Q};
static const uint16_t SuccessWrenchFreqs[3] = {Cs5, D5, E5};
static const uint16_t SuccessWrenchDelays[3] = {0.25*Q, 0.25*Q, 0.25*Q};
static const uint16_t SuccessBucketFreqs[3] = {Cs5, E5, A5};
static const uint16_t SuccessBucketDelays[3] = {0.25*Q, 0.25*Q, 0.25*Q};
static const uint16_t FailBucketFreqs[1] = {A3};
static const uint16_t FailBucketDelays[1] = {0.75*Q};
static const uint16_t PipeOutFreqs[3] = {E4, Cs4, C4};
static const uint16_t PipeOutDelays[3] = {0.25*Q, 0.25*Q, 0.25*Q};
static const uint16_t PipeInFreqs[3] = {C4, Cs4, E4};
static const uint16_t PipeInDelays[3] = {0.25*Q, 0.25*Q, 0.25*Q};
static const uint16_t CelebrationModeFreqs[74] = {E5, 0, E5, Cs5, 0, Cs5, E5, 0, E5, B4, 0, B4, Cs5, D5, E5, Fs5, Gs5, E5, 0, E5, 0, E5, Cs5, 0, Cs5, E5, 0, E5, B4, 0, B4, B5, As5, B5, Cs6, Fs5, B5, E5, Cs6, 0, Cs6, B5, A5, 0, A5, Gs5, 0, Gs5, A5, B5, Gs5, Fs5, E5, A5, 0, A5, 0, A5, Fs5, 0, Fs5, A5, 0, A5, E5, 0, E5, 0, E5, Fs5, A5, E5, B5, A5};
static const uint16_t CelebrationModeDelays[74] = {0.9*Q, 0.1*Q, 1.5*Q, 0.4*Q, 0.1*Q, Q, 0.9*Q, 0.1*Q, 1.5*Q, 0.4*Q, 0.1*Q, Q, Q, Q, Q, Q, Q, 2.9*Q, 0.1*Q, 0.9*Q, 0.1*Q, 1.5*Q, 0.4*Q, 0.1*Q, Q, 0.9*Q, 0.1*Q, 1.5*Q, 0.4*Q, 0.1*Q, Q, Q, Q, Q, Q, Q, 3*Q, Q, 1.4*Q, 0.1*Q, 0.5*Q, Q, 0.9*Q, 0.1*Q, 1.5*Q, 0.4*Q, 0.1*Q, Q, Q, Q, Q, Q, Q, 2.9*Q, 0.1*Q, 0.9*Q, 0.1*Q, 1.5*Q, 0.4*Q, 0.1*Q, Q, 0.9*Q, 0.1*Q, 1.5*Q, 0.4*Q, 0.1*Q, 0.9*Q, 0.1*Q, Q, Q, Q, Q, Q, 3*Q};
static const uint16_t FailureModeFreqs[5] = {E4, Ds4, D4, Cs4, C4};
static const uint16_t FailureModeDelays[5] = {Q, Q, Q, Q, 2*Q};
/*------------------------------ Module Code ------------------------------*/
/****************************************************************************
Function
InitAudio2
Parameters
uint8_t : the priority 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
Margaret Coad, 11/10/15
****************************************************************************/
bool InitAudio2 ( uint8_t Priority )
{
//Initialize the MyPriority variable with the passed in parameter.
MyPriority = Priority;
//Initialize the port line (A6) to write to speaker 2
// Enable GPIO Port A
HWREG(SYSCTL_RCGCGPIO) |= BIT0HI;
// Wait until peripheral reports that clock is ready
while ((HWREG(SYSCTL_PRGPIO) & SYSCTL_PRGPIO_R0) !=
SYSCTL_PRGPIO_R0);
// Set bit 6 on Port A to be a digital I/O line
HWREG(GPIO_PORTA_BASE+GPIO_O_DEN) |= (GPIO_PIN_6);
// Set bit 6 on Port A to be an input
HWREG(GPIO_PORTA_BASE+GPIO_O_DIR) &= (~GPIO_PIN_6);
//Set CurrentState to Waiting2Play
CurrentState = Waiting2Play;
//End of InitAudio2 (return True)
return true;
}
/****************************************************************************
Function
PostAudio2
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
Margaret Coad, 11/10/15
****************************************************************************/
bool PostAudio2( ES_Event ThisEvent )
{
return ES_PostToService( MyPriority, ThisEvent);
}
/****************************************************************************
Function
RunAudio2 (implements 2-state state machine for player 2's audio)
Parameters
ES_Event : the event to process
Returns
ES_Event, ES_NO_EVENT if no error, ES_ERROR otherwise
Description
The EventType of ThisEvent will be ES_PLAY_TUNE,
ES_START_BUTTON_DB_DOWN, ES_PIPE_RECOVERED, ES_TIMEOUT,
ES_GAINED_POINT, or ES_GAMEOVER; the EventParam will be ARMedMode,
StartButton, SuccessWrench, SuccessBucket, FailBucket, PipeOut,
PipeIn, CelebrationMode, FailureMode, PIPE_TIMER, or AUDIO2_TIMER
Notes
Author
Margaret Coad, 11/10/15
****************************************************************************/
ES_Event RunAudio2( ES_Event ThisEvent )
{
ES_Event ReturnEvent;
ReturnEvent.EventType = ES_NO_EVENT; // assume no errors
//Local Variables: NextState (state)
Audio2State_t NextState;
//Static Local Variable: TuneFreqs (array); create enough space
//for max length tune
static uint16_t TuneFreqs[ARRAY_SIZE(ARMedModeFreqs)];
//Static Local Variable: TuneDelays (array)
static uint16_t TuneDelays[ARRAY_SIZE(ARMedModeFreqs)];
//Static Local Variable: NumberOfNotes (number)
static uint16_t NumberOfNotes;
//Static Local Variable: CurrentNote (number)
static uint16_t CurrentNote;
//Set NextState to CurrentState
NextState = CurrentState;
//Based on the state of the CurrentState variable choose one of
//the following blocks of code:
switch (CurrentState){
case Waiting2Play:
//If ThisEvent is ES_PLAY_TUNE
if (ThisEvent.EventType == ES_PLAY_TUNE) {
//Initialize flags to say that we are not in
//ARMedMode, PipeOut, or Celebration
inARMedMode = 0;
inPipeOut = 0;
inCelebration = 0;
//Set TuneFreqs to frequency array //corresponding to Event Parameter
//Set TuneDelays to delay array corresponding
//to Event Parameter
//Set NumberOfNotes to length of TuneFreqs
uint16_t i;
switch (ThisEvent.EventParam) {
case ARMedMode:
NumberOfNotes =
ARRAY_SIZE(ARMedModeFreqs);
for (i = 0; i < NumberOfNotes;
i++){
TuneFreqs[i] =
ARMedModeFreqs[i];
TuneDelays[i] =
ARMedModeDelays[i];
inARMedMode = 1;
}
break;
case StartButton:
NumberOfNotes =
ARRAY_SIZE(StartButtonFreqs);
for (i = 0; i < NumberOfNotes;
i++){
TuneFreqs[i] =
StartButtonFreqs[i];
TuneDelays[i] =
StartButtonDelays[i];
}
break;
case SuccessWrench:
NumberOfNotes =
ARRAY_SIZE(SuccessWrenchFreqs);
for (i = 0; i < NumberOfNotes;
i++){
TuneFreqs[i] =
SuccessWrenchFreqs[i];
TuneDelays[i] =
SuccessWrenchDelays[i];
}
break;
case SuccessBucket:
NumberOfNotes =
ARRAY_SIZE(SuccessBucketFreqs);
for (i = 0; i < NumberOfNotes;
i++){
TuneFreqs[i] =
SuccessBucketFreqs[i];
TuneDelays[i] =
SuccessBucketDelays[i];
}
break;
case FailBucket:
NumberOfNotes =
ARRAY_SIZE(FailBucketFreqs);
for (i = 0; i < NumberOfNotes;
i++){
TuneFreqs[i] =
FailBucketFreqs[i];
TuneDelays[i] =
FailBucketDelays[i];
}
break;
case PipeOut:
NumberOfNotes =
ARRAY_SIZE(PipeOutFreqs);
for (i = 0; i < NumberOfNotes;
i++){
TuneFreqs[i] =
PipeOutFreqs[i];
TuneDelays[i] =
PipeOutDelays[i];
inPipeOut = 1;
}
break;
case PipeIn:
NumberOfNotes =
ARRAY_SIZE(PipeInFreqs);
for (i = 0; i < NumberOfNotes;
i++){
TuneFreqs[i] =
PipeInFreqs[i];
TuneDelays[i] =
PipeInDelays[i];
}
break;
case CelebrationMode:
inCelebration = 1;
NumberOfNotes =
ARRAY_SIZE(CelebrationModeFreqs);
for (i = 0; i < NumberOfNotes;
i++){
TuneFreqs[i] =
CelebrationModeFreqs[i];
TuneDelays[i] =
CelebrationModeDelays[i];
}
break;
case FailureMode:
NumberOfNotes =
ARRAY_SIZE(FailureModeFreqs);
for (i = 0; i < NumberOfNotes;
i++){
TuneFreqs[i] =
FailureModeFreqs[i];
TuneDelays[i] =
FailureModeDelays[i];
}
break;
}
// Play first note of TuneFreqs
PWM_TIVA_SetDuty(50, 10);
PWM_TIVA_SetFreq(TuneFreqs[0], 5);
// Set audio timer for length of first note in // TuneDelays
ES_Timer_InitTimer(AUDIO2_TIMER,TuneDelays[0]);
// Set CurrentNote to 1
CurrentNote = 1;
// Set NextState to Playing
NextState = Playing;
//Endif
}
break;
case Playing:
// If statement to interrupt a tune under certain
// circumstances
if (ThisEvent.EventType==ES_START_BUTTON_DBDOWN ||
ThisEvent.EventType == ES_PIPE_RECOVERED ||
(ThisEvent.EventType == ES_TIMEOUT &&
ThisEvent.EventParam == PIPE_TIMER && inCelebration
==0) || (ThisEvent.EventType == ES_GAINED_POINT) || (ThisEvent.EventType==ES_GAMEOVER)){
NextState = Waiting2Play;
//Play nothing (set duty cycle to 0)
PWM_TIVA_SetDuty(0, 10);
}
else if ((ThisEvent.EventType == ES_TIMEOUT) &&
(ThisEvent.EventParam == AUDIO2_TIMER)){
//If CurrentNote = NumberOfNotes
if (CurrentNote == NumberOfNotes){
if (inARMedMode==1){
ES_Event ThatEvent;
ThatEvent.EventType = ES_PLAY_TUNE;
ThatEvent.EventParam = ARMedMode;
PostAudio2(ThatEvent);
}
if (inPipeOut==1){
ES_Event OtherEvent;
OtherEvent.EventType =ES_PLAY_TUNE;
OtherEvent.EventParam = PipeOut;
PostAudio2(OtherEvent);
}
//Play nothing (set duty cycle to 0)
PWM_TIVA_SetDuty(0, 10);
//Set NextState to Waiting2Play
NextState = Waiting2Play;
//Endif
}
//If CurrentNote < NumberOfNotes
if (CurrentNote < NumberOfNotes){
//Play note of TuneFreqs with index
//CurrentNote
PWM_TIVA_SetFreq(TuneFreqs[CurrentNote],5);
//Set audio timer for length of note in
TuneDelays with index CurrentNote
ES_Timer_InitTimer(AUDIO2_TIMER,
TuneDelays[CurrentNote]);
//Increment CurrentNote
CurrentNote++;
//Endif
}
//Endif
}
break;
}
//Set CurrentState to NextState
CurrentState = NextState;
//Return ES_NO_EVENT
return ReturnEvent;
}
/***************************************************************************
private functions
***************************************************************************/
/*------------------------------- Footnotes -------------------------------*/
/*------------------------------ End of file ------------------------------*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment