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

View File

@@ -20,18 +20,25 @@ NeoBrgFeature KEYWORD1
NeoRbgFeature KEYWORD1
DotStarBgrFeature KEYWORD1
DotStarLbgrFeature KEYWORD1
NeoWs2813Method KEYWORD1
Neo800KbpsMethod KEYWORD1
Neo400KbpsMethod KEYWORD1
NeoAvrWs2813Method KEYWORD1
NeoAvr800KbpsMethod KEYWORD1
NeoAvr400KbpsMethod KEYWORD1
NeoEsp8266DmaWs2813Method KEYWORD1
NeoEsp8266Dma800KbpsMethod KEYWORD1
NeoEsp8266Dma400KbpsMethod KEYWORD1
NeoEsp8266UartWs2813Method KEYWORD1
NeoEsp8266Uart800KbpsMethod KEYWORD1
NeoEsp8266Uart400KbpsMethod KEYWORD1
NeoEsp8266AsyncUartWs2813Method KEYWORD1
NeoEsp8266AsyncUart800KbpsMethod KEYWORD1
NeoEsp8266AsyncUart400KbpsMethod KEYWORD1
NeoEsp8266BitBangWs2813Method KEYWORD1
NeoEsp8266BitBang800KbpsMethod KEYWORD1
NeoEsp8266BitBang400KbpsMethod KEYWORD1
NeoEsp32BitBangWs2813Method KEYWORD1
NeoEsp32BitBang800KbpsMethod KEYWORD1
NeoEsp32BitBang400KbpsMethod KEYWORD1
DotStarMethod KEYWORD1

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;

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;

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;

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;

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;