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