WS2812B

Dependents:   high speed light Bracelet

Fork of PololuLedStrip by David Grayson

Committer:
DavidEGrayson
Date:
Fri Mar 01 05:00:49 2013 +0000
Revision:
14:672baf3cf941
Parent:
13:9c72841ec45e
Child:
15:d69eebdee025
Cleaned up calculateDelays and made it work on the M0 48MHz again.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DavidEGrayson 1:102307d9b701 1 #include "PololuLedStrip.h"
DavidEGrayson 1:102307d9b701 2
DavidEGrayson 1:102307d9b701 3 bool PololuLedStrip::interruptFriendly = false;
DavidEGrayson 1:102307d9b701 4
DavidEGrayson 14:672baf3cf941 5 // The three timed delays, in units of half-instructions.
DavidEGrayson 7:9a088f042ee0 6 uint8_t led_strip_write_delays[3];
DavidEGrayson 4:d3b60bd43811 7
DavidEGrayson 7:9a088f042ee0 8 void PololuLedStrip::calculateDelays()
DavidEGrayson 7:9a088f042ee0 9 {
DavidEGrayson 8:1578776ceac5 10 // Get the clock frequency in MHz.
DavidEGrayson 8:1578776ceac5 11 int f_mhz = SystemCoreClock / 1000000;
DavidEGrayson 14:672baf3cf941 12
DavidEGrayson 14:672baf3cf941 13 if (f_mhz <= 48)
DavidEGrayson 14:672baf3cf941 14 {
DavidEGrayson 14:672baf3cf941 15 // The delays below result in 800/1590 ns pulses and a 2500 ns period on the mbed NXP LPC11U24.
DavidEGrayson 14:672baf3cf941 16 led_strip_write_delays[0] = 0;
DavidEGrayson 14:672baf3cf941 17 led_strip_write_delays[1] = 0;
DavidEGrayson 14:672baf3cf941 18 led_strip_write_delays[2] = 5 << 1;
DavidEGrayson 14:672baf3cf941 19 }
DavidEGrayson 14:672baf3cf941 20 else
DavidEGrayson 14:672baf3cf941 21 {
DavidEGrayson 14:672baf3cf941 22 // Try to generally compute what the delays should be for any frequency clock.
DavidEGrayson 14:672baf3cf941 23
DavidEGrayson 14:672baf3cf941 24 // The fudge factors below were experimentally chosen so that we would have
DavidEGrayson 14:672baf3cf941 25 // 700/1300 ns pulses and a ~ 2500 ns period on the mbed NXP LPC1768 (96 MHz Cortex-M3).
DavidEGrayson 14:672baf3cf941 26 // If you ever change these numbers, it is important to check the the subtractions below
DavidEGrayson 14:672baf3cf941 27 // will not overflow in the worst case, which is f_mhz = 48.
DavidEGrayson 14:672baf3cf941 28 static const uint8_t delay_fudges[] = { 23, 28, 23 };
DavidEGrayson 14:672baf3cf941 29
DavidEGrayson 14:672baf3cf941 30 led_strip_write_delays[0] = 700*f_mhz/1000;
DavidEGrayson 14:672baf3cf941 31 led_strip_write_delays[1] = 600*f_mhz/1000;
DavidEGrayson 14:672baf3cf941 32 led_strip_write_delays[2] = 1200*f_mhz/1000;
DavidEGrayson 8:1578776ceac5 33
DavidEGrayson 14:672baf3cf941 34 for(int i = 0; i < 3; i++)
DavidEGrayson 12:b6df8ac053c8 35 {
DavidEGrayson 14:672baf3cf941 36 if (led_strip_write_delays[i] < delay_fudges[i])
DavidEGrayson 14:672baf3cf941 37 {
DavidEGrayson 14:672baf3cf941 38 led_strip_write_delays[i] = 0;
DavidEGrayson 14:672baf3cf941 39 }
DavidEGrayson 14:672baf3cf941 40 else
DavidEGrayson 14:672baf3cf941 41 {
DavidEGrayson 14:672baf3cf941 42 led_strip_write_delays[i] -= delay_fudges[i];
DavidEGrayson 14:672baf3cf941 43 led_strip_write_delays[i] <<= 1;
DavidEGrayson 14:672baf3cf941 44 }
DavidEGrayson 12:b6df8ac053c8 45 }
DavidEGrayson 12:b6df8ac053c8 46 }
DavidEGrayson 7:9a088f042ee0 47 }
DavidEGrayson 6:9d0530b7dae2 48
DavidEGrayson 1:102307d9b701 49 PololuLedStrip::PololuLedStrip(PinName pinName)
DavidEGrayson 1:102307d9b701 50 {
DavidEGrayson 1:102307d9b701 51 gpio_init(&gpio, pinName, PIN_OUTPUT);
DavidEGrayson 1:102307d9b701 52 }
DavidEGrayson 1:102307d9b701 53
DavidEGrayson 1:102307d9b701 54 void PololuLedStrip::write(rgb_color * colors, unsigned int count)
DavidEGrayson 1:102307d9b701 55 {
DavidEGrayson 8:1578776ceac5 56 calculateDelays();
DavidEGrayson 8:1578776ceac5 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 {
DavidEGrayson 9:6ffb85d69eaf 62 led_strip_write_color(colors, gpio.reg_set, gpio.reg_clr, gpio.mask);
DavidEGrayson 9:6ffb85d69eaf 63 colors++;
DavidEGrayson 9:6ffb85d69eaf 64
DavidEGrayson 1:102307d9b701 65 if (interruptFriendly)
DavidEGrayson 1:102307d9b701 66 {
DavidEGrayson 1:102307d9b701 67 __enable_irq();
DavidEGrayson 1:102307d9b701 68 __nop();
DavidEGrayson 1:102307d9b701 69 __nop();
DavidEGrayson 1:102307d9b701 70 __nop();
DavidEGrayson 1:102307d9b701 71 __disable_irq();
DavidEGrayson 1:102307d9b701 72 }
DavidEGrayson 1:102307d9b701 73 }
DavidEGrayson 1:102307d9b701 74
DavidEGrayson 1:102307d9b701 75 __enable_irq(); // Re-enable interrupts now that we are done.
DavidEGrayson 1:102307d9b701 76 wait_us(24); // Hold the line low for 24 microseconds to send the reset signal.
DavidEGrayson 9:6ffb85d69eaf 77
DavidEGrayson 9:6ffb85d69eaf 78 //*(gpio.reg_set) = gpio.mask;
DavidEGrayson 9:6ffb85d69eaf 79 //*(gpio.reg_clr) = gpio.mask;
DavidEGrayson 9:6ffb85d69eaf 80
DavidEGrayson 1:102307d9b701 81 }