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