An example program using the NeoMatrix library to control an Adafruit NeoPixel 8x8 NeoMatrix (http://www.adafruit.com/products/1487)
Fork of NeoMatrix_Demo by
main.cpp@0:f38492690f0e, 2014-03-12 (annotated)
- Committer:
- aswild
- Date:
- Wed Mar 12 18:41:42 2014 +0000
- Revision:
- 0:f38492690f0e
- Child:
- 1:daf38bb2801e
Initial version
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
aswild | 0:f38492690f0e | 1 | /* |
aswild | 0:f38492690f0e | 2 | * Adafruit NeoPixel 8x8 matrix example |
aswild | 0:f38492690f0e | 3 | * |
aswild | 0:f38492690f0e | 4 | * This program displays a couple simple patterns on an 8x8 NeoPixel matrix. |
aswild | 0:f38492690f0e | 5 | * |
aswild | 0:f38492690f0e | 6 | * 3 buttons are used for DigitalIns, 2 control the brightness up and down, |
aswild | 0:f38492690f0e | 7 | * and the third switches patterns |
aswild | 0:f38492690f0e | 8 | */ |
aswild | 0:f38492690f0e | 9 | |
aswild | 0:f38492690f0e | 10 | #include "mbed.h" |
aswild | 0:f38492690f0e | 11 | #include "NeoStrip.h" |
aswild | 0:f38492690f0e | 12 | #include "gt.h" |
aswild | 0:f38492690f0e | 13 | |
aswild | 0:f38492690f0e | 14 | #define N 64 |
aswild | 0:f38492690f0e | 15 | #define PATTERNS 3 |
aswild | 0:f38492690f0e | 16 | |
aswild | 0:f38492690f0e | 17 | int hueToRGB(float h); |
aswild | 0:f38492690f0e | 18 | void pattern0(); |
aswild | 0:f38492690f0e | 19 | void pattern1(); |
aswild | 0:f38492690f0e | 20 | void pattern2(); |
aswild | 0:f38492690f0e | 21 | |
aswild | 0:f38492690f0e | 22 | // array of function pointers to the various patterns |
aswild | 0:f38492690f0e | 23 | void (*patterns[])(void) = {&pattern0, &pattern1, &pattern2}; |
aswild | 0:f38492690f0e | 24 | |
aswild | 0:f38492690f0e | 25 | NeoStrip strip(p18, N); |
aswild | 0:f38492690f0e | 26 | DigitalIn b1(p20); // brightness up |
aswild | 0:f38492690f0e | 27 | DigitalIn b2(p19); // brightness down |
aswild | 0:f38492690f0e | 28 | DigitalIn b3(p21); // next pattern |
aswild | 0:f38492690f0e | 29 | |
aswild | 0:f38492690f0e | 30 | // timer used for debugging |
aswild | 0:f38492690f0e | 31 | Timer timer; |
aswild | 0:f38492690f0e | 32 | |
aswild | 0:f38492690f0e | 33 | int main() |
aswild | 0:f38492690f0e | 34 | { |
aswild | 0:f38492690f0e | 35 | b1.mode(PullDown); |
aswild | 0:f38492690f0e | 36 | b2.mode(PullDown); |
aswild | 0:f38492690f0e | 37 | b3.mode(PullDown); |
aswild | 0:f38492690f0e | 38 | |
aswild | 0:f38492690f0e | 39 | int pattern = 0; |
aswild | 0:f38492690f0e | 40 | float bright = 0.2; // 20% is plenty for indoor use |
aswild | 0:f38492690f0e | 41 | bool b3o = b3; // old copy of button 3 to poll for changes |
aswild | 0:f38492690f0e | 42 | |
aswild | 0:f38492690f0e | 43 | strip.setBrightness(bright); // set default brightness |
aswild | 0:f38492690f0e | 44 | |
aswild | 0:f38492690f0e | 45 | while (true) |
aswild | 0:f38492690f0e | 46 | { |
aswild | 0:f38492690f0e | 47 | timer.reset(); // use a timer to measure loop execution time for debugging purposes |
aswild | 0:f38492690f0e | 48 | timer.start(); // for this application, the main loop takes approximately 3ms to run |
aswild | 0:f38492690f0e | 49 | |
aswild | 0:f38492690f0e | 50 | // button 1 increases brightness |
aswild | 0:f38492690f0e | 51 | if (b1 && bright < 1) |
aswild | 0:f38492690f0e | 52 | { |
aswild | 0:f38492690f0e | 53 | bright += 0.01; |
aswild | 0:f38492690f0e | 54 | if (bright > 1) |
aswild | 0:f38492690f0e | 55 | bright = 1; |
aswild | 0:f38492690f0e | 56 | strip.setBrightness(bright); |
aswild | 0:f38492690f0e | 57 | } |
aswild | 0:f38492690f0e | 58 | |
aswild | 0:f38492690f0e | 59 | // button 2 decreases brightness |
aswild | 0:f38492690f0e | 60 | if (b2 && bright > 0) |
aswild | 0:f38492690f0e | 61 | { |
aswild | 0:f38492690f0e | 62 | bright -= 0.01; |
aswild | 0:f38492690f0e | 63 | if (bright < 0) |
aswild | 0:f38492690f0e | 64 | bright = 0; |
aswild | 0:f38492690f0e | 65 | strip.setBrightness(bright); |
aswild | 0:f38492690f0e | 66 | } |
aswild | 0:f38492690f0e | 67 | |
aswild | 0:f38492690f0e | 68 | // button 3 changes the pattern, only do stuff when its state has changed |
aswild | 0:f38492690f0e | 69 | if (b3 != b3o) |
aswild | 0:f38492690f0e | 70 | { |
aswild | 0:f38492690f0e | 71 | if (b3 && ++pattern == PATTERNS) |
aswild | 0:f38492690f0e | 72 | pattern = 0; |
aswild | 0:f38492690f0e | 73 | b3o = b3; |
aswild | 0:f38492690f0e | 74 | } |
aswild | 0:f38492690f0e | 75 | |
aswild | 0:f38492690f0e | 76 | // run the pattern update function which sets the strip's pixels |
aswild | 0:f38492690f0e | 77 | patterns[pattern](); |
aswild | 0:f38492690f0e | 78 | strip.write(); |
aswild | 0:f38492690f0e | 79 | |
aswild | 0:f38492690f0e | 80 | timer.stop(); |
aswild | 0:f38492690f0e | 81 | // print loop time if b3 is pressed |
aswild | 0:f38492690f0e | 82 | if (b3) |
aswild | 0:f38492690f0e | 83 | printf("Loop Time: %dus\n", timer.read_us()); |
aswild | 0:f38492690f0e | 84 | |
aswild | 0:f38492690f0e | 85 | wait_ms(10); |
aswild | 0:f38492690f0e | 86 | } |
aswild | 0:f38492690f0e | 87 | } |
aswild | 0:f38492690f0e | 88 | |
aswild | 0:f38492690f0e | 89 | // pattern0 displays a static image |
aswild | 0:f38492690f0e | 90 | void pattern0() |
aswild | 0:f38492690f0e | 91 | { |
aswild | 0:f38492690f0e | 92 | strip.setPixels(0, N, gt_img); |
aswild | 0:f38492690f0e | 93 | } |
aswild | 0:f38492690f0e | 94 | |
aswild | 0:f38492690f0e | 95 | // display a shifting rainbow, all colors have maximum |
aswild | 0:f38492690f0e | 96 | // saturation and value, with evenly spaced hue |
aswild | 0:f38492690f0e | 97 | void pattern1() |
aswild | 0:f38492690f0e | 98 | { |
aswild | 0:f38492690f0e | 99 | static float dh = 360.0 / N; |
aswild | 0:f38492690f0e | 100 | static float x = 0; |
aswild | 0:f38492690f0e | 101 | |
aswild | 0:f38492690f0e | 102 | for (int i = 0; i < N; i++) |
aswild | 0:f38492690f0e | 103 | strip.setPixel(i, hueToRGB((dh * i) - x)); |
aswild | 0:f38492690f0e | 104 | |
aswild | 0:f38492690f0e | 105 | x += 1; |
aswild | 0:f38492690f0e | 106 | if (x > 360) |
aswild | 0:f38492690f0e | 107 | x = 0; |
aswild | 0:f38492690f0e | 108 | } |
aswild | 0:f38492690f0e | 109 | |
aswild | 0:f38492690f0e | 110 | // display a shifting gradient between red and blue |
aswild | 0:f38492690f0e | 111 | void pattern2() |
aswild | 0:f38492690f0e | 112 | { |
aswild | 0:f38492690f0e | 113 | // offset for each pixel to allow the pattern to move |
aswild | 0:f38492690f0e | 114 | static float x = 0; |
aswild | 0:f38492690f0e | 115 | |
aswild | 0:f38492690f0e | 116 | float r, b, y; |
aswild | 0:f38492690f0e | 117 | |
aswild | 0:f38492690f0e | 118 | for (int i = 0; i < N; i++) |
aswild | 0:f38492690f0e | 119 | { |
aswild | 0:f38492690f0e | 120 | // y is a scaled position between 0 (red) and 1.0 (blue) |
aswild | 0:f38492690f0e | 121 | y = 1.0 * i / (N - 1) + x; |
aswild | 0:f38492690f0e | 122 | if (y > 1) |
aswild | 0:f38492690f0e | 123 | y -= 1; |
aswild | 0:f38492690f0e | 124 | |
aswild | 0:f38492690f0e | 125 | // if on the left half, red is decreasing and blue is increasng |
aswild | 0:f38492690f0e | 126 | if (y < 0.5) |
aswild | 0:f38492690f0e | 127 | { |
aswild | 0:f38492690f0e | 128 | b = 2 * y; |
aswild | 0:f38492690f0e | 129 | r = 1 - b; |
aswild | 0:f38492690f0e | 130 | } |
aswild | 0:f38492690f0e | 131 | |
aswild | 0:f38492690f0e | 132 | // else red is increasing and blue is decreasing |
aswild | 0:f38492690f0e | 133 | else |
aswild | 0:f38492690f0e | 134 | { |
aswild | 0:f38492690f0e | 135 | r = 2 * (y - 0.5); |
aswild | 0:f38492690f0e | 136 | b = 1 - r; |
aswild | 0:f38492690f0e | 137 | } |
aswild | 0:f38492690f0e | 138 | |
aswild | 0:f38492690f0e | 139 | // scale to integers and set the pixel |
aswild | 0:f38492690f0e | 140 | strip.setPixel(i, (uint8_t)(r * 255), 0, (uint8_t)(b * 200)); |
aswild | 0:f38492690f0e | 141 | } |
aswild | 0:f38492690f0e | 142 | |
aswild | 0:f38492690f0e | 143 | x += 0.003; |
aswild | 0:f38492690f0e | 144 | if (x > 1) |
aswild | 0:f38492690f0e | 145 | x = 0; |
aswild | 0:f38492690f0e | 146 | } |
aswild | 0:f38492690f0e | 147 | |
aswild | 0:f38492690f0e | 148 | // Converts HSV to RGB with the given hue, assuming |
aswild | 0:f38492690f0e | 149 | // maximum saturation and value |
aswild | 0:f38492690f0e | 150 | int hueToRGB(float h) |
aswild | 0:f38492690f0e | 151 | { |
aswild | 0:f38492690f0e | 152 | // lots of floating point magic from the internet and scratching my head |
aswild | 0:f38492690f0e | 153 | float r, g, b; |
aswild | 0:f38492690f0e | 154 | if (h > 360) |
aswild | 0:f38492690f0e | 155 | h -= 360; |
aswild | 0:f38492690f0e | 156 | if (h < 0) |
aswild | 0:f38492690f0e | 157 | h += 360; |
aswild | 0:f38492690f0e | 158 | int i = (int)(h / 60.0); |
aswild | 0:f38492690f0e | 159 | float f = (h / 60.0) - i; |
aswild | 0:f38492690f0e | 160 | float q = 1 - f; |
aswild | 0:f38492690f0e | 161 | |
aswild | 0:f38492690f0e | 162 | switch (i % 6) |
aswild | 0:f38492690f0e | 163 | { |
aswild | 0:f38492690f0e | 164 | case 0: r = 1; g = f; b = 0; break; |
aswild | 0:f38492690f0e | 165 | case 1: r = q; g = 1; b = 0; break; |
aswild | 0:f38492690f0e | 166 | case 2: r = 0; g = 1; b = f; break; |
aswild | 0:f38492690f0e | 167 | case 3: r = 0; g = q; b = 1; break; |
aswild | 0:f38492690f0e | 168 | case 4: r = f; g = 0; b = 1; break; |
aswild | 0:f38492690f0e | 169 | case 5: r = 1; g = 0; b = q; break; |
aswild | 0:f38492690f0e | 170 | default: r = 0; g = 0; b = 0; break; |
aswild | 0:f38492690f0e | 171 | } |
aswild | 0:f38492690f0e | 172 | |
aswild | 0:f38492690f0e | 173 | // scale to integers and return the packed value |
aswild | 0:f38492690f0e | 174 | uint8_t R = (uint8_t)(r * 255); |
aswild | 0:f38492690f0e | 175 | uint8_t G = (uint8_t)(g * 255); |
aswild | 0:f38492690f0e | 176 | uint8_t B = (uint8_t)(b * 255); |
aswild | 0:f38492690f0e | 177 | |
aswild | 0:f38492690f0e | 178 | return (R << 16) | (G << 8) | B; |
aswild | 0:f38492690f0e | 179 | } |
aswild | 0:f38492690f0e | 180 |