From 1bff517adf624648c71fabbe8e8302ecbf235802 Mon Sep 17 00:00:00 2001 From: penfold42 Date: Sun, 14 May 2017 03:09:26 +1000 Subject: [PATCH] Ammeded timing to suit new revision of ws2812c (#439) Should also work with WS2813 (but untested) Included comments on the timing calculations --- libsrc/leddevice/LedDeviceWs2812SPI.cpp | 47 +++++++++++++++++++++---- libsrc/leddevice/LedDeviceWs2812SPI.h | 2 ++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/libsrc/leddevice/LedDeviceWs2812SPI.cpp b/libsrc/leddevice/LedDeviceWs2812SPI.cpp index b211e56d..b98db68f 100644 --- a/libsrc/leddevice/LedDeviceWs2812SPI.cpp +++ b/libsrc/leddevice/LedDeviceWs2812SPI.cpp @@ -1,8 +1,43 @@ #include "LedDeviceWs2812SPI.h" +/* +From the data sheet: + +(TH+TL=1.25μs±600ns) + +T0H, 0 code, high level time, 0.40µs ±0.150ns +T0L, 0 code, low level time, 0.85µs ±0.150ns +T1H, 1 code, high level time, 0.80µs ±0.150ns +T1L, 1 code, low level time, 0.45µs ±0.150ns +WT, Wait for the processing time, NA +Trst, Reset code,low level time, 50µs (not anymore... need 300uS for latest revision) + +To normalise the pulse times so they fit in 4 SPI bits: + +On the assumption that the "low" time doesnt matter much + +A SPI bit time of 0.40uS = 2.5 Mbit/sec +T0 is sent as 1000 +T1 is sent as 1100 + +With a bit of excel testing, we can work out the maximum and minimum speeds: +2106000 MIN +2590500 AVG +3075000 MAX + +Wait time: +Not Applicable for WS2812 + +Reset time: +using the max of 3075000, the bit time is 0.325 +Reset time is 300uS = 923 bits = 116 bytes + +*/ + LedDeviceWs2812SPI::LedDeviceWs2812SPI(const QJsonObject &deviceConfig) : ProviderSpi() , SPI_BYTES_PER_COLOUR(4) + , SPI_FRAME_END_LATCH_BYTES(116) , bitpair_to_byte { 0b10001000, 0b10001100, @@ -20,14 +55,13 @@ LedDevice* LedDeviceWs2812SPI::construct(const QJsonObject &deviceConfig) bool LedDeviceWs2812SPI::init(const QJsonObject &deviceConfig) { - _baudRate_Hz = 3000000; + _baudRate_Hz = 2600000; if ( !ProviderSpi::init(deviceConfig) ) { return false; } - WarningIf(( _baudRate_Hz < 2050000 || _baudRate_Hz > 4000000 ), _log, "SPI rate %d outside recommended range (2050000 -> 4000000)", _baudRate_Hz); + WarningIf(( _baudRate_Hz < 2106000 || _baudRate_Hz > 3075000 ), _log, "SPI rate %d outside recommended range (2106000 -> 3075000)", _baudRate_Hz); - const int SPI_FRAME_END_LATCH_BYTES = 3; _ledBuffer.resize(_ledRGBCount * SPI_BYTES_PER_COLOUR + SPI_FRAME_END_LATCH_BYTES, 0x00); return true; @@ -52,9 +86,10 @@ int LedDeviceWs2812SPI::write(const std::vector &ledValues) spi_ptr += SPI_BYTES_PER_LED; } - _ledBuffer[spi_ptr++] = 0; - _ledBuffer[spi_ptr++] = 0; - _ledBuffer[spi_ptr++] = 0; + for (int j=0; j < SPI_FRAME_END_LATCH_BYTES; j++) + { + _ledBuffer[spi_ptr++] = 0; + } return writeBytes(_ledBuffer.size(), _ledBuffer.data()); } diff --git a/libsrc/leddevice/LedDeviceWs2812SPI.h b/libsrc/leddevice/LedDeviceWs2812SPI.h index b7facf8c..4da3d9fb 100644 --- a/libsrc/leddevice/LedDeviceWs2812SPI.h +++ b/libsrc/leddevice/LedDeviceWs2812SPI.h @@ -37,5 +37,7 @@ private: const int SPI_BYTES_PER_COLOUR; + const int SPI_FRAME_END_LATCH_BYTES; + uint8_t bitpair_to_byte[4]; };