Rock, Paper, Scissors game - remote controller

Dependencies:   fsl_phy_mcr20a fsl_smac mbed-rtos mbed

Fork of mcr20_RPS_GameController by Freescale

Revision:
0:7654345263e0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Nov 17 17:15:28 2015 +0000
@@ -0,0 +1,363 @@
+#include "mbed.h"
+#include "rtos.h"
+#include "Phy.h"
+#include "SMAC_Interface.h"
+#include "SMAC_Config.h"
+#include "MemManager.h"
+#include "circular_buffer.h"
+
+/* 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<<0)
+#define gPushbutton_K64F_SW3    (1<<1)
+#define gPushbutton_CR20A_SW1   (1<<2)
+#define gPushbutton_CR20A_SW2   (1<<3)
+#define gPushbutton_CR20A_SW3   (1<<4)
+
+#define gResultWin              (1<<0)
+#define gResultLose             (1<<1)
+#define gResultDraw             (1<<2)
+
+/* 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 ResultThreadID;
+osThreadId EventsThreadID;
+osThreadId MainThreadID;
+
+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); }
+
+void HeartbeatThread(void const *argument)
+{
+    while (true) {
+        k64f_led_green = LED_ON;
+        Thread::wait(50);
+        k64f_led_green = LED_OFF;
+        Thread::wait(1950);
+    }
+}
+
+void ResultThread(void const *argument)
+{
+    ResultThreadID = Thread::gettid();
+    osEvent event;
+    DigitalOut *led;
+    
+    while (true) {
+        event = Thread::signal_wait(0, osWaitForever);
+        if (event.value.signals & gResultWin) {
+            led = &cr20a_led_green;
+        }
+        else if (event.value.signals & gResultDraw) {
+            led = &cr20a_led_blue;
+        }
+        else {
+            led = &cr20a_led_red;
+        }
+        *led = LED_ON;
+        Thread::wait(200);
+        *led = LED_OFF;
+        Thread::wait(200);
+        *led = LED_ON;
+        Thread::wait(200);
+        *led = LED_OFF;
+        Thread::wait(200);
+        *led = LED_ON;
+        Thread::wait(200);
+        *led = LED_OFF;
+        Thread::wait(200);
+        *led = LED_ON;
+        Thread::wait(200);
+        *led = LED_OFF;
+        Thread::wait(200);
+        *led = LED_ON;
+        Thread::wait(200);
+        *led = LED_OFF;
+        Thread::wait(200);
+        *led = LED_ON;
+        Thread::wait(200);
+        *led = LED_OFF;
+    }
+}
+
+/* Constants used to build the single byte game selection and results */
+char const PlayerA  = 0xA0;
+char const PlayerB  = 0xB0;
+char const Player   = PlayerB;
+char const Rock     = 0x01;
+char const Paper    = 0x02;
+char const Scissors = 0x03;
+char const Winner   = 0x08;
+char const Loser    = 0x0F;
+char const Draw     = 0xFF;
+
+void PushbuttonThread(void const *argument)
+{
+    PushbuttonThreadID = Thread::gettid();
+    osEvent event;
+
+    while (true) {
+        event = Thread::signal_wait(0, osWaitForever);
+        if (event.value.signals & gPushbutton_CR20A_SW1) {
+            (void)uartBuf.addToBuffer(uint8_t(Player | Rock));
+        }
+        if (event.value.signals & gPushbutton_CR20A_SW2) {
+            (void)uartBuf.addToBuffer(uint8_t(Player | Paper));     
+        }
+        if (event.value.signals & gPushbutton_CR20A_SW3) {
+            (void)uartBuf.addToBuffer(uint8_t(Player | Scissors));      
+        }
+        if (uartBuf.getCount())
+        {
+            gTaskEventFlags |= gWUSelf_EVENT_c;
+            osSignalSet(EventsThreadID, 0x1);
+        }
+        
+        Thread::wait(500);
+        osSignalClear(PushbuttonThreadID, 0xFF);
+    }
+}
+
+void CheckReceivedData (uint8_t data)
+{
+    uint8_t player = (data & 0xF0);
+    uint8_t result = (data & 0x0F);
+    
+    if (result == Winner) {
+        if (player == Player)
+            osSignalSet(ResultThreadID, gResultWin);
+        else
+            osSignalSet(ResultThreadID, gResultLose);
+    }
+    if (data == Draw) 
+        osSignalSet(ResultThreadID, gResultDraw);
+}
+
+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];
+            //uart.printf("%c", rcvd);
+            CheckReceivedData(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();
+    
+    /* Init the threads */
+    Thread heartbeat(HeartbeatThread);
+    Thread pushbuttons(PushbuttonThread);
+    Thread events(EventsThread);
+    Thread result(ResultThread);
+    MainThreadID = Thread::gettid();
+
+    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();
+
+    if (Player == 0xA0)
+        uart.printf("Player A is online\r\n");
+    else
+        uart.printf("Player B is online\r\n");
+
+    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);
+}