Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: fsl_phy_mcr20a fsl_smac mbed-rtos mbed
Fork of mcr20_RPS_GameController by
Diff: main.cpp
- 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);
+}
