diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index cfb7219..2c3885a 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -578,7 +578,11 @@ bool DCCEXParser::parseZ(Print *stream, int16_t params, int16_t p[]) } return true; - case 3: // + case 3: // + if (p[0] < 0 || + p[1] > 255 || p[1] <= 1 || // Pins 0 and 1 are Serial to USB + p[2] < 0 || p[2] > 7 ) + return false; if (!Output::create(p[0], p[1], p[2], 1)) return false; StringFormatter::send(stream, F("\n")); diff --git a/EEStore.h b/EEStore.h index aaecf4a..77136ae 100644 --- a/EEStore.h +++ b/EEStore.h @@ -33,9 +33,9 @@ extern ExternalEEPROM EEPROM; struct EEStoreData{ char id[sizeof(EESTORE_ID)]; - int nTurnouts; - int nSensors; - int nOutputs; + uint16_t nTurnouts; + uint16_t nSensors; + uint16_t nOutputs; }; struct EEStore{ diff --git a/Outputs.cpp b/Outputs.cpp index b7aa7bc..52cafb8 100644 --- a/Outputs.cpp +++ b/Outputs.cpp @@ -100,14 +100,14 @@ void Output::activate(int s){ /////////////////////////////////////////////////////////////////////////////// -Output* Output::get(int n){ +Output* Output::get(uint16_t n){ Output *tt; for(tt=firstOutput;tt!=NULL && tt->data.id!=n;tt=tt->nextOutput); return(tt); } /////////////////////////////////////////////////////////////////////////////// -bool Output::remove(int n){ +bool Output::remove(uint16_t n){ Output *tt,*pp=NULL; for(tt=firstOutput;tt!=NULL && tt->data.id!=n;pp=tt,tt=tt->nextOutput); @@ -127,17 +127,46 @@ bool Output::remove(int n){ /////////////////////////////////////////////////////////////////////////////// void Output::load(){ - struct OutputData data; + struct BrokenOutputData bdata; Output *tt; + bool isBroken=1; - for(int i=0;idata.nOutputs;i++){ - EEPROM.get(EEStore::pointer(),data); - tt=create(data.id,data.pin,data.iFlag); - tt->data.oStatus=bitRead(tt->data.iFlag,1)?bitRead(tt->data.iFlag,2):data.oStatus; // restore status to EEPROM value is bit 1 of iFlag=0, otherwise set to value of bit 2 of iFlag - digitalWrite(tt->data.pin,tt->data.oStatus ^ bitRead(tt->data.iFlag,0)); - pinMode(tt->data.pin,OUTPUT); - tt->num=EEStore::pointer(); - EEStore::advance(sizeof(tt->data)); + // This is a scary kluge. As we have two formats in EEPROM due to an + // earlier bug, we don't know which we encounter now. So we guess + // that if in all entries this byte has value of 7 or lower this is + // an iFlag and thus the broken format. Otherwise it would be a pin + // id. If someone uses only pins 0 to 7 of their arduino, they + // loose. This is (if you look at an arduino) however unlikely. + + for(uint16_t i=0;idata.nOutputs;i++){ + EEPROM.get(EEStore::pointer()+ i*sizeof(struct BrokenOutputData),bdata); + if (bdata.iFlag > 7) { // it's a pin and not an iFlag! + isBroken=0; + break; + } + } + if ( isBroken ) { + for(uint16_t i=0;idata.nOutputs;i++){ + EEPROM.get(EEStore::pointer(),bdata); + tt=create(bdata.id,bdata.pin,bdata.iFlag); + tt->data.oStatus=bitRead(tt->data.iFlag,1)?bitRead(tt->data.iFlag,2):bdata.oStatus; // restore status to EEPROM value is bit 1 of iFlag=0, otherwise set to value of bit 2 of iFlag + digitalWrite(tt->data.pin,tt->data.oStatus ^ bitRead(tt->data.iFlag,0)); + pinMode(tt->data.pin,OUTPUT); + tt->num=EEStore::pointer(); + EEStore::advance(sizeof(struct BrokenOutputData)); + } + } else { + struct OutputData data; + + for(uint16_t i=0;idata.nOutputs;i++){ + EEPROM.get(EEStore::pointer(),data); + tt=create(data.id,data.pin,data.iFlag); + tt->data.oStatus=bitRead(tt->data.iFlag,1)?bitRead(tt->data.iFlag,2):data.oStatus; // restore status to EEPROM value is bit 1 of iFlag=0, otherwise set to value of bit 2 of iFlag + digitalWrite(tt->data.pin,tt->data.oStatus ^ bitRead(tt->data.iFlag,0)); + pinMode(tt->data.pin,OUTPUT); + tt->num=EEStore::pointer(); + EEStore::advance(sizeof(struct OutputData)); + } } } @@ -160,7 +189,7 @@ void Output::store(){ } /////////////////////////////////////////////////////////////////////////////// -Output *Output::create(int id, int pin, int iFlag, int v){ +Output *Output::create(uint16_t id, uint8_t pin, uint8_t iFlag, uint8_t v){ Output *tt; if(firstOutput==NULL){ diff --git a/Outputs.h b/Outputs.h index 319f704..6132102 100644 --- a/Outputs.h +++ b/Outputs.h @@ -23,25 +23,34 @@ struct OutputData { uint8_t oStatus; - uint8_t id; + uint16_t id; uint8_t pin; uint8_t iFlag; }; +struct BrokenOutputData { + uint8_t oStatus; + uint8_t id; + uint8_t pin; + uint8_t iFlag; +}; + class Output{ - public: + +public: void activate(int s); - static Output* get(int); - static bool remove(int); + static Output* get(uint16_t); + static bool remove(uint16_t); static void load(); static void store(); - static Output *create(int, int, int, int=0); + static Output *create(uint16_t, uint8_t, uint8_t, uint8_t=0); static Output *firstOutput; struct OutputData data; Output *nextOutput; static void printAll(Print *); - private: - int num; // Chris has no idea what this is all about! + +private: + int num; // EEPROM pointer (Chris has no idea what this is all about!) }; // Output diff --git a/Sensors.cpp b/Sensors.cpp index d04f99e..33c3fd6 100644 --- a/Sensors.cpp +++ b/Sensors.cpp @@ -184,7 +184,7 @@ void Sensor::load(){ struct SensorData data; Sensor *tt; - for(int i=0;idata.nSensors;i++){ + for(uint16_t i=0;idata.nSensors;i++){ EEPROM.get(EEStore::pointer(),data); tt=create(data.snum,data.pin,data.pullUp); EEStore::advance(sizeof(tt->data)); diff --git a/Turnouts.cpp b/Turnouts.cpp index 677e746..4c46a68 100644 --- a/Turnouts.cpp +++ b/Turnouts.cpp @@ -103,7 +103,7 @@ void Turnout::load(){ struct TurnoutData data; Turnout *tt; - for(int i=0;idata.nTurnouts;i++){ + for(uint16_t i=0;idata.nTurnouts;i++){ EEPROM.get(EEStore::pointer(),data); if (data.tStatus & STATUS_PWM) tt=create(data.id,data.tStatus & STATUS_PWMPIN, data.inactiveAngle,data.moveAngle); else tt=create(data.id,data.address,data.subAddress); diff --git a/version.h b/version.h index 074a09b..09211fa 100644 --- a/version.h +++ b/version.h @@ -3,8 +3,9 @@ #include "StringFormatter.h" -#define VERSION "3.1.5" -// 3.1.6 Make output ID two bytes (reserved version number for that merge/branch) + +#define VERSION "3.1.6" +// 3.1.6 Make output ID two bytes and guess format/size of registered outputs found in EEPROM // 3.1.5 Fix LCD corruption on power-up // 3.1.4 Refactor OLED and LCD drivers and remove unused code // 3.1.3 Add a loop delay to give more time for sensing an Ethernet cable connection