WS2812
Dependents: pelion-example-common
WS2812.cpp@3:6e60574091dd, 2018-11-12 (annotated)
- Committer:
- MACRUM
- Date:
- Mon Nov 12 05:05:50 2018 +0000
- Revision:
- 3:6e60574091dd
- Parent:
- 1:aadbf08c62a2
- Child:
- 4:11215bdf5084
Support GCC_ARM compiler
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
bridadan | 0:0b79cafcb387 | 1 | #include "WS2812.h" |
bridadan | 0:0b79cafcb387 | 2 | |
MACRUM | 3:6e60574091dd | 3 | #if defined ( __GNUC__ ) /* GCC Compiler */ |
MACRUM | 3:6e60574091dd | 4 | #define NOP __asm __volatile("nop\n") |
MACRUM | 3:6e60574091dd | 5 | #else |
MACRUM | 3:6e60574091dd | 6 | #define NOP __nop() |
MACRUM | 3:6e60574091dd | 7 | #endif |
MACRUM | 3:6e60574091dd | 8 | |
bridadan | 1:aadbf08c62a2 | 9 | WS2812::WS2812(PinName pin, int size, int zeroHigh, int zeroLow, int oneHigh, int oneLow) : __gpo(pin) |
bridadan | 0:0b79cafcb387 | 10 | { |
bridadan | 0:0b79cafcb387 | 11 | __size = size; |
bridadan | 0:0b79cafcb387 | 12 | __transmitBuf = new bool[size * FRAME_SIZE]; |
bridadan | 1:aadbf08c62a2 | 13 | __use_II = OFF; |
bridadan | 0:0b79cafcb387 | 14 | __II = 0xFF; // set global intensity to full |
bridadan | 1:aadbf08c62a2 | 15 | __outPin = pin; |
bridadan | 0:0b79cafcb387 | 16 | |
bridadan | 0:0b79cafcb387 | 17 | // Default values designed for K64f. Assumes GPIO toggle takes ~0.4us |
bridadan | 1:aadbf08c62a2 | 18 | setDelays(zeroHigh, zeroLow, oneHigh, oneLow); |
bridadan | 0:0b79cafcb387 | 19 | } |
bridadan | 0:0b79cafcb387 | 20 | |
bridadan | 0:0b79cafcb387 | 21 | |
bridadan | 0:0b79cafcb387 | 22 | WS2812::~WS2812() |
bridadan | 0:0b79cafcb387 | 23 | { |
bridadan | 0:0b79cafcb387 | 24 | delete[] __transmitBuf; |
bridadan | 0:0b79cafcb387 | 25 | } |
bridadan | 0:0b79cafcb387 | 26 | |
bridadan | 0:0b79cafcb387 | 27 | void WS2812::setDelays(int zeroHigh, int zeroLow, int oneHigh, int oneLow) { |
bridadan | 0:0b79cafcb387 | 28 | __zeroHigh = zeroHigh; |
bridadan | 0:0b79cafcb387 | 29 | __zeroLow = zeroLow; |
bridadan | 0:0b79cafcb387 | 30 | __oneHigh = oneHigh; |
bridadan | 0:0b79cafcb387 | 31 | __oneLow = oneLow; |
bridadan | 0:0b79cafcb387 | 32 | } |
bridadan | 0:0b79cafcb387 | 33 | |
bridadan | 0:0b79cafcb387 | 34 | void WS2812::__loadBuf(int buf[],int r_offset, int g_offset, int b_offset) { |
bridadan | 0:0b79cafcb387 | 35 | for (int i = 0; i < __size; i++) { |
bridadan | 0:0b79cafcb387 | 36 | int color = 0; |
bridadan | 0:0b79cafcb387 | 37 | |
bridadan | 0:0b79cafcb387 | 38 | color |= ((buf[(i+g_offset)%__size] & 0x0000FF00)); |
bridadan | 0:0b79cafcb387 | 39 | color |= ((buf[(i+r_offset)%__size] & 0x00FF0000)); |
bridadan | 0:0b79cafcb387 | 40 | color |= (buf[(i+b_offset)%__size] & 0x000000FF); |
bridadan | 0:0b79cafcb387 | 41 | color |= (buf[i] & 0xFF000000); |
bridadan | 0:0b79cafcb387 | 42 | |
bridadan | 0:0b79cafcb387 | 43 | // Outut format : GGRRBB |
bridadan | 0:0b79cafcb387 | 44 | // Inout format : IIRRGGBB |
bridadan | 0:0b79cafcb387 | 45 | unsigned char agrb[4] = {0x0, 0x0, 0x0, 0x0}; |
bridadan | 0:0b79cafcb387 | 46 | |
bridadan | 0:0b79cafcb387 | 47 | unsigned char sf; // scaling factor for II |
bridadan | 0:0b79cafcb387 | 48 | |
bridadan | 0:0b79cafcb387 | 49 | // extract colour fields from incoming |
bridadan | 0:0b79cafcb387 | 50 | // 0 = green, 1 = red, 2 = blue, 3 = brightness |
bridadan | 0:0b79cafcb387 | 51 | agrb[0] = (color & 0x0000FF00) >> 8; |
bridadan | 0:0b79cafcb387 | 52 | agrb[1] = (color & 0x00FF0000) >> 16; |
bridadan | 0:0b79cafcb387 | 53 | agrb[2] = color & 0x000000FF; |
bridadan | 0:0b79cafcb387 | 54 | agrb[3] = (color & 0xFF000000) >> 24; |
bridadan | 0:0b79cafcb387 | 55 | |
bridadan | 1:aadbf08c62a2 | 56 | // set the intensity scaling factor (global, per pixel, none) |
bridadan | 1:aadbf08c62a2 | 57 | if (__use_II == GLOBAL) { |
bridadan | 0:0b79cafcb387 | 58 | sf = __II; |
bridadan | 1:aadbf08c62a2 | 59 | } else if (__use_II == PER_PIXEL) { |
bridadan | 0:0b79cafcb387 | 60 | sf = agrb[3]; |
bridadan | 0:0b79cafcb387 | 61 | } else { |
bridadan | 0:0b79cafcb387 | 62 | sf = 0xFF; |
bridadan | 0:0b79cafcb387 | 63 | } |
bridadan | 0:0b79cafcb387 | 64 | |
bridadan | 0:0b79cafcb387 | 65 | // Apply the scaling factor to each othe colour components |
bridadan | 0:0b79cafcb387 | 66 | for (int clr = 0; clr < 3; clr++) { |
bridadan | 0:0b79cafcb387 | 67 | agrb[clr] = ((agrb[clr] * sf) >> 8); |
bridadan | 0:0b79cafcb387 | 68 | |
bridadan | 0:0b79cafcb387 | 69 | for (int j = 0; j < 8; j++) { |
bridadan | 0:0b79cafcb387 | 70 | if (((agrb[clr] << j) & 0x80) == 0x80) { |
bridadan | 0:0b79cafcb387 | 71 | // Bit is set (checks MSB fist) |
bridadan | 0:0b79cafcb387 | 72 | __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 1; |
bridadan | 0:0b79cafcb387 | 73 | } else { |
bridadan | 0:0b79cafcb387 | 74 | // Bit is clear |
bridadan | 0:0b79cafcb387 | 75 | __transmitBuf[(i * FRAME_SIZE) + (clr * 8) + j] = 0; |
bridadan | 0:0b79cafcb387 | 76 | } |
bridadan | 0:0b79cafcb387 | 77 | } |
bridadan | 0:0b79cafcb387 | 78 | } |
bridadan | 0:0b79cafcb387 | 79 | } |
bridadan | 0:0b79cafcb387 | 80 | } |
bridadan | 0:0b79cafcb387 | 81 | |
bridadan | 0:0b79cafcb387 | 82 | void WS2812::write(int buf[]) { |
bridadan | 0:0b79cafcb387 | 83 | write_offsets(buf, 0, 0, 0); |
bridadan | 0:0b79cafcb387 | 84 | } |
bridadan | 0:0b79cafcb387 | 85 | |
bridadan | 0:0b79cafcb387 | 86 | void WS2812::write_offsets (int buf[],int r_offset, int g_offset, int b_offset) { |
bridadan | 0:0b79cafcb387 | 87 | int i, j; |
bridadan | 0:0b79cafcb387 | 88 | |
bridadan | 1:aadbf08c62a2 | 89 | // Load the transmit buffer |
bridadan | 0:0b79cafcb387 | 90 | __loadBuf(buf, r_offset, g_offset, b_offset); |
bridadan | 0:0b79cafcb387 | 91 | |
bridadan | 1:aadbf08c62a2 | 92 | // Entering timing critical section, so disabling interrupts |
bridadan | 1:aadbf08c62a2 | 93 | __disable_irq(); |
bridadan | 1:aadbf08c62a2 | 94 | |
bridadan | 1:aadbf08c62a2 | 95 | // Begin bit-banging |
bridadan | 0:0b79cafcb387 | 96 | for (i = 0; i < FRAME_SIZE * __size; i++) { |
bridadan | 0:0b79cafcb387 | 97 | j = 0; |
bridadan | 0:0b79cafcb387 | 98 | if (__transmitBuf[i]){ |
bridadan | 0:0b79cafcb387 | 99 | __gpo = 1; |
bridadan | 0:0b79cafcb387 | 100 | for (; j < __oneHigh; j++) { |
MACRUM | 3:6e60574091dd | 101 | NOP; |
bridadan | 0:0b79cafcb387 | 102 | } |
bridadan | 0:0b79cafcb387 | 103 | __gpo = 0; |
bridadan | 0:0b79cafcb387 | 104 | for (; j < __oneLow; j++) { |
MACRUM | 3:6e60574091dd | 105 | NOP; |
bridadan | 0:0b79cafcb387 | 106 | } |
bridadan | 0:0b79cafcb387 | 107 | } else { |
bridadan | 0:0b79cafcb387 | 108 | __gpo = 1; |
bridadan | 0:0b79cafcb387 | 109 | for (; j < __zeroHigh; j++) { |
MACRUM | 3:6e60574091dd | 110 | NOP; |
bridadan | 0:0b79cafcb387 | 111 | } |
bridadan | 0:0b79cafcb387 | 112 | __gpo = 0; |
bridadan | 0:0b79cafcb387 | 113 | for (; j < __zeroLow; j++) { |
MACRUM | 3:6e60574091dd | 114 | NOP; |
bridadan | 0:0b79cafcb387 | 115 | } |
bridadan | 0:0b79cafcb387 | 116 | } |
bridadan | 0:0b79cafcb387 | 117 | } |
bridadan | 1:aadbf08c62a2 | 118 | |
bridadan | 1:aadbf08c62a2 | 119 | // Exiting timing critical section, so enabling interrutps |
bridadan | 1:aadbf08c62a2 | 120 | __enable_irq(); |
bridadan | 0:0b79cafcb387 | 121 | } |
bridadan | 0:0b79cafcb387 | 122 | |
bridadan | 0:0b79cafcb387 | 123 | |
bridadan | 1:aadbf08c62a2 | 124 | void WS2812::useII(BrightnessControl bc) |
bridadan | 0:0b79cafcb387 | 125 | { |
bridadan | 1:aadbf08c62a2 | 126 | if (bc > OFF) { |
bridadan | 1:aadbf08c62a2 | 127 | __use_II = bc; |
bridadan | 0:0b79cafcb387 | 128 | } else { |
bridadan | 1:aadbf08c62a2 | 129 | __use_II = OFF; |
bridadan | 0:0b79cafcb387 | 130 | } |
bridadan | 0:0b79cafcb387 | 131 | } |
bridadan | 0:0b79cafcb387 | 132 | |
bridadan | 0:0b79cafcb387 | 133 | void WS2812::setII(unsigned char II) |
bridadan | 0:0b79cafcb387 | 134 | { |
bridadan | 0:0b79cafcb387 | 135 | __II = II; |
bridadan | 0:0b79cafcb387 | 136 | } |
bridadan | 0:0b79cafcb387 | 137 | |
bridadan | 0:0b79cafcb387 | 138 | |
bridadan | 0:0b79cafcb387 | 139 | |
bridadan | 0:0b79cafcb387 | 140 | |
bridadan | 0:0b79cafcb387 | 141 | |
bridadan | 0:0b79cafcb387 | 142 |