Initial support for Ws2813 (#170)

This commit is contained in:
Michael Miller
2017-04-09 14:22:07 -07:00
committed by GitHub
parent 073c89deb6
commit 6a33cbf710
6 changed files with 150 additions and 13 deletions
+81 -8
View File
@@ -56,7 +56,7 @@ public:
{
uint32_t delta = micros() - _endTime;
return (delta >= 50L);
return (delta >= T_SPEED::ResetTimeUs);
}
void Initialize()
@@ -109,12 +109,22 @@ private:
#if defined(__MK20DX128__) || defined(__MK20DX256__) // Teensy 3.0 & 3.1
class NeoArmMk20dxSpeedPropsWs2813
{
public:
static const uint32_t CyclesT0h = (F_CPU / 4000000);
static const uint32_t CyclesT1h = (F_CPU / 1250000);
static const uint32_t Cycles = (F_CPU / 800000);
static const uint32_t ResetTimeUs = 250;
};
class NeoArmMk20dxSpeedProps800Kbps
{
public:
static const uint32_t CyclesT0h = (F_CPU / 4000000);
static const uint32_t CyclesT1h = (F_CPU / 1250000);
static const uint32_t Cycles = (F_CPU / 800000);
static const uint32_t ResetTimeUs = 50;
};
class NeoArmMk20dxSpeedProps400Kbps
@@ -123,11 +133,14 @@ public:
static const uint32_t CyclesT0h = (F_CPU / 2000000);
static const uint32_t CyclesT1h = (F_CPU / 833333);
static const uint32_t Cycles = (F_CPU / 400000);
static const uint32_t ResetTimeUs = 50;
};
template<typename T_SPEEDPROPS> class NeoArmMk20dxSpeedBase
{
public:
static const uint32_t ResetTimeUs = T_SPEEDPROPS::ResetTimeUs;
static void send_pixels(uint8_t* pixels, size_t sizePixels, uint8_t pin)
{
uint8_t* p = pixels;
@@ -167,6 +180,7 @@ public:
}
};
typedef NeoArmMethodBase<NeoArmMk20dxSpeedBase<NeoArmMk20dxSpeedPropsWs2813>> NeoArmWs2813Method;
typedef NeoArmMethodBase<NeoArmMk20dxSpeedBase<NeoArmMk20dxSpeedProps800Kbps>> NeoArm800KbpsMethod;
typedef NeoArmMethodBase<NeoArmMk20dxSpeedBase<NeoArmMk20dxSpeedProps400Kbps>> NeoArm400KbpsMethod;
@@ -176,7 +190,7 @@ typedef NeoArmMethodBase<NeoArmMk20dxSpeedBase<NeoArmMk20dxSpeedProps400Kbps>> N
class NeoArmMk26z64Speed800Kbps
class NeoArmMk26z64Speed800KbpsBase
{
public:
static void send_pixels(uint8_t* pixels, size_t sizePixels, uint8_t pin)
@@ -266,6 +280,19 @@ public:
}
};
class NeoArmMk26z64SpeedWs2813 : public NeoArmMk26z64Speed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 250;
};
class NeoArmMk26z64Speed800Kbps : public NeoArmMk26z64Speed800KbpsBase
{
public:
const static uint32_t ResetTimeUs = 50;
}
typedef NeoArmMethodBase<NeoArmMk26z64SpeedWs2813> NeoArmWs2813Method;
typedef NeoArmMethodBase<NeoArmMk26z64Speed800Kbps> NeoArm800KbpsMethod;
#else
@@ -275,7 +302,7 @@ typedef NeoArmMethodBase<NeoArmMk26z64Speed800Kbps> NeoArm800KbpsMethod;
#elif defined(__SAMD21G18A__) // Arduino Zero
class NeoArmSamd21g18aSpeedProps800Kbps
class NeoArmSamd21g18aSpeedProps800KbpsBase
{
public:
static void BitPreWait()
@@ -300,6 +327,19 @@ public:
}
};
class NeoArmSamd21g18aSpeedPropsWs2813 : public NeoArmSamd21g18aSpeedProps800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 250;
};
class NeoArmSamd21g18aSpeedProps800Kbps : public NeoArmSamd21g18aSpeedProps800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 50;
};
class NeoArmSamd21g18aSpeedProps400Kbps
{
public:
@@ -325,11 +365,14 @@ public:
{
asm("nop; nop; nop; nop; nop; nop; nop;");
}
static const uint32_t ResetTimeUs = 50;
};
template<typename T_SPEEDPROPS> class NeoArmSamd21g18aSpeedBase
{
public:
static const uint32_t ResetTimeUs = T_SPEEDPROPS::ResetTimeUs;
static void send_pixels(uint8_t* pixels, size_t sizePixels, uint8_t pin)
{
// Tried this with a timer/counter, couldn't quite get adequate
@@ -376,15 +419,15 @@ public:
}
};
typedef NeoArmMethodBase<NeoArmSamd21g18aSpeedBase<NeoArmSamd21g18aSpeedPropsWs2813>> NeoArmWs2813Method;
typedef NeoArmMethodBase<NeoArmSamd21g18aSpeedBase<NeoArmSamd21g18aSpeedProps800Kbps>> NeoArm800KbpsMethod;
typedef NeoArmMethodBase<NeoArmSamd21g18aSpeedBase<NeoArmSamd21g18aSpeedProps400Kbps>> NeoArm400KbpsMethod;
#elif defined (ARDUINO_STM32_FEATHER) // FEATHER WICED (120MHz)
class NeoArmStm32SpeedProps800Kbps
class NeoArmStm32SpeedProps800KbpsBase
{
public:
static void BitT1hWait()
{
asm("nop; nop; nop; nop; nop; nop; nop; nop;"
@@ -432,9 +475,20 @@ class NeoArmStm32SpeedProps800Kbps
"nop; nop; nop; nop; nop; nop; nop; nop;"
"nop; nop; nop; nop;");
}
};
class NeoArmStm32SpeedProps800Kbps : public NeoArmStm32SpeedProps800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 50;
};
class NeoArmStm32SpeedPropsWs2813 : public NeoArmStm32SpeedProps800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 250;
};
/* TODO - not found in Adafruit library
class NeoArmStm32SpeedProps400Kbps
{
@@ -455,6 +509,9 @@ static void BitT0lWait()
template<typename T_SPEEDPROPS> class NeoArmStm32SpeedBase
{
public:
static const uint32_t ResetTimeUs = T_SPEEDPROPS::ResetTimeUs;
static void send_pixels(uint8_t* pixels, size_t sizePixels, uint8_t pin)
{
// Tried this with a timer/counter, couldn't quite get adequate
@@ -510,6 +567,7 @@ template<typename T_SPEEDPROPS> class NeoArmStm32SpeedBase
}
};
typedef NeoArmMethodBase<NeoArmStm32SpeedBase<NeoArmStm32SpeedPropsWs2813>> NeoArmWs2813Method;
typedef NeoArmMethodBase<NeoArmStm32SpeedBase<NeoArmStm32SpeedProps800Kbps>> NeoArm800KbpsMethod;
#else // Other ARM architecture -- Presumed Arduino Due
@@ -518,12 +576,22 @@ typedef NeoArmMethodBase<NeoArmStm32SpeedBase<NeoArmStm32SpeedProps800Kbps>> Neo
#define ARM_OTHER_SCALE VARIANT_MCK / 2UL / 1000000UL
#define ARM_OTHER_INST (2UL * F_CPU / VARIANT_MCK)
class NeoArmOtherSpeedPropsWs2813
{
public:
static const uint32_t CyclesT0h = ((uint32_t)(0.40 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST));
static const uint32_t CyclesT1h = ((uint32_t)(0.80 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST));
static const uint32_t Cycles = ((uint32_t)(1.25 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST));
static const uint32_t ResetTimeUs = 250;
};
class NeoArmOtherSpeedProps800Kbps
{
public:
static const uint32_t CyclesT0h = ((uint32_t)(0.40 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST));
static const uint32_t CyclesT1h = ((uint32_t)(0.80 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST));
static const uint32_t Cycles = ((uint32_t)(1.25 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST));
static const uint32_t ResetTimeUs = 50;
};
class NeoArmOtherSpeedProps400Kbps
@@ -532,11 +600,14 @@ public:
static const uint32_t CyclesT0h = ((uint32_t)(0.50 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST));
static const uint32_t CyclesT1h = ((uint32_t)(1.20 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST));
static const uint32_t Cycles = ((uint32_t)(2.50 * ARM_OTHER_SCALE + 0.5) - (5 * ARM_OTHER_INST));
static const uint32_t ResetTimeUs = 50;
};
template<typename T_SPEEDPROPS> class NeoArmOtherSpeedBase
{
public:
static const uint32_t ResetTimeUs = T_SPEEDPROPS::ResetTimeUs;
static void send_pixels(uint8_t* pixels, size_t sizePixels, uint8_t pin)
{
uint32_t pinMask;
@@ -608,6 +679,7 @@ public:
}
};
typedef NeoArmMethodBase<NeoArmOtherSpeedBase<NeoArmOtherSpeedPropsWs2813>> NeoArmWs2813Method;
typedef NeoArmMethodBase<NeoArmOtherSpeedBase<NeoArmOtherSpeedProps800Kbps>> NeoArm800KbpsMethod;
typedef NeoArmMethodBase<NeoArmOtherSpeedBase<NeoArmOtherSpeedProps400Kbps>> NeoArm400KbpsMethod;
@@ -615,6 +687,7 @@ typedef NeoArmMethodBase<NeoArmOtherSpeedBase<NeoArmOtherSpeedProps400Kbps>> Neo
// Arm doesn't have alternatives methods yet, so only one to make the default
typedef NeoArmWs2813Method NeoWs2813Method;
typedef NeoArm800KbpsMethod Neo800KbpsMethod;
#ifdef NeoArm400KbpsMethod // this is needed due to missing 400Kbps for some platforms
typedef NeoArm400KbpsMethod Neo400KbpsMethod;
+18 -2
View File
@@ -41,7 +41,7 @@ extern "C"
void send_pixels_16mhz_400(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask);
}
class NeoAvrSpeed800Kbps
class NeoAvrSpeed800KbpsBase
{
public:
static void send_pixels(uint8_t* pixels, size_t sizePixels, volatile uint8_t* port, uint8_t pinMask)
@@ -68,6 +68,19 @@ public:
#error "CPU SPEED NOT SUPPORTED"
#endif
}
};
class NeoAvrSpeedWs2813 : public NeoAvrSpeed800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 250;
};
class NeoAvrSpeed800Kbps: public NeoAvrSpeed800KbpsBase
{
public:
static const uint32_t ResetTimeUs = 50;
};
class NeoAvrSpeed400Kbps
@@ -87,6 +100,7 @@ public:
#error "CPU SPEED NOT SUPPORTED"
#endif
}
static const uint32_t ResetTimeUs = 50;
};
template<typename T_SPEED> class NeoAvrMethodBase
@@ -118,7 +132,7 @@ public:
{
uint32_t delta = micros() - _endTime;
return (delta >= 50L);
return (delta >= T_SPEED::ResetTimeUs);
}
void Initialize()
@@ -173,10 +187,12 @@ private:
uint8_t _pinMask; // Output PORT bitmask
};
typedef NeoAvrMethodBase<NeoAvrSpeedWs2813> NeoAvrWs2813Method;
typedef NeoAvrMethodBase<NeoAvrSpeed800Kbps> NeoAvr800KbpsMethod;
typedef NeoAvrMethodBase<NeoAvrSpeed400Kbps> NeoAvr400KbpsMethod;
// AVR doesn't have alternatives yet, so there is just the default
typedef NeoAvrWs2813Method NeoWs2813Method;
typedef NeoAvr800KbpsMethod Neo800KbpsMethod;
typedef NeoAvr400KbpsMethod Neo400KbpsMethod;
+13 -1
View File
@@ -63,12 +63,20 @@ struct slc_queue_item
uint32 next_link_ptr;
};
class NeoEsp8266DmaSpeedWs2813
{
public:
const static uint32_t I2sClockDivisor = 3;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ResetTimeUs = 250;
};
class NeoEsp8266DmaSpeed800Kbps
{
public:
const static uint32_t I2sClockDivisor = 3;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ResetTimeUs = 50;
};
class NeoEsp8266DmaSpeed400Kbps
@@ -76,6 +84,7 @@ class NeoEsp8266DmaSpeed400Kbps
public:
const static uint32_t I2sClockDivisor = 6;
const static uint32_t I2sBaseClockDivisor = 16;
const static uint32_t ResetTimeUs = 50;
};
enum NeoDmaState
@@ -268,7 +277,8 @@ private:
// normally 24 bytes creates the minimum 50us latch per spec, but
// with the new logic, this latch is used to space between three states
uint8_t _i2sZeroes[8];
// buffer size = (24 * (speed / 50)) / 3
uint8_t _i2sZeroes[(24L * (T_SPEED::ResetTimeUs / 50L)) / 3L];
slc_queue_item* _i2sBufDesc; // dma block descriptors
uint16_t _i2sBufDescCount; // count of block descriptors in _i2sBufDesc
@@ -360,10 +370,12 @@ private:
template<typename T_SPEED>
NeoEsp8266DmaMethodBase<T_SPEED>* NeoEsp8266DmaMethodBase<T_SPEED>::s_this;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeedWs2813> NeoEsp8266DmaWs2813Method;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeed800Kbps> NeoEsp8266Dma800KbpsMethod;
typedef NeoEsp8266DmaMethodBase<NeoEsp8266DmaSpeed400Kbps> NeoEsp8266Dma400KbpsMethod;
// Dma method is the default method for Esp8266
typedef NeoEsp8266DmaWs2813Method NeoWs2813Method;
typedef NeoEsp8266Dma800KbpsMethod Neo800KbpsMethod;
typedef NeoEsp8266Dma400KbpsMethod Neo400KbpsMethod;
+15 -1
View File
@@ -75,12 +75,22 @@ private:
uint8_t* _asyncPixels; // Holds a copy of LED color values taken when UpdateUart began
};
// NeoEsp8266UartSpeedWs2813 contains the timing constants used to get NeoPixelBus running with the Ws2813
class NeoEsp8266UartSpeedWs2813
{
public:
static const uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element at 800khz speed
static const uint32_t UartBaud = 3200000; // 800mhz, 4 serial bytes per NeoByte
static const uint32_t ResetTimeUs = 250; // us between data send bursts to reset for next update
};
// NeoEsp8266UartSpeed800Kbps contains the timing constant used to get NeoPixelBus running at 800Khz
class NeoEsp8266UartSpeed800Kbps
{
public:
static const uint32_t ByteSendTimeUs = 10; // us it takes to send a single pixel element at 800khz speed
static const uint32_t UartBaud = 3200000; // 800mhz, 4 serial bytes per NeoByte
static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update
};
// NeoEsp8266UartSpeed800Kbps contains the timing constant used to get NeoPixelBus running at 400Khz
@@ -89,6 +99,7 @@ class NeoEsp8266UartSpeed400Kbps
public:
static const uint32_t ByteSendTimeUs = 20; // us it takes to send a single pixel element at 400khz speed
static const uint32_t UartBaud = 1600000; // 400mhz, 4 serial bytes per NeoByte
static const uint32_t ResetTimeUs = 50; // us between data send bursts to reset for next update
};
// NeoEsp8266UartMethodBase is a light shell arround NeoEsp8266Uart or NeoEsp8266AsyncUart that
@@ -109,7 +120,7 @@ public:
bool IsReadyToUpdate() const
{
uint32_t delta = micros() - this->_startTime;
return delta >= getPixelTime() + 50;
return delta >= getPixelTime() + T_SPEED::ResetTimeUs;
}
void Initialize()
@@ -155,8 +166,11 @@ private:
};
};
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2813, NeoEsp8266Uart> NeoEsp8266UartWs2813Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266Uart> NeoEsp8266Uart800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266Uart> NeoEsp8266Uart400KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeedWs2813, NeoEsp8266AsyncUart> NeoEsp8266AsyncUartWs2813Method;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed800Kbps, NeoEsp8266AsyncUart> NeoEsp8266AsyncUart800KbpsMethod;
typedef NeoEsp8266UartMethodBase<NeoEsp8266UartSpeed400Kbps, NeoEsp8266AsyncUart> NeoEsp8266AsyncUart400KbpsMethod;
+16 -1
View File
@@ -39,6 +39,16 @@ License along with NeoPixel. If not, see
extern "C" void ICACHE_RAM_ATTR bitbang_send_pixels_800(uint8_t* pixels, uint8_t* end, uint8_t pin);
extern "C" void ICACHE_RAM_ATTR bitbang_send_pixels_400(uint8_t* pixels, uint8_t* end, uint8_t pin);
class NeoEspBitBangSpeedWs2813
{
public:
static void send_pixels(uint8_t* pixels, uint8_t* end, uint8_t pin)
{
bitbang_send_pixels_800(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 250;
};
class NeoEspBitBangSpeed800Kbps
{
public:
@@ -46,6 +56,7 @@ public:
{
bitbang_send_pixels_800(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 50;
};
class NeoEspBitBangSpeed400Kbps
@@ -55,6 +66,7 @@ public:
{
bitbang_send_pixels_400(pixels, end, pin);
}
static const uint32_t ResetTimeUs = 50;
};
template<typename T_SPEED> class NeoEspBitBangMethodBase
@@ -81,7 +93,7 @@ public:
{
uint32_t delta = micros() - _endTime;
return (delta >= 50L);
return (delta >= T_SPEED::ResetTimeUs);
}
void Initialize()
@@ -134,15 +146,18 @@ private:
#if defined(ARDUINO_ARCH_ESP32)
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2813> NeoEsp32BitBangWs2813Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps> NeoEsp32BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps> NeoEsp32BitBang400KbpsMethod;
// Bitbang method is the default method for Esp32
typedef NeoEsp32BitBangWs2813Method NeoWs2813Method;
typedef NeoEsp32BitBang800KbpsMethod Neo800KbpsMethod;
typedef NeoEsp32BitBang400KbpsMethod Neo400KbpsMethod;
#else
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeedWs2813> NeoEsp8266BitBangWs2813Method;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed800Kbps> NeoEsp8266BitBang800KbpsMethod;
typedef NeoEspBitBangMethodBase<NeoEspBitBangSpeed400Kbps> NeoEsp8266BitBang400KbpsMethod;