diff --git a/IODevice.h b/IODevice.h
index bccf39b..6f12969 100644
--- a/IODevice.h
+++ b/IODevice.h
@@ -408,6 +408,6 @@ private:
#include "IO_MCP23008.h"
#include "IO_MCP23017.h"
#include "IO_PCF8574.h"
-#include "IO_DNOU8.h"
+#include "IO_LEWDUINO.h"
#endif // iodevice_h
diff --git a/IO_DNOU8.h b/IO_DNOU8.h
deleted file mode 100644
index b73f1f0..0000000
--- a/IO_DNOU8.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * © 2022, Chris Harlow. 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_DNOU8_h
- #define IO_DNOU8_h
-#include
-#include "IODevice.h"
-#define GET_BIT(bit) ((_pinValues[bit/8] >>(bit%8) == 1))
-#define SET_BIT(bit) _pinValues[bit/8] |= 1<<(bit%8)
-#define CLR_BIT(bit) _pinValues[bit/8] &= ~(1<<(bit%8))
-
-class IO_DNOU8 : public IODevice {
-public:
- static void create(VPIN firstVpin, int nPins, byte latchPin, byte clockPin, byte dataPin )
- {
- new IO_DNOU8( firstVpin, nPins, latchPin, clockPin, dataPin);
- }
-
-protected:
- IO_DNOU8(VPIN firstVpin, int nPins, byte latchPin, byte clockPin, byte dataPin) :
- IODevice(firstVpin, nPins) {
- _latchPin=latchPin;
- _clockPin=clockPin;
- _dataPin=dataPin;
- _nShiftBytes=(nPins+7)/8; // rounded up to multiples of 8 bits
- _pinValues=(byte*) calloc(_nShiftBytes,1);
- // Connect to HAL so my _write, _read and _loop will be called as required.
- IODevice::addDevice(this);
- }
-
-// Called by HAL to start handling this device
- void _begin() override {
- _xmitPending=true; // will cause transmission of all zeros first time out
- _deviceState = DEVSTATE_NORMAL;
- pinMode(_latchPin,OUTPUT);
- pinMode(_clockPin,OUTPUT);
- pinMode(_dataPin,OUTPUT);
- _display();
- }
-
-void _loop(unsigned long currentMicros) override {
- (void)currentMicros; // Not needed
-
- if (!_xmitPending) return; // Nothing to do
-
- #ifdef DIAG_IO
- // We will create a DIAG on the fly
- USB_SERIAL.print("<* DNOU8 ");
- #endif
-
- // stream out the bitmap (highest pin first)
- _xmitPending=false;
- digitalWrite(_latchPin, LOW);
-
- for (int xmitBit=_nShiftBytes*8 -1; xmitBit>=0; xmitBit--) {
- bool bit=GET_BIT(xmitBit);
- #ifdef DIAG_IO
- USB_SERIAL.print(bit?'1':'0');
- #endif
- digitalWrite(_dataPin,bit);
- digitalWrite(_clockPin,HIGH);
- digitalWrite(_clockPin,LOW);
- }
-
- digitalWrite(_latchPin, HIGH);
- #ifdef DIAG_IO
- USB_SERIAL.print(" *>\n");
- #endif
- }
-
- void _write(VPIN vpin, int value) override {
- int pin = vpin - _firstVpin;
- bool oldval=GET_BIT(pin);
- bool newval=value!=0;
- if (newval==oldval) return; // no change
- if (newval) SET_BIT(pin);
- else CLR_BIT(pin);
- _xmitPending=true; // shift register will be sent on next _loop()
- }
-
- int _read(VPIN vpin) override {
- int pin = vpin - _firstVpin;
- return GET_BIT(pin);
- }
-
- void _display() override {
- DIAG(F("IO_DNOU8 Configured on VPins:%d-%d"), (int)_firstVpin,
- (int)_firstVpin+_nPins-1);
- }
-
-private:
- bool _xmitPending=false;
- int _nShiftBytes=0;
- VPIN _latchPin,_clockPin,_dataPin;
- byte* _pinValues;
-};
-
-#endif
\ No newline at end of file
diff --git a/IO_LEWDUINO.h b/IO_LEWDUINO.h
new file mode 100644
index 0000000..dfa549d
--- /dev/null
+++ b/IO_LEWDUINO.h
@@ -0,0 +1,159 @@
+/*
+ * © 2022, Chris Harlow. 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_DNIN8_h
+ #define IO_DNIN8_h
+#include
+#define PIN_MASK(bit) (0x80>>(bit%8))
+#define GET_BIT(bit) (_pinValues[bit/8] & PIN_MASK(bit) )
+#define SET_BIT(bit) _pinValues[bit/8] |= PIN_MASK(bit)
+#define CLR_BIT(bit) _pinValues[bit/8] &= ~PIN_MASK(bit)
+#define DIAG_IO
+
+
+
+class IO_LEWDUINO : public IODevice {
+
+public:
+ IO_LEWDUINO(VPIN firstVpin, int nPins,
+ byte clockPin, byte latchPin, byte dataPin,
+ const byte* pinmap) :
+ IODevice(firstVpin, nPins) {
+
+ _latchPin=latchPin;
+ _clockPin=clockPin;
+ _dataPin=dataPin;
+ _pinMap=pinmap;
+ _nShiftBytes=(nPins+7)/8; // rounded up to multiples of 8 bits
+ _pinValues=(byte*) calloc(_nShiftBytes,1);
+ // Connect to HAL so my _write, _read and _loop will be called as required.
+ IODevice::addDevice(this);
+ }
+
+// Called by HAL to start handling this device
+ void _begin() override {
+ _deviceState = DEVSTATE_NORMAL;
+ pinMode(_latchPin,OUTPUT);
+ pinMode(_clockPin,OUTPUT);
+ pinMode(_dataPin,INPUT_PULLUP);
+ _display();
+ }
+
+// loop called by HAL supervisor
+void _loop(unsigned long currentMicros) override {
+ if (_pinMap) _loopInput(currentMicros);
+ else if (_xmitPending) _loopOutput();
+}
+
+void _loopInput(unsigned long currentMicros) {
+
+ if (currentMicros-_prevMicros < POLL_MICROS) return; // Nothing to do
+ _prevMicros=currentMicros;
+
+ //set latch to HIGH to freeze & store parallel data
+ ArduinoPins::fastWriteDigital(_latchPin, HIGH);
+ delayMicroseconds(20);
+ //set latch to LOW to enable the data to be transmitted serially
+ ArduinoPins::fastWriteDigital(_latchPin, LOW);
+
+ // stream in the bitmap useing mapping order provided at constructor
+ for (int xmitBit=0;xmitBit<_nShiftBytes*8; xmitBit++) {
+ ArduinoPins::fastWriteDigital(_clockPin, LOW);
+ delayMicroseconds(4);
+ bool data = ArduinoPins::fastReadDigital(_dataPin);
+ byte map=_pinMap[xmitBit%8];
+ //DIAG(F("DIN x=%d,d=%d m=%x"),xmitBit,data,map);
+ if (data) _pinValues[xmitBit/8] |= map;
+ else _pinValues[xmitBit/8] &= ~map;
+ ArduinoPins::fastWriteDigital(_clockPin, HIGH);
+ }
+ // DIAG(F("DIN %x"),_pinValues[0]);
+ }
+
+void _loopOutput() {
+ // stream out the bitmap (highest pin first)
+ _xmitPending=false;
+ ArduinoPins::fastWriteDigital(_latchPin, LOW);
+ for (int xmitBit=_nShiftBytes*8 -1; xmitBit>=0; xmitBit--) {
+ ArduinoPins::fastWriteDigital(_dataPin,GET_BIT(xmitBit));
+ ArduinoPins::fastWriteDigital(_clockPin,HIGH);
+ ArduinoPins::fastWriteDigital(_clockPin,LOW);
+ }
+ digitalWrite(_latchPin, HIGH);
+ }
+
+ int _read(VPIN vpin) override {
+ return GET_BIT(vpin - _firstVpin);
+ }
+
+ void _write(VPIN vpin, int value) override {
+ int pin = vpin - _firstVpin;
+ bool oldval=GET_BIT(pin);
+ bool newval=value!=0;
+ if (newval==oldval) return; // no change
+ if (newval) SET_BIT(pin);
+ else CLR_BIT(pin);
+ _xmitPending=true; // shift register will be sent on next _loop()
+ }
+
+ void _display() override {
+ DIAG(F("IO_LEWDUINO %SPUT Configured on VPins:%d-%d"),
+ _pinMap?F("IN"):F("OUT"),
+ (int)_firstVpin,
+ (int)_firstVpin+_nPins-1);
+ }
+
+private:
+ static const unsigned long POLL_MICROS=100000; // 10 / S
+ unsigned long _prevMicros;
+ int _nShiftBytes=0;
+ VPIN _latchPin,_clockPin,_dataPin;
+ byte* _pinValues;
+ bool _xmitPending; // Only relevant in output mode
+ const byte* _pinMap; // NULL in output mode
+};
+
+class IO_DNIN8 {
+public:
+ static void create(VPIN firstVpin, int nPins, byte latchPin, byte clockPin, byte dataPin )
+ {
+ // input arrives as board pin 0,7,6,5,1,2,3,4
+ static const byte pinmap[8]={0x80,0x01,0x02,0x04,0x40,0x20,0x10,0x08};
+ new IO_LEWDUINO( firstVpin, nPins, latchPin, clockPin, dataPin,pinmap);
+ }
+
+};
+
+class IO_DNIN8K {
+public:
+ static void create(VPIN firstVpin, int nPins, byte clockPin, byte latchPin, byte dataPin )
+ {
+ static const byte pinmap[8]={0x80,0x01,0x02,0x04,0x40,0x20,0x10,0x08}; // TODO
+ new IO_LEWDUINO( firstVpin, nPins, clockPin, latchPin, dataPin,pinmap);
+ }
+};
+
+class IO_DNOUT8 {
+public:
+ static void create(VPIN firstVpin, int nPins, byte clockPin, byte latchPin, byte dataPin )
+ {
+ new IO_LEWDUINO( firstVpin, nPins, clockPin, latchPin, dataPin,NULL);
+ }
+
+};
+#endif
\ No newline at end of file