A somewhat silly project that uses an LPC11U24 to control the system, a Neopixel stick to provide light, and a sound FX board with a small speaker to make noise. I set the pins to inputs with pull-ups then connected 14 jumper wires to ground. Every time a wire was disconnected, the system changed its lighting pattern: color, blink timing, blink pattern (blink to white, black, random, or opposite the main color). The system also played a random audio clip. More details on http://embedded.fm/blog/2016/5/24/fistful-of-wires License: CC-A-NC
main.cpp@0:21fea82c85fc, 2016-05-15 (annotated)
- Committer:
- Elecia
- Date:
- Sun May 15 18:06:06 2016 +0000
- Revision:
- 0:21fea82c85fc
- Child:
- 1:0a051df78be2
Blinking works, colors work. No speaker yet.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Elecia | 0:21fea82c85fc | 1 | /* |
Elecia | 0:21fea82c85fc | 2 | Fist full of wires! |
Elecia | 0:21fea82c85fc | 3 | The intention here is to make a ball of wires that someone can reach in and |
Elecia | 0:21fea82c85fc | 4 | grab, changing the behavior of the system. |
Elecia | 0:21fea82c85fc | 5 | |
Elecia | 0:21fea82c85fc | 6 | So we read in the free IO lines, build up a variable. |
Elecia | 0:21fea82c85fc | 7 | If it has changed, |
Elecia | 0:21fea82c85fc | 8 | do the change actions: |
Elecia | 0:21fea82c85fc | 9 | make a bzzzzt sound |
Elecia | 0:21fea82c85fc | 10 | vibrate the motor |
Elecia | 0:21fea82c85fc | 11 | turn off all of the LEDs for a brief instant |
Elecia | 0:21fea82c85fc | 12 | |
Elecia | 0:21fea82c85fc | 13 | Use the created variable to choose the neopixel pattern |
Elecia | 0:21fea82c85fc | 14 | and the sound pattern to output to the audio (intermittent beeps) |
Elecia | 0:21fea82c85fc | 15 | |
Elecia | 0:21fea82c85fc | 16 | |
Elecia | 0:21fea82c85fc | 17 | This program depends on neopixel library. |
Elecia | 0:21fea82c85fc | 18 | http://developer.mbed.org/users/JacobBramley/code/PixelArray/ |
Elecia | 0:21fea82c85fc | 19 | |
Elecia | 0:21fea82c85fc | 20 | Audio (R2D2 sounds) from Szilard Liptak: |
Elecia | 0:21fea82c85fc | 21 | https://developer.mbed.org/users/Szilard/notebook/mbed-r2d2-robot/ |
Elecia | 0:21fea82c85fc | 22 | Sounds in general: https://developer.mbed.org/users/4180_1/notebook/using-a-speaker-for-audio-output/ |
Elecia | 0:21fea82c85fc | 23 | |
Elecia | 0:21fea82c85fc | 24 | Todo: |
Elecia | 0:21fea82c85fc | 25 | Blinking needs a timer attachment |
Elecia | 0:21fea82c85fc | 26 | |
Elecia | 0:21fea82c85fc | 27 | |
Elecia | 0:21fea82c85fc | 28 | |
Elecia | 0:21fea82c85fc | 29 | */ |
Elecia | 0:21fea82c85fc | 30 | #include "mbed.h" |
Elecia | 0:21fea82c85fc | 31 | #include "neopixel.h" |
Elecia | 0:21fea82c85fc | 32 | #include "SongPlayer.h" |
Elecia | 0:21fea82c85fc | 33 | |
Elecia | 0:21fea82c85fc | 34 | #include <stdlib.h> /* srand, rand */ |
Elecia | 0:21fea82c85fc | 35 | #define NLED (8) |
Elecia | 0:21fea82c85fc | 36 | #define ONE_COLOR |
Elecia | 0:21fea82c85fc | 37 | |
Elecia | 0:21fea82c85fc | 38 | BusIn mColorWires( |
Elecia | 0:21fea82c85fc | 39 | p20, p19, p18, p17, p16, p15 // six color, two each, RGB |
Elecia | 0:21fea82c85fc | 40 | ); |
Elecia | 0:21fea82c85fc | 41 | BusIn mBlinkConfig( |
Elecia | 0:21fea82c85fc | 42 | p14, p13, p12, // three timing: indexes into mBlinkTiming |
Elecia | 0:21fea82c85fc | 43 | p30, p29 ); // two for blink type |
Elecia | 0:21fea82c85fc | 44 | |
Elecia | 0:21fea82c85fc | 45 | typedef union { |
Elecia | 0:21fea82c85fc | 46 | struct |
Elecia | 0:21fea82c85fc | 47 | { |
Elecia | 0:21fea82c85fc | 48 | uint32_t green:2; |
Elecia | 0:21fea82c85fc | 49 | uint32_t blue:2; |
Elecia | 0:21fea82c85fc | 50 | uint32_t red:2; |
Elecia | 0:21fea82c85fc | 51 | uint32_t junk:26; |
Elecia | 0:21fea82c85fc | 52 | }; |
Elecia | 0:21fea82c85fc | 53 | uint32_t value; |
Elecia | 0:21fea82c85fc | 54 | } tLedBehaviorWires; |
Elecia | 0:21fea82c85fc | 55 | |
Elecia | 0:21fea82c85fc | 56 | BusIn mLedBitmask (p11, p10, p9, p8, p36, p35, p34, p33); // eight to for bitmask which LED indexes are on... this is not enough of a difference |
Elecia | 0:21fea82c85fc | 57 | |
Elecia | 0:21fea82c85fc | 58 | #define COLOR_WHITE 0xFFFFFF |
Elecia | 0:21fea82c85fc | 59 | #define COLOR_BLACK 0x000000 |
Elecia | 0:21fea82c85fc | 60 | |
Elecia | 0:21fea82c85fc | 61 | void InitializePins(void); |
Elecia | 0:21fea82c85fc | 62 | void AllOneColorLeds(neopixel::Pixel * out, uint32_t index, uintptr_t color); |
Elecia | 0:21fea82c85fc | 63 | void OnChangeMode(neopixel::PixelArray array); |
Elecia | 0:21fea82c85fc | 64 | neopixel::Pixel GetCurrentColor(uint32_t wireConfig); |
Elecia | 0:21fea82c85fc | 65 | void SetLeds(neopixel::Pixel * out, uint32_t index, uintptr_t wireConfig); |
Elecia | 0:21fea82c85fc | 66 | |
Elecia | 0:21fea82c85fc | 67 | class LedArrayController { |
Elecia | 0:21fea82c85fc | 68 | public: |
Elecia | 0:21fea82c85fc | 69 | LedArrayController(BusIn *bus, neopixel::PixelArray *array) : mBus(bus), mArray(array) |
Elecia | 0:21fea82c85fc | 70 | { |
Elecia | 0:21fea82c85fc | 71 | mBus->mode(PullUp); |
Elecia | 0:21fea82c85fc | 72 | srand (time(NULL)); |
Elecia | 0:21fea82c85fc | 73 | } |
Elecia | 0:21fea82c85fc | 74 | void OnChangeMode(uint32_t baseColor) |
Elecia | 0:21fea82c85fc | 75 | { |
Elecia | 0:21fea82c85fc | 76 | // 000 001 010 011 100 101 110, 111 |
Elecia | 0:21fea82c85fc | 77 | const float mBlinkTiming[] = {1.0, 0.1, 0.5, 0.0, 2.0, 0.0, 0.0, 5.0}; |
Elecia | 0:21fea82c85fc | 78 | mBaseColor = baseColor; |
Elecia | 0:21fea82c85fc | 79 | mIsBaseColor = false; |
Elecia | 0:21fea82c85fc | 80 | mBehavior.value = *mBus; |
Elecia | 0:21fea82c85fc | 81 | Update(); |
Elecia | 0:21fea82c85fc | 82 | |
Elecia | 0:21fea82c85fc | 83 | mTiming = mBlinkTiming[mBehavior.timingIndex]; |
Elecia | 0:21fea82c85fc | 84 | if (mTiming > 0.0f) |
Elecia | 0:21fea82c85fc | 85 | { |
Elecia | 0:21fea82c85fc | 86 | mTimer.attach(this, &LedArrayController::Update, mTiming); |
Elecia | 0:21fea82c85fc | 87 | } else { |
Elecia | 0:21fea82c85fc | 88 | mTimer.detach(); |
Elecia | 0:21fea82c85fc | 89 | } |
Elecia | 0:21fea82c85fc | 90 | } |
Elecia | 0:21fea82c85fc | 91 | void Update() { |
Elecia | 0:21fea82c85fc | 92 | // called by timer for updating LEDs: |
Elecia | 0:21fea82c85fc | 93 | if (mIsBaseColor) |
Elecia | 0:21fea82c85fc | 94 | { |
Elecia | 0:21fea82c85fc | 95 | switch (mBehavior.type) { |
Elecia | 0:21fea82c85fc | 96 | case (BLINK_TO_WHITE): |
Elecia | 0:21fea82c85fc | 97 | mArray->update(AllOneColorLeds, NLED, COLOR_WHITE); |
Elecia | 0:21fea82c85fc | 98 | break; |
Elecia | 0:21fea82c85fc | 99 | case (BLINK_TO_BLACK): |
Elecia | 0:21fea82c85fc | 100 | mArray->update(AllOneColorLeds, NLED, COLOR_BLACK); |
Elecia | 0:21fea82c85fc | 101 | break; |
Elecia | 0:21fea82c85fc | 102 | case (BLINK_TO_RANDOM): |
Elecia | 0:21fea82c85fc | 103 | mArray->update(AllOneColorLeds, NLED, (rand() & COLOR_WHITE)); |
Elecia | 0:21fea82c85fc | 104 | break; |
Elecia | 0:21fea82c85fc | 105 | case (BLINK_TO_OPPOSITE): |
Elecia | 0:21fea82c85fc | 106 | mArray->update(AllOneColorLeds, NLED, ~mBaseColor); |
Elecia | 0:21fea82c85fc | 107 | break; |
Elecia | 0:21fea82c85fc | 108 | } |
Elecia | 0:21fea82c85fc | 109 | mIsBaseColor = false; |
Elecia | 0:21fea82c85fc | 110 | |
Elecia | 0:21fea82c85fc | 111 | } else { |
Elecia | 0:21fea82c85fc | 112 | // set to base color |
Elecia | 0:21fea82c85fc | 113 | mArray->update(AllOneColorLeds, NLED, mBaseColor); |
Elecia | 0:21fea82c85fc | 114 | mIsBaseColor = true; |
Elecia | 0:21fea82c85fc | 115 | } |
Elecia | 0:21fea82c85fc | 116 | mTimer.attach(this, &LedArrayController::Update, mTiming); |
Elecia | 0:21fea82c85fc | 117 | |
Elecia | 0:21fea82c85fc | 118 | } |
Elecia | 0:21fea82c85fc | 119 | private: |
Elecia | 0:21fea82c85fc | 120 | float mTiming; |
Elecia | 0:21fea82c85fc | 121 | BusIn *mBus; |
Elecia | 0:21fea82c85fc | 122 | neopixel::PixelArray *mArray; |
Elecia | 0:21fea82c85fc | 123 | Timeout mTimer; |
Elecia | 0:21fea82c85fc | 124 | bool mIsBaseColor; |
Elecia | 0:21fea82c85fc | 125 | uint32_t mBaseColor; |
Elecia | 0:21fea82c85fc | 126 | typedef enum {BLINK_TO_WHITE=0, BLINK_TO_BLACK=1, BLINK_TO_RANDOM=2, BLINK_TO_OPPOSITE=3 } eBlinkType; |
Elecia | 0:21fea82c85fc | 127 | union { |
Elecia | 0:21fea82c85fc | 128 | struct { |
Elecia | 0:21fea82c85fc | 129 | uint32_t timingIndex:3; |
Elecia | 0:21fea82c85fc | 130 | uint32_t type:2; |
Elecia | 0:21fea82c85fc | 131 | uint32_t junk:28; |
Elecia | 0:21fea82c85fc | 132 | }; |
Elecia | 0:21fea82c85fc | 133 | uint32_t value; |
Elecia | 0:21fea82c85fc | 134 | } mBehavior; |
Elecia | 0:21fea82c85fc | 135 | }; |
Elecia | 0:21fea82c85fc | 136 | |
Elecia | 0:21fea82c85fc | 137 | |
Elecia | 0:21fea82c85fc | 138 | void InitializePins(void) |
Elecia | 0:21fea82c85fc | 139 | { |
Elecia | 0:21fea82c85fc | 140 | mColorWires.mode(PullUp); |
Elecia | 0:21fea82c85fc | 141 | mLedBitmask.mode(PullUp); |
Elecia | 0:21fea82c85fc | 142 | mBlinkConfig.mode(PullUp); |
Elecia | 0:21fea82c85fc | 143 | } |
Elecia | 0:21fea82c85fc | 144 | |
Elecia | 0:21fea82c85fc | 145 | void OnChangeMode(neopixel::PixelArray array) |
Elecia | 0:21fea82c85fc | 146 | { |
Elecia | 0:21fea82c85fc | 147 | // FIXME play bzzzt sound |
Elecia | 0:21fea82c85fc | 148 | |
Elecia | 0:21fea82c85fc | 149 | // all white, delay all black |
Elecia | 0:21fea82c85fc | 150 | array.update(AllOneColorLeds, NLED, COLOR_WHITE); |
Elecia | 0:21fea82c85fc | 151 | wait_ms(200); |
Elecia | 0:21fea82c85fc | 152 | array.update(AllOneColorLeds, NLED, COLOR_BLACK); |
Elecia | 0:21fea82c85fc | 153 | wait_ms(200); |
Elecia | 0:21fea82c85fc | 154 | // FIXME mBlinkTimer.detach(); // clear timer functionality |
Elecia | 0:21fea82c85fc | 155 | } |
Elecia | 0:21fea82c85fc | 156 | |
Elecia | 0:21fea82c85fc | 157 | uint8_t MakeColorFromWires(uint32_t singleColorWireConfig) |
Elecia | 0:21fea82c85fc | 158 | { |
Elecia | 0:21fea82c85fc | 159 | uint8_t color; |
Elecia | 0:21fea82c85fc | 160 | if (singleColorWireConfig == 3u) { color = 0xFF; } |
Elecia | 0:21fea82c85fc | 161 | else if (singleColorWireConfig == 0u) { color = 0x00; } |
Elecia | 0:21fea82c85fc | 162 | else /* one bit on */ { color = 0x80; } |
Elecia | 0:21fea82c85fc | 163 | return color; |
Elecia | 0:21fea82c85fc | 164 | } |
Elecia | 0:21fea82c85fc | 165 | |
Elecia | 0:21fea82c85fc | 166 | void AllOneColorLeds(neopixel::Pixel * out, uint32_t index, uintptr_t color) |
Elecia | 0:21fea82c85fc | 167 | { |
Elecia | 0:21fea82c85fc | 168 | out->red = (color >> 16) & 0xFF; |
Elecia | 0:21fea82c85fc | 169 | out->green = (color >> 8 ) & 0xFF; |
Elecia | 0:21fea82c85fc | 170 | out->blue = (color ) & 0xFF; |
Elecia | 0:21fea82c85fc | 171 | } |
Elecia | 0:21fea82c85fc | 172 | |
Elecia | 0:21fea82c85fc | 173 | uint32_t GetCurrentColorU32(uint32_t wireConfig) |
Elecia | 0:21fea82c85fc | 174 | { |
Elecia | 0:21fea82c85fc | 175 | neopixel::Pixel pix; |
Elecia | 0:21fea82c85fc | 176 | uint32_t out; |
Elecia | 0:21fea82c85fc | 177 | pix = GetCurrentColor(wireConfig); |
Elecia | 0:21fea82c85fc | 178 | out = pix.blue + (pix.green << 8) + (pix.red << 16); |
Elecia | 0:21fea82c85fc | 179 | return out; |
Elecia | 0:21fea82c85fc | 180 | } |
Elecia | 0:21fea82c85fc | 181 | |
Elecia | 0:21fea82c85fc | 182 | |
Elecia | 0:21fea82c85fc | 183 | neopixel::Pixel GetCurrentColor(uint32_t wireConfig) |
Elecia | 0:21fea82c85fc | 184 | { |
Elecia | 0:21fea82c85fc | 185 | tLedBehaviorWires config; |
Elecia | 0:21fea82c85fc | 186 | neopixel::Pixel out; |
Elecia | 0:21fea82c85fc | 187 | config.value = wireConfig; |
Elecia | 0:21fea82c85fc | 188 | if ( (config.red == 0u) && (config.green == 0u) && (config.blue == 0u) ) |
Elecia | 0:21fea82c85fc | 189 | { |
Elecia | 0:21fea82c85fc | 190 | out.red = 0x10u; |
Elecia | 0:21fea82c85fc | 191 | out.green = 0x10u; |
Elecia | 0:21fea82c85fc | 192 | out.blue = 0x10u; |
Elecia | 0:21fea82c85fc | 193 | } else { |
Elecia | 0:21fea82c85fc | 194 | out.red = MakeColorFromWires(config.red); |
Elecia | 0:21fea82c85fc | 195 | out.green = MakeColorFromWires(config.green); |
Elecia | 0:21fea82c85fc | 196 | out.blue = MakeColorFromWires(config.blue); |
Elecia | 0:21fea82c85fc | 197 | } |
Elecia | 0:21fea82c85fc | 198 | return out; |
Elecia | 0:21fea82c85fc | 199 | } |
Elecia | 0:21fea82c85fc | 200 | void SetLeds(neopixel::Pixel * out, uint32_t index, uintptr_t wireConfig) |
Elecia | 0:21fea82c85fc | 201 | { |
Elecia | 0:21fea82c85fc | 202 | bool thisOneOn = false; |
Elecia | 0:21fea82c85fc | 203 | uint32_t indexMask = 1u << index; |
Elecia | 0:21fea82c85fc | 204 | |
Elecia | 0:21fea82c85fc | 205 | indexMask &= mLedBitmask; |
Elecia | 0:21fea82c85fc | 206 | if (indexMask) // if this one set |
Elecia | 0:21fea82c85fc | 207 | { |
Elecia | 0:21fea82c85fc | 208 | thisOneOn = true; |
Elecia | 0:21fea82c85fc | 209 | } else if (mLedBitmask == 0u) // all wires plugged in, let all LEDs turn on |
Elecia | 0:21fea82c85fc | 210 | { |
Elecia | 0:21fea82c85fc | 211 | thisOneOn = true; |
Elecia | 0:21fea82c85fc | 212 | } |
Elecia | 0:21fea82c85fc | 213 | |
Elecia | 0:21fea82c85fc | 214 | if (thisOneOn) |
Elecia | 0:21fea82c85fc | 215 | { |
Elecia | 0:21fea82c85fc | 216 | *out = GetCurrentColor(wireConfig); |
Elecia | 0:21fea82c85fc | 217 | } else { |
Elecia | 0:21fea82c85fc | 218 | AllOneColorLeds(out, index, COLOR_BLACK); |
Elecia | 0:21fea82c85fc | 219 | } |
Elecia | 0:21fea82c85fc | 220 | } |
Elecia | 0:21fea82c85fc | 221 | |
Elecia | 0:21fea82c85fc | 222 | |
Elecia | 0:21fea82c85fc | 223 | int main() { |
Elecia | 0:21fea82c85fc | 224 | uint32_t ledBehaviorWires; |
Elecia | 0:21fea82c85fc | 225 | uint32_t ledBitMask; |
Elecia | 0:21fea82c85fc | 226 | uint32_t ledBlinkConfig; |
Elecia | 0:21fea82c85fc | 227 | bool change = true; |
Elecia | 0:21fea82c85fc | 228 | neopixel::PixelArray array(p5); |
Elecia | 0:21fea82c85fc | 229 | LedArrayController ledArrayController(&mBlinkConfig, &array); |
Elecia | 0:21fea82c85fc | 230 | // SongPlayer mySpeaker(p21); |
Elecia | 0:21fea82c85fc | 231 | |
Elecia | 0:21fea82c85fc | 232 | InitializePins(); |
Elecia | 0:21fea82c85fc | 233 | |
Elecia | 0:21fea82c85fc | 234 | // float note[18]= {3520, 3135.96, 2637.02, 2093, 2349.32, 3951.07, 2793.83, 4186.01, 3520, 3135.96, 2637.02, 2093, 2349.32, 3951.07, 2793.83, 4186.01}; //R2D2 sound effect |
Elecia | 0:21fea82c85fc | 235 | // float duration[18]= {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}; //for a bit of variety, multiple sound samples could be chosen at random |
Elecia | 0:21fea82c85fc | 236 | |
Elecia | 0:21fea82c85fc | 237 | // float note[18]= {1568.0,1396.9,1244.5,1244.5,1396.9,1568.0,1568.0,1568.0,1396.9, |
Elecia | 0:21fea82c85fc | 238 | // 1244.5,1396.9,1568.0,1396.9,1244.5,1174.7,1244.5,1244.5, 0.0 |
Elecia | 0:21fea82c85fc | 239 | // }; |
Elecia | 0:21fea82c85fc | 240 | //float duration[18]= {0.48,0.24,0.72,0.48,0.24,0.48,0.24,0.24,0.24, |
Elecia | 0:21fea82c85fc | 241 | // 0.24,0.24,0.24,0.24,0.48,0.24,0.48,0.48, 0.0 |
Elecia | 0:21fea82c85fc | 242 | // }; |
Elecia | 0:21fea82c85fc | 243 | |
Elecia | 0:21fea82c85fc | 244 | // uint32_t val = 0; |
Elecia | 0:21fea82c85fc | 245 | while (1) |
Elecia | 0:21fea82c85fc | 246 | { |
Elecia | 0:21fea82c85fc | 247 | if ((ledBehaviorWires != mColorWires) || |
Elecia | 0:21fea82c85fc | 248 | (ledBitMask != mLedBitmask) || |
Elecia | 0:21fea82c85fc | 249 | (ledBlinkConfig != mBlinkConfig) ) |
Elecia | 0:21fea82c85fc | 250 | { |
Elecia | 0:21fea82c85fc | 251 | change = true; |
Elecia | 0:21fea82c85fc | 252 | } |
Elecia | 0:21fea82c85fc | 253 | if (change) |
Elecia | 0:21fea82c85fc | 254 | { |
Elecia | 0:21fea82c85fc | 255 | change = false; |
Elecia | 0:21fea82c85fc | 256 | ledBehaviorWires = mColorWires; |
Elecia | 0:21fea82c85fc | 257 | ledBitMask = mLedBitmask; |
Elecia | 0:21fea82c85fc | 258 | ledBlinkConfig = mBlinkConfig; |
Elecia | 0:21fea82c85fc | 259 | ledArrayController.OnChangeMode(GetCurrentColorU32(ledBehaviorWires)); |
Elecia | 0:21fea82c85fc | 260 | // OnChangeMode(array); |
Elecia | 0:21fea82c85fc | 261 | |
Elecia | 0:21fea82c85fc | 262 | array.update(SetLeds, NLED, ledBehaviorWires); |
Elecia | 0:21fea82c85fc | 263 | } |
Elecia | 0:21fea82c85fc | 264 | |
Elecia | 0:21fea82c85fc | 265 | // mySpeaker.PlaySong(note,duration); //play R2D2 sound effects |
Elecia | 0:21fea82c85fc | 266 | wait_ms(10); |
Elecia | 0:21fea82c85fc | 267 | } |
Elecia | 0:21fea82c85fc | 268 | } |