David Grayson / PololuLedStrip

Dependents:   WoYaoChengGOng V2-WoYaoChengGOng STM32_MagneticLight tape_Led_Sample ... more

Committer:
DavidEGrayson
Date:
Wed Nov 01 23:11:49 2017 +0000
Revision:
26:c3193bc73cff
Parent:
25:d72818ba17cc
Make it be a compile-time error if GPIO_IP_WITHOUT_BRR is set.

Who changed what in which revision?

UserRevisionLine numberNew 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 {
DavidEGrayson 8:1578776ceac5 55 calculateDelays();
DavidEGrayson 8:1578776ceac5 56
DavidEGrayson 1:102307d9b701 57 __disable_irq(); // Disable interrupts temporarily because we don't want our pulse timing to be messed up.
DavidEGrayson 7:9a088f042ee0 58
DavidEGrayson 1:102307d9b701 59 while(count--)
DavidEGrayson 1:102307d9b701 60 {
DavidEGrayson 9:6ffb85d69eaf 61 led_strip_write_color(colors, gpio.reg_set, gpio.reg_clr, gpio.mask);
DavidEGrayson 9:6ffb85d69eaf 62 colors++;
DavidEGrayson 9:6ffb85d69eaf 63
DavidEGrayson 1:102307d9b701 64 if (interruptFriendly)
DavidEGrayson 1:102307d9b701 65 {
DavidEGrayson 1:102307d9b701 66 __enable_irq();
DavidEGrayson 1:102307d9b701 67 __nop();
DavidEGrayson 1:102307d9b701 68 __nop();
DavidEGrayson 1:102307d9b701 69 __nop();
DavidEGrayson 1:102307d9b701 70 __disable_irq();
DavidEGrayson 1:102307d9b701 71 }
DavidEGrayson 1:102307d9b701 72 }
DavidEGrayson 1:102307d9b701 73
DavidEGrayson 1:102307d9b701 74 __enable_irq(); // Re-enable interrupts now that we are done.
DavidEGrayson 25:d72818ba17cc 75 wait_us(80); // Send the reset signal.
DavidEGrayson 1:102307d9b701 76 }