// BBC micro:bit code pfodMenu.h and pfodMenu.cpp for Netbeans // This cpp code needs pfodParserMicroBit support files from www.pfod.com.au // copy this code into pfodMenu.h // ============= start of pfodMenu.h file ============= /* ===== pfod Command for Menu_1 ==== pfodApp msg {.} --> {,<+6>~BBC micro:bit`1000~V1|!C~|!A<+5>`775~P0 ~V`1023`0~3.3~0~|!D~|B<+6>`0~P1 is ~~Off\On~} */ /* * File: pfodMenu.h for BBC micro:bit */ /* Code generated by pfodDesignerV2 V2.0.2211 * (c)2014-2016 Forward Computing and Control Pty. Ltd. * NSW Australia, www.forward.com.au * This code is not warranted to be fit for any purpose. You may only use it at your own risk. * This generated code may be freely used for both private and commercial use * Provide this copyright is maintained. */ #ifndef PFODMENU_H #define PFODMENU_H #include #include "pfodParser.h" #include "MicroBit.h" class pfodMenu : pfodParser { public: // public vars set by parser, access and update these in your main program int cmd_A_var; // name the variable for 'P0' int cmd_B_var; // name the variable for 'P1 is' 0=Off 1=On unsigned long plotTime; // used in sendData in main.cpp and below void sendData(void); // This method is call automatically if plotInterval > 0 You can also call it from your own fiber bool isConnected(void); // set true when {.} parsed, set false when {!} parsed. pfodMenu(void); void init(MicroBit* _uBit); private: void sendMainMenu(); void sendMainMenuUpdate(); static const int maxRxMsgSize; //max size of pfodCmd ALWAYS <= 255 static const unsigned long plotInterval; // used to sendData in main.cpp void initGlobalVars(void); void createStream(); void processCmd(); static void fiber_SendData(void); static void pfodAppDisconnected(MicroBitEvent); static void pfodProcessRx(MicroBitEvent); static const char *vers; // the menu version no static pfodMenu* menuParserPtr; }; #endif /* PFODMENU_H */ // =============== end of pfodMenu.h file ================ // copy this code into pfodMenu.cpp // ============= start of pfodMenu.cpp file ============= /* ===== pfod Command for Menu_1 ==== pfodApp msg {.} --> {,<+6>~BBC micro:bit`1000~V1|!C~|!A<+5>`775~P0 ~V`1023`0~3.3~0~|!D~|B<+6>`0~P1 is ~~Off\On~} */ /* * File: pfodMenu.cpp */ /* Code generated by pfodDesignerV2 V2.0.2211 * (c)2014-2016 Forward Computing and Control Pty. Ltd. * NSW Australia, www.forward.com.au * This code is not warranted to be fit for any purpose. You may only use it at your own risk. * This generated code may be freely used for both private and commercial use * Provide this copyright is maintained. */ #include "pfodMenu.h" #include "pfodBleUart.h" #include "pfodParserStream.h" #include "pfodSerialUart.h" #include "pfodParser.h" const char *pfodMenu::vers = "V1"; // change this if you edit the sendMenu.. methods const unsigned long pfodMenu::plotInterval = 0; // mS interval to send data const int pfodMenu::maxRxMsgSize = 17; // pfodDesignerV2 sets this value to suit the possible pfodApp command sizes. // increase this if pfodApp is sending back text or multi-selection lists. // NOTE: carefully pfodMenu::maxRxMsgSize must be set greater than the max message length sent from pfodApp. // If in doubt set to 255. pfodApp NEVER sends a command longer than 255 /** * set initial values for pfod variables */ void pfodMenu::initGlobalVars() { plotTime = uBitPtr->systemTime(); cmd_A_var = uBitPtr->io.P0.getAnalogValue(); cmd_B_var = 0; uBitPtr->io.P1.setDigitalValue(cmd_B_var); } /** * Process cmd from pfodApp * This is called after a full command from pfodApp has been parsed */ void pfodMenu::processCmd() { uint8_t cmd = *getCmd(); // pick up cmd from parser if (cmd != 0) { // have parsed a complete msg { to } if ((cmd != '!') && !isConnected()) { connect(); // set this true first to enable parser prints } uint8_t* pfodFirstArg = getFirstArg(); // may point to \0 if no arguments in this msg. UNUSED(pfodFirstArg); long pfodLongRtn; // used for parsing long return arguments, if any UNUSED(pfodLongRtn); // read inputs, if any, for menu update; cmd_A_var = uBitPtr->io.P0.getAnalogValue(); if ('.' == cmd) { // pfodApp has connected and sent {.} , it is asking for the main menu if (!isRefresh()) { sendMainMenu(); // send back the menu designed } else { sendMainMenuUpdate(); // menu is cached just send update } // now handle commands returned from button/sliders // } else if('C'==cmd) { // this is a label. pfodApp NEVER sends this cmd -- '' // // in the main Menu of Menu_1 // } else if('A'==cmd) { // this is a label. pfodApp NEVER sends this cmd -- 'P0' // // in the main Menu of Menu_1 // } else if('D'==cmd) { // this is a label. pfodApp NEVER sends this cmd -- '' // // in the main Menu of Menu_1 } else if('B'==cmd) { // user moved slider -- 'P1 is' // in the main Menu of Menu_1 // set output based on slider 0=Off 1=On parseLong(pfodFirstArg,&pfodLongRtn); // parse first arg as a long cmd_B_var = (int)pfodLongRtn; // set variable uBitPtr->io.P1.setDigitalValue(cmd_B_var); // set output sendMainMenuUpdate(); // always send back a pfod msg otherwise pfodApp will disconnect. } else if ('!' == cmd) { // CloseConnection command closeConnection(); // = false; } else { // unknown command print("{}"); // always send back a pfod msg otherwise pfodApp will disconnect. } } } void pfodMenu::sendMainMenu(void) { // !! Remember to change the parser version string // every time you edit this method print("{,"); // start a Menu screen pfod message // send menu background, format, prompt, refresh and version print("<+6>~BBC micro:bit`1000"); sendVersion(); // send the menu version // send menu items print("|!C"); print("~"); print("|!A<+5>"); print('`'); print(cmd_A_var); // output the current ADC reading print("~P0 ~V`1023`0~3.3~0~"); print("|!D"); print("~"); print("|B<+6>"); print('`'); print(cmd_B_var); // output the current state 0 Low or 1 High print("~P1 is ~~Off\\On~"); // Note the \\ inside the "'s to send \ ... print("}"); // close pfod message } void pfodMenu::sendMainMenuUpdate(void) { print("{;"); // start an Update Menu pfod message // send menu items print("|A"); print('`'); print(cmd_A_var); // output the current ADC reading print("|B"); print('`'); print(cmd_B_var); // output the current state 0 Low or 1 High print("}"); // close pfod message // ============ end of menu =========== } /** * Send global plot/data variables * This method is call automatically if plotInterval > 0 * You can also call it from your own fibers. */ void pfodMenu::sendData() { if (!isConnected()) return; // don't send data if not connected waitForParserStreamLock(); // wait for parser print lock to be free // ---- send data - plotTime = uBitPtr->systemTime(); print(plotTime/1000.0); // print(','); print(plot_n_var); // Add extra lines here to send more data println(); // end of CSV data record // ---- end send data unlockParserStream(); // must call this at end to release lock } // ==================SUPPORT METHODS ========================= // ========= !!! Do NOT Change these methods !!! ============ pfodMenu* pfodMenu::menuParserPtr; // for event handlers void pfodMenu::createStream() { pfodParserStream *stream = new pfodBleUart(*(uBitPtr->ble), pfodMaxMsgLen); //pfodMaxMsgLen is maxRxMsgSize limited to <=255 if (stream->init() != 0) { // initialize/check buffers uBitPtr->panic(MICROBIT_OOM); //out of memory } if (stream->isBle()) { // add a listener for disconnect uBitPtr->messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, pfodAppDisconnected); } setStream(stream); // set stream in parser } void pfodMenu::init(MicroBit *_uBitPtr) { pfodParser::init(_uBitPtr,vers,maxRxMsgSize); // this sets uBitPtr var initGlobalVars(); createStream(); uBitPtr->messageBus.listen(PFOD_ID_UART, PFOD_UART_EVT_DATA_AVAILABLE, pfodProcessRx); if (plotInterval > 0) { create_fiber(fiber_SendData); // create fiber and start it to send data at regular intervals } } void pfodMenu::fiber_SendData() { unsigned long dataTime = menuParserPtr->uBitPtr->systemTime(); while (plotInterval) { // loop for ever if plotInterval > 0 menuParserPtr->sendData(); // send the data unsigned long sysTime = menuParserPtr->uBitPtr->systemTime(); if ((sysTime - dataTime) <= plotInterval) { menuParserPtr->uBitPtr->sleep(plotInterval - (sysTime - dataTime)); } else { // else already passed time for next send data // just loop menuParserPtr->uBitPtr->sleep(0); // sleep to give other fibers a change to run } dataTime += plotInterval; // ignores delay in waking from sleep } } pfodMenu::pfodMenu() : pfodParser() { menuParserPtr = this; } /** * Called when there is new UART data. Parses pfod commands and sends response */ void pfodMenu::pfodProcessRx(MicroBitEvent) { menuParserPtr->parseCmd(); // parse input from uart instance } /* * onDisconnected used with Bluetooth UART */ void pfodMenu::pfodAppDisconnected(MicroBitEvent) { menuParserPtr->closeConnection(); // stop sending and clear buffers menuParserPtr->setCmd((uint8_t) '!'); menuParserPtr->uBitPtr->sleep(0); // put on end of fiber queue menuParserPtr->processCmd(); // process the ! cmd incase pfodApp died or when outOfRange } bool pfodMenu::isConnected() { return pfodParser::isConnected(); // from parser } // =============== end of pfodMenu.cpp file ================