![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Fork to see if I can get working
Dependencies: BufferedSerial OneWire WinbondSPIFlash libxDot-dev-mbed5-deprecated
Fork of xDotBridge_update_test20180823 by
xDotBridge/src/SerialTermMgr.cpp
- Committer:
- mbriggs_vortex
- Date:
- 2017-11-21
- Revision:
- 93:f3adc409c54e
- Parent:
- 92:1f86edb14cbe
- Child:
- 94:8028c07f71fa
File content as of revision 93:f3adc409c54e:
/* * SerialTermMgr.cpp * * Created on: May 8, 2017 * Author: mbriggs */ #include "SerialTermMgr.h" #include "UserInterface.h" extern Serial pc; const char ACK = 0x06; const char NAK = 0x15; const char SOH = 0x01; const char EOT = 0x04; const char SUB = 0x1A; SerialTermMgr::SerialTermMgr(BaseboardIO *bbio, WinbondSPIFlash *flash, float fwVersion) { mPc = NULL; mFwVersion = fwVersion; mCurrScreen = mainScreenId; mBbio = bbio; mFlash = flash; } void SerialTermMgr::printScreen() { switch (mCurrScreen) { case mainScreenId: printMainScreen(); break; case genInfoScreenId: printGenInfo(); break; case settingsScreenId: case statsScreenId: case errorLogScreenId: case liveLogScreenId: case enterSerialBridgeScreenId: printMainScreen(); break; case enterProgModeScreenId: printEnterProgMode(); } } bool SerialTermMgr::input() { if (mPc == NULL) { return true; } bool quit = false; char c = 10; if (mPc->readable()) { c = mPc->getc(); } else { return false; // Do nothing if there is no input } switch (mCurrScreen) { case mainScreenId: quit = inputMainPage(c); break; case genInfoScreenId: inputGenInfo(c); break; case settingsScreenId: case statsScreenId: case errorLogScreenId: case liveLogScreenId: case enterSerialBridgeScreenId: inputMainPage(c); break; case enterProgModeScreenId: inputEnterProgMode(c); } return quit; } // private methods bool SerialTermMgr::inputMainPage (char in) { bool quit = false; switch (in) { case '1': mCurrScreen = genInfoScreenId; break; case '2': mCurrScreen = enterProgModeScreenId; break; case '3': mPc->printf("\r\nNot implemented yet.\r\n"); // mCurrScreen = settingsScreenId; break; // Future // case '4': // mPc->printf("\r\nNot implemented yet.\r\n"); //// mCurrScreen = statsScreenId; // break; // case '5': // mPc->printf("\r\nNot implemented yet.\r\n"); //// mCurrScreen = errorLogScreenId; // break; // case '6': // mPc->printf("\r\nNot implemented yet.\r\n"); //// mCurrScreen = liveLogScreenId; // break; // case '7': // mPc->printf("\r\nNot implemented yet.\r\n"); //// mCurrScreen = enterSerialBridgeScreenId; // break; case 0x11: // ctrl-q quit=true; break; default: mCurrScreen = mainScreenId; } if (!quit) { printScreen(); } return quit; } void SerialTermMgr::printMainScreen() { if (mPc == NULL) { return; } mPc->printf("\r\n\r\n"); mPc->printf("===============================================\r\n"); mPc->printf("= Wireless Bridge Terminal (Firmware: v%0.2f) =\r\n", mFwVersion); mPc->printf("===============================================\r\n"); mPc->printf("===============================================\r\n"); mPc->printf("= Selection Options =\r\n"); mPc->printf("===============================================\r\n"); mPc->printf("= 0: Refresh (Enter and space also work) =\r\n"); mPc->printf("= 1: General information =\r\n"); mPc->printf("= 2: Enter programming mode =\r\n"); mPc->printf("= 3: Settings =\r\n"); // Future // mPc->printf("= 4: Statistics =\r\n"); // mPc->printf("= 5: Error log =\r\n"); // mPc->printf("= 6: Live log =\r\n"); // mPc->printf("= 7: Enter serial bridge mode =\r\n"); mPc->printf("= <ctrl>-q: Exit terminal =\r\n"); mPc->printf("===============================================\r\n"); } void SerialTermMgr::inputGenInfo (char in) { if (mPc == NULL) { return; } switch (in) { case 0x1B: // esc mCurrScreen = mainScreenId; break; case 'r': mBbio->sampleUserSwitches(); mPc->printf("User switches sampled.\r\n"); break; default: mPc->printf("Invalid key.\r\n"); } printScreen(); } void SerialTermMgr::printGenInfo() { if (mPc == NULL) { return; } mPc->printf("\r\n\r\n"); mPc->printf("===============================================\r\n"); mPc->printf("= General Info (ESC to return to main menu) =\r\n", mFwVersion); mPc->printf("===============================================\r\n"); mPc->printf("= Press r to sample user switch values =\r\n"); // FIXME mPc->printf("===============================================\r\n"); mPc->printf("===============================================\r\n"); mPc->printf("= Firmware version: v%0.2f =\r\n", mFwVersion); //TODO // mPc->printf("= Radio EUI: %s =\r\n", mts::Text::bin2hexString(dot->getDeviceId()).c_str()); mPc->printf("= Contact closure: %s =\r\n", mBbio->isCCNO() ? "Normally open " : "Normally closed"); mPc->printf("= WB Mode: %s =\r\n", mBbio->isTx() ? "Transmitter" : "Receiver "); // mPc->printf("= Comm Mode: %s =\r\n", mBbio->isLoRaWANMode() ? "LoRaWAN " : // "Peer-to-peer"); // mPc->printf("= Serial Mode: %s =\r\n", mBbio->isSerialEnabled() ? "Enabled " : // "Disabled"); if (mBbio->isTx()) { mPc->printf("= Currently no rotary switches apply for TX =\r\n"); } else { mPc->printf("= Rotary 1 hold setting is %0.1f seconds =\r\n", HoldTimeSetting::rotVal2Sec(mBbio->rotarySwitch1())); mPc->printf("= Rotary 2 currently does not apply for RX =\r\n"); } mPc->printf("===============================================\r\n"); } void SerialTermMgr::printEnterProgMode() { if (mPc == NULL) { return; } mPc->printf("\r\n\r\n"); mPc->printf("===============================================\r\n"); mPc->printf("= Serial Firmware Prog Mode (Esc to return) =\r\n"); mPc->printf("===============================================\r\n"); mPc->printf("===============================================\r\n"); mPc->printf("= To program firmware: \r\n"); mPc->printf("= 1: Have bin file ready =\r\n"); mPc->printf("= 2: Hit <ctrl>-d to enter XMODEM mode =\r\n"); mPc->printf("= 3: In terminal program (such as teraterm) =\r\n"); mPc->printf("= select transfer via XMODEM =\r\n"); mPc->printf("= 4: Programming may take up to a minute =\r\n"); mPc->printf("= 5: If successful terminal prints \"Success\" =\r\n"); mPc->printf("= 6: Wireless Bridge will then automatically =\r\n"); mPc->printf("= reboot with new firmware. =\r\n"); mPc->printf("===============================================\r\n"); } void SerialTermMgr::inputEnterProgMode (char in) { if (mPc == NULL) { return; } switch (in) { case 0x1B: // esc: mCurrScreen = mainScreenId; break; case 0x04: xmodem2Flash(); break; default: mPc->printf("Invalid key.\r\n"); } printScreen(); } bool SerialTermMgr::xmodem2Flash () { mPc->printf("Ready to receive file\r\n"); mFlash->releaseFromPowerDown(); mFlash->chipErase(); char packetBuf[132]; uint16_t packetNum = 1; uint8_t csum = 0; unsigned char pktIdx = 0; time_t lastValidInput = 0; unsigned char nTimeouts = 0; while (1) { // Send a NAK if a packet is not received within timeout period if ((time(NULL)-lastValidInput) > XMODEM_TIMEOUT){ pc.printf("Total chars: %d\r\n", pktIdx); pktIdx = 0; mPc->printf("%c", NAK); // Send NAK lastValidInput = time(NULL); nTimeouts++; if (nTimeouts >= MAX_TIMEOUTS) { mPc->printf("Programming timed out.\r\n"); pc.printf("Programming timed out.\r\n"); break; } } if (mPc->readable()) { packetBuf[pktIdx++] = mPc->getc(); if (pktIdx == 1 && packetBuf[0] == EOT) { lastValidInput = time(NULL); mPc->printf("%c", ACK); // Last ACK // Check for update string in last packet bool foundKey; for (int packetIdx=3;packetIdx<sizeof(packetBuf)-sizeof(VORTEX_UPDATE_KEY)-1;packetIdx++) { foundKey = true; for (int i=0;i<sizeof(VORTEX_UPDATE_KEY)-1;i++) { if (packetBuf[packetIdx+i] != VORTEX_UPDATE_KEY[i]) { foundKey = false; break; } } if (foundKey) { break; } } if (foundKey) { mPc->printf("Success.\r\n"); pc.printf("Success on xmodem. Reset in progress.\r\n"); writeBootloaderCtrlPage(packetNum*XMODEM_PACKET_SIZE); } else { mPc->printf("Failed update key validation.\r\n"); pc.printf("Failed update key validation\r\n"); } wait(0.01); mFlash->powerDown(); if (foundKey) { NVIC_SystemReset(); } break; } else if (pktIdx >= 132) { lastValidInput = time(NULL); nTimeouts = 0; // Clear n timeouts with new packet csum = 0; for (int i=3; i<131; i++) { csum += packetBuf[i]; } pktIdx = 0; if ((csum == packetBuf[131]) && (packetBuf[0] == SOH) && (packetBuf[1] == ((uint8_t)packetNum)) && (((uint8_t)~packetBuf[2]) == ((uint8_t)packetNum))) { mFlash->writeStream(FLASH_BIN_OFFSET+(packetNum-1)*XMODEM_PACKET_SIZE, packetBuf+3, XMODEM_PACKET_SIZE); mPc->printf("%c", ACK); packetNum++; } else { mPc->printf("%c", NAK); } } } } mCurrScreen = mainScreenId; // Just return to main screen for now mFlash->powerDown(); return true; } void SerialTermMgr::writeBootloaderCtrlPage(uint32_t nBytes) { // This should always be less than 256 bytes // Zero updates the bootloader version so that is cleared until the bootloader adds its back const uint32_t zeroBootloaderVersion = 0; const unsigned int ctrlSize = sizeof(NEW_CODE)+sizeof(nBytes)+sizeof(zeroBootloaderVersion); char buf[ctrlSize]; std::memcpy(buf, NEW_CODE, sizeof(NEW_CODE)); std::memcpy(buf+sizeof(NEW_CODE), &nBytes, sizeof(nBytes)); std::memcpy(buf+sizeof(NEW_CODE)+sizeof(nBytes), &zeroBootloaderVersion, sizeof(zeroBootloaderVersion)); // TODO add reprogram counter or other functions // Copy to first page of flash mFlash->writeStream(0, buf, sizeof(buf)); }