From 96fdbfdc89843a75ec69a1b8ded71161ba1de2e1 Mon Sep 17 00:00:00 2001 From: Asbelos Date: Sun, 26 Nov 2023 12:31:41 +0000 Subject: [PATCH] Trainbrains block occupancy --- IODevice.h | 2 + IO_trainbrains.h | 98 ++++++++++++++++++++++++++++++++++++++++++++++++ version.h | 4 +- 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 IO_trainbrains.h diff --git a/IODevice.h b/IODevice.h index 74fe49b..d12fafd 100644 --- a/IODevice.h +++ b/IODevice.h @@ -542,8 +542,10 @@ protected: #include "IO_MCP23017.h" #include "IO_PCF8574.h" #include "IO_PCF8575.h" +#include "IO_PCA9555.h" #include "IO_duinoNodes.h" #include "IO_EXIOExpander.h" +#include "IO_trainbrains.h" #endif // iodevice_h diff --git a/IO_trainbrains.h b/IO_trainbrains.h new file mode 100644 index 0000000..058fe02 --- /dev/null +++ b/IO_trainbrains.h @@ -0,0 +1,98 @@ +/* + * © 2023, Chris Harlow. All rights reserved. + * © 2021, Neil McKechnie. All rights reserved. + * + * This file is part of DCC++EX API + * + * This is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * It is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with CommandStation. If not, see . + */ + +#ifndef io_trainbrains_h +#define io_trainbrains_h + +#include "IO_GPIOBase.h" +#include "FSH.h" + +///////////////////////////////////////////////////////////////////////////////////////////////////// +/* + * IODevice subclass for trainbrains 3-block occupancy detector. + * For details see http://trainbrains.eu + */ + + enum TrackUnoccupancy +{ + TRACK_UNOCCUPANCY_UNKNOWN = 0, + TRACK_OCCUPIED = 1, + TRACK_UNOCCUPIED = 2 +}; + +class Trainbrains02 : public GPIOBase { +public: + static void create(VPIN vpin, uint8_t nPins, I2CAddress i2cAddress) { + if (checkNoOverlap(vpin, nPins, i2cAddress)) new Trainbrains02(vpin, nPins, i2cAddress); + } + +private: + // Constructor + Trainbrains02(VPIN vpin, uint8_t nPins, I2CAddress i2cAddress, int interruptPin=-1) + : GPIOBase((FSH *)F("Trainbrains02"), vpin, nPins, i2cAddress, interruptPin) + { + requestBlock.setRequestParams(_I2CAddress, inputBuffer, sizeof(inputBuffer), + outputBuffer, sizeof(outputBuffer)); + + outputBuffer[0] = (uint8_t)_I2CAddress; // strips away the mux part. + outputBuffer[1] =14; + outputBuffer[2] =1; + outputBuffer[3] =0; // This is the channel updated at each poling call + outputBuffer[4] =0; + outputBuffer[5] =0; + outputBuffer[6] =0; + outputBuffer[7] =0; + outputBuffer[8] =0; + outputBuffer[9] =0; + } + + void _writeGpioPort() override {} + + void _readGpioPort(bool immediate) override { + // cycle channel on device each time + outputBuffer[3]=channelInProgress+1; // 1-origin + channelInProgress++; + if(channelInProgress>=_nPins) channelInProgress=0; + + if (immediate) { + _processCompletion(I2CManager.read(_I2CAddress, inputBuffer, sizeof(inputBuffer), + outputBuffer, sizeof(outputBuffer))); + } else { + // Queue new request + requestBlock.wait(); // Wait for preceding operation to complete + // Issue new request to read GPIO register + I2CManager.queueRequest(&requestBlock); + } + } + + // This function is invoked when an I/O operation on the requestBlock completes. + void _processCompletion(uint8_t status) override { + if (status != I2C_STATUS_OK) inputBuffer[6]=TRACK_UNOCCUPANCY_UNKNOWN; + if (inputBuffer[6] == TRACK_UNOCCUPIED ) _portInputState |= 0x01 <