This is a Shield Bot Library

Committer:
Kevin_Lee
Date:
Wed Sep 09 05:53:29 2015 +0000
Revision:
0:7535295d1670
Shield Bot Library

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Kevin_Lee 0:7535295d1670 1 /** Color pixels library using WS2812B and nRF51822 (16MHz)
Kevin_Lee 0:7535295d1670 2 * It's for
Kevin_Lee 0:7535295d1670 3 * + http://www.seeedstudio.com/depot/Digital-RGB-LED-FlexiStrip-60-LED-1-Meter-p-1666.html
Kevin_Lee 0:7535295d1670 4 * + http://www.seeedstudio.com/depot/WS2812B-Digital-RGB-LED-Waterproof-FlexiStrip-144-LEDmeter-2-meter-p-1869.html
Kevin_Lee 0:7535295d1670 5 * + http://www.seeedstudio.com/depot/WS2812B-RGB-LED-with-Integrated-Driver-Chip-10-PCs-pack-p-1675.html
Kevin_Lee 0:7535295d1670 6 *
Kevin_Lee 0:7535295d1670 7 * The MIT License (MIT)
Kevin_Lee 0:7535295d1670 8 *
Kevin_Lee 0:7535295d1670 9 * Copyright (c) 2014 Seeed Technology Inc.
Kevin_Lee 0:7535295d1670 10 *
Kevin_Lee 0:7535295d1670 11 * Permission is hereby granted, free of charge, to any person obtaining a copy
Kevin_Lee 0:7535295d1670 12 * of this software and associated documentation files (the "Software"), to deal
Kevin_Lee 0:7535295d1670 13 * in the Software without restriction, including without limitation the rights
Kevin_Lee 0:7535295d1670 14 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
Kevin_Lee 0:7535295d1670 15 * copies of the Software, and to permit persons to whom the Software is
Kevin_Lee 0:7535295d1670 16 * furnished to do so, subject to the following conditions:
Kevin_Lee 0:7535295d1670 17
Kevin_Lee 0:7535295d1670 18 * The above copyright notice and this permission notice shall be included in
Kevin_Lee 0:7535295d1670 19 * all copies or substantial portions of the Software.
Kevin_Lee 0:7535295d1670 20
Kevin_Lee 0:7535295d1670 21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Kevin_Lee 0:7535295d1670 22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Kevin_Lee 0:7535295d1670 23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Kevin_Lee 0:7535295d1670 24 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Kevin_Lee 0:7535295d1670 25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
Kevin_Lee 0:7535295d1670 26 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
Kevin_Lee 0:7535295d1670 27 * THE SOFTWARE.
Kevin_Lee 0:7535295d1670 28 */
Kevin_Lee 0:7535295d1670 29
Kevin_Lee 0:7535295d1670 30 #include "ShieldBot_v12.h"
Kevin_Lee 0:7535295d1670 31 #include "nrf51.h"
Kevin_Lee 0:7535295d1670 32 #include "nrf51_bitfields.h"
Kevin_Lee 0:7535295d1670 33
Kevin_Lee 0:7535295d1670 34 #if !defined ( __GNUC__ )
Kevin_Lee 0:7535295d1670 35 // Generate a high level pulse (0.81us) of WS2812B's 1 code (0.9us +- 0.15us)
Kevin_Lee 0:7535295d1670 36 #define COLOR_PIXELS_ONE_HIGH(mask) \
Kevin_Lee 0:7535295d1670 37 NRF_GPIO->OUTSET = (mask); \
Kevin_Lee 0:7535295d1670 38 __ASM ( \
Kevin_Lee 0:7535295d1670 39 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 40 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 41 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 42 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 43 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 44 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 45 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 46 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 47 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 48 ); \
Kevin_Lee 0:7535295d1670 49 NRF_GPIO->OUTCLR = (mask)
Kevin_Lee 0:7535295d1670 50
Kevin_Lee 0:7535295d1670 51 // Generate a high level pulse (0.31us) of WS2812B's 0 code (0.35us +- 0.15us)
Kevin_Lee 0:7535295d1670 52 #define COLOR_PIXELS_ZERO_HIGH(mask) \
Kevin_Lee 0:7535295d1670 53 NRF_GPIO->OUTSET = (mask); \
Kevin_Lee 0:7535295d1670 54 __ASM ( \
Kevin_Lee 0:7535295d1670 55 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 56 ); \
Kevin_Lee 0:7535295d1670 57 NRF_GPIO->OUTCLR = (mask); \
Kevin_Lee 0:7535295d1670 58 __ASM ( \
Kevin_Lee 0:7535295d1670 59 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 60 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 61 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 62 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 63 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 64 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 65 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 66 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 67 )
Kevin_Lee 0:7535295d1670 68 #else
Kevin_Lee 0:7535295d1670 69 // Generate a high level pulse (0.94us) of WS2812B's 1 code (0.9us +- 0.15us)
Kevin_Lee 0:7535295d1670 70 #define COLOR_PIXELS_ONE_HIGH(mask) \
Kevin_Lee 0:7535295d1670 71 NRF_GPIO->OUTSET = (mask); \
Kevin_Lee 0:7535295d1670 72 __ASM ( \
Kevin_Lee 0:7535295d1670 73 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 74 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 75 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 76 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 77 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 78 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 79 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 80 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 81 ); \
Kevin_Lee 0:7535295d1670 82 NRF_GPIO->OUTCLR = (mask)
Kevin_Lee 0:7535295d1670 83
Kevin_Lee 0:7535295d1670 84 // Generate a high level pulse (0.44us) of WS2812B's 0 code (0.35us +- 0.15us)
Kevin_Lee 0:7535295d1670 85 #define COLOR_PIXELS_ZERO_HIGH(mask) \
Kevin_Lee 0:7535295d1670 86 NRF_GPIO->OUTSET = (mask); \
Kevin_Lee 0:7535295d1670 87 __ASM ( \
Kevin_Lee 0:7535295d1670 88 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 89 ); \
Kevin_Lee 0:7535295d1670 90 NRF_GPIO->OUTCLR = (mask); \
Kevin_Lee 0:7535295d1670 91 __ASM ( \
Kevin_Lee 0:7535295d1670 92 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 93 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 94 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 95 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 96 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 97 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 98 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 99 " NOP\n\t" \
Kevin_Lee 0:7535295d1670 100 )
Kevin_Lee 0:7535295d1670 101 #endif
Kevin_Lee 0:7535295d1670 102
Kevin_Lee 0:7535295d1670 103 static void delay_us(uint32_t us)
Kevin_Lee 0:7535295d1670 104 {
Kevin_Lee 0:7535295d1670 105 do {
Kevin_Lee 0:7535295d1670 106 __ASM volatile (
Kevin_Lee 0:7535295d1670 107 "NOP\n\t"
Kevin_Lee 0:7535295d1670 108 "NOP\n\t"
Kevin_Lee 0:7535295d1670 109 "NOP\n\t"
Kevin_Lee 0:7535295d1670 110 "NOP\n\t"
Kevin_Lee 0:7535295d1670 111 "NOP\n\t"
Kevin_Lee 0:7535295d1670 112 "NOP\n\t"
Kevin_Lee 0:7535295d1670 113 "NOP\n\t"
Kevin_Lee 0:7535295d1670 114 "NOP\n\t"
Kevin_Lee 0:7535295d1670 115 "NOP\n\t"
Kevin_Lee 0:7535295d1670 116 "NOP\n\t"
Kevin_Lee 0:7535295d1670 117 "NOP\n\t"
Kevin_Lee 0:7535295d1670 118 "NOP\n\t"
Kevin_Lee 0:7535295d1670 119 );
Kevin_Lee 0:7535295d1670 120 } while (--us);
Kevin_Lee 0:7535295d1670 121 }
Kevin_Lee 0:7535295d1670 122
Kevin_Lee 0:7535295d1670 123 ColorPixels::ColorPixels(uint8_t pin, uint16_t num)
Kevin_Lee 0:7535295d1670 124 {
Kevin_Lee 0:7535295d1670 125 this->pin = pin;
Kevin_Lee 0:7535295d1670 126 this->num = num;
Kevin_Lee 0:7535295d1670 127
Kevin_Lee 0:7535295d1670 128 NRF_GPIO->PIN_CNF[pin] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
Kevin_Lee 0:7535295d1670 129 | (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
Kevin_Lee 0:7535295d1670 130 | (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
Kevin_Lee 0:7535295d1670 131 | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
Kevin_Lee 0:7535295d1670 132 | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
Kevin_Lee 0:7535295d1670 133 NRF_GPIO->OUTCLR = (1UL << pin);
Kevin_Lee 0:7535295d1670 134
Kevin_Lee 0:7535295d1670 135 colors = new grb_t[num];
Kevin_Lee 0:7535295d1670 136 for (int i = 0; i < num; i++) {
Kevin_Lee 0:7535295d1670 137 colors[i].grb = 0;
Kevin_Lee 0:7535295d1670 138 }
Kevin_Lee 0:7535295d1670 139 }
Kevin_Lee 0:7535295d1670 140
Kevin_Lee 0:7535295d1670 141 ColorPixels::~ColorPixels()
Kevin_Lee 0:7535295d1670 142 {
Kevin_Lee 0:7535295d1670 143 delete colors;
Kevin_Lee 0:7535295d1670 144 }
Kevin_Lee 0:7535295d1670 145
Kevin_Lee 0:7535295d1670 146
Kevin_Lee 0:7535295d1670 147 void ColorPixels::set_color(uint16_t index, uint8_t r, uint8_t g, uint8_t b)
Kevin_Lee 0:7535295d1670 148 {
Kevin_Lee 0:7535295d1670 149 if (index < num) {
Kevin_Lee 0:7535295d1670 150 colors[index].r = r;
Kevin_Lee 0:7535295d1670 151 colors[index].g = g;
Kevin_Lee 0:7535295d1670 152 colors[index].b = b;
Kevin_Lee 0:7535295d1670 153 }
Kevin_Lee 0:7535295d1670 154 }
Kevin_Lee 0:7535295d1670 155
Kevin_Lee 0:7535295d1670 156 void ColorPixels::set_color(uint16_t index, uint32_t rgb) {
Kevin_Lee 0:7535295d1670 157 color_t c = *(color_t *)&rgb;
Kevin_Lee 0:7535295d1670 158 set_color(index, c.r, c.g, c.b);
Kevin_Lee 0:7535295d1670 159 }
Kevin_Lee 0:7535295d1670 160
Kevin_Lee 0:7535295d1670 161 void ColorPixels::set_all_color(uint8_t r, uint8_t g, uint8_t b)
Kevin_Lee 0:7535295d1670 162 {
Kevin_Lee 0:7535295d1670 163 for (int i = 0; i < num; i++) {
Kevin_Lee 0:7535295d1670 164 colors[i].r = r;
Kevin_Lee 0:7535295d1670 165 colors[i].g = g;
Kevin_Lee 0:7535295d1670 166 colors[i].b = b;
Kevin_Lee 0:7535295d1670 167 }
Kevin_Lee 0:7535295d1670 168
Kevin_Lee 0:7535295d1670 169 update();
Kevin_Lee 0:7535295d1670 170 }
Kevin_Lee 0:7535295d1670 171
Kevin_Lee 0:7535295d1670 172 void ColorPixels::update()
Kevin_Lee 0:7535295d1670 173 {
Kevin_Lee 0:7535295d1670 174 uint32_t mask = 1 << pin;
Kevin_Lee 0:7535295d1670 175 NRF_GPIO->OUTCLR = mask;
Kevin_Lee 0:7535295d1670 176 delay_us(50);
Kevin_Lee 0:7535295d1670 177
Kevin_Lee 0:7535295d1670 178 grb_t *pcolor = colors;
Kevin_Lee 0:7535295d1670 179 for (int i = 0; i < num; i++) {
Kevin_Lee 0:7535295d1670 180 uint32_t grb = (*pcolor).grb;
Kevin_Lee 0:7535295d1670 181 for (int bit = 0; bit < 24; bit++) {
Kevin_Lee 0:7535295d1670 182 if (grb & 1) {
Kevin_Lee 0:7535295d1670 183 COLOR_PIXELS_ONE_HIGH(mask);
Kevin_Lee 0:7535295d1670 184 } else {
Kevin_Lee 0:7535295d1670 185 COLOR_PIXELS_ZERO_HIGH(mask);
Kevin_Lee 0:7535295d1670 186 }
Kevin_Lee 0:7535295d1670 187 grb >>= 1;
Kevin_Lee 0:7535295d1670 188 }
Kevin_Lee 0:7535295d1670 189 pcolor++;
Kevin_Lee 0:7535295d1670 190 }
Kevin_Lee 0:7535295d1670 191 }
Kevin_Lee 0:7535295d1670 192
Kevin_Lee 0:7535295d1670 193 void ColorPixels::clear()
Kevin_Lee 0:7535295d1670 194 {
Kevin_Lee 0:7535295d1670 195 for (int i = 0; i < num; i++) {
Kevin_Lee 0:7535295d1670 196 colors[i].grb = 0;
Kevin_Lee 0:7535295d1670 197 }
Kevin_Lee 0:7535295d1670 198
Kevin_Lee 0:7535295d1670 199 update();
Kevin_Lee 0:7535295d1670 200 }
Kevin_Lee 0:7535295d1670 201
Kevin_Lee 0:7535295d1670 202 uint32_t toRGB(uint8_t red, uint8_t green, uint8_t blue)
Kevin_Lee 0:7535295d1670 203 {
Kevin_Lee 0:7535295d1670 204 color_t c;
Kevin_Lee 0:7535295d1670 205
Kevin_Lee 0:7535295d1670 206 c.r = red;
Kevin_Lee 0:7535295d1670 207 c.g = green;
Kevin_Lee 0:7535295d1670 208 c.b = blue;
Kevin_Lee 0:7535295d1670 209
Kevin_Lee 0:7535295d1670 210 return c.rgb;
Kevin_Lee 0:7535295d1670 211 };
Kevin_Lee 0:7535295d1670 212
Kevin_Lee 0:7535295d1670 213 uint32_t wheel(float position, uint8_t min = 0, uint8_t max = 255)
Kevin_Lee 0:7535295d1670 214 {
Kevin_Lee 0:7535295d1670 215 uint8_t d = max - min;
Kevin_Lee 0:7535295d1670 216 uint32_t c;
Kevin_Lee 0:7535295d1670 217
Kevin_Lee 0:7535295d1670 218 if(position < 0.166) {
Kevin_Lee 0:7535295d1670 219 c = toRGB(max, min + position * 6 * d, min);
Kevin_Lee 0:7535295d1670 220 } else if(position < 0.332) {
Kevin_Lee 0:7535295d1670 221 position -= 0.166;
Kevin_Lee 0:7535295d1670 222 c = toRGB(max - position * 6 * d, max, min);
Kevin_Lee 0:7535295d1670 223 } else if(position < 0.498) {
Kevin_Lee 0:7535295d1670 224 position -= 0.332;
Kevin_Lee 0:7535295d1670 225 c = toRGB(min, max, min + position * 6 * d);
Kevin_Lee 0:7535295d1670 226 } else if(position < 0.664) {
Kevin_Lee 0:7535295d1670 227 position -= 0.498;
Kevin_Lee 0:7535295d1670 228 c = toRGB(min, max - position * 6 * d, max);
Kevin_Lee 0:7535295d1670 229 } else if(position < 0.83) {
Kevin_Lee 0:7535295d1670 230 position -= 0.664;
Kevin_Lee 0:7535295d1670 231 c = toRGB(min + d * position * 6, min, max);
Kevin_Lee 0:7535295d1670 232 } else {
Kevin_Lee 0:7535295d1670 233 position -= 0.83;
Kevin_Lee 0:7535295d1670 234 c = toRGB(max, min, max - position * 6 * d);
Kevin_Lee 0:7535295d1670 235 }
Kevin_Lee 0:7535295d1670 236
Kevin_Lee 0:7535295d1670 237 return c;
Kevin_Lee 0:7535295d1670 238 }
Kevin_Lee 0:7535295d1670 239
Kevin_Lee 0:7535295d1670 240 void find_wheel_options(uint32_t rgb, float *position, uint8_t *min, uint8_t *max)
Kevin_Lee 0:7535295d1670 241 {
Kevin_Lee 0:7535295d1670 242 color_t c;
Kevin_Lee 0:7535295d1670 243 c.rgb = rgb;
Kevin_Lee 0:7535295d1670 244
Kevin_Lee 0:7535295d1670 245 if (c.r > c.g) {
Kevin_Lee 0:7535295d1670 246 if (c.g >= c.b) {
Kevin_Lee 0:7535295d1670 247 *max = c.r;
Kevin_Lee 0:7535295d1670 248 *min = c.b;
Kevin_Lee 0:7535295d1670 249 *position = (float)(c.g - c.b) / (c.r - c.b) / 6.0;
Kevin_Lee 0:7535295d1670 250 } else if (c.b >= c.r) {
Kevin_Lee 0:7535295d1670 251 *max = c.b;
Kevin_Lee 0:7535295d1670 252 *min = c.g;
Kevin_Lee 0:7535295d1670 253 *position = (float)(c.r - c.g) / (c.b - c.g) / 6.0 + 0.664;
Kevin_Lee 0:7535295d1670 254 } else {
Kevin_Lee 0:7535295d1670 255 *max = c.r;
Kevin_Lee 0:7535295d1670 256 *min = c.g;
Kevin_Lee 0:7535295d1670 257 *position = (float)(c.b - c.g) / (c.r - c.g) / 6.0 + 0.83;
Kevin_Lee 0:7535295d1670 258 }
Kevin_Lee 0:7535295d1670 259 } else {
Kevin_Lee 0:7535295d1670 260 if (c.r > c.b) {
Kevin_Lee 0:7535295d1670 261 *max = c.g;
Kevin_Lee 0:7535295d1670 262 *min = c.b;
Kevin_Lee 0:7535295d1670 263 *position = (float)(c.r - c.b) / (c.g - c.b) / 6.0 + 0.166;
Kevin_Lee 0:7535295d1670 264 } else if (c.b > c.g) {
Kevin_Lee 0:7535295d1670 265 *max = c.b;
Kevin_Lee 0:7535295d1670 266 *min = c.r;
Kevin_Lee 0:7535295d1670 267 *position = (float)(c.g - c.r) / (c.b - c.r) / 6.0 + 0.498;
Kevin_Lee 0:7535295d1670 268 } else {
Kevin_Lee 0:7535295d1670 269 *max = c.g;
Kevin_Lee 0:7535295d1670 270 *min = c.r;
Kevin_Lee 0:7535295d1670 271 *position = (float)(c.b - c.r) / (c.g - c.r) / 6.0 + 0.332;
Kevin_Lee 0:7535295d1670 272 }
Kevin_Lee 0:7535295d1670 273 }
Kevin_Lee 0:7535295d1670 274 }
Kevin_Lee 0:7535295d1670 275
Kevin_Lee 0:7535295d1670 276 void ColorPixels::rainbow(uint32_t rgb)
Kevin_Lee 0:7535295d1670 277 {
Kevin_Lee 0:7535295d1670 278 float position;
Kevin_Lee 0:7535295d1670 279 uint8_t min, max;
Kevin_Lee 0:7535295d1670 280
Kevin_Lee 0:7535295d1670 281 find_wheel_options(rgb, &position, &min, &max);
Kevin_Lee 0:7535295d1670 282 for (int i = 0; i < num; i++) {
Kevin_Lee 0:7535295d1670 283 float current = ((int)(i + num * position) % num) / (float)num;
Kevin_Lee 0:7535295d1670 284 set_color(i, wheel(current, min, max));
Kevin_Lee 0:7535295d1670 285 }
Kevin_Lee 0:7535295d1670 286
Kevin_Lee 0:7535295d1670 287 update();
Kevin_Lee 0:7535295d1670 288 }
Kevin_Lee 0:7535295d1670 289
Kevin_Lee 0:7535295d1670 290 void ColorPixels::rainbow(uint8_t r, uint8_t g, uint8_t b)
Kevin_Lee 0:7535295d1670 291 {
Kevin_Lee 0:7535295d1670 292 color_t c;
Kevin_Lee 0:7535295d1670 293
Kevin_Lee 0:7535295d1670 294 c.r = r;
Kevin_Lee 0:7535295d1670 295 c.g = g;
Kevin_Lee 0:7535295d1670 296 c.b = b;
Kevin_Lee 0:7535295d1670 297
Kevin_Lee 0:7535295d1670 298 rainbow(c.rgb);
Kevin_Lee 0:7535295d1670 299 }
Kevin_Lee 0:7535295d1670 300