From 03ffce54f001cd26a55e84724c53ade93b2d23dd Mon Sep 17 00:00:00 2001 From: Rishi Groen Date: Fri, 8 Nov 2024 11:35:13 +0100 Subject: [PATCH] For Review Only --- src/internal/methods/11StepDMXEncoding.PNG | Bin 0 -> 24210 bytes .../methods/EndianDependantByteOrder.PNG | Bin 0 -> 11581 bytes src/internal/methods/NeoBits.h | 30 +- src/internal/methods/NeoEsp32I2sMethod.h | 413 +++++++++++++++++- .../methods/NeoEsp8266I2sDmx512Method.h | 2 +- 5 files changed, 411 insertions(+), 34 deletions(-) create mode 100644 src/internal/methods/11StepDMXEncoding.PNG create mode 100644 src/internal/methods/EndianDependantByteOrder.PNG diff --git a/src/internal/methods/11StepDMXEncoding.PNG b/src/internal/methods/11StepDMXEncoding.PNG new file mode 100644 index 0000000000000000000000000000000000000000..0b61bc8943cbfb22993de12d5e5c6925af1ffd73 GIT binary patch literal 24210 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

Gva@l+mr;T_|!<^z<^6M7(a3|1=`rsc29 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 literal 0 HcmV?d00001 diff --git a/src/internal/methods/NeoBits.h b/src/internal/methods/NeoBits.h index ba7ab42..2a65cb0 100644 --- a/src/internal/methods/NeoBits.h +++ b/src/internal/methods/NeoBits.h @@ -5,7 +5,7 @@ NeoPixel library helper functions for Methods. Written by Michael C. Miller. I invest time and resources providing this open source code, -please support me by donating (see https://github.com/Makuna/NeoPixelBus) +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) ------------------------------------------------------------------------- This file is part of the Makuna/NeoPixelBus library. @@ -25,73 +25,71 @@ License along with NeoPixel. If not, see . -------------------------------------------------------------------------*/ -class NeoBitsSpeedBase +// -------------------------------------------------------- +class NeoBitsSpeedDmx512 { public: - static uint16_t ByteSendTimeUs(uint16_t bitSendTimeNs) - { - return (bitSendTimeNs * 8) / 1000; - } + const static uint16_t BitSendTimeNs = 4000; //5500; // 4us, 250Kbps so 4000 * 11 / 8 + const static uint16_t ResetTimeUs = 500; // 6 x 32us equals 3 Words. }; -// -------------------------------------------------------- -class NeoBitsSpeedWs2812x : public NeoBitsSpeedBase +class NeoBitsSpeedWs2812x { public: const static uint16_t BitSendTimeNs = 1250; const static uint16_t ResetTimeUs = 300; }; -class NeoBitsSpeedWs2805 : public NeoBitsSpeedBase +class NeoBitsSpeedWs2805 { public: const static uint16_t BitSendTimeNs = 1125; const static uint16_t ResetTimeUs = 300; // spec is 280, intentionally longer for compatiblity use }; -class NeoBitsSpeedSk6812 : public NeoBitsSpeedBase +class NeoBitsSpeedSk6812 { public: const static uint16_t BitSendTimeNs = 1250; const static uint16_t ResetTimeUs = 80; }; -class NeoBitsSpeedTm1814 : public NeoBitsSpeedBase +class NeoBitsSpeedTm1814 { public: const static uint16_t BitSendTimeNs = 1250; const static uint16_t ResetTimeUs = 200; }; -class NeoBitsSpeedTm1914 : public NeoBitsSpeedBase +class NeoBitsSpeedTm1914 { public: const static uint16_t BitSendTimeNs = 1250; const static uint16_t ResetTimeUs = 200; }; -class NeoBitsSpeedTm1829 : public NeoBitsSpeedBase +class NeoBitsSpeedTm1829 { public: const static uint16_t BitSendTimeNs = 1250; const static uint16_t ResetTimeUs = 200; }; -class NeoBitsSpeed800Kbps : public NeoBitsSpeedBase +class NeoBitsSpeed800Kbps { public: const static uint16_t BitSendTimeNs = 1250; const static uint16_t ResetTimeUs = 50; }; -class NeoBitsSpeed400Kbps : public NeoBitsSpeedBase +class NeoBitsSpeed400Kbps { public: const static uint16_t BitSendTimeNs = 2500; const static uint16_t ResetTimeUs = 50; }; -class NeoBitsSpeedApa106 : public NeoBitsSpeedBase +class NeoBitsSpeedApa106 { public: const static uint16_t BitSendTimeNs = 1710; diff --git a/src/internal/methods/NeoEsp32I2sMethod.h b/src/internal/methods/NeoEsp32I2sMethod.h index 85aae16..9ed3783 100644 --- a/src/internal/methods/NeoEsp32I2sMethod.h +++ b/src/internal/methods/NeoEsp32I2sMethod.h @@ -4,7 +4,7 @@ NeoPixel library helper functions for Esp32. Written by Michael C. Miller. I invest time and resources providing this open source code, -please support me by donating (see https://github.com/Makuna/NeoPixelBus) +please support me by dontating (see https://github.com/Makuna/NeoPixelBus) ------------------------------------------------------------------------- This file is part of the Makuna/NeoPixelBus library. @@ -65,16 +65,248 @@ class NeoEsp32I2sBusN const uint8_t I2sBusNumber; }; +//---------------------------------------------------------- // -------------------------------------------------------- +// 11 step cadences, specifically for DMX output +// + +class NeoEsp32I2sCadence11Step11BitLookup // this is the quickest, include start & stop bits in the lookup + // and use a double lookup to reduce bit-shifting +{ +//#define _USE32BIT_ // the 32_bit lookup table is faster since it omits the clearing of the lsWord + // but of course uses more memory on the stack +public: + const static size_t DmaBitsPerPixelByte = 11; + + static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData) + { + uint16_t* pDma = reinterpret_cast(dmaBuffer); + uint16_t dmaValue[2] = {0, 0}; // 16-bit dual buffer, used for reading the created word(s) +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ // See 11-Step DMX Encoding.PNG for schematic explanation + const uint8_t msW = 0, lsW = 1; +#else + const uint8_t lsW = 0, msW = 1; +#endif + uint32_t* dmaV32 = reinterpret_cast(dmaValue); // pointer for the 32-bit version + // the 32-bit version is used to shift the bits so the lsBits shift into the lsWord + // and are not just discarded + const uint8_t* pSrc = data; + const uint8_t* pEnd = pSrc + sizeData; + const uint8_t BitsInSample = 16; //sizeof(dmaValue) * 8; + uint8_t destBitsLeft = BitsInSample; + *(pDma++) = 0x0000; // start the break. + *(pDma++) = 0x0000; // with the headebyte added it doesn't fit into 4 bytes anymore + *(pDma++) = 0xf803; // 0b1111 1000 0000 0011 + *pDma = 0x0; // clear the first word !! + +#ifndef _USE32BIT_ + const uint16_t LookUpMsN[16] = {0x003, 0x023, 0x013, 0x033, 0x00b, 0x02b, 0x01b, 0x03b, + 0x007, 0x027, 0x017, 0x037, 0x00f, 0x02f, 0x01f, 0x03f + }; + const uint16_t LookUpLsN[16] = {0x000, 0x200, 0x100, 0x300, 0x080, 0x280, 0x180, 0x380, + 0x040, 0x240, 0x140, 0x340, 0x0c0, 0x2c0, 0x1c0, 0x3c0 + }; +#else + const uint32_t LookUpMsN[16] = {0x0030000, 0x0230000, 0x0130000, 0x0330000, 0x00b0000, 0x02b0000, 0x01b0000, 0x03b0000, + 0x0070000, 0x0270000, 0x0170000, 0x0370000, 0x00f0000, 0x02f0000, 0x01f0000, 0x03f0000 + }; + const uint32_t LookUpLsN[16] = {0x0000000, 0x2000000, 0x1000000, 0x3000000, 0x0800000, 0x2800000, 0x1800000, 0x3800000, + 0x0400000, 0x2400000, 0x1400000, 0x3400000, 0x0c00000, 0x2c00000, 0x1c00000, 0x3c00000 + }; +#endif + + while (pSrc < pEnd) + { +#ifndef _USE32BIT_ + dmaValue[msW] = LookUpLsN[(*pSrc) & 0x0f] | LookUpMsN[(*pSrc) >> 4]; // lookup value into the msWord + // works like an automatic 16-bit Shift +#else + *dmaV32 = LookUpLsN[(*pSrc) & 0x0f] | LookUpMsN[(*pSrc) >> 4]; + // basically read it as a 32-bit (asignment clears lsWord automatically) +#endif + pSrc++; + if (destBitsLeft < 11) // Split the Bits + { + *dmaV32 = *dmaV32 >> (11 - destBitsLeft); // shift it as a 32-bit, so the rightshifted bits end up in the lsWord + *(pDma++) |= dmaValue[msW]; // the msWord & and up the 16-bit Dma buffer pointer + *pDma = dmaValue[lsW]; // lsWord aka whatever got shifted out of the variable + // instead of shifting again to obtain these bits, they are available and ready for 'or' +#ifndef _USE32BIT_ + dmaValue[lsW] = 0; // clear the lsWord after use, not needed when using 32-bit lookup +#endif + destBitsLeft += 5; // 11 bits subtracted but rolled over backwards = 5 bits added. + } + else + { + *dmaV32 = *dmaV32 << (destBitsLeft - 11); // shift to be the next bit + *pDma |= dmaValue[msW]; // 'or' the most significant Word + destBitsLeft -= 11; // substract the 11 bits added + } + } + if (destBitsLeft) + { + *pDma |= 0xffff >> (16 - destBitsLeft); + } + } +}; + + + +class NeoEsp32I2sCadence11Step8BitLookup +{ +public: + const static size_t DmaBitsPerPixelByte = 11; + + static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData) + { + const uint8_t* pSrc = data; + const uint8_t* pEnd = pSrc + sizeData; + uint16_t* pDma = reinterpret_cast(dmaBuffer); + const uint8_t Reverse8BitsLookup[16] = {0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf}; + // significantly quicker than calling a separate function, at least in my speed test. + + int8_t outputBit = 16; + uint16_t output = 0; + + *(pDma++) = 0x0000; // start the break. + *(pDma++) = 0x0000; // with the headebyte added it doesn't fit into 4 bytes anymore + *(pDma++) = 0xf803; // 0b1111 1000 0000 0011 + while (pSrc < pEnd) + { + uint8_t invertedByte = (Reverse8BitsLookup[*pSrc & 0xf] << 4) | Reverse8BitsLookup[*pSrc >> 4]; + pSrc++; + if (outputBit > 10) + { + outputBit -= 1; + output |= 0 << outputBit; + outputBit -= 8; + output |= invertedByte << outputBit; + outputBit -= 2; + output |= 3 << outputBit; + } + else + { + // split across an output uint16_t + // handle start bit + if (outputBit < 1) + { + *(pDma++) = output; + output = 0; + outputBit += 16; + } + outputBit -= 1; + output |= 0 << outputBit; + // handle data bits + if (outputBit < 8) + { + output |= invertedByte >> (8 - outputBit); + *(pDma++) = output; + output = 0; + outputBit += 16; + } + outputBit -= 8; + output |= invertedByte << outputBit; + // handle stop bits + if (outputBit < 2) + { + output |= 3 >> (2 - outputBit); + *(pDma++) = output; + output = 0; + outputBit += 16; + } + outputBit -= 2; + output |= 3 << outputBit; + } + } + if (outputBit > 0) + { + // padd last output uint16_t with Mtbp + output |= 0xffff >> (16 - outputBit); + *(pDma++) = output; + } + } +}; + + +class NeoEsp32I2sCadence11StepNoLookup +{ +public: + const static size_t DmaBitsPerPixelByte = 11; + + static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData) + { + + uint16_t* pDma = reinterpret_cast(dmaBuffer); + uint16_t dmaValue = 0; + const uint8_t* pSrc = data; + const uint8_t* pEnd = pSrc + sizeData; + const size_t BitsInSample = sizeof(dmaValue) * 8; + + uint8_t destBitsLeft = BitsInSample; + + + *(pDma++) = 0x0000; // start the break. + *(pDma++) = 0x0000; // with the headerbyte added it doesn't fit into 4 bytes anymore + *(pDma++) = 0xf803; // 0b1111 1000 0000 0011 + + + while (pSrc < pEnd) + { + uint8_t source = *(pSrc++); + if (!destBitsLeft) + { + destBitsLeft = BitsInSample; + *(pDma++) = dmaValue; + //dmaValue = 0; // not needed and a waste of time. + } + dmaValue = dmaValue << 1; // start Bit + destBitsLeft--; + + for (uint8_t i = 0; i < 8; i++) // data bits + { + if (!destBitsLeft) + { + destBitsLeft = BitsInSample; + *(pDma++) = dmaValue; + //dmaValue = 0; // not needed all bits will have been shifted out + } + dmaValue = dmaValue << 1; + dmaValue |= (source & 1); + source = source >> 1; + destBitsLeft--; + } + + for (uint8_t i = 0; i < 2; i++) // stop bits + { + if (!destBitsLeft) + { + destBitsLeft = BitsInSample; + *(pDma++) = dmaValue; + //dmaValue = 0; + } + dmaValue = dmaValue << 1; + dmaValue |= 1; + destBitsLeft--; + } + } + if (destBitsLeft) { + dmaValue = dmaValue << destBitsLeft; // shift the significant bits fully left + dmaValue |= (0xffff >> (BitsInSample - destBitsLeft)); // fill it up with HIGh bits + *pDma++ = dmaValue; // and store the remaining bits + } + } +}; + // 4 step cadence, so pulses are 1/4 and 3/4 of pulse width // class NeoEsp32I2sCadence4Step { public: - const static size_t DmaBitsPerPixelBit = 4; // 4 step cadence, matches encoding + //const static size_t DmaBitsPerPixelBit = 4; // 4 step cadence, matches encoding + const static size_t DmaBitsPerPixelByte = 32; // 4 step cadence, matches encoding static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData) { @@ -90,12 +322,140 @@ class NeoEsp32I2sCadence4Step const uint8_t* pEnd = data + sizeData; for (const uint8_t* pSrc = data; pSrc < pEnd; pSrc++) { - *(pDma++) = bitpatterns[((*pSrc) >> 4) & 0x0f]; + *(pDma++) = bitpatterns[((*pSrc) >> 4) /*& 0x0f*/]; // the mask is obsolete, an 8-bit shifted 4 + // bits doesn't have any other bits left. *(pDma++) = bitpatterns[((*pSrc) & 0x0f)]; } } }; +class NeoEsp32I2sCadence3Stepfast +{ +public: + //const static size_t DmaBitsPerPixelBit = 3; // 3 step cadence, matches encoding + const static size_t DmaBitsPerPixelByte = 24; // 3 step cadence, matches encoding + + static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData) + { + const uint32_t bitpatternsLow[16] = + { + 0x000924, 0x000926, 0x000934, 0x000936, 0x0009A4, 0x0009A6, 0x0009B4, 0x0009B6, + 0x000D24, 0x000D26, 0x000D34, 0x000D36, 0x000DA4, 0x000DA6, 0x000DB4, 0x000DB6 + + }; + const uint32_t bitpatternsHigh[16] = + { + 0x924000, 0x926000, 0x934000, 0x936000, 0x9A4000, 0x9A6000, 0x9B4000, 0x9B6000, + 0xD24000, 0xD26000, 0xD34000, 0xD36000, 0xDA4000, 0xDA6000, 0xDB4000, 0xDB6000 + + }; + uint32_t output[2]; // 2x 24-bit bitPattern in consequetive location + uint8_t * output8 = reinterpret_cast(output); + + uint8_t* pDma = dmaBuffer; + const uint8_t* pEnd = data + sizeData - 1; // Encode 2 bytes at a time, make sure they are there + const uint8_t* pSrc = data; + while (pSrc < pEnd) + { + output[0] = bitpatternsHigh[((*pSrc) >> 4)] | bitpatternsLow[((*pSrc) & 0x0f)]; + pSrc++; + output[1] = bitpatternsHigh[((*pSrc) >> 4)] | bitpatternsLow[((*pSrc) & 0x0f)]; + pSrc++; // note: the mask for the bitpatternsHigh index should be obsolete + // To get the 2x 3-byte values in the right order copy them Byte by Byte +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ // see Endian Dependant Byte Order.PNG for schematic explanation + memcpy(pDma++, output8 + 1 , 1); + memcpy(pDma++, output8 + 2 , 1); + memcpy(pDma++, output8 + 3 , 1); + memcpy(pDma++, output8 + 5 , 1); + memcpy(pDma++, output8 + 6 , 1); + memcpy(pDma++, output8 + 7 , 1); +#else + memcpy(pDma++, output8 + 1 , 1); + memcpy(pDma++, output8 + 2 , 1); + memcpy(pDma++, output8 + 6 , 1); + memcpy(pDma++, output8 + 0 , 1); + memcpy(pDma++, output8 + 4 , 1); + memcpy(pDma++, output8 + 5 , 1); +#endif + } + if (pSrc == pEnd) // the last pixelbuffer byte if it exists + { + output[0] = bitpatternsHigh[((*pSrc) >> 4) & 0x0f] | bitpatternsLow[((*pSrc) & 0x0f)]; +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + memcpy(pDma++, output8 + 1 , 1); + memcpy(pDma++, output8 + 2 , 1); + memcpy(pDma++, output8 + 3 , 1); +#else + memcpy(pDma++, output8 + 1 , 1); + memcpy(pDma++, output8 + 2 , 1); + pDma++; + memcpy(pDma++, output8 + 0 , 1); +#endif + } + } +}; + +/* Not used, kept for reference, slower than the previous method +class NeoEsp32I2sCadence3Stepfast2 +{ +public: + //const static size_t DmaBitsPerPixelBit = 3; // 3 step cadence, matches encoding + const static size_t DmaBitsPerPixelByte = 24; // 3 step cadence, matches encoding + static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData) + { + const uint16_t bitpatterns[6][16] = { + { + 0x9240, 0x9260, 0x9340, 0x9360, 0x9A40, 0x9A60, 0x9B40, 0x9B60, + 0xD240, 0xD260, 0xD340, 0xD360, 0xDA40, 0xDA60, 0xDB40, 0xDB60 + }, + { + 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, + 0x000D, 0x000D, 0x000D, 0x000D, 0x000D, 0x000D, 0x000D, 0x000D + }, + { + 0x0092, 0x0092, 0x0093, 0x0093, 0x009A, 0x009A, 0x009B, 0x009B, + 0x00D2, 0x00D2, 0x00D3, 0x00D3, 0x00DA, 0x00DA, 0x00DB, 0x00DB + }, + { + 0x2400, 0x2600, 0x3400, 0x3600, 0xA400, 0xA600, 0xB400, 0xB600, + 0x2400, 0x2600, 0x3400, 0x3600, 0xA400, 0xA600, 0xB400, 0xB600 + }, + { + 0x4000, 0x6000, 0x4000, 0x6000, 0x4000, 0x6000, 0x4000, 0x6000, + 0x4000, 0x6000, 0x4000, 0x6000, 0x4000, 0x6000, 0x4000, 0x6000 + }, + { + 0x0924, 0x0926, 0x0934, 0x0936, 0x09A4, 0x09A6, 0x09B4, 0x09B6, + 0x0D24, 0x0D26, 0x0D34, 0x0D36, 0x0DA4, 0x0DA6, 0x0DB4, 0x0DB6 + }}; + + + uint16_t* pDma = reinterpret_cast(dmaBuffer); + const uint8_t* pEnd = data + sizeData - 1; // Encode 2 bytes at a time, make sure they are there + const uint8_t* pSrc = data; + + while (pSrc < pEnd) + { + uint8_t msNibble = ((*pSrc) >> 4) & 0x0f, lsNibble = (*pSrc) & 0x0f; + *(pDma++) = bitpatterns[0][msNibble] | bitpatterns[1][lsNibble]; + pSrc++; + msNibble = ((*pSrc) >> 4) & 0x0f; + *(pDma++) = bitpatterns[2][msNibble] | bitpatterns[3][lsNibble]; + lsNibble = (*pSrc) & 0x0f; + *(pDma++) = bitpatterns[4][msNibble] | bitpatterns[5][lsNibble]; + pSrc++; + } + if (pSrc == pEnd) // the last pixelbuffer byte if it exists + { + uint8_t msNibble = ((*pSrc) >> 4) & 0x0f, lsNibble = (*pSrc) & 0x0f; + *(pDma++) = bitpatterns[0][msNibble] | bitpatterns[1][lsNibble]; + *(pDma++) = bitpatterns[3][lsNibble]; + } + } +}; +*/ + + // fedc ba98 7654 3210 // 0000 0000 0000 0000 // 111 @@ -104,7 +464,8 @@ class NeoEsp32I2sCadence4Step class NeoEsp32I2sCadence3Step { public: - const static size_t DmaBitsPerPixelBit = 3; // 3 step cadence, matches encoding + //const static size_t DmaBitsPerPixelBit = 3; // 3 step cadence, matches encoding + const static size_t DmaBitsPerPixelByte = 24; // 3 step cadence, matches encoding static void EncodeIntoDma(uint8_t* dmaBuffer, const uint8_t* data, size_t sizeData) { @@ -224,8 +585,9 @@ template(heap_caps_malloc(_i2sBufferSize, MALLOC_CAP_DMA)); // no need to initialize all of it, but since it contains - // "reset" bits that don't latter get overwritten we just clear it all - memset(_i2sBuffer, 0x00, _i2sBufferSize); + // "reset" bits that don't later get overwritten we just clear it all + + memset(_i2sBuffer, 0x00, _i2sBufferSize); + } +}; + +//typedef NeoEsp32I2sCadence11StepNoLookup NeoEsp32I2sCadence11Step; + +//typedef NeoEsp32I2sCadence11Step8BitLookup NeoEsp32I2sCadence11Step; + +typedef NeoEsp32I2sCadence11Step11BitLookup NeoEsp32I2sCadence11Step; + +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Dmx512Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Dmx512InvertedMethod; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Dmx512Method; +typedef NeoEsp32I2sMethodBase NeoEsp32I2s1Dmx512InvertedMethod; -}; #if defined(NPB_CONF_4STEP_CADENCE) typedef NeoEsp32I2sCadence4Step NeoEsp32I2sCadence; #else + +//typedef NeoEsp32I2sCadence3Step NeoEsp32I2sCadence; -typedef NeoEsp32I2sCadence3Step NeoEsp32I2sCadence; +typedef NeoEsp32I2sCadence3Stepfast NeoEsp32I2sCadence; #endif + typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Ws2812xMethod; typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Ws2805Method; typedef NeoEsp32I2sMethodBase NeoEsp32I2s0Sk6812Method; diff --git a/src/internal/methods/NeoEsp8266I2sDmx512Method.h b/src/internal/methods/NeoEsp8266I2sDmx512Method.h index 9dc717d..28de195 100644 --- a/src/internal/methods/NeoEsp8266I2sDmx512Method.h +++ b/src/internal/methods/NeoEsp8266I2sDmx512Method.h @@ -241,7 +241,7 @@ template class NeoEsp8266I2sDmx512MethodBase : NeoEsp8266I2sMe // encodes the data with start and stop bits // input buffer is bytes - // output stream is uint31_t + // output stream is uint32_t static void Encoder(const uint8_t* pSrc, const uint8_t* pSrcEnd, uint32_t* pOutput, const uint32_t* pOutputEnd) {