Fork to see if I can get working

Dependencies:   BufferedSerial OneWire WinbondSPIFlash libxDot-dev-mbed5-deprecated

Fork of xDotBridge_update_test20180823 by Matt Briggs

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers BaseboardIO.cpp Source File

BaseboardIO.cpp

00001 /*
00002  * baseboardIO.cpp
00003  *
00004  *  Created on: Jan 25, 2017
00005  *      Author: mbriggs
00006  */
00007 
00008 #include "BaseboardIO.h"
00009 #include "dot_util.h" // XXX just need the reference to dot somehow
00010 #include "xdot_low_power.h"
00011 #include "MyLog.h"
00012 
00013 // Original
00014 //const float COIL_ON_TIME = 0.030; // 30 ms
00015 // Test
00016 const float COIL_ON_TIME = 0.300; // 300 ms
00017 
00018 
00019 // Port expander 0 (Currently U7)
00020 const uint8_t pEx0232En     = 0x01;
00021 const uint8_t pEx0232TxDis  = 0x02;
00022 const uint8_t pEx0Rot1B1    = 0x04;
00023 const uint8_t pEx0Rot1B2    = 0x08;
00024 const uint8_t pEx0Rot1B4    = 0x10;
00025 const uint8_t pEx0Rot1B8    = 0x20;
00026 const uint8_t pEx0Rot2B1    = 0x40;
00027 const uint8_t pEx0Rot2B2    = 0x80;
00028 const uint8_t pEx0OutMask   = 0x03; // Only allow bits 0,1 to be changed
00029 
00030 // Port expander 1 (Currently U8)
00031 const uint8_t pEx1NoNcSel   = 0x01;
00032 const uint8_t pEx1RxTxSel   = 0x02;
00033 const uint8_t pEx1WanSel    = 0x04;
00034 const uint8_t pEx1SerialEn  = 0x08; // Labeled as reserved
00035 const uint8_t pEx1Rot2B8    = 0x10;
00036 const uint8_t pEx1Rot2B4    = 0x20;
00037 const uint8_t pEx1RlyB      = 0x40; // This is actually a coil
00038 const uint8_t pEx1RlyA      = 0x80; // This is actually a coil
00039 const uint8_t pEx1OutMask   = 0xC0; // Only allow bits 6,7 to be changed
00040 
00041 /**
00042  * Note for interrupt within uC cannot use two pins with the same numeric suffix (e.g. cannot
00043  * use both PA_0 and PB_0).  Note 1, 6, 7, 8, and 13 are used by LoRa radio.
00044  */
00045 
00046 BaseboardIO::BaseboardIO()
00047     : mOWMaster(OneWireMasterPinName),
00048       mCCIn(CCInPinName),
00049       mTamper(TamperPinName),
00050       mPairBtn(PairBtnPinName),
00051       mLed(LedPinName),
00052       mLrrLed(LrrLedPinName, 0),
00053       mSwitchedIOCtrl(SwitchedIOCtrlPinName, 0)
00054 {
00055     mPortExpanderVal0 = 0x00;
00056     mPortExpanderVal1 = 0x00;
00057 
00058     mPortEx0 = NULL;
00059     mPortEx1 = NULL;
00060 }
00061 CmdResult BaseboardIO::init(bool overwriteNvm)
00062 {
00063     bool storedROMsGood = false;
00064     uint8_t val;
00065     // Setup port expanders
00066     if (readInfoFromNVM() == cmdSuccess && !overwriteNvm) {
00067         myLogInfo("Stored ROM0 Addr: %02x:%02x:%02x:%02x:%02x:%02x:%02x%02x found.",
00068                    mNvmObj.mPortExpanderROM0[7],
00069                    mNvmObj.mPortExpanderROM0[6],
00070                    mNvmObj.mPortExpanderROM0[5],
00071                    mNvmObj.mPortExpanderROM0[4],
00072                    mNvmObj.mPortExpanderROM0[3],
00073                    mNvmObj.mPortExpanderROM0[2],
00074                    mNvmObj.mPortExpanderROM0[1],
00075                    mNvmObj.mPortExpanderROM0[0]);
00076         myLogInfo("Stored ROM1 Addr: %02x:%02x:%02x:%02x:%02x:%02x:%02x%02x found.",
00077                    mNvmObj.mPortExpanderROM1[7],
00078                    mNvmObj.mPortExpanderROM1[6],
00079                    mNvmObj.mPortExpanderROM1[5],
00080                    mNvmObj.mPortExpanderROM1[4],
00081                    mNvmObj.mPortExpanderROM1[3],
00082                    mNvmObj.mPortExpanderROM1[2],
00083                    mNvmObj.mPortExpanderROM1[1],
00084                    mNvmObj.mPortExpanderROM1[0]);
00085         myLogInfo("BaseboardIO parameters successfully loaded from NVM");
00086         // Check that the ROM Addresses are correct and valid
00087         uint8_t portEx0Ctrl, portEx1Ctrl;
00088         mPortEx0 = new DS2408(&mOWMaster, mNvmObj.mPortExpanderROM0);
00089         mPortEx0->registerReadReliable(0x8D, portEx0Ctrl);
00090         // Gets 0xFF if it is not the correct address
00091         myLogInfo("PortEx0 Control register reads %02X", portEx0Ctrl);
00092 
00093         mPortEx1 = new DS2408(&mOWMaster, mNvmObj.mPortExpanderROM1);
00094         mPortEx1->registerReadReliable(0x8D, portEx1Ctrl);
00095         myLogInfo("PortEx1 Control register reads %02X", portEx1Ctrl);
00096         if ((portEx0Ctrl == 0xFF) || (portEx1Ctrl == 0xFF)) {
00097             myLogError("Stored port expander ROM check failed.  Set EEPROM to defaults.");
00098         }
00099         else {
00100             storedROMsGood = true;
00101         }
00102     }
00103     if (!storedROMsGood)
00104     { // EEPROM values not there or corrupt.  Should only happen in factory.
00105         mNvmObj.setDefaults();
00106         // Find ROM address and test which one is which.  Requires user
00107         // switches to be in known state.
00108         if (identifyPortExpanders() != cmdSuccess) {
00109             myLogError("Error identifying port expanders");
00110             return cmdError;
00111         }
00112         if (writeInfoToNVM() == cmdSuccess) {
00113             myLogInfo("Baseboard config saved to NVM");
00114         }
00115         else {
00116             myLogError("Baseboard config failed to save to NVM");
00117         }
00118         mPortEx0 = new DS2408(&mOWMaster, mNvmObj.mPortExpanderROM0);
00119         mPortEx0->registerReadReliable(0x8D, val);
00120         // Gets 0xFF if it is not the correct address
00121         myLogInfo("PortEx0 Control register reads %02X", val);
00122         mPortEx1 = new DS2408(&mOWMaster, mNvmObj.mPortExpanderROM1);
00123         mPortEx1->registerReadReliable(0x8D, val);
00124         myLogInfo("PortEx1 Control register reads %02X", val);
00125     }
00126 
00127     if (sampleUserSwitches() != cmdSuccess) {
00128         myLogError("Error sampling user switches");
00129         return cmdError;
00130     }
00131 
00132     // Put relay in known state
00133     if (relayNormal() != cmdSuccess) {
00134         myLogError("Error setting relay during init");
00135         return cmdError;
00136     }
00137     ledOff();
00138 
00139     myLogInfo("Baseboard IO initialization successful");
00140     return cmdSuccess;
00141 }
00142 
00143 // Registering for interrupts
00144 void BaseboardIO::regCCInInt(Callback<void()> func)
00145 {
00146     if (isCCNO()) {
00147         // Pulled high, switched low
00148         mCCIn.fall(func);
00149     }
00150     else {
00151         mCCIn.rise(func);
00152     }
00153     mCCIn.mode(PullNone);
00154     mCCIn.enable_irq();
00155 }
00156 void BaseboardIO::regTamperInt(Callback<void()> func)
00157 {
00158     // Pulled high, switched low
00159     mTamper.mode(PullNone);
00160     mTamper.rise(func);
00161     mTamper.fall(func);
00162     mTamper.enable_irq();
00163 }
00164 void BaseboardIO::regPairBtnInt(Callback<void()> func)
00165 {
00166     // Pulled low, switched high
00167     mPairBtn.mode(PullNone);
00168     mPairBtn.rise(func);
00169     mPairBtn.enable_irq();
00170 }
00171 
00172 // Input
00173 CmdResult BaseboardIO::sampleUserSwitches()
00174 {
00175     if ((mPortEx0 == NULL) || (mPortEx1 == NULL))
00176         return cmdError;
00177     // Sample port expanders
00178     enableSwitchedIO();
00179     wait(0.001);  // Wait 1 ms
00180     if (mPortEx0->pioLogicReliableRead(mPortExpanderVal0) != cmdSuccess) {
00181         disableSwitchedIO();
00182         myLogError("Error reading port expander 0.");
00183         return cmdError;
00184     }
00185     if (mPortEx1->pioLogicReliableRead(mPortExpanderVal1) != cmdSuccess) {
00186         disableSwitchedIO();
00187         myLogError("Error reading port expander 1.");
00188         return cmdError;
00189     }
00190     disableSwitchedIO();
00191     return cmdSuccess;
00192 }
00193 bool BaseboardIO::isCCInAlert()
00194 {
00195     if (isCCNO()) { // If NO then the CCIn should float high if not in alert state
00196         return mCCIn == 0;
00197     }
00198     else { // If NC then the CCIN should be held low if not in alert state
00199         return mCCIn == 1;
00200     }
00201 }
00202 bool BaseboardIO::isPairBtn()
00203 {
00204     // Depressed button is high
00205     return mPairBtn.read() == 1;
00206 }
00207 bool BaseboardIO::isCCNO()
00208 {
00209     // When DIP switch is not closed (i.e. value reads high) assume NO
00210     return (mPortExpanderVal1 & pEx1NoNcSel) != 0; // Open NO, closed NC
00211 }
00212 void BaseboardIO::setIsCCNO(bool val)
00213 {
00214     // When DIP switch is not closed (i.e. value reads high) assume NO
00215     if (val) {
00216         mPortExpanderVal1 |= pEx1NoNcSel; // Set bit
00217     }
00218     else {
00219         mPortExpanderVal1 &= ~pEx1NoNcSel; // Clear bit
00220     }
00221 }
00222 bool BaseboardIO::isRx()
00223 {
00224     // When DIP switch is not closed (i.e. value reads high) assume RX
00225     return (mPortExpanderVal1 & pEx1RxTxSel) != 0;
00226 }
00227 void BaseboardIO::setIsRx(bool val)
00228 {
00229     // When DIP switch is not closed (i.e. value reads high) assume RX
00230     if (val) {
00231         mPortExpanderVal1 |= pEx1RxTxSel; // Set bit
00232     }
00233     else {
00234         mPortExpanderVal1 &= ~pEx1RxTxSel; // Clear bit
00235     }
00236 }
00237 bool BaseboardIO::isLoRaWANMode()
00238 {
00239     // When DIP switch is not closed (i.e. value reads high) assume P2P not WAN
00240     return (mPortExpanderVal1 & pEx1WanSel) == 0;
00241 }
00242 bool BaseboardIO::isSerialEnabled()
00243 {
00244     // When DIP switch is not closed (i.e. value reads high) assume not in serial mode
00245     return (mPortExpanderVal1 & pEx1SerialEn) == 0;
00246 }
00247 uint8_t BaseboardIO::rotarySwitch1()
00248 {
00249     // If a bit of a nibble is asserted then the port expander line is switched low.
00250     uint8_t val = 0;
00251     if ((mPortExpanderVal0 & pEx0Rot1B8) == 0)
00252         val |= 0x08;
00253     if ((mPortExpanderVal0 & pEx0Rot1B4) == 0)
00254         val |= 0x04;
00255     if ((mPortExpanderVal0 & pEx0Rot1B2) == 0)
00256         val |= 0x02;
00257     if ((mPortExpanderVal0 & pEx0Rot1B1) == 0)
00258         val |= 0x01;
00259     return val;
00260 }
00261 void BaseboardIO::setRotarySwitch1(uint8_t val)
00262 {
00263     // Clear all then set
00264     mPortExpanderVal0 &= ~pEx0Rot1B8;
00265     mPortExpanderVal0 &= ~pEx0Rot1B4;
00266     mPortExpanderVal0 &= ~pEx0Rot1B2;
00267     mPortExpanderVal0 &= ~pEx0Rot1B1;
00268     
00269     if ((val & 0x08) == 0) {
00270         mPortExpanderVal0 |= pEx0Rot1B8;
00271     }
00272     if ((val & 0x04) == 0) {
00273         mPortExpanderVal0 |= pEx0Rot1B4;
00274     }
00275     if ((val & 0x02) == 0) {
00276         mPortExpanderVal0 |= pEx0Rot1B2;
00277     }
00278     if ((val & 0x01) == 0) {
00279         mPortExpanderVal0 |= pEx0Rot1B1;
00280     }
00281 }
00282 uint8_t BaseboardIO::rotarySwitch2()
00283 {
00284     // If a bit of a nibble is asserted then the port expander line is switched low.
00285     uint8_t val = 0;
00286     if ((mPortExpanderVal1 & pEx1Rot2B8) == 0)
00287         val |= 0x08;
00288     if ((mPortExpanderVal1 & pEx1Rot2B4) == 0)
00289         val |= 0x04;
00290     if ((mPortExpanderVal0 & pEx0Rot2B2) == 0)
00291         val |= 0x02;
00292     if ((mPortExpanderVal0 & pEx0Rot2B1) == 0)
00293         val |= 0x01;
00294     return val;
00295 }
00296 
00297 // Output
00298 CmdResult BaseboardIO::ledOn()
00299 {
00300     mLed = 1;
00301 #if ALSO_USE_LRR_LED
00302     mLrrLed = 1;
00303 #endif
00304     return cmdSuccess;
00305 }
00306 CmdResult BaseboardIO::ledOff()
00307 {
00308     mLed = 0;
00309     // Always allow setting GPIO0 to 0
00310 //#if ALSO_USE_LRR_LED
00311     mLrrLed = 0;
00312 //#endif
00313     return cmdSuccess;
00314 }
00315 CmdResult BaseboardIO::relayAlert()
00316 {
00317     if (isCCNO()) { // Normally Open
00318         return closeRelay();
00319     }
00320     else { // Normally Close
00321         return openRelay();
00322     }
00323 }
00324 CmdResult BaseboardIO::relayNormal()
00325 {
00326     if (isCCNO()) { // Normally Open
00327         return openRelay();
00328     }
00329     else { // Normally Close
00330         return closeRelay();
00331     }
00332 }
00333 
00334 // Future
00335 CmdResult BaseboardIO::serialRx(bool enable)
00336 {
00337     uint8_t val;
00338     if (mPortEx0 == NULL) {
00339         myLogError("Error enabling 232.  Port expanders not initialized.");
00340         return cmdError;
00341     }
00342     mPortEx0->pioLogicReliableRead(val);
00343 
00344     // Active low from port expander -> pmos -> 232 (active chip EN)
00345     if (enable) {
00346         val &= ~pEx0232En;
00347     }
00348     else {
00349         val |= pEx0232En;
00350     }
00351 
00352     if (mPortEx0->pioLogicReliableWrite(val | ~pEx0OutMask) != cmdSuccess) {
00353         myLogError("Error enabling 232");
00354         return cmdError;
00355     }
00356     return cmdSuccess;
00357 }
00358 CmdResult BaseboardIO::serialTx(bool enable)
00359 {
00360     uint8_t val;
00361     if (mPortEx0 == NULL) {
00362         myLogError("Error enabling 232 TX.  Port expanders not initialized.");
00363         return cmdError;
00364     }
00365     mPortEx0->pioLogicReliableRead(val);
00366 
00367     // Active high tx disable therefore active low tx enable (note chip must also be enabled for TX)
00368     if (enable) {
00369         val &= ~pEx0232TxDis;
00370     }
00371     else {
00372         val |= pEx0232TxDis;
00373     }
00374 
00375     if (mPortEx0->pioLogicReliableWrite(val | ~pEx0OutMask) != cmdSuccess) {
00376         myLogError("Error enabling 232 TX");
00377         return cmdError;
00378     }
00379     return cmdSuccess;
00380 }
00381 
00382 // private
00383 CmdResult BaseboardIO::readInfoFromNVM()
00384 {
00385     bool nvmReadResult;
00386     uint8_t *data = new uint8_t [BASEBOARDIO_NVM_SIZE];
00387 
00388     nvmReadResult = dot->nvmRead(BASEBOARDIO_NVM_START_ADDR, data, BASEBOARDIO_NVM_SIZE);
00389     if (!nvmReadResult) {
00390         delete [] data;
00391         return cmdError;
00392     }
00393     mNvmObj.fromBytes(data, BASEBOARDIO_NVM_SIZE);
00394     delete [] data;
00395     if (!mNvmObj.validBaseboardIOFlag()) {
00396         myLogWarning("Invalid BaseboardIO Flag.  Using default values.");
00397         return cmdError;
00398     }
00399     else if (!mNvmObj.validBaseboardIORev()) {
00400         myLogWarning("Invalid BaseboardIO Rev.  Using default values.");
00401         return cmdError;
00402     }
00403     else {
00404         return cmdSuccess;
00405     }
00406 }
00407 CmdResult BaseboardIO::writeInfoToNVM()
00408 {
00409     uint8_t *data = new uint8_t [BASEBOARDIO_NVM_SIZE];
00410     uint8_t size = BASEBOARDIO_NVM_SIZE;
00411     mNvmObj.toBytes(data, size);
00412     dot->nvmWrite(BASEBOARDIO_NVM_START_ADDR, data, BASEBOARDIO_NVM_SIZE);
00413 
00414     delete [] data;
00415     return cmdSuccess;
00416 }
00417 CmdResult BaseboardIO::identifyPortExpanders()
00418 {
00419     uint8_t addr[8];
00420     uint8_t result;
00421     int i;
00422 
00423     // Search Bus
00424     myLogInfo("Starting OneWire Search");
00425     enableSwitchedIO();
00426     for (int j=0;j<10;j++) { // Try 5 times
00427         i=0;
00428         mOWMaster.reset();
00429         mOWMaster.reset_search();
00430         wait(1.0);
00431         while (true) {
00432             // TODO maybe change to family based search
00433             result = mOWMaster.search(addr);
00434             if (result != 1) {
00435                 break;
00436             }
00437             myLogInfo("ROM Addr: %02x:%02x:%02x:%02x:%02x:%02x:%02x%02x found.",
00438                     addr[7],addr[6],addr[5],addr[4],addr[3],addr[2],addr[1],addr[0]);
00439             if (i == 0) {
00440                 std::memcpy(mNvmObj.mPortExpanderROM0, addr, sizeof(mNvmObj.mPortExpanderROM0));
00441             }
00442             else if (i == 1) {
00443                 std::memcpy(mNvmObj.mPortExpanderROM1, addr, sizeof(mNvmObj.mPortExpanderROM1));
00444             }
00445             i++;
00446         }
00447             // TODO maybe only allow a reasonable number of Port Expanders
00448         if (i >=2) {
00449             break;
00450         }
00451     }
00452 
00453     myLogInfo("Finished OneWire Search");
00454     if (i != 2) {
00455         myLogError("Incorrect Number of OneWire devices (Got %d.  Expected 2) OneWire port expanders found.", i);
00456         return cmdError;
00457     }
00458 
00459     // All rotary switches should be at 0.  DIPS should be asserted.
00460     // If switches are set in factory default mode then port expander 1 should read 0xFF and
00461     // port expander 2 should read 0xF0.
00462 
00463     mPortEx0 = new DS2408(&mOWMaster, mNvmObj.mPortExpanderROM0);
00464     mPortEx1 = new DS2408(&mOWMaster, mNvmObj.mPortExpanderROM1);
00465 
00466 
00467     enableSwitchedIO();
00468     if (mPortEx0->pioLogicReliableRead(mPortExpanderVal0) != cmdSuccess) {
00469         myLogError("Error during port expander ID.  Read failed.");
00470         disableSwitchedIO();
00471         delete mPortEx0;
00472         delete mPortEx1;
00473         return cmdError;
00474     }
00475     if (mPortEx1->pioLogicReliableRead(mPortExpanderVal1) != cmdSuccess) {
00476         myLogError("Error during port expander ID.  Read failed.");
00477         disableSwitchedIO();
00478         delete mPortEx0;
00479         delete mPortEx1;
00480         return cmdError;
00481     }
00482 
00483     disableSwitchedIO();
00484     if ((mPortExpanderVal0 == 0xFF) and (mPortExpanderVal1 == 0xF0)) { // Luckily got it right
00485         myLogInfo("ROMS Swap Not Needed.");
00486     }
00487     else if ((mPortExpanderVal0 == 0xF0) and (mPortExpanderVal1 == 0xFF)) { // Just need to swap
00488         std::memcpy(addr, mNvmObj.mPortExpanderROM0, sizeof(addr)); // Store Orig ROM0 -> addr
00489         std::memcpy(mNvmObj.mPortExpanderROM0, mNvmObj.mPortExpanderROM1, sizeof(mNvmObj.mPortExpanderROM0)); // Store Orig ROM1 -> ROM0
00490         std::memcpy(mNvmObj.mPortExpanderROM1, addr, sizeof(mNvmObj.mPortExpanderROM1)); // Store Orig ROM0 (addr) -> ROM1
00491         myLogInfo("Swapped ROMS.");
00492     }
00493     else {
00494         myLogError("Error during port expander ID.  Port expanders not in "
00495                 "expected states (0xFF and 0xF0).  Check user switches.  Got %02X and %02X",
00496                 mPortExpanderVal0, mPortExpanderVal1);
00497         delete mPortEx0;
00498         delete mPortEx1;
00499         return cmdError;
00500     }
00501 
00502     // Cleanup
00503     delete mPortEx0;
00504     delete mPortEx1;
00505 
00506     return cmdSuccess;
00507 }
00508 CmdResult BaseboardIO::openRelay() {
00509     uint8_t val;
00510     mPortEx1->pioLogicReliableRead(val);
00511 
00512     val |= pEx1RlyA; // Make sure Relay A is off
00513     val &= ~pEx1RlyB; // Turn on Relay B
00514 
00515     if (mPortEx1->pioLogicReliableWrite(val | ~pEx1OutMask) != cmdSuccess) {
00516         val |= pEx1RlyA; // Turn Relay A off
00517         val |= pEx1RlyB; // Turn Relay B off
00518         mPortEx1->pioLogicReliableWrite(val | ~pEx1OutMask); // Write a non assert value just to try to overcome an error
00519         myLogError ("Error turning on coil.  Turning both coils off.");
00520         return cmdError;
00521     }
00522 
00523     wait(COIL_ON_TIME);
00524 
00525     val |= pEx1RlyA; // Turn Relay A off
00526     val |= pEx1RlyB; // Turn Relay B off
00527 
00528     if (mPortEx1->pioLogicReliableWrite(val | ~pEx1OutMask) != cmdSuccess) {
00529         mPortEx1->pioLogicReliableWrite(val | ~pEx1OutMask);
00530         myLogError ("Error turning off coils.  Trying again.");
00531         return cmdError;
00532     }
00533 
00534     return cmdSuccess;
00535 }
00536 CmdResult BaseboardIO::closeRelay() {
00537     uint8_t val;
00538     mPortEx1->pioLogicReliableRead(val);
00539 
00540     val &= ~pEx1RlyA; // Turn on Relay A
00541     val |= pEx1RlyB; // Make sure Relay B is off
00542 
00543     if (mPortEx1->pioLogicReliableWrite(val | ~pEx1OutMask) != cmdSuccess) {
00544         val |= pEx1RlyA; // Turn Relay A off
00545         val |= pEx1RlyB; // Turn Relay B off
00546         mPortEx1->pioLogicReliableWrite(val | ~pEx1OutMask); // Write a non assert value just to try to overcome an error
00547         myLogError ("Error turning on coil.  Turning both coils off.");
00548         return cmdError;
00549     }
00550 
00551     wait(COIL_ON_TIME);
00552 
00553     val |= pEx1RlyA; // Turn Relay A off
00554     val |= pEx1RlyB; // Turn Relay B off
00555 
00556     if (mPortEx1->pioLogicReliableWrite(val | ~pEx1OutMask) != cmdSuccess) {
00557         mPortEx1->pioLogicReliableWrite(val | ~pEx1OutMask);
00558         myLogError ("Error turning off coils.  Trying again.");
00559         return cmdError;
00560     }
00561 
00562     return cmdSuccess;
00563 }
00564 
00565 CmdResult BaseboardIO::prepareSleep()
00566 {
00567     // Save current GPUIO state
00568     xdot_save_gpio_state();
00569 
00570     // Configure all IO expect for pins for interrupt in lowest mode possible
00571     // GPIO Ports Clock Enable
00572     __GPIOA_CLK_ENABLE();
00573     __GPIOB_CLK_ENABLE();
00574     __GPIOC_CLK_ENABLE();
00575     __GPIOH_CLK_ENABLE();
00576 
00577     GPIO_InitTypeDef GPIO_InitStruct;
00578 
00579     // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
00580     // UART1_TX, UART1_RTS & UART1_CTS to analog nopull - RX could be a wakeup source
00581 //    GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_11 | GPIO_PIN_12;
00582     GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_12;
00583     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
00584     GPIO_InitStruct.Pull = GPIO_NOPULL;
00585     HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
00586 
00587     // I2C_SDA & I2C_SCL to analog nopull
00588     GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9;
00589     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
00590     GPIO_InitStruct.Pull = GPIO_NOPULL;
00591     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
00592 
00593     // SPI_MOSI, SPI_MISO, SPI_SCK, & SPI_NSS to analog nopull
00594     GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15;
00595     GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
00596     GPIO_InitStruct.Pull = GPIO_NOPULL;
00597     HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
00598 
00599     // iterate through potential wake pins - leave the configured wake pin alone if one is needed
00600     if ((CCInPinName != WAKE && TamperPinName != WAKE && PairBtnPinName != WAKE)
00601             || dot->getWakeMode() == mDot::RTC_ALARM) {
00602         GPIO_InitStruct.Pin = GPIO_PIN_0;
00603         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
00604         GPIO_InitStruct.Pull = GPIO_NOPULL;
00605         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
00606     }
00607     if ((CCInPinName != GPIO0 && TamperPinName != GPIO0 && PairBtnPinName != GPIO0)
00608             || dot->getWakeMode() == mDot::RTC_ALARM) {
00609         GPIO_InitStruct.Pin = GPIO_PIN_4;
00610         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
00611         GPIO_InitStruct.Pull = GPIO_NOPULL;
00612         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
00613     }
00614     if ((CCInPinName != GPIO1 && TamperPinName != GPIO1 && PairBtnPinName != GPIO1)
00615             || dot->getWakeMode() == mDot::RTC_ALARM) {
00616         GPIO_InitStruct.Pin = GPIO_PIN_5;
00617         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
00618         GPIO_InitStruct.Pull = GPIO_NOPULL;
00619         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
00620     }
00621     if ((CCInPinName != GPIO2 && TamperPinName != GPIO2 && PairBtnPinName != GPIO2)
00622             || dot->getWakeMode() == mDot::RTC_ALARM) {
00623         GPIO_InitStruct.Pin = GPIO_PIN_0;
00624         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
00625         GPIO_InitStruct.Pull = GPIO_NOPULL;
00626         HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
00627     }
00628     // Changed to always do pull down for now.. Should implement discrete pull on new rev
00629 //    if ((CCInPinName != GPIO3 && TamperPinName != GPIO3 && PairBtnPinName != GPIO3)
00630 //            || dot->getWakeMode() == mDot::RTC_ALARM) {
00631 //        GPIO_InitStruct.Pin = GPIO_PIN_2;
00632 //        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
00633 //        GPIO_InitStruct.Pull = GPIO_NOPULL;
00634 //        HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
00635 //    }
00636 
00637     // Try doing nothing so that the GPIO3 is still and active output
00638 
00639 
00640     // Cannot do this and have serial data
00641 //    if ((CCInPinName != UART1_RX && TamperPinName != UART1_RX && PairBtnPinName != UART1_RX)
00642 //            || dot->getWakeMode() == mDot::RTC_ALARM) {
00643 //        GPIO_InitStruct.Pin = GPIO_PIN_10;
00644 //        GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
00645 //        GPIO_InitStruct.Pull = GPIO_NOPULL;
00646 //        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
00647 //    }
00648     if ((CCInPinName != UART_CTS && TamperPinName != UART_CTS && PairBtnPinName != UART_CTS)
00649             || dot->getWakeMode() == mDot::RTC_ALARM) {
00650         GPIO_InitStruct.Pin = GPIO_PIN_11;
00651         GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
00652         GPIO_InitStruct.Pull = GPIO_NOPULL;
00653         HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
00654     }
00655 
00656     return cmdSuccess;
00657 }
00658 
00659 CmdResult BaseboardIO::exitSleep()
00660 {
00661     xdot_restore_gpio_state();
00662     return cmdSuccess;
00663 }
00664 
00665 // NvmBBIOObj
00666 NvmBBIOObj::NvmBBIOObj()
00667 {
00668     setDefaults();
00669 }
00670 void NvmBBIOObj::setDefaults()
00671 {
00672     mBaseboardIOFlag = BASEBOARDIO_FLAG;
00673     mBaseboardIORev  = BASEBOARDIO_REV;
00674     mSerialNum = 0x0000;
00675     mBaseboardIOConfig = 0x0000;
00676     std::memset(mPortExpanderROM0, 0x00, 8);
00677     std::memset(mPortExpanderROM1, 0x00, 8);
00678 }
00679 CmdResult NvmBBIOObj::fromBytes(uint8_t *data, uint8_t size)
00680 {
00681     if (size != BASEBOARDIO_NVM_SIZE) {
00682         return cmdError;
00683     }
00684 
00685     mBaseboardIOFlag    = *((uint16_t *) (data));
00686     mBaseboardIORev     = *((uint16_t *) (data+2));
00687     mSerialNum          = *((uint32_t *) (data+4));
00688     mBaseboardIOConfig  = *((uint32_t *) (data+6));
00689 
00690     std::memcpy(&mPortExpanderROM0, data+0x10, 8);
00691     std::memcpy(&mPortExpanderROM1, data+0x18, 8);
00692 
00693     return cmdSuccess;
00694 }
00695 CmdResult NvmBBIOObj::toBytes(uint8_t *data, uint8_t &size) {
00696     // TODO check data size
00697 
00698     *((uint16_t *) (data))   = mBaseboardIOFlag;
00699     *((uint16_t *) (data+2)) = mBaseboardIORev;
00700     *((uint32_t *) (data+4)) = mSerialNum;
00701     *((uint32_t *) (data+6)) = mBaseboardIOConfig;
00702 
00703     std::memcpy(data+0x10, &mPortExpanderROM0, 8);
00704     std::memcpy(data+0x18, &mPortExpanderROM1, 8);
00705 
00706     size = BASEBOARDIO_NVM_SIZE;
00707 
00708     return cmdSuccess;
00709 }
00710 uint16_t NvmBBIOObj::getBaseboardIOFlag()
00711 {
00712     return mBaseboardIOFlag;
00713 }
00714 bool NvmBBIOObj::validBaseboardIOFlag()
00715 {
00716     return mBaseboardIOFlag == BASEBOARDIO_FLAG;
00717 }
00718 uint16_t NvmBBIOObj::getBaseboardIORev()
00719 {
00720     return mBaseboardIORev;
00721 }
00722 bool NvmBBIOObj::validBaseboardIORev()
00723 {
00724     return mBaseboardIORev == BASEBOARDIO_REV;
00725 }
00726 uint16_t NvmBBIOObj::getSerialNum()
00727 {
00728     return mSerialNum;
00729 }
00730 void NvmBBIOObj::setSerialNum(uint16_t in)
00731 {
00732     mSerialNum = in;
00733 }
00734 uint32_t NvmBBIOObj::getBaseboardIOConfig()
00735 {
00736     return mBaseboardIOConfig;
00737 }
00738 void NvmBBIOObj::setBaseboardIOConfig(uint32_t in)
00739 {
00740     mBaseboardIOConfig = in;
00741 }
00742 void NvmBBIOObj::getPortExpanderROM0(uint8_t *addr)
00743 {
00744     std::memcpy(addr, &mPortExpanderROM0, 8);
00745 }
00746 void NvmBBIOObj::setPortExpanderROM0(const uint8_t *addr)
00747 {
00748     std::memcpy(&mPortExpanderROM0, addr, 8);
00749 }
00750 void NvmBBIOObj::getPortExpanderROM1(uint8_t *addr)
00751 {
00752     std::memcpy(addr, &mPortExpanderROM1, 8);
00753 }
00754 void NvmBBIOObj::setPortExpanderROM1(const uint8_t *addr)
00755 {
00756     std::memcpy(&mPortExpanderROM1, addr, 8);
00757 }