![](/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
Diff: xDotBridge/src/BaseboardIO.cpp
- Revision:
- 44:ece6330e9b57
- Parent:
- 41:9ef4c4d77711
- Child:
- 47:a68747642a7a
--- a/xDotBridge/src/BaseboardIO.cpp Tue Jan 31 21:02:56 2017 +0000 +++ b/xDotBridge/src/BaseboardIO.cpp Wed Feb 01 15:20:45 2017 -0700 @@ -8,121 +8,363 @@ #include "BaseboardIO.h" #include "MTSLog.h" +const float coilOnTime = 0.030; // 30 ms + +// Port expander 0 +const uint8_t pEx0232En = 0x01; +const uint8_t pEx0232TxDis = 0x02; +const uint8_t pEx0Rot1B1 = 0x04; +const uint8_t pEx0Rot1B2 = 0x08; +const uint8_t pEx0Rot1B4 = 0x10; +const uint8_t pEx0Rot1B8 = 0x20; +const uint8_t pEx0Rot2B1 = 0x40; +const uint8_t pEx0Rot2B2 = 0x80; + +// Port expander 1 +const uint8_t pEx1NoNcSel = 0x01; +const uint8_t pEx1RxTxSel = 0x02; +const uint8_t pEx1WanSel = 0x04; +const uint8_t pEx1SerialEn = 0x08; // Labeled as reserved +const uint8_t pEx1Rot2B8 = 0x10; +const uint8_t pEx1Rot2B4 = 0x20; +const uint8_t pEx1RlyB = 0x40; // This is actually a coil +const uint8_t pEx1RlyA = 0x80; // This is actually a coil + +/** + * Note for interrupt within uC cannot use two pins with the same numeric suffix (e.g. cannot + * use both PA_0 and PB_0). Note 1, 6, 7, 8, and 13 are used by LoRa radio. + */ + BaseboardIO::BaseboardIO() + : mOWMaster(I2C_SDA), + mCCIn(WAKE), // Interrupt pin PA_0 + mTamper(GPIO1), // Interrupt pin PA_5 + mPairBtn(UART_CTS), // Interrupt pin PA_11 + mLed(SWDIO), + mSwitchedIOCtrl(I2C_SCL) { - mCCInIntCallback = NULL; - mTamperIntCallback = NULL; - mPairBtnIntCallback = NULL; +// mCCInIntCallback = NULL; +// mTamperIntCallback = NULL; +// mPairBtnIntCallback = NULL; - std::memset(portExpanderROM0, 0x00, 8); - std::memset(portExpanderROM1, 0x00, 8); - portExpanderVal0 = 0x00; - portExpanderVal1 = 0x00; + std::memset(mPortExpanderROM0, 0x00, 8); + std::memset(mPortExpanderROM1, 0x00, 8); + mPortExpanderVal0 = 0x00; + mPortExpanderVal1 = 0x00; + + mPortEx0 = NULL; + mPortEx1 = NULL; } CmdResult BaseboardIO::init() { logError("Not implemented yet!!!"); + // Setup port expanders + CmdResult result = readInfoFromNVM(); + if (result == cmdSuccess) { + // Values stored just read them foo + logError("Not implemented yet!!!"); + } + else { // EEPROM values not there or corrupt + result = identifyPortExpanders(); // Get ROM addresses + if (result != cmdSuccess) { + logError("Error identifying port expanders"); + return cmdError; + } + } + mPortEx0 = new DS2408(&mOWMaster, mPortExpanderROM0); + mPortEx1 = new DS2408(&mOWMaster, mPortExpanderROM1); + + // Put relay in known state + + logInfo("Baseboard IO initialization successful"); + return cmdSuccess; } // Registering for interrupts -void BaseboardIO::regCCInInt(void (*callback) (void)) +void BaseboardIO::regCCInInt(Callback<void()> func) { - mCCInIntCallback = callback; + // Pulled high, switched low + mCCIn.fall(func); } -void BaseboardIO::regTamperInt(void (*callback) (void)) +void BaseboardIO::regTamperInt(Callback<void()> func) { - mTamperIntCallback = callback; + // Pulled high, switched low + mTamper.fall(func); } -void BaseboardIO::regPairBtnInt(void (*callback) (void)) +void BaseboardIO::regPairBtnInt(Callback<void()> func) { - logError("Not implemented yet!!!"); + // Pulled low, switched high + mPairBtn.rise(func); } // Input CmdResult BaseboardIO::sampleUserSwitches() { - logError("Not implemented yet!!!"); - return cmdError; + // Sample port expanders + if (mPortEx0->pioLogicRead(mPortExpanderVal0) != cmdSuccess) { + logError("Error reading port expander 0."); + return cmdError; + } + if (mPortEx1->pioLogicRead(mPortExpanderVal1) != cmdSuccess) { + logError("Error reading port expander 1."); + return cmdError; + } + return cmdSuccess; } bool BaseboardIO::isPairBtn() { - logError("Not implemented yet!!!"); - return false; + // Depressed button is high + return mPairBtn.read() == 1; } bool BaseboardIO::isCCOutNO() { - logError("Not implemented yet!!!"); - return false; + // When DIP switch is not closed (i.e. value reads high) assume NO + return (mPortExpanderVal1 & pEx1NoNcSel) != 0; } bool BaseboardIO::isRx() { - logError("Not implemented yet!!!"); - return false; + // When DIP switch is not closed (i.e. value reads high) assume RX + return (mPortExpanderVal1 & pEx1RxTxSel) != 0; } bool BaseboardIO::isLoRaWANMode() { - logError("Not implemented yet!!!"); - return false; + // When DIP switch is not closed (i.e. value reads high) assume P2P not WAN + return (mPortExpanderVal1 & pEx1WanSel) == 0; } uint8_t BaseboardIO::rotarySwitch1() { - logError("Not implemented yet!!!"); - return 0; + // If a bit of a nibble is asserted then the port expander line is switched low. + uint8_t val = 0; + if ((mPortExpanderVal0 & pEx0Rot1B8) == 0) + val |= 0x08; + if ((mPortExpanderVal0 & pEx0Rot1B4) == 0) + val |= 0x04; + if ((mPortExpanderVal0 & pEx0Rot1B2) == 0) + val |= 0x02; + if ((mPortExpanderVal0 & pEx0Rot1B1) == 0) + val |= 0x01; + return val; } uint8_t BaseboardIO::rotarySwitch2() { - logError("Not implemented yet!!!"); - return 0; + // If a bit of a nibble is asserted then the port expander line is switched low. + uint8_t val = 0; + if ((mPortExpanderVal1 & pEx1Rot2B8) == 0) + val |= 0x08; + if ((mPortExpanderVal1 & pEx1Rot2B4) == 0) + val |= 0x04; + if ((mPortExpanderVal0 & pEx0Rot2B2) == 0) + val |= 0x02; + if ((mPortExpanderVal0 & pEx0Rot2B1) == 0) + val |= 0x01; + return val; } // Output CmdResult BaseboardIO::ledOn() { - logError("Not implemented yet!!!"); - return cmdError; + mLed = 1; + return cmdSuccess; } CmdResult BaseboardIO::ledOff() { - logError("Not implemented yet!!!"); - return cmdError; + mLed = 0; + return cmdSuccess; } CmdResult BaseboardIO::relayAlert() { - logError("Not implemented yet!!!"); - return cmdError; + if (isCCOutNO()) { // Normally Open + return closeRelay(); + } + else { // Normally Close + return openRelay(); + } } CmdResult BaseboardIO::relayNormal() { - logError("Not implemented yet!!!"); - return cmdError; + if (isCCOutNO()) { // Normally Open + return openRelay(); + } + else { // Normally Close + return closeRelay(); + } } // Future CmdResult BaseboardIO::serialRx(bool enable) { + uint8_t val; + mPortEx0->pioLogicRead(val); + + // Active low from port expander -> pmos -> 232 (active chip EN) + if (enable) { + val &= ~pEx0232En; + } + else { + val |= pEx0232En; + } + + if (mPortEx1->pioLogicWrite(val) != cmdSuccess) { + logError("Error enabling 232"); + return cmdError; + } + return cmdSuccess; +} +CmdResult BaseboardIO::serialTx(bool enable) +{ + uint8_t val; + mPortEx0->pioLogicRead(val); + + // Active high tx disable therefore active low tx enable (note chip must also be enabled for TX) + if (enable) { + val &= ~pEx0232TxDis; + } + else { + val |= pEx0232TxDis; + } + + if (mPortEx1->pioLogicWrite(val) != cmdSuccess) { + logError("Error enabling 232 TX"); + return cmdError; + } + return cmdSuccess; +} + +// private +CmdResult BaseboardIO::readInfoFromNVM() +{ logError("Not implemented yet!!!"); return cmdError; } -CmdResult BaseboardIO::serialTx(bool enable) +CmdResult BaseboardIO::writeInfoToNVM() { logError("Not implemented yet!!!"); return cmdError; } +CmdResult BaseboardIO::identifyPortExpanders() +{ + uint8_t addr[8]; + uint8_t result; -// private + // Search Bus + logInfo("Starting OneWire Search"); + int i=0; + while (true) { + // TODO maybe change to family based search + result = mOWMaster.search(addr); + logInfo("ROM Addr: %02x:%02x:%02x:%02x:%02x:%02x:%02x%02x found.", + addr[7],addr[6],addr[5],addr[4],addr[3],addr[2],addr[1],addr[0]); + if (result != 1) + break; + if (i == 0) { + std::memcpy(mPortExpanderROM0, addr, sizeof(mPortExpanderROM0)); + } + else if (i == 1) { + std::memcpy(mPortExpanderROM1, addr, sizeof(mPortExpanderROM1)); + } + i++; + } + + logInfo("Finished OneWire Search"); + if (i != 2) { + logError("Incorrect Number (Got %d. Expected 2) OneWire port expanders found.", i); + return cmdError; + } + + // If switches are set in factory default mode then port expander 1 should read 0xFF and + // port expander 2 should read 0xF0. -CmdResult readInfoFromEEPROM() -{ - logError("Not implemented yet!!!"); - return cmdError; + mPortEx0 = new DS2408(&mOWMaster, mPortExpanderROM0); + mPortEx1 = new DS2408(&mOWMaster, mPortExpanderROM1); + + if (mPortEx0->pioLogicRead(mPortExpanderVal0) != cmdSuccess) { + logError("Error during port expander ID. Read failed."); + delete mPortEx0; + delete mPortEx1; + return cmdError; + } + if (mPortEx1->pioLogicRead(mPortExpanderVal1) != cmdSuccess) { + logError("Error during port expander ID. Read failed."); + delete mPortEx0; + delete mPortEx1; + return cmdError; + } + + if ((mPortExpanderVal0 == 0xFF) and (mPortExpanderVal1 == 0xF0)) { // Luckily got it right + logInfo("ROMS Swap Not Needed."); + } + else if ((mPortExpanderVal0 == 0xF0) and (mPortExpanderVal1 == 0xFF)) { // Just need to swap + std::memcpy(addr, mPortExpanderROM0, sizeof(addr)); // Store Orig ROM0 -> addr + std::memcpy(mPortExpanderROM0, mPortExpanderROM1, sizeof(mPortExpanderROM0)); // Store Orig ROM1 -> ROM0 + std::memcpy(mPortExpanderROM1, addr, sizeof(mPortExpanderROM1)); // Store Orig ROM0 (addr) -> ROM1 + logInfo("Swapped ROMS."); + } + else { + logError("Error during port expander ID. Port expanders not in expected states. Check user switches."); + delete mPortEx0; + delete mPortEx1; + return cmdError; + } + + // Cleanup + delete mPortEx0; + delete mPortEx1; + + return cmdSuccess; } -CmdResult writeInfoToEEPROM() -{ - logError("Not implemented yet!!!"); - return cmdError; +CmdResult BaseboardIO::closeRelay() { + uint8_t val; + mPortEx1->pioLogicRead(val); + + val |= pEx1RlyA; // Turn on Relay A + val &= ~pEx1RlyB; // Make sure Relay B is off + + if (mPortEx1->pioLogicWrite(val) != cmdSuccess) { + val &= ~pEx1RlyA; // Turn Relay A off + val &= ~pEx1RlyB; // Turn Relay B off + mPortEx1->pioLogicWrite(val); // Write a non assert value just to try to overcome an error + logError ("Error turning on coil. Turning both coils off."); + return cmdError; + } + + wait(coilOnTime); + + val &= ~pEx1RlyA; // Turn Relay A off + val &= ~pEx1RlyB; // Turn Relay B off + + if (mPortEx1->pioLogicWrite(val) != cmdSuccess) { + mPortEx1->pioLogicWrite(val); + logError ("Error turning off coils. Trying again."); + return cmdError; + } + + return cmdSuccess; } -CmdResult identifyPortExpanders() -{ - logError("Not implemented yet!!!"); - return cmdError; +CmdResult BaseboardIO::openRelay() { + uint8_t val; + mPortEx1->pioLogicRead(val); + + val &= ~pEx1RlyA; // Make sure Relay A is off + val |= pEx1RlyB; // Turn on Relay B + + if (mPortEx1->pioLogicWrite(val) != cmdSuccess) { + val &= ~pEx1RlyA; // Turn Relay A off + val &= ~pEx1RlyB; // Turn Relay B off + mPortEx1->pioLogicWrite(val); // Write a non assert value just to try to overcome an error + logError ("Error turning on coil. Turning both coils off."); + return cmdError; + } + + wait(coilOnTime); + + val &= ~pEx1RlyA; // Turn Relay A off + val &= ~pEx1RlyB; // Turn Relay B off + + if (mPortEx1->pioLogicWrite(val) != cmdSuccess) { + mPortEx1->pioLogicWrite(val); + logError ("Error turning off coils. Trying again."); + return cmdError; + } + + return cmdSuccess; }