Rock, Paper, Scissors game coordinator

Dependencies:   fsl_phy_mcr20a fsl_smac mbed-rtos mbed

Fork of mcr20_RPS_Coordinator by Freescale

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }