This library lets you control the addressable RGB LED strips from Pololu Robotics. Forked to add selectable colour order (Support RGB or GRB Leds)
Fork of PololuLedStrip by
PololuLedStrip.cpp@27:9a62663f3de2, 2018-05-19 (annotated)
- Committer:
- thegink
- Date:
- Sat May 19 14:16:38 2018 +0000
- Revision:
- 27:9a62663f3de2
- Parent:
- 26:c3193bc73cff
Added #define for RGB/GRB order for WS2811 and WS2812b based strips, respectively. Ideally this should be selectable per instance, but it's late, and I'm tired.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
DavidEGrayson | 1:102307d9b701 | 1 | #include "PololuLedStrip.h" |
DavidEGrayson | 1:102307d9b701 | 2 | |
DavidEGrayson | 26:c3193bc73cff | 3 | // Our assembly code currently does not work with chip families like the STM32F4 |
DavidEGrayson | 26:c3193bc73cff | 4 | // that use the same register and a different mask for setting and clearing |
DavidEGrayson | 26:c3193bc73cff | 5 | // outputs. |
DavidEGrayson | 26:c3193bc73cff | 6 | #ifdef GPIO_IP_WITHOUT_BRR |
DavidEGrayson | 26:c3193bc73cff | 7 | #error This chip is not supported: does not have separate registers for setting and clearing GPIO outputs. |
DavidEGrayson | 26:c3193bc73cff | 8 | #endif |
DavidEGrayson | 26:c3193bc73cff | 9 | |
DavidEGrayson | 1:102307d9b701 | 10 | bool PololuLedStrip::interruptFriendly = false; |
DavidEGrayson | 1:102307d9b701 | 11 | |
DavidEGrayson | 19:46d7ab0ba3e7 | 12 | // The two timed delays, in units of half-cycles. |
DavidEGrayson | 19:46d7ab0ba3e7 | 13 | uint8_t led_strip_write_delays[2]; |
DavidEGrayson | 4:d3b60bd43811 | 14 | |
DavidEGrayson | 7:9a088f042ee0 | 15 | void PololuLedStrip::calculateDelays() |
DavidEGrayson | 7:9a088f042ee0 | 16 | { |
DavidEGrayson | 15:d69eebdee025 | 17 | int f_mhz = SystemCoreClock / 1000000; // Clock frequency in MHz. |
DavidEGrayson | 14:672baf3cf941 | 18 | |
DavidEGrayson | 14:672baf3cf941 | 19 | if (f_mhz <= 48) |
DavidEGrayson | 14:672baf3cf941 | 20 | { |
DavidEGrayson | 19:46d7ab0ba3e7 | 21 | // The delays below result in 360/1120 ns pulses and a 1880 ns period on the mbed NXP LPC11U24. |
DavidEGrayson | 14:672baf3cf941 | 22 | led_strip_write_delays[0] = 0; |
DavidEGrayson | 14:672baf3cf941 | 23 | led_strip_write_delays[1] = 0; |
DavidEGrayson | 14:672baf3cf941 | 24 | } |
DavidEGrayson | 14:672baf3cf941 | 25 | else |
DavidEGrayson | 14:672baf3cf941 | 26 | { |
DavidEGrayson | 22:5368af3ff07d | 27 | // Try to generally compute what the delays should be for a wide range of clock frequencies. |
DavidEGrayson | 14:672baf3cf941 | 28 | |
DavidEGrayson | 14:672baf3cf941 | 29 | // The fudge factors below were experimentally chosen so that we would have |
DavidEGrayson | 23:881d93b8749a | 30 | // ~100 ns and ~840 ns pulses and a ~1430 ns period on the mbed NXP LPC1768 (96 MHz Cortex-M3). |
DavidEGrayson | 17:91fb934a2166 | 31 | // There seem to be some ~100 ns inconsistencies in the timing depending on which example program is |
DavidEGrayson | 17:91fb934a2166 | 32 | // running; the most likely explanation is some kind of flash caching that affects the timing. |
DavidEGrayson | 14:672baf3cf941 | 33 | // If you ever change these numbers, it is important to check the the subtractions below |
DavidEGrayson | 19:46d7ab0ba3e7 | 34 | // will not overflow in the worst case (smallest possible f_mhz). |
DavidEGrayson | 23:881d93b8749a | 35 | // |
DavidEGrayson | 23:881d93b8749a | 36 | // On an STM32F303K8 (72 MHz Cortex-M4), these delays give us ~170 ns and ~840 ns pulses |
DavidEGrayson | 23:881d93b8749a | 37 | // and a ~1595 ns period, and there were no timing differences between the two |
DavidEGrayson | 23:881d93b8749a | 38 | // example programs. |
DavidEGrayson | 19:46d7ab0ba3e7 | 39 | led_strip_write_delays[0] = 750*f_mhz/1000 - 33; |
DavidEGrayson | 19:46d7ab0ba3e7 | 40 | led_strip_write_delays[1] = 550*f_mhz/1000 - 20; |
DavidEGrayson | 15:d69eebdee025 | 41 | } |
DavidEGrayson | 15:d69eebdee025 | 42 | |
DavidEGrayson | 15:d69eebdee025 | 43 | // Convert from units of cycles to units of half-cycles; it makes the assembly faster. |
DavidEGrayson | 22:5368af3ff07d | 44 | led_strip_write_delays[0] <<= 1; |
DavidEGrayson | 22:5368af3ff07d | 45 | led_strip_write_delays[1] <<= 1; |
DavidEGrayson | 7:9a088f042ee0 | 46 | } |
DavidEGrayson | 6:9d0530b7dae2 | 47 | |
DavidEGrayson | 1:102307d9b701 | 48 | PololuLedStrip::PololuLedStrip(PinName pinName) |
DavidEGrayson | 1:102307d9b701 | 49 | { |
DavidEGrayson | 22:5368af3ff07d | 50 | gpio_init_out(&gpio, pinName); |
DavidEGrayson | 1:102307d9b701 | 51 | } |
DavidEGrayson | 1:102307d9b701 | 52 | |
DavidEGrayson | 1:102307d9b701 | 53 | void PololuLedStrip::write(rgb_color * colors, unsigned int count) |
DavidEGrayson | 1:102307d9b701 | 54 | { |
thegink | 27:9a62663f3de2 | 55 | uint8_t t; |
DavidEGrayson | 8:1578776ceac5 | 56 | calculateDelays(); |
thegink | 27:9a62663f3de2 | 57 | |
DavidEGrayson | 1:102307d9b701 | 58 | __disable_irq(); // Disable interrupts temporarily because we don't want our pulse timing to be messed up. |
DavidEGrayson | 7:9a088f042ee0 | 59 | |
DavidEGrayson | 1:102307d9b701 | 60 | while(count--) |
DavidEGrayson | 1:102307d9b701 | 61 | { |
thegink | 27:9a62663f3de2 | 62 | |
thegink | 27:9a62663f3de2 | 63 | #ifdef _POLOLU_ORDER_GRB |
thegink | 27:9a62663f3de2 | 64 | //swap red and green for WS2812b strips |
thegink | 27:9a62663f3de2 | 65 | t = colors->red; |
thegink | 27:9a62663f3de2 | 66 | colors->red = colors->green; |
thegink | 27:9a62663f3de2 | 67 | colors->green = t; |
thegink | 27:9a62663f3de2 | 68 | #endif |
thegink | 27:9a62663f3de2 | 69 | |
DavidEGrayson | 9:6ffb85d69eaf | 70 | led_strip_write_color(colors, gpio.reg_set, gpio.reg_clr, gpio.mask); |
DavidEGrayson | 9:6ffb85d69eaf | 71 | colors++; |
DavidEGrayson | 9:6ffb85d69eaf | 72 | |
DavidEGrayson | 1:102307d9b701 | 73 | if (interruptFriendly) |
DavidEGrayson | 1:102307d9b701 | 74 | { |
DavidEGrayson | 1:102307d9b701 | 75 | __enable_irq(); |
DavidEGrayson | 1:102307d9b701 | 76 | __nop(); |
DavidEGrayson | 1:102307d9b701 | 77 | __nop(); |
DavidEGrayson | 1:102307d9b701 | 78 | __nop(); |
DavidEGrayson | 1:102307d9b701 | 79 | __disable_irq(); |
DavidEGrayson | 1:102307d9b701 | 80 | } |
DavidEGrayson | 1:102307d9b701 | 81 | } |
DavidEGrayson | 1:102307d9b701 | 82 | |
DavidEGrayson | 1:102307d9b701 | 83 | __enable_irq(); // Re-enable interrupts now that we are done. |
DavidEGrayson | 25:d72818ba17cc | 84 | wait_us(80); // Send the reset signal. |
DavidEGrayson | 1:102307d9b701 | 85 | } |