LED bus driver on any GPIO pin for addressable RGB LEDs (like NeoPixels or other WS2812 based LEDs)
LEDBus.cpp@3:67e68c46daef, 2017-06-14 (annotated)
- Committer:
- koengroener
- Date:
- Wed Jun 14 20:37:31 2017 +0000
- Revision:
- 3:67e68c46daef
- Parent:
- 2:735bb1b9cfc2
Added LEDArray class, for a more simplistic way of communcation with the LED strip
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
koengroener | 0:1e68c70236a4 | 1 | #include "LEDBus.h" |
koengroener | 0:1e68c70236a4 | 2 | |
koengroener | 2:735bb1b9cfc2 | 3 | LEDBus::LEDBus(PinName wirePin, ColorByteOrder byteOrder, float t0h_us, float t0l_us, float t1h_us, float t1l_us, float tReset_us) : _wire(wirePin) |
koengroener | 0:1e68c70236a4 | 4 | { |
koengroener | 0:1e68c70236a4 | 5 | float ticksPerMicroSecond = SystemCoreClock/MICRO_SECOND; |
koengroener | 0:1e68c70236a4 | 6 | |
koengroener | 0:1e68c70236a4 | 7 | _byteOrder = byteOrder; |
koengroener | 0:1e68c70236a4 | 8 | |
koengroener | 0:1e68c70236a4 | 9 | _delayT1H = ticksPerMicroSecond * t1h_us; |
koengroener | 0:1e68c70236a4 | 10 | _delayT0H = ticksPerMicroSecond * t0h_us; |
koengroener | 0:1e68c70236a4 | 11 | _delayT1L = ticksPerMicroSecond * t1l_us; |
koengroener | 0:1e68c70236a4 | 12 | _delayT0L = ticksPerMicroSecond * t0l_us; |
koengroener | 0:1e68c70236a4 | 13 | |
koengroener | 0:1e68c70236a4 | 14 | _delayReset = ticksPerMicroSecond * tReset_us; |
koengroener | 0:1e68c70236a4 | 15 | |
koengroener | 0:1e68c70236a4 | 16 | // Uncomment to see micro controller frequency and delays |
koengroener | 1:6119419c2730 | 17 | // Serial pc(USBTX, USBRX); |
koengroener | 1:6119419c2730 | 18 | // pc.printf("%d Hz\n\r", SystemCoreClock); |
koengroener | 1:6119419c2730 | 19 | // pc.printf("%f ticks/us\n\r", ticksPerMicroSecond); |
koengroener | 1:6119419c2730 | 20 | // pc.printf("T0H: %d ticks\n\r", _delayT0H); |
koengroener | 1:6119419c2730 | 21 | // pc.printf("T1H: %d ticks\n\r", _delayT1H); |
koengroener | 1:6119419c2730 | 22 | // pc.printf("T0L: %d ticks\n\r", _delayT0L); |
koengroener | 1:6119419c2730 | 23 | // pc.printf("T1L: %d ticks\n\r", _delayT1L); |
koengroener | 1:6119419c2730 | 24 | // pc.printf("Reset: %d ticks\n\r", _delayReset); |
koengroener | 0:1e68c70236a4 | 25 | |
koengroener | 0:1e68c70236a4 | 26 | } |
koengroener | 0:1e68c70236a4 | 27 | |
koengroener | 0:1e68c70236a4 | 28 | LEDBus::~LEDBus() |
koengroener | 0:1e68c70236a4 | 29 | { |
koengroener | 0:1e68c70236a4 | 30 | } |
koengroener | 0:1e68c70236a4 | 31 | |
koengroener | 0:1e68c70236a4 | 32 | void LEDBus::write(uint8_t byte) |
koengroener | 0:1e68c70236a4 | 33 | { |
koengroener | 0:1e68c70236a4 | 34 | for (int b = 7; b >= 0; b--) { |
koengroener | 0:1e68c70236a4 | 35 | bool bit = byte & (1 << b); |
koengroener | 0:1e68c70236a4 | 36 | |
koengroener | 0:1e68c70236a4 | 37 | _wire = 1; |
koengroener | 0:1e68c70236a4 | 38 | |
koengroener | 0:1e68c70236a4 | 39 | if (bit) { |
koengroener | 0:1e68c70236a4 | 40 | delay(_delayT1H); |
koengroener | 0:1e68c70236a4 | 41 | } else { |
koengroener | 0:1e68c70236a4 | 42 | delay(_delayT0H); |
koengroener | 0:1e68c70236a4 | 43 | } |
koengroener | 0:1e68c70236a4 | 44 | |
koengroener | 0:1e68c70236a4 | 45 | _wire = 0; |
koengroener | 0:1e68c70236a4 | 46 | |
koengroener | 0:1e68c70236a4 | 47 | if (bit) { |
koengroener | 0:1e68c70236a4 | 48 | delay(_delayT1L); |
koengroener | 0:1e68c70236a4 | 49 | } else { |
koengroener | 0:1e68c70236a4 | 50 | delay(_delayT0L); |
koengroener | 0:1e68c70236a4 | 51 | } |
koengroener | 0:1e68c70236a4 | 52 | } |
koengroener | 0:1e68c70236a4 | 53 | } |
koengroener | 0:1e68c70236a4 | 54 | |
koengroener | 2:735bb1b9cfc2 | 55 | void LEDBus::delay(unsigned const int ticks) |
koengroener | 0:1e68c70236a4 | 56 | { |
koengroener | 2:735bb1b9cfc2 | 57 | //loop_ticks is empirically determined (aka: works on my machine...) |
koengroener | 2:735bb1b9cfc2 | 58 | const int loop_ticks = 8; |
koengroener | 2:735bb1b9cfc2 | 59 | for (unsigned volatile int i = 0; i <= ticks-(loop_ticks/2); i+=loop_ticks) { |
koengroener | 0:1e68c70236a4 | 60 | /* nop */ |
koengroener | 0:1e68c70236a4 | 61 | } |
koengroener | 0:1e68c70236a4 | 62 | } |
koengroener | 0:1e68c70236a4 | 63 | |
koengroener | 0:1e68c70236a4 | 64 | void LEDBus::write(uint8_t* buffer, unsigned int size) |
koengroener | 0:1e68c70236a4 | 65 | { |
koengroener | 0:1e68c70236a4 | 66 | for (int i = 0; i < size; i++) { |
koengroener | 0:1e68c70236a4 | 67 | write(buffer[i]); |
koengroener | 0:1e68c70236a4 | 68 | } |
koengroener | 0:1e68c70236a4 | 69 | |
koengroener | 0:1e68c70236a4 | 70 | delay(_delayReset); |
koengroener | 0:1e68c70236a4 | 71 | } |
koengroener | 0:1e68c70236a4 | 72 | |
koengroener | 0:1e68c70236a4 | 73 | void LEDBus::write(Color** buffer, unsigned int size) |
koengroener | 0:1e68c70236a4 | 74 | { |
koengroener | 0:1e68c70236a4 | 75 | for (int i = 0; i < size; i++) { |
koengroener | 0:1e68c70236a4 | 76 | switch(_byteOrder) { |
koengroener | 0:1e68c70236a4 | 77 | case RGB: |
koengroener | 0:1e68c70236a4 | 78 | write(buffer[i]->red); |
koengroener | 0:1e68c70236a4 | 79 | write(buffer[i]->green); |
koengroener | 0:1e68c70236a4 | 80 | write(buffer[i]->blue); |
koengroener | 0:1e68c70236a4 | 81 | break; |
koengroener | 0:1e68c70236a4 | 82 | case RBG: |
koengroener | 0:1e68c70236a4 | 83 | write(buffer[i]->red); |
koengroener | 0:1e68c70236a4 | 84 | write(buffer[i]->blue); |
koengroener | 0:1e68c70236a4 | 85 | write(buffer[i]->green); |
koengroener | 0:1e68c70236a4 | 86 | break; |
koengroener | 0:1e68c70236a4 | 87 | case GRB: |
koengroener | 0:1e68c70236a4 | 88 | write(buffer[i]->green); |
koengroener | 0:1e68c70236a4 | 89 | write(buffer[i]->red); |
koengroener | 0:1e68c70236a4 | 90 | write(buffer[i]->blue); |
koengroener | 0:1e68c70236a4 | 91 | break; |
koengroener | 0:1e68c70236a4 | 92 | case GBR: |
koengroener | 0:1e68c70236a4 | 93 | write(buffer[i]->green); |
koengroener | 0:1e68c70236a4 | 94 | write(buffer[i]->blue); |
koengroener | 0:1e68c70236a4 | 95 | write(buffer[i]->red); |
koengroener | 0:1e68c70236a4 | 96 | break; |
koengroener | 0:1e68c70236a4 | 97 | case BRG: |
koengroener | 0:1e68c70236a4 | 98 | write(buffer[i]->blue); |
koengroener | 0:1e68c70236a4 | 99 | write(buffer[i]->red); |
koengroener | 0:1e68c70236a4 | 100 | write(buffer[i]->green); |
koengroener | 0:1e68c70236a4 | 101 | case BGR: |
koengroener | 0:1e68c70236a4 | 102 | write(buffer[i]->blue); |
koengroener | 0:1e68c70236a4 | 103 | write(buffer[i]->green); |
koengroener | 0:1e68c70236a4 | 104 | write(buffer[i]->red); |
koengroener | 0:1e68c70236a4 | 105 | break; |
koengroener | 0:1e68c70236a4 | 106 | } |
koengroener | 0:1e68c70236a4 | 107 | |
koengroener | 0:1e68c70236a4 | 108 | } |
koengroener | 0:1e68c70236a4 | 109 | |
koengroener | 0:1e68c70236a4 | 110 | delay(_delayReset); |
koengroener | 0:1e68c70236a4 | 111 | } |
koengroener | 0:1e68c70236a4 | 112 | |
koengroener | 0:1e68c70236a4 | 113 | |
koengroener | 0:1e68c70236a4 | 114 | void LEDBus::update(ColorGenerator generator, unsigned int numberOfLEDs) |
koengroener | 0:1e68c70236a4 | 115 | { |
koengroener | 0:1e68c70236a4 | 116 | unsigned char buffer[numberOfLEDs*3]; |
koengroener | 0:1e68c70236a4 | 117 | |
koengroener | 0:1e68c70236a4 | 118 | for (int i = 0; i < numberOfLEDs; i++) { |
koengroener | 0:1e68c70236a4 | 119 | Color* color = new Color(); |
koengroener | 0:1e68c70236a4 | 120 | generator(color, i); |
koengroener | 0:1e68c70236a4 | 121 | |
koengroener | 0:1e68c70236a4 | 122 | int ir,ig,ib; |
koengroener | 0:1e68c70236a4 | 123 | |
koengroener | 0:1e68c70236a4 | 124 | switch(_byteOrder) { |
koengroener | 0:1e68c70236a4 | 125 | case RGB: |
koengroener | 0:1e68c70236a4 | 126 | ir = 0; |
koengroener | 0:1e68c70236a4 | 127 | ig = 1; |
koengroener | 0:1e68c70236a4 | 128 | ib = 2; |
koengroener | 0:1e68c70236a4 | 129 | break; |
koengroener | 0:1e68c70236a4 | 130 | case RBG: |
koengroener | 0:1e68c70236a4 | 131 | ir = 0; |
koengroener | 0:1e68c70236a4 | 132 | ig = 2; |
koengroener | 0:1e68c70236a4 | 133 | ib = 1; |
koengroener | 0:1e68c70236a4 | 134 | break; |
koengroener | 0:1e68c70236a4 | 135 | case GRB: |
koengroener | 0:1e68c70236a4 | 136 | ir = 1; |
koengroener | 0:1e68c70236a4 | 137 | ig = 0; |
koengroener | 0:1e68c70236a4 | 138 | ib = 2; |
koengroener | 0:1e68c70236a4 | 139 | break; |
koengroener | 0:1e68c70236a4 | 140 | case GBR: |
koengroener | 0:1e68c70236a4 | 141 | ir = 2; |
koengroener | 0:1e68c70236a4 | 142 | ig = 0; |
koengroener | 0:1e68c70236a4 | 143 | ib = 1; |
koengroener | 0:1e68c70236a4 | 144 | break; |
koengroener | 0:1e68c70236a4 | 145 | case BRG: |
koengroener | 0:1e68c70236a4 | 146 | ir = 1; |
koengroener | 0:1e68c70236a4 | 147 | ig = 2; |
koengroener | 0:1e68c70236a4 | 148 | ib = 0; |
koengroener | 0:1e68c70236a4 | 149 | case BGR: |
koengroener | 0:1e68c70236a4 | 150 | ir = 2; |
koengroener | 0:1e68c70236a4 | 151 | ig = 1; |
koengroener | 0:1e68c70236a4 | 152 | ib = 0; |
koengroener | 0:1e68c70236a4 | 153 | break; |
koengroener | 0:1e68c70236a4 | 154 | } |
koengroener | 0:1e68c70236a4 | 155 | |
koengroener | 0:1e68c70236a4 | 156 | buffer[i*3 +ir] = color->red; |
koengroener | 0:1e68c70236a4 | 157 | buffer[i*3 +ig] = color->green; |
koengroener | 0:1e68c70236a4 | 158 | buffer[i*3 +ib] = color->blue; |
koengroener | 0:1e68c70236a4 | 159 | |
koengroener | 0:1e68c70236a4 | 160 | delete color; |
koengroener | 0:1e68c70236a4 | 161 | } |
koengroener | 0:1e68c70236a4 | 162 | |
koengroener | 0:1e68c70236a4 | 163 | write(buffer, numberOfLEDs*3); |
koengroener | 0:1e68c70236a4 | 164 | } |
koengroener | 0:1e68c70236a4 | 165 | |
koengroener | 0:1e68c70236a4 | 166 |