Rock, Paper, Scissors game coordinator
Dependencies: fsl_phy_mcr20a fsl_smac mbed-rtos mbed
Fork of mcr20_RPS_Coordinator by
main.cpp
- Committer:
- mnorman4
- Date:
- 2015-11-17
- Revision:
- 0:9c8c234fd5ae
File content as of revision 0:9c8c234fd5ae:
#include "mbed.h" #include "rtos.h" #include "Phy.h" #include "SMAC_Interface.h" #include "SMAC_Config.h" #include "MemManager.h" #include "circular_buffer.h" /* Constant Strings */ char const StartupMessage[]= "\rGame Controller Bridge is online.\r\n\n"; char const LetsPlay[] = "Let's play Rock, Paper, Scissors!\r\n"; char const PlayerAString[] = "Player A"; char const PlayerBString[] = "Player B"; char const StrRock[] = "Rock"; char const StrPaper[] = "Paper"; char const StrScissors[] = "Scissors"; /* Hardware Resources */ /* LEDs */ DigitalOut k64f_led_red(LED_RED, 1); DigitalOut k64f_led_green(LED_GREEN, 1); DigitalOut k64f_led_blue(LED_BLUE, 1); DigitalOut cr20a_led_red(PTC11, 1); DigitalOut cr20a_led_green(PTC10, 1); DigitalOut cr20a_led_blue(PTB11, 1); #define LED_ON (0) #define LED_OFF (1) /* Pushbuttons */ InterruptIn k64f_sw2(SW2); InterruptIn k64f_sw3(SW3); InterruptIn cr20a_sw1(PTB23); InterruptIn cr20a_sw2(PTA1); InterruptIn cr20a_sw3(PTC4); #define gPushbutton_K64F_SW2 (1<<1) #define gPushbutton_K64F_SW3 (1<<2) #define gPushbutton_CR20A_SW1 (1<<3) #define gPushbutton_CR20A_SW2 (1<<4) #define gPushbutton_CR20A_SW3 (1<<5) /* OpenSDA Serial Port (UART) */ Serial uart(USBTX, USBRX); CircularBuffer uartBuf; #define gDefaultBaudRate_UART_c 115200UL /* Event Flags */ #define gMcps_Cnf_EVENT_c (1<<1) #define gMcps_Ind_EVENT_c (1<<2) #define gMlme_EdCnf_EVENT_c (1<<3) #define gMlme_CcaCnf_EVENT_c (1<<4) #define gMlme_TimeoutInd_EVENT_c (1<<5) #define gWUSelf_EVENT_c (1<<6) #ifdef VERBOSE static bool_t bCCAFailed; static bool_t bACKFailed; #endif uint32_t gTaskEventFlags; static uint8_t gau8TxDataBuffer[gMaxSmacSDULength_c + sizeof(rxPacket_t)]; txPacket_t *gAppTxPacket; rxPacket_t *gAppRxPacket; static txContextConfig_t txConfigContext; void InitProject(void); void InitApp(void); extern smacErrors_t smacToAppMlmeSap(smacToAppMlmeMessage_t* pMsg, instanceId_t instance); extern smacErrors_t smacToAppMcpsSap(smacToAppDataMessage_t* pMsg, instanceId_t instance); osThreadId PushbuttonThreadID; osThreadId EventsThreadID; void k64f_sw2_press(void) { osSignalSet(PushbuttonThreadID, gPushbutton_K64F_SW2); } void k64f_sw3_press(void) { osSignalSet(PushbuttonThreadID, gPushbutton_K64F_SW3); } void cr20a_sw1_press(void) { osSignalSet(PushbuttonThreadID, gPushbutton_CR20A_SW1); } void cr20a_sw2_press(void) { osSignalSet(PushbuttonThreadID, gPushbutton_CR20A_SW2); } void cr20a_sw3_press(void) { osSignalSet(PushbuttonThreadID, gPushbutton_CR20A_SW3); } /* Constants used to build the single byte game selection */ char const PlayerA = 0xA0; char const PlayerB = 0xB0; char const Rock = 0x01; char const Paper = 0x02; char const Scissors = 0x03; char const Winner = 0x08; char const Loser = 0x0F; char const Draw = 0xFF; /* RPS States */ #define GameStateWaitingBoth (1<<0) #define GameStateWaitingA (1<<1) #define GameStateWaitingB (1<<2) #define GameStateReady (1<<3) #define GameStateAWins (1<<4) #define GameStateBWins (1<<5) #define GameStateDraw (1<<6) int GameState = GameStateWaitingBoth; uint8_t Aselection = 0; uint8_t Bselection = 0; /* Stats */ int GameNum = 0; int NumWinsA = 0; int NumWinsB = 0; int NumDraws = 0; void HeartbeatThread(void const *argument) { while (true) { k64f_led_green = LED_ON; Thread::wait(50); k64f_led_green = LED_OFF; Thread::wait(1950); } } void PushbuttonThread(void const *argument) { PushbuttonThreadID = Thread::gettid(); osEvent event; while (true) { event = Thread::signal_wait(0, osWaitForever); //TODO: Consider using pushbuttons on bridge to set game mode (single/dual player, etc.) if (event.value.signals & gPushbutton_K64F_SW2) { uart.printf("K64F_SW2\r\n"); } if (event.value.signals & gPushbutton_K64F_SW3) { uart.printf("K64F_SW3\r\n"); } if (event.value.signals & gPushbutton_CR20A_SW1) { uart.printf("CR20A_SW1\r\n"); } if (event.value.signals & gPushbutton_CR20A_SW2) { uart.printf("CR20A_SW2\r\n"); } if (event.value.signals & gPushbutton_CR20A_SW3) { uart.printf("CR20A_SW3\r\n"); } } } void PrintSelection (uint8_t selection) { const char *PlayerString; const char *WeaponString; uint8_t player = ((selection & 0xF0) >> 4); uint8_t weapon = ((selection & 0x0F) >> 0); if (player == 0xA) PlayerString = PlayerAString; else if (player == 0xB) PlayerString = PlayerBString; else { uart.printf("Invalid Player\r\n"); return; } switch (weapon) { case Rock: WeaponString = StrRock; break; case Paper: WeaponString = StrPaper; break; case Scissors: WeaponString = StrScissors; break; default: uart.printf("Invalid Weapon: 0x%d\r\n", weapon); return; } uart.printf("%s: %s\r\n", PlayerString, WeaponString); } void RockPaperScissors (uint8_t selection) { uint8_t player = ((selection & 0xF0) >> 4); uint8_t weapon = ((selection & 0x0F) >> 0); switch (GameState) { case GameStateWaitingBoth: if (player == 0xA) { Aselection = weapon; GameState = GameStateWaitingB; uart.printf("Player A: Ready\r\n"); } if (player == 0xB) { Bselection = weapon; GameState = GameStateWaitingA; uart.printf("Player B: Ready\r\n"); } break; case GameStateWaitingA: if (player == 0xA) { Aselection = weapon; uart.printf("Player A: Ready\r\n"); GameState = GameStateReady; } break; case GameStateWaitingB: if (player == 0xB) { Bselection = weapon; uart.printf("Player B: Ready\r\n"); GameState = GameStateReady; } break; } if (GameState == GameStateReady) { if (Aselection == Rock) { uart.printf("\nRock vs. "); if (Bselection == Rock) { uart.printf("Rock\r\n"); GameState = GameStateDraw; } if (Bselection == Paper) { uart.printf("Paper\r\n"); GameState = GameStateBWins; } if (Bselection == Scissors) { uart.printf("Scissors\r\n"); GameState = GameStateAWins; } } if (Aselection == Paper) { uart.printf("\nPaper vs. "); if (Bselection == Rock) { uart.printf("Rock\r\n"); GameState = GameStateAWins; } if (Bselection == Paper) { uart.printf("Paper\r\n"); GameState = GameStateDraw; } if (Bselection == Scissors) { uart.printf("Scissors\r\n"); GameState = GameStateBWins; } } if (Aselection == Scissors) { uart.printf("\nScissors vs. "); if (Bselection == Rock) { uart.printf("Rock\r\n"); GameState = GameStateBWins; } if (Bselection == Paper) { uart.printf("Paper\r\n"); GameState = GameStateAWins; } if (Bselection == Scissors) { uart.printf("Scissors\r\n"); GameState = GameStateDraw; } } } if (GameState == GameStateAWins) { uart.printf("Player A Wins!\r\n\n"); (void)uartBuf.addToBuffer(uint8_t(PlayerA | Winner)); ++NumWinsA; GameState = GameStateWaitingBoth; } if (GameState == GameStateBWins) { uart.printf("Player B Wins!\r\n\n"); (void)uartBuf.addToBuffer(uint8_t(PlayerB | Winner)); ++NumWinsB; GameState = GameStateWaitingBoth; } if (GameState == GameStateDraw) { uart.printf("It's a draw.\r\n\n"); (void)uartBuf.addToBuffer(uint8_t(Draw)); ++NumDraws; GameState = GameStateWaitingBoth; } if (GameState == GameStateWaitingBoth) { uart.printf("%s", LetsPlay); } if (uartBuf.getCount()) { gTaskEventFlags |= gWUSelf_EVENT_c; osSignalSet(EventsThreadID, 0x1); } } void EventsThread(void const *argument) { EventsThreadID = Thread::gettid(); uint8_t rcvd = 0, c = 0; while (true) { Thread::signal_wait(0x1); if(gMcps_Cnf_EVENT_c == (gTaskEventFlags & gMcps_Cnf_EVENT_c)) { MLMERXEnableRequest(gAppRxPacket, 0); } if(gMcps_Ind_EVENT_c == (gTaskEventFlags & gMcps_Ind_EVENT_c)) { rcvd = gAppRxPacket->smacPdu.smacPdu[0]; RockPaperScissors(rcvd); MLMERXEnableRequest(gAppRxPacket, 0); } if(gMlme_TimeoutInd_EVENT_c == (gTaskEventFlags & gMlme_TimeoutInd_EVENT_c)) { uart.printf("MlmeTimeoutInd: \r\n"); } if(gMlme_EdCnf_EVENT_c == (gTaskEventFlags & gMlme_EdCnf_EVENT_c)) { uart.printf("EdCnf: \r\n"); } if(gMlme_CcaCnf_EVENT_c == (gTaskEventFlags & gMlme_CcaCnf_EVENT_c)) { uart.printf("CcaCnf: \r\n"); } if(gWUSelf_EVENT_c == (gTaskEventFlags & gWUSelf_EVENT_c)) { if (buffer_Ok_c == uartBuf.getFromBuffer(&c)) { gAppTxPacket->smacPdu.smacPdu[0] = c; gAppTxPacket->u8DataLength = 1; (void)MLMERXDisableRequest(); (void)MCPSDataRequest(gAppTxPacket); } } gTaskEventFlags = 0; } } int main() { MEM_Init(); Thread heartbeat(HeartbeatThread); Thread pushbuttons(PushbuttonThread); Thread events(EventsThread); Phy_Init(); InitSmac(); //Tell SMAC who to call when it needs to pass a message to the application thread. Smac_RegisterSapHandlers((SMAC_APP_MCPS_SapHandler_t)smacToAppMcpsSap,(SMAC_APP_MLME_SapHandler_t)smacToAppMlmeSap,0); InitApp(); //uart.printf(StartupMessage); uart.printf("%s", LetsPlay); while (true) { Thread::yield(); } } void InitApp() { gAppTxPacket = (txPacket_t*)gau8TxDataBuffer; //Map TX packet to buffer gAppRxPacket = (rxPacket_t*)MEM_BufferAlloc(gMaxSmacSDULength_c + sizeof(rxPacket_t)); InitProject(); SMACFillHeader(&(gAppTxPacket->smacHeader), gDefaultAddress_c); (void)MLMEPAOutputAdjust(gDefaultOutputPower_c); (void)MLMESetChannelRequest(gDefaultChannelNumber_c); (void)MLMEConfigureTxContext(&txConfigContext); //AppDelayTmr = TMR_AllocateTimer(); gAppRxPacket->u8MaxDataLength = gMaxSmacSDULength_c; (void)MLMERXEnableRequest(gAppRxPacket, 0); } /* (Management) Sap handler for managing timeout indication and ED confirm This is running in INTERRUPT context, so need to send messages to one of the task */ smacErrors_t smacToAppMlmeSap(smacToAppMlmeMessage_t* pMsg, instanceId_t instance) { switch(pMsg->msgType) { case gMlmeEdCnf_c: gTaskEventFlags |= gMlme_EdCnf_EVENT_c; break; case gMlmeCcaCnf_c: gTaskEventFlags |= gMlme_CcaCnf_EVENT_c; break; case gMlmeTimeoutInd_c: gTaskEventFlags |= gMlme_TimeoutInd_EVENT_c; break; default: break; } osSignalSet(EventsThreadID, 0x1); MEM_BufferFree(pMsg); return gErrorNoError_c; } /* (Data) Sap handler for managing data confirm and data indication This is running in INTERRUPT context, so need to send messages to one of the task */ smacErrors_t smacToAppMcpsSap(smacToAppDataMessage_t* pMsg, instanceId_t instance) { switch(pMsg->msgType) { case gMcpsDataInd_c: if(pMsg->msgData.dataInd.pRxPacket->rxStatus == rxSuccessStatus_c) { gTaskEventFlags |= gMcps_Ind_EVENT_c; } break; case gMcpsDataCnf_c: #ifdef VERBOSE if(pMsg->msgData.dataCnf.status == gErrorChannelBusy_c) { bCCAFailed = TRUE; } if(pMsg->msgData.dataCnf.status == gErrorNoAck_c) { bACKFailed = TRUE; } #endif gTaskEventFlags |= gMcps_Cnf_EVENT_c; break; default: break; } osSignalSet(EventsThreadID, 0x1); MEM_BufferFree(pMsg); return gErrorNoError_c; } void InitProject(void) { /*Global Data init*/ #ifdef VERBOSE bACKFailed = FALSE; bCCAFailed = FALSE; #endif gTaskEventFlags = 0; txConfigContext.autoAck = FALSE; txConfigContext.ccaBeforeTx = FALSE; txConfigContext.retryCountAckFail = 0; txConfigContext.retryCountCCAFail = 0; /* Setup UART */ uart.baud(gDefaultBaudRate_UART_c); /* Setup Pushbutton Interrupt Callbacks */ k64f_sw2.fall(&k64f_sw2_press); k64f_sw3.fall(&k64f_sw3_press); cr20a_sw1.fall(&cr20a_sw1_press); cr20a_sw2.fall(&cr20a_sw2_press); cr20a_sw3.fall(&cr20a_sw3_press); }