WS2812

Dependents:   EITI_Neopixel

Committer:
villemejane
Date:
Mon Dec 13 08:57:11 2021 +0000
Revision:
3:adfd3b002caa
Parent:
1:aadbf08c62a2
WS2812

Who changed what in which revision?

UserRevisionLine numberNew 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