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