Rock, Paper, Scissors game coordinator
Dependencies: fsl_phy_mcr20a fsl_smac mbed-rtos mbed
Fork of mcr20_RPS_Coordinator by
main.cpp
00001 #include "mbed.h" 00002 #include "rtos.h" 00003 #include "Phy.h" 00004 #include "SMAC_Interface.h" 00005 #include "SMAC_Config.h" 00006 #include "MemManager.h" 00007 #include "circular_buffer.h" 00008 00009 /* Constant Strings */ 00010 char const StartupMessage[]= "\rGame Controller Bridge is online.\r\n\n"; 00011 char const LetsPlay[] = "Let's play Rock, Paper, Scissors!\r\n"; 00012 char const PlayerAString[] = "Player A"; 00013 char const PlayerBString[] = "Player B"; 00014 char const StrRock[] = "Rock"; 00015 char const StrPaper[] = "Paper"; 00016 char const StrScissors[] = "Scissors"; 00017 00018 /* Hardware Resources */ 00019 /* LEDs */ 00020 DigitalOut k64f_led_red(LED_RED, 1); 00021 DigitalOut k64f_led_green(LED_GREEN, 1); 00022 DigitalOut k64f_led_blue(LED_BLUE, 1); 00023 DigitalOut cr20a_led_red(PTC11, 1); 00024 DigitalOut cr20a_led_green(PTC10, 1); 00025 DigitalOut cr20a_led_blue(PTB11, 1); 00026 00027 #define LED_ON (0) 00028 #define LED_OFF (1) 00029 00030 /* Pushbuttons */ 00031 InterruptIn k64f_sw2(SW2); 00032 InterruptIn k64f_sw3(SW3); 00033 InterruptIn cr20a_sw1(PTB23); 00034 InterruptIn cr20a_sw2(PTA1); 00035 InterruptIn cr20a_sw3(PTC4); 00036 00037 #define gPushbutton_K64F_SW2 (1<<1) 00038 #define gPushbutton_K64F_SW3 (1<<2) 00039 #define gPushbutton_CR20A_SW1 (1<<3) 00040 #define gPushbutton_CR20A_SW2 (1<<4) 00041 #define gPushbutton_CR20A_SW3 (1<<5) 00042 00043 /* OpenSDA Serial Port (UART) */ 00044 Serial uart(USBTX, USBRX); 00045 CircularBuffer uartBuf; 00046 #define gDefaultBaudRate_UART_c 115200UL 00047 00048 /* Event Flags */ 00049 #define gMcps_Cnf_EVENT_c (1<<1) 00050 #define gMcps_Ind_EVENT_c (1<<2) 00051 #define gMlme_EdCnf_EVENT_c (1<<3) 00052 #define gMlme_CcaCnf_EVENT_c (1<<4) 00053 #define gMlme_TimeoutInd_EVENT_c (1<<5) 00054 #define gWUSelf_EVENT_c (1<<6) 00055 00056 #ifdef VERBOSE 00057 static bool_t bCCAFailed; 00058 static bool_t bACKFailed; 00059 #endif 00060 00061 uint32_t gTaskEventFlags; 00062 static uint8_t gau8TxDataBuffer[gMaxSmacSDULength_c + sizeof(rxPacket_t)]; 00063 txPacket_t *gAppTxPacket; 00064 rxPacket_t *gAppRxPacket; 00065 static txContextConfig_t txConfigContext; 00066 00067 void InitProject(void); 00068 void InitApp(void); 00069 00070 extern smacErrors_t smacToAppMlmeSap(smacToAppMlmeMessage_t* pMsg, instanceId_t instance); 00071 extern smacErrors_t smacToAppMcpsSap(smacToAppDataMessage_t* pMsg, instanceId_t instance); 00072 00073 osThreadId PushbuttonThreadID; 00074 osThreadId EventsThreadID; 00075 00076 void k64f_sw2_press(void) { osSignalSet(PushbuttonThreadID, gPushbutton_K64F_SW2); } 00077 void k64f_sw3_press(void) { osSignalSet(PushbuttonThreadID, gPushbutton_K64F_SW3); } 00078 void cr20a_sw1_press(void) { osSignalSet(PushbuttonThreadID, gPushbutton_CR20A_SW1); } 00079 void cr20a_sw2_press(void) { osSignalSet(PushbuttonThreadID, gPushbutton_CR20A_SW2); } 00080 void cr20a_sw3_press(void) { osSignalSet(PushbuttonThreadID, gPushbutton_CR20A_SW3); } 00081 00082 /* Constants used to build the single byte game selection */ 00083 char const PlayerA = 0xA0; 00084 char const PlayerB = 0xB0; 00085 char const Rock = 0x01; 00086 char const Paper = 0x02; 00087 char const Scissors = 0x03; 00088 char const Winner = 0x08; 00089 char const Loser = 0x0F; 00090 char const Draw = 0xFF; 00091 00092 /* RPS States */ 00093 #define GameStateWaitingBoth (1<<0) 00094 #define GameStateWaitingA (1<<1) 00095 #define GameStateWaitingB (1<<2) 00096 #define GameStateReady (1<<3) 00097 #define GameStateAWins (1<<4) 00098 #define GameStateBWins (1<<5) 00099 #define GameStateDraw (1<<6) 00100 00101 int GameState = GameStateWaitingBoth; 00102 uint8_t Aselection = 0; 00103 uint8_t Bselection = 0; 00104 00105 /* Stats */ 00106 int GameNum = 0; 00107 int NumWinsA = 0; 00108 int NumWinsB = 0; 00109 int NumDraws = 0; 00110 00111 void HeartbeatThread(void const *argument) 00112 { 00113 while (true) { 00114 k64f_led_green = LED_ON; 00115 Thread::wait(50); 00116 k64f_led_green = LED_OFF; 00117 Thread::wait(1950); 00118 } 00119 } 00120 00121 void PushbuttonThread(void const *argument) 00122 { 00123 PushbuttonThreadID = Thread::gettid(); 00124 osEvent event; 00125 00126 while (true) { 00127 event = Thread::signal_wait(0, osWaitForever); 00128 00129 //TODO: Consider using pushbuttons on bridge to set game mode (single/dual player, etc.) 00130 00131 if (event.value.signals & gPushbutton_K64F_SW2) { 00132 uart.printf("K64F_SW2\r\n"); 00133 } 00134 if (event.value.signals & gPushbutton_K64F_SW3) { 00135 uart.printf("K64F_SW3\r\n"); 00136 } 00137 if (event.value.signals & gPushbutton_CR20A_SW1) { 00138 uart.printf("CR20A_SW1\r\n"); 00139 } 00140 if (event.value.signals & gPushbutton_CR20A_SW2) { 00141 uart.printf("CR20A_SW2\r\n"); 00142 } 00143 if (event.value.signals & gPushbutton_CR20A_SW3) { 00144 uart.printf("CR20A_SW3\r\n"); 00145 } 00146 } 00147 } 00148 00149 void PrintSelection (uint8_t selection) 00150 { 00151 const char *PlayerString; 00152 const char *WeaponString; 00153 uint8_t player = ((selection & 0xF0) >> 4); 00154 uint8_t weapon = ((selection & 0x0F) >> 0); 00155 00156 if (player == 0xA) 00157 PlayerString = PlayerAString; 00158 else if (player == 0xB) 00159 PlayerString = PlayerBString; 00160 else { 00161 uart.printf("Invalid Player\r\n"); 00162 return; 00163 } 00164 00165 switch (weapon) 00166 { 00167 case Rock: 00168 WeaponString = StrRock; 00169 break; 00170 case Paper: 00171 WeaponString = StrPaper; 00172 break; 00173 case Scissors: 00174 WeaponString = StrScissors; 00175 break; 00176 default: 00177 uart.printf("Invalid Weapon: 0x%d\r\n", weapon); 00178 return; 00179 } 00180 00181 uart.printf("%s: %s\r\n", PlayerString, WeaponString); 00182 } 00183 00184 void RockPaperScissors (uint8_t selection) 00185 { 00186 uint8_t player = ((selection & 0xF0) >> 4); 00187 uint8_t weapon = ((selection & 0x0F) >> 0); 00188 00189 switch (GameState) { 00190 case GameStateWaitingBoth: 00191 if (player == 0xA) { 00192 Aselection = weapon; 00193 GameState = GameStateWaitingB; 00194 uart.printf("Player A: Ready\r\n"); 00195 } 00196 if (player == 0xB) { 00197 Bselection = weapon; 00198 GameState = GameStateWaitingA; 00199 uart.printf("Player B: Ready\r\n"); 00200 } 00201 break; 00202 case GameStateWaitingA: 00203 if (player == 0xA) { 00204 Aselection = weapon; 00205 uart.printf("Player A: Ready\r\n"); 00206 GameState = GameStateReady; 00207 } 00208 break; 00209 case GameStateWaitingB: 00210 if (player == 0xB) { 00211 Bselection = weapon; 00212 uart.printf("Player B: Ready\r\n"); 00213 GameState = GameStateReady; 00214 } 00215 break; 00216 } 00217 00218 if (GameState == GameStateReady) 00219 { 00220 if (Aselection == Rock) 00221 { 00222 uart.printf("\nRock vs. "); 00223 if (Bselection == Rock) 00224 { 00225 uart.printf("Rock\r\n"); 00226 GameState = GameStateDraw; 00227 } 00228 if (Bselection == Paper) 00229 { 00230 uart.printf("Paper\r\n"); 00231 GameState = GameStateBWins; 00232 } 00233 if (Bselection == Scissors) 00234 { 00235 uart.printf("Scissors\r\n"); 00236 GameState = GameStateAWins; 00237 } 00238 } 00239 if (Aselection == Paper) 00240 { 00241 uart.printf("\nPaper vs. "); 00242 if (Bselection == Rock) 00243 { 00244 uart.printf("Rock\r\n"); 00245 GameState = GameStateAWins; 00246 } 00247 if (Bselection == Paper) 00248 { 00249 uart.printf("Paper\r\n"); 00250 GameState = GameStateDraw; 00251 } 00252 if (Bselection == Scissors) 00253 { 00254 uart.printf("Scissors\r\n"); 00255 GameState = GameStateBWins; 00256 } 00257 } 00258 if (Aselection == Scissors) 00259 { 00260 uart.printf("\nScissors vs. "); 00261 if (Bselection == Rock) 00262 { 00263 uart.printf("Rock\r\n"); 00264 GameState = GameStateBWins; 00265 } 00266 if (Bselection == Paper) 00267 { 00268 uart.printf("Paper\r\n"); 00269 GameState = GameStateAWins; 00270 } 00271 if (Bselection == Scissors) 00272 { 00273 uart.printf("Scissors\r\n"); 00274 GameState = GameStateDraw; 00275 } 00276 } 00277 } 00278 if (GameState == GameStateAWins) 00279 { 00280 uart.printf("Player A Wins!\r\n\n"); 00281 (void)uartBuf.addToBuffer(uint8_t(PlayerA | Winner)); 00282 ++NumWinsA; 00283 GameState = GameStateWaitingBoth; 00284 } 00285 if (GameState == GameStateBWins) 00286 { 00287 uart.printf("Player B Wins!\r\n\n"); 00288 (void)uartBuf.addToBuffer(uint8_t(PlayerB | Winner)); 00289 ++NumWinsB; 00290 GameState = GameStateWaitingBoth; 00291 } 00292 if (GameState == GameStateDraw) 00293 { 00294 uart.printf("It's a draw.\r\n\n"); 00295 (void)uartBuf.addToBuffer(uint8_t(Draw)); 00296 ++NumDraws; 00297 GameState = GameStateWaitingBoth; 00298 } 00299 if (GameState == GameStateWaitingBoth) 00300 { 00301 uart.printf("%s", LetsPlay); 00302 } 00303 if (uartBuf.getCount()) 00304 { 00305 gTaskEventFlags |= gWUSelf_EVENT_c; 00306 osSignalSet(EventsThreadID, 0x1); 00307 } 00308 } 00309 00310 void EventsThread(void const *argument) 00311 { 00312 EventsThreadID = Thread::gettid(); 00313 uint8_t rcvd = 0, c = 0; 00314 00315 while (true) 00316 { 00317 Thread::signal_wait(0x1); 00318 if(gMcps_Cnf_EVENT_c == (gTaskEventFlags & gMcps_Cnf_EVENT_c)) 00319 { 00320 MLMERXEnableRequest(gAppRxPacket, 0); 00321 } 00322 if(gMcps_Ind_EVENT_c == (gTaskEventFlags & gMcps_Ind_EVENT_c)) 00323 { 00324 rcvd = gAppRxPacket->smacPdu.smacPdu[0]; 00325 RockPaperScissors(rcvd); 00326 MLMERXEnableRequest(gAppRxPacket, 0); 00327 } 00328 if(gMlme_TimeoutInd_EVENT_c == (gTaskEventFlags & gMlme_TimeoutInd_EVENT_c)) 00329 { 00330 uart.printf("MlmeTimeoutInd: \r\n"); 00331 } 00332 if(gMlme_EdCnf_EVENT_c == (gTaskEventFlags & gMlme_EdCnf_EVENT_c)) 00333 { 00334 uart.printf("EdCnf: \r\n"); 00335 } 00336 if(gMlme_CcaCnf_EVENT_c == (gTaskEventFlags & gMlme_CcaCnf_EVENT_c)) 00337 { 00338 uart.printf("CcaCnf: \r\n"); 00339 } 00340 if(gWUSelf_EVENT_c == (gTaskEventFlags & gWUSelf_EVENT_c)) 00341 { 00342 if (buffer_Ok_c == uartBuf.getFromBuffer(&c)) 00343 { 00344 gAppTxPacket->smacPdu.smacPdu[0] = c; 00345 gAppTxPacket->u8DataLength = 1; 00346 (void)MLMERXDisableRequest(); 00347 (void)MCPSDataRequest(gAppTxPacket); 00348 } 00349 } 00350 gTaskEventFlags = 0; 00351 } 00352 } 00353 00354 int main() 00355 { 00356 MEM_Init(); 00357 Thread heartbeat(HeartbeatThread); 00358 Thread pushbuttons(PushbuttonThread); 00359 Thread events(EventsThread); 00360 Phy_Init(); 00361 InitSmac(); 00362 00363 //Tell SMAC who to call when it needs to pass a message to the application thread. 00364 Smac_RegisterSapHandlers((SMAC_APP_MCPS_SapHandler_t)smacToAppMcpsSap,(SMAC_APP_MLME_SapHandler_t)smacToAppMlmeSap,0); 00365 00366 InitApp(); 00367 00368 //uart.printf(StartupMessage); 00369 uart.printf("%s", LetsPlay); 00370 00371 while (true) 00372 { 00373 Thread::yield(); 00374 } 00375 } 00376 00377 void InitApp() 00378 { 00379 gAppTxPacket = (txPacket_t*)gau8TxDataBuffer; //Map TX packet to buffer 00380 gAppRxPacket = (rxPacket_t*)MEM_BufferAlloc(gMaxSmacSDULength_c + sizeof(rxPacket_t)); 00381 00382 InitProject(); 00383 00384 SMACFillHeader(&(gAppTxPacket->smacHeader), gDefaultAddress_c); 00385 00386 (void)MLMEPAOutputAdjust(gDefaultOutputPower_c); 00387 (void)MLMESetChannelRequest(gDefaultChannelNumber_c); 00388 (void)MLMEConfigureTxContext(&txConfigContext); 00389 //AppDelayTmr = TMR_AllocateTimer(); 00390 gAppRxPacket->u8MaxDataLength = gMaxSmacSDULength_c; 00391 (void)MLMERXEnableRequest(gAppRxPacket, 0); 00392 } 00393 00394 /* (Management) Sap handler for managing timeout indication and ED confirm 00395 This is running in INTERRUPT context, so need to send messages to one of the task */ 00396 smacErrors_t smacToAppMlmeSap(smacToAppMlmeMessage_t* pMsg, instanceId_t instance) 00397 { 00398 switch(pMsg->msgType) 00399 { 00400 case gMlmeEdCnf_c: 00401 gTaskEventFlags |= gMlme_EdCnf_EVENT_c; 00402 break; 00403 case gMlmeCcaCnf_c: 00404 gTaskEventFlags |= gMlme_CcaCnf_EVENT_c; 00405 break; 00406 case gMlmeTimeoutInd_c: 00407 gTaskEventFlags |= gMlme_TimeoutInd_EVENT_c; 00408 break; 00409 default: 00410 break; 00411 } 00412 osSignalSet(EventsThreadID, 0x1); 00413 MEM_BufferFree(pMsg); 00414 return gErrorNoError_c; 00415 } 00416 00417 /* (Data) Sap handler for managing data confirm and data indication 00418 This is running in INTERRUPT context, so need to send messages to one of the task */ 00419 smacErrors_t smacToAppMcpsSap(smacToAppDataMessage_t* pMsg, instanceId_t instance) 00420 { 00421 switch(pMsg->msgType) 00422 { 00423 case gMcpsDataInd_c: 00424 if(pMsg->msgData.dataInd.pRxPacket->rxStatus == rxSuccessStatus_c) 00425 { 00426 gTaskEventFlags |= gMcps_Ind_EVENT_c; 00427 } 00428 break; 00429 00430 case gMcpsDataCnf_c: 00431 #ifdef VERBOSE 00432 if(pMsg->msgData.dataCnf.status == gErrorChannelBusy_c) 00433 { 00434 bCCAFailed = TRUE; 00435 } 00436 00437 if(pMsg->msgData.dataCnf.status == gErrorNoAck_c) 00438 { 00439 bACKFailed = TRUE; 00440 } 00441 #endif 00442 gTaskEventFlags |= gMcps_Cnf_EVENT_c; 00443 break; 00444 default: 00445 break; 00446 } 00447 osSignalSet(EventsThreadID, 0x1); 00448 MEM_BufferFree(pMsg); 00449 00450 return gErrorNoError_c; 00451 } 00452 00453 void InitProject(void) 00454 { 00455 /*Global Data init*/ 00456 #ifdef VERBOSE 00457 bACKFailed = FALSE; 00458 bCCAFailed = FALSE; 00459 #endif 00460 00461 gTaskEventFlags = 0; 00462 00463 txConfigContext.autoAck = FALSE; 00464 txConfigContext.ccaBeforeTx = FALSE; 00465 txConfigContext.retryCountAckFail = 0; 00466 txConfigContext.retryCountCCAFail = 0; 00467 00468 /* Setup UART */ 00469 uart.baud(gDefaultBaudRate_UART_c); 00470 00471 /* Setup Pushbutton Interrupt Callbacks */ 00472 k64f_sw2.fall(&k64f_sw2_press); 00473 k64f_sw3.fall(&k64f_sw3_press); 00474 cr20a_sw1.fall(&cr20a_sw1_press); 00475 cr20a_sw2.fall(&cr20a_sw2_press); 00476 cr20a_sw3.fall(&cr20a_sw3_press); 00477 }
Generated on Thu Jul 14 2022 12:33:50 by 1.7.2