diff --git a/DCCEXParser.cpp b/DCCEXParser.cpp index 0d70895..45327ba 100644 --- a/DCCEXParser.cpp +++ b/DCCEXParser.cpp @@ -405,7 +405,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) return; } if (params==2) { // - for (auto pix=vpin;pix @@ -416,7 +416,7 @@ void DCCEXParser::parseOne(Print *stream, byte *com, RingStream * ringStream) // strange parameter mangling... see IO_NeoPixel.h NeoPixel::_writeAnalogue int colour_RG=(p[1]<<8) | p[2]; uint16_t colour_B=p[3]; - for (auto pix=vpin;pix_writeRange(vpin, value,count); + count-= vpin-vpinBefore; // decrement by number of vpins changed + } + else { + // skip a vpin if no device handler + vpin++; + count--; + } + } +} + // Write analogue value to virtual pin(s). If multiple devices are allocated // the same pin then only the first one found will be used. // @@ -270,6 +290,24 @@ void IODevice::writeAnalogue(VPIN vpin, int value, uint8_t param1, uint16_t para #endif } +// +void IODevice::writeAnalogueRange(VPIN vpin, int value, uint8_t param1, uint16_t param2,int count) { + while(count) { + auto dev = findDevice(vpin); + if (dev) { + auto vpinBefore=vpin; + // write to driver, driver will return next vpin it cant handle + vpin=dev->_writeAnalogueRange(vpin, value, param1, param2,count); + count-= vpin-vpinBefore; // decrement by number of vpins changed + } + else { + // skip a vpin if no device handler + vpin++; + count--; + } + } +} + // isBusy, when called for a device pin is always a digital output or analogue output, // returns input feedback state of the pin, i.e. whether the pin is busy performing // an animation or fade over a period of time. diff --git a/IODevice.h b/IODevice.h index 250f7b4..05df4df 100644 --- a/IODevice.h +++ b/IODevice.h @@ -128,9 +128,11 @@ public: // write invokes the IODevice instance's _write method. static void write(VPIN vpin, int value); + static void writeRange(VPIN vpin, int value,int count); // write invokes the IODevice instance's _writeAnalogue method (not applicable for digital outputs) static void writeAnalogue(VPIN vpin, int value, uint8_t profile=0, uint16_t duration=0); + static void writeAnalogueRange(VPIN vpin, int value, uint8_t profile, uint16_t duration, int count); // isBusy returns true if the device is currently in an animation of some sort, e.g. is changing // the output over a period of time. @@ -177,11 +179,29 @@ public: virtual void _write(VPIN vpin, int value) { (void)vpin; (void)value; }; + + // Method to write new state (optionally implemented within device class) + // This will, by default just write to one vpin and return whet to do next. + // the real power comes where a single driver can update many vpins in one call. + virtual VPIN _writeRange(VPIN vpin, int value, int count) { + (void)count; + _write(vpin,value); + return vpin+1; // try next vpin + }; // Method to write an 'analogue' value (optionally implemented within device class) virtual void _writeAnalogue(VPIN vpin, int value, uint8_t param1=0, uint16_t param2=0) { (void)vpin; (void)value; (void) param1; (void)param2; }; + + // Method to write an 'analogue' value to a VPIN range (optionally implemented within device class) + // This will, by default just write to one vpin and return whet to do next. + // the real power comes where a single driver can update many vpins in one call. + virtual VPIN _writeAnalogueRange(VPIN vpin, int value, uint8_t param1, uint16_t param2, int count) { + (void) count; + _writeAnalogue(vpin, value, param1, param2); + return vpin+1; + }; // Method to read digital pin state (optionally implemented within device class) virtual int _read(VPIN vpin) { diff --git a/IO_NeoPixel.h b/IO_NeoPixel.h index 297e97f..09966b5 100644 --- a/IO_NeoPixel.h +++ b/IO_NeoPixel.h @@ -233,7 +233,17 @@ private: } transmit(pixel); } - + + VPIN _writeRange(VPIN vpin,int value, int count) { + // using write range cuts out the constant vpin to driver lookup so + // we can update multiple pixels much faster. + VPIN nextVpin=vpin + (count>_nPins ? _nPins : count); + if (_deviceState != DEVSTATE_FAILED) while(vpin_nPins ? _nPins : count); + if (_deviceState != DEVSTATE_FAILED) while(vpin