├── ESP_LEDtester ├── ESPdotstar.ino └── README.md ├── README.md ├── adafruitsVersion ├── README.md ├── bikewheel.ino └── pixels.h ├── convertImages ├── README.md ├── convert.py ├── forrest.png ├── færrefremmede.png ├── graphics.h ├── moth.png ├── nastywoman.png ├── pride.png ├── runningdollar.png └── trump.png └── pov_bike ├── README.md ├── nasty.h └── pov_bike.ino /ESP_LEDtester/ESPdotstar.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define NUMPIXELS 289 5 | 6 | #define DATAPIN MOSI 7 | #define CLOCKPIN SCK 8 | Adafruit_DotStar strip = Adafruit_DotStar(NUMPIXELS, DATAPIN, CLOCKPIN); 9 | 10 | void setup() { 11 | strip.begin(); 12 | strip.show(); 13 | } 14 | int head = 0, tail = -10; 15 | uint32_t color = 0x110000; 16 | 17 | void loop() { 18 | 19 | strip.setPixelColor(head, color); 20 | strip.setPixelColor(tail, 0); 21 | strip.show(); 22 | delay(1); 23 | 24 | if(++head >= NUMPIXELS) { 25 | head = 0; 26 | if((color >>= 8) == 0) 27 | color = 0x110000; 28 | } 29 | if(++tail >= NUMPIXELS) tail = 0; 30 | } 31 | -------------------------------------------------------------------------------- /ESP_LEDtester/README.md: -------------------------------------------------------------------------------- 1 | ESPdotstar 2 | =============== 3 | A sketch to test esp with dotstar library and a way to test your APA102 led strip, to see if there is any production errors and/or dead pixels 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Bike POV display 2 | =============== 3 | This is my version of a persistence-of-vision display attached on a bike. In my version I'm using a ESP8266 module for future WiFi integration. 4 | 5 | Instructable can be found here: https://www.instructables.com/id/POV-Bike-Display-ESP8266-APA102-UNDER-CONSTRUCTION/ 6 | This is not complete yet, and it's only 8-bits photos that works at the moment but that should be enough to display great images. 7 | 8 | Below is thanks and license remarks from adafruit's software. A big thanks for your work. 9 | 10 | Groundwork made by Adafruit 11 | =========== 12 | Software related to DotStar LED persistence-of-vision performance items -- initially just the Trinket-based "Genesis Poi," but might devise more POV projects later...this is where they'll go. 13 | 14 | Guide: https://learn.adafruit.com/genesis-poi-dotstar-led-persistence-of-vision-poi 15 | 16 | Requires DotStar library for Arduino: https://github.com/adafruit/Adafruit_DotStar 17 | 18 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 19 | 20 | Written by Phil Burgess / Paint Your Dragon for Adafruit Industries. MIT license, all text above must be included in any redistribution. See 'COPYING' file for additional notes. 21 | -------------------------------------------------------------------------------- /adafruitsVersion/README.md: -------------------------------------------------------------------------------- 1 | ORIGINAL CODE FROM ADAFRUIT 2 | ============================== 3 | Find full tutorial on https://learn.adafruit.com/bike-wheel-pov-display/overview 4 | 5 | 6 | And again. Thank you so much for your work. 7 | -------------------------------------------------------------------------------- /adafruitsVersion/bikewheel.ino: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------------------ 2 | POV LED bike wheel sketch. Uses the following Adafruit parts: 3 | 4 | - Pro Trinket 5V (www.adafruit.com/product/2000) 5 | (NOT Trinket or 3V Pro Trinket) 6 | - Waterproof 3xAA battery holder with on/off switch (#771) 7 | - 144 LED/m DotStar strip (#2328 or #2329) ONE is enough for 8 | both sides of one bike wheel 9 | - Tactile switch button (#1119) (optional) 10 | 11 | Needs Adafruit_DotStar library: github.com/adafruit/Adafruit_DotStar 12 | 13 | Full instructions: https://learn.adafruit.com/bike-wheel-pov-display 14 | 15 | This project is based on Phil B's Genesis Poi: 16 | learn.adafruit.com/genesis-poi-dotstar-led-persistence-of-vision-poi 17 | and has been adapted to the Pro Trinket to accomodate more and larger 18 | images than Trinket. 19 | 20 | Adafruit invests time and resources providing this open source code, 21 | please support Adafruit and open-source hardware by purchasing 22 | products from Adafruit! 23 | 24 | Written by Phil Burgess / Paint Your Dragon for Adafruit Industries. 25 | MIT license, all text above must be included in any redistribution. 26 | See 'COPYING' file for additional notes. 27 | ------------------------------------------------------------------------*/ 28 | 29 | #include //maybe that includes pgmspace 30 | #include 31 | //#include 32 | //#include 33 | #include // Enable this line on Pro Trinket 34 | 35 | #ifdef ESP8266 36 | #include 37 | #else 38 | #include 39 | #endif 40 | 41 | #ifdef __AVR_ATtiny85__ 42 | typedef uint8_t line_t; // Max 255 lines/image on Trinket 43 | #else 44 | typedef uint16_t line_t; // Bigger images OK on other boards 45 | #endif 46 | 47 | // CONFIGURABLE STUFF ------------------------------------------------------ 48 | 49 | #include "pixels.h" // Graphics data is contained in this header file. 50 | // It's generated using the 'convert.py' Python script. Various image 51 | // formats are supported, trading off color fidelity for PROGMEM space 52 | // (particularly limited on Trinket). Handles 1-, 4- and 8-bit-per-pixel 53 | // palette-based images, plus 24-bit truecolor. 1- and 4-bit palettes can 54 | // be altered in RAM while running to provide additional colors, but be 55 | // mindful of peak & average current draw if you do that! Power limiting 56 | // is normally done in convert.py (keeps this code relatively small & fast). 57 | // 1/4/8/24 were chosen because the AVR can handle these operations fairly 58 | // easily (have idea for handing arbitrary bit depth w/328P, but this margin 59 | // is too narrow to contain). 60 | 61 | // Ideally you use hardware SPI as it's much faster, though limited to 62 | // specific pins. If you really need to bitbang DotStar data & clock on 63 | // different pins, optionally define those here: 64 | #ifdef ESP8266 65 | #define LED_DATA_PIN MOSI //changed to fit ESP8266 modules. look in ESPdotstar 66 | #define LED_CLOCK_PIN SCK // same 67 | #else 68 | #define LED_DATA_PIN 11 69 | #define LED_CLOCK_PIN 12 70 | #endif 71 | // Select from multiple images using tactile button (#1489) between pin and 72 | // ground. Requires suitably-built pixels.h file w/more than one image. 73 | #define SELECT_PIN 3 74 | 75 | // Optional feature -- not enabled here, no space -- a vibration switch 76 | // (aligned perpendicular to leash) is used as a poor man's accelerometer. 77 | // Poi then lights only when moving, saving some power. The 'fast' 78 | // vibration switch is VERY sensitive and will trigger at the slightest 79 | // bump, while the 'medium' switch requires a certain spin rate which may 80 | // not trigger if you're doing mellow spins. Neither is perfect. To leave 81 | // that out and simply have the poi run always-on, comment out this line: 82 | //#define MOTION_PIN 2 83 | 84 | // Another optional feature not enable due to physical size -- powering down 85 | // DotStars when idle conserves more battery. Use a PNP transistor (e.g. 86 | // 2N2907) (w/220 Ohm resistor to base) as a 'high side' switch to DotStar 87 | // +V. DON'T do this NPN/low-side, may damage strip. MOTION_PIN must also 88 | // be defined to use this (pointless without). 89 | //#define POWER_PIN 4 90 | 91 | #define SLEEP_TIME 2000 // Not-spinning time before sleep, in milliseconds 92 | 93 | // Empty and full thresholds (millivolts) used for battery level display: 94 | #define BATT_MIN_MV 3350 // Some headroom over battery cutoff near 2.9V 95 | #define BATT_MAX_MV 4000 // And little below fresh-charged battery near 4.1V 96 | // These figures are based on LiPoly cell and will need to be tweaked for 97 | // 3X NiMH or alkaline batteries! 98 | 99 | boolean autoCycle = true; // Set to true to cycle images by default 100 | #define CYCLE_TIME 10 // Time, in seconds, between auto-cycle images 101 | 102 | // ------------------------------------------------------------------------- 103 | 104 | #if defined(LED_DATA_PIN) && defined(LED_CLOCK_PIN) 105 | // Older DotStar LEDs use GBR order. If colors are wrong, edit here. 106 | Adafruit_DotStar strip = Adafruit_DotStar(NUM_LEDS, 107 | LED_DATA_PIN, LED_CLOCK_PIN, DOTSTAR_BRG); 108 | #else 109 | Adafruit_DotStar strip = Adafruit_DotStar(NUM_LEDS, DOTSTAR_BGR); 110 | #endif 111 | 112 | void imageInit(void); 113 | uint16_t readVoltage(void); 114 | #ifdef MOTION_PIN 115 | void sleep(void); 116 | #endif 117 | 118 | void setup() { 119 | #if defined(__AVR_ATtiny85__) && (F_CPU == 16000000L) 120 | clock_prescale_set(clock_div_1); // Enable 16 MHz on Trinket 121 | #endif 122 | 123 | #ifdef POWER_PIN 124 | pinMode(POWER_PIN, OUTPUT); 125 | digitalWrite(POWER_PIN, LOW); // Power-on LED strip 126 | #endif 127 | strip.begin(); // Allocate DotStar buffer, init SPI 128 | strip.clear(); // Make sure strip is clear 129 | strip.show(); // before measuring battery 130 | 131 | // Display battery level bargraph on startup. It's just a vague estimate 132 | // based on cell voltage (drops with discharge) but doesn't handle curve. 133 | uint16_t mV = readVoltage(); 134 | uint8_t lvl = (mV >= BATT_MAX_MV) ? NUM_LEDS : // Full (or nearly) 135 | (mV <= BATT_MIN_MV) ? 1 : // Drained 136 | 1 + ((mV - BATT_MIN_MV) * NUM_LEDS + (NUM_LEDS / 2)) / 137 | (BATT_MAX_MV - BATT_MIN_MV + 1); // # LEDs lit (1-NUM_LEDS) 138 | for(uint8_t i=0; i palette data in PROGMEM 168 | *imagePixels, // -> pixel data in PROGMEM 169 | palette[16][3]; // RAM-based color table for 1- or 4-bit images 170 | line_t imageLines, // Number of lines in active image 171 | imageLine; // Current line number in image 172 | #ifdef SELECT_PIN 173 | uint8_t debounce = 0; // Debounce counter for image select pin 174 | #endif 175 | 176 | void imageInit() { // Initialize global image state for current imageNumber 177 | imageType = pgm_read_byte(&images[imageNumber].type); 178 | #ifdef __AVR_ATtiny85__ 179 | imageLines = pgm_read_byte(&images[imageNumber].lines); 180 | #else 181 | imageLines = pgm_read_word(&images[imageNumber].lines); 182 | #endif 183 | imageLine = 0; 184 | imagePalette = (uint8_t *)pgm_read_word(&images[imageNumber].palette); 185 | imagePixels = (uint8_t *)pgm_read_word(&images[imageNumber].pixels); 186 | // 1- and 4-bit images have their color palette loaded into RAM both for 187 | // faster access and to allow dynamic color changing. Not done w/8-bit 188 | // because that would require inordinate RAM (328P could handle it, but 189 | // I'd rather keep the RAM free for other features in the future). 190 | if(imageType == PALETTE1) memcpy_P(palette, imagePalette, 2 * 3); 191 | else if(imageType == PALETTE4) memcpy_P(palette, imagePalette, 16 * 3); 192 | lastImageTime = millis(); // Save time of image init for next auto-cycle 193 | } 194 | 195 | void nextImage(void) { 196 | if(++imageNumber >= NUM_IMAGES) imageNumber = 0; 197 | imageInit(); 198 | } 199 | 200 | // MAIN LOOP --------------------------------------------------------------- 201 | 202 | void loop() { 203 | uint32_t t = millis(); // Current time, milliseconds 204 | #ifdef MOTION_PIN 205 | // Tried to do this with watchdog timer but encountered gas pains, so... 206 | if(!digitalRead(MOTION_PIN)) { // Vibration switch pulled down? 207 | prev = t; // Yes, reset timer 208 | } else if((t - prev) > SLEEP_TIME) { // No, SLEEP_TIME elapsed w/no switch? 209 | sleep(); // Power down 210 | prev = t; // Reset timer on wake 211 | } 212 | #endif 213 | 214 | if(autoCycle) { 215 | if((t - lastImageTime) >= (CYCLE_TIME * 1000L)) nextImage(); 216 | // CPU clocks vary slightly; multiple poi won't stay in perfect sync. 217 | // Keep this in mind when using auto-cycle mode, you may want to cull 218 | // the image selection to avoid unintentional regrettable combinations. 219 | } 220 | #ifdef SELECT_PIN 221 | if(digitalRead(SELECT_PIN)) { // Image select? 222 | debounce = 0; // Not pressed -- reset counter 223 | } else { // Pressed... 224 | if(++debounce >= 25) { // Debounce input 225 | nextImage(); // Switch to next image 226 | while(!digitalRead(SELECT_PIN)); // Wait for release 227 | // If held 1+ sec, toggle auto-cycle mode on/off 228 | if((millis() - t) >= 1000L) autoCycle = !autoCycle; 229 | debounce = 0; 230 | } 231 | } 232 | #endif 233 | 234 | // Transfer one scanline from pixel data to LED strip: 235 | 236 | // If you're really pressed for graphics space and need just a few extra 237 | // scanlines, and know for a fact you won't be using certain image modes, 238 | // you can comment out the corresponding blocks below. e.g. PALETTE8 and 239 | // TRUECOLOR are somewhat impractical on Trinket, and commenting them out 240 | // can free up nearly 200 bytes of extra image storage. 241 | 242 | switch(imageType) { 243 | 244 | case PALETTE1: { // 1-bit (2 color) palette-based image 245 | uint8_t pixelNum = 0, byteNum, bitNum, pixels, idx, 246 | *ptr = (uint8_t *)&imagePixels[imageLine * NUM_LEDS / 8]; 247 | for(byteNum = NUM_LEDS/8; byteNum--; ) { // Always padded to next byte 248 | pixels = pgm_read_byte(ptr++); // 8 pixels of data (pixel 0 = LSB) 249 | for(bitNum = 8; bitNum--; pixels >>= 1) { 250 | idx = pixels & 1; // Color table index for pixel (0 or 1) 251 | strip.setPixelColor(pixelNum++, 252 | palette[idx][0], palette[idx][1], palette[idx][2]); 253 | } 254 | } 255 | break; 256 | } 257 | 258 | case PALETTE4: { // 4-bit (16 color) palette-based image 259 | uint8_t pixelNum, p1, p2, 260 | *ptr = (uint8_t *)&imagePixels[imageLine * NUM_LEDS / 2]; 261 | for(pixelNum = 0; pixelNum < NUM_LEDS; ) { 262 | p2 = pgm_read_byte(ptr++); // Data for two pixels... 263 | p1 = p2 >> 4; // Shift down 4 bits for first pixel 264 | p2 &= 0x0F; // Mask out low 4 bits for second pixel 265 | strip.setPixelColor(pixelNum++, 266 | palette[p1][0], palette[p1][1], palette[p1][2]); 267 | strip.setPixelColor(pixelNum++, 268 | palette[p2][0], palette[p2][1], palette[p2][2]); 269 | } 270 | break; 271 | } 272 | 273 | case PALETTE8: { // 8-bit (256 color) PROGMEM-palette-based image 274 | uint16_t o; 275 | uint8_t pixelNum, 276 | *ptr = (uint8_t *)&imagePixels[imageLine * NUM_LEDS]; 277 | for(pixelNum = 0; pixelNum < NUM_LEDS; pixelNum++) { 278 | o = pgm_read_byte(ptr++) * 3; // Offset into imagePalette 279 | strip.setPixelColor(pixelNum, 280 | pgm_read_byte(&imagePalette[o]), 281 | pgm_read_byte(&imagePalette[o + 1]), 282 | pgm_read_byte(&imagePalette[o + 2])); 283 | } 284 | break; 285 | } 286 | 287 | case TRUECOLOR: { // 24-bit ('truecolor') image (no palette) 288 | uint8_t pixelNum, r, g, b, 289 | *ptr = (uint8_t *)&imagePixels[imageLine * NUM_LEDS * 3]; 290 | for(pixelNum = 0; pixelNum < NUM_LEDS; pixelNum++) { 291 | r = pgm_read_byte(ptr++); 292 | g = pgm_read_byte(ptr++); 293 | b = pgm_read_byte(ptr++); 294 | strip.setPixelColor(pixelNum, r, g, b); 295 | } 296 | break; 297 | } 298 | } 299 | 300 | strip.show(); // Refresh LEDs 301 | #if !defined(LED_DATA_PIN) && !defined(LED_CLOCK_PIN) 302 | delayMicroseconds(900); // Because hardware SPI is ludicrously fast 303 | #endif 304 | if(++imageLine >= imageLines) imageLine = 0; // Next scanline, wrap around 305 | } 306 | 307 | // POWER-SAVING STUFF -- Relentlessly non-portable ------------------------- 308 | 309 | #ifdef MOTION_PIN 310 | void sleep() { 311 | 312 | // Turn off LEDs... 313 | strip.clear(); // Issue '0' data 314 | strip.show(); 315 | #ifdef POWER_PIN 316 | digitalWrite(POWER_PIN, HIGH); // Cut power 317 | #if !defined(LED_DATA_PIN) && !defined(LED_CLOCK_PIN) 318 | #ifdef __AVR_ATtiny85__ 319 | pinMode(1, INPUT); // Set SPI data & clock to inputs else 320 | pinMode(2, INPUT); // DotStars power parasitically, jerks. 321 | #else 322 | pinMode(11, INPUT); 323 | pinMode(13, INPUT); 324 | #endif // ATtiny 325 | #endif // Data/clock/pins 326 | #endif // POWER_PIN 327 | 328 | power_all_disable(); // Peripherals ALL OFF, best sleep-state battery use 329 | 330 | // Enable pin-change interrupt on motion pin 331 | #ifdef __AVR_ATtiny85__ 332 | PCMSK = _BV(MOTION_PIN); // Pin mask 333 | GIMSK = _BV(PCIE); // Interrupt enable 334 | #else 335 | volatile uint8_t *p = portInputRegister(digitalPinToPort(MOTION_PIN)); 336 | if(p == &PIND) { // Pins 0-7 = PCINT16-23 337 | PCMSK2 = _BV(MOTION_PIN); 338 | PCICR = _BV(PCIE2); 339 | } else if(p == &PINB) { // Pins 8-13 = PCINT0-5 340 | PCMSK0 = _BV(MOTION_PIN- 8); 341 | PCICR = _BV(PCIE0); 342 | } else if(p == &PINC) { // Pins 14-20 = PCINT8-14 343 | PCMSK1 = _BV(MOTION_PIN-14); 344 | PCICR = _BV(PCIE1); 345 | } 346 | #endif 347 | 348 | // If select pin is enabled, that wakes too! 349 | #ifdef SELECT_PIN 350 | debounce = 0; 351 | #ifdef __AVR_ATtiny85__ 352 | PCMSK |= _BV(SELECT_PIN); // Add'l pin mask 353 | #else 354 | volatile uint8_t *p = portInputRegister(digitalPinToPort(SELECT_PIN)); 355 | if(p == &PIND) { // Pins 0-7 = PCINT16-23 356 | PCMSK2 = _BV(SELECT_PIN); 357 | PCICR = _BV(PCIE2); 358 | } else if(p == &PINB) { // Pins 8-13 = PCINT0-5 359 | PCMSK0 = _BV(SELECT_PIN- 8); 360 | PCICR = _BV(PCIE0); 361 | } else if(p == &PINC) { // Pins 14-20 = PCINT8-14 362 | PCMSK1 = _BV(SELECT_PIN-14); 363 | PCICR = _BV(PCIE1); 364 | } 365 | #endif // ATtiny 366 | #endif // SELECT_PIN 367 | 368 | set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Deepest sleep mode 369 | sleep_enable(); 370 | interrupts(); 371 | sleep_mode(); // Power down 372 | 373 | // Resumes here on wake 374 | 375 | // Clear pin change settings so interrupt won't fire again 376 | #ifdef __AVR_ATtiny85__ 377 | GIMSK = PCMSK = 0; 378 | #else 379 | PCICR = PCMSK0 = PCMSK1 = PCMSK2 = 0; 380 | #endif 381 | power_timer0_enable(); // Used by millis() 382 | #if !defined(LED_DATA_PIN) && !defined(LED_CLOCK_PIN) 383 | #ifdef __AVR_ATtiny85__ 384 | pinMode(1, OUTPUT); // Re-enable SPI pins 385 | pinMode(2, OUTPUT); 386 | power_usi_enable(); // Used by DotStar 387 | //#else 388 | // pinMode(11, OUTPUT); // Re-enable SPI pins 389 | // pinMode(13, OUTPUT); 390 | power_spi_enable(); // Used by DotStar 391 | #endif // ATtiny 392 | #endif // Data/clock pins 393 | #ifdef POWER_PIN 394 | digitalWrite(POWER_PIN, LOW); // Power-up LEDs 395 | #endif 396 | prev = millis(); // Save wake time 397 | } 398 | 399 | EMPTY_INTERRUPT(PCINT0_vect); // Pin change (does nothing, but required) 400 | #ifndef __AVR_ATtiny85__ 401 | ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect)); 402 | ISR(PCINT2_vect, ISR_ALIASOF(PCINT0_vect)); 403 | #endif 404 | 405 | #endif // MOTION_PIN 406 | 407 | // Battery monitoring idea adapted from JeeLabs article: 408 | // jeelabs.org/2012/05/04/measuring-vcc-via-the-bandgap/ 409 | // Code from Adafruit TimeSquare project, added Trinket support. 410 | // In a pinch, the poi code can work on a 3V Trinket, but the battery 411 | // monitor will not work correctly (due to the 3.3V regulator), so 412 | // maybe just comment out any reference to this code in that case. 413 | uint16_t readVoltage() { 414 | int i, prev; 415 | uint8_t count; 416 | uint16_t mV; 417 | 418 | // Select AVcc voltage reference + Bandgap (1.8V) input 419 | #ifdef __AVR_ATtiny85__ 420 | ADMUX = _BV(MUX3) | _BV(MUX2); 421 | #else 422 | //ADMUX = _BV(REFS0) | 423 | // _BV(MUX3) | _BV(MUX2) | _BV(MUX1); 424 | #endif 425 | // ADCSRA = _BV(ADEN) | // Enable ADC 426 | // _BV(ADPS2) | _BV(ADPS1) | _BV(ADPS0); // 1/128 prescaler (125 KHz) 427 | // Datasheet notes that the first bandgap reading is usually garbage as 428 | // voltages are stabilizing. It practice, it seems to take a bit longer 429 | // than that. Tried various delays, but still inconsistent and kludgey. 430 | // Instead, repeated readings are taken until four concurrent readings 431 | // stabilize within 10 mV. 432 | for(prev=9999, count=0; count<4; ) { 433 | // for(ADCSRA |= _BV(ADSC); ADCSRA & _BV(ADSC); ); // Start, await ADC conv. 434 | // i = ADC; // Result 435 | mV = i ? (1100L * 1023 / i) : 0; // Scale to millivolts 436 | if(abs((int)mV - prev) <= 10) count++; // +1 stable reading 437 | else count = 0; // too much change, start over 438 | prev = mV; 439 | } 440 | // ADCSRA = 0; // ADC off 441 | return mV; 442 | } 443 | -------------------------------------------------------------------------------- /adafruitsVersion/pixels.h: -------------------------------------------------------------------------------- 1 | // Don't edit this file! It's software-generated. 2 | // See convert.py script instead. 3 | 4 | #define PALETTE1 0 5 | #define PALETTE4 1 6 | #define PALETTE8 2 7 | #define TRUECOLOR 3 8 | 9 | #define NUM_LEDS 16 10 | 11 | // pride.gif --------------------------------------------------------------- 12 | 13 | const uint8_t PROGMEM palette00[][3] = { 14 | { 34, 0, 75 }, 15 | { 75, 75, 0 }, 16 | { 0, 50, 0 }, 17 | { 0, 0, 0 }, 18 | { 75, 0, 0 }, 19 | { 75, 18, 0 }, 20 | { 0, 6, 75 } }; 21 | 22 | const uint8_t PROGMEM pixels00[] = { 23 | 0X34, 0X44, 0X44, 0X44, 0X44, 0X44, 0X44, 0X43, 24 | 0X33, 0X44, 0X44, 0X44, 0X44, 0X44, 0X44, 0X33, 25 | 0X53, 0X34, 0X44, 0X44, 0X44, 0X44, 0X43, 0X35, 26 | 0X55, 0X33, 0X44, 0X44, 0X44, 0X44, 0X33, 0X55, 27 | 0X55, 0X53, 0X34, 0X44, 0X44, 0X43, 0X35, 0X55, 28 | 0X55, 0X55, 0X33, 0X44, 0X44, 0X33, 0X55, 0X55, 29 | 0X55, 0X55, 0X53, 0X34, 0X43, 0X35, 0X55, 0X55, 30 | 0X55, 0X55, 0X55, 0X33, 0X33, 0X55, 0X55, 0X55, 31 | 0X55, 0X55, 0X55, 0X53, 0X35, 0X55, 0X55, 0X55, 32 | 0X35, 0X55, 0X55, 0X55, 0X55, 0X55, 0X55, 0X53, 33 | 0X33, 0X55, 0X55, 0X55, 0X55, 0X55, 0X55, 0X33, 34 | 0X13, 0X35, 0X55, 0X55, 0X55, 0X55, 0X53, 0X31, 35 | 0X11, 0X33, 0X55, 0X55, 0X55, 0X55, 0X33, 0X11, 36 | 0X11, 0X13, 0X35, 0X55, 0X55, 0X53, 0X31, 0X11, 37 | 0X11, 0X11, 0X33, 0X55, 0X55, 0X33, 0X11, 0X11, 38 | 0X11, 0X11, 0X13, 0X35, 0X53, 0X31, 0X11, 0X11, 39 | 0X11, 0X11, 0X11, 0X33, 0X33, 0X11, 0X11, 0X11, 40 | 0X11, 0X11, 0X11, 0X13, 0X31, 0X11, 0X11, 0X11, 41 | 0X31, 0X11, 0X11, 0X11, 0X11, 0X11, 0X11, 0X13, 42 | 0X33, 0X11, 0X11, 0X11, 0X11, 0X11, 0X11, 0X33, 43 | 0X23, 0X31, 0X11, 0X11, 0X11, 0X11, 0X13, 0X32, 44 | 0X22, 0X33, 0X11, 0X11, 0X11, 0X11, 0X33, 0X22, 45 | 0X22, 0X23, 0X31, 0X11, 0X11, 0X13, 0X32, 0X22, 46 | 0X22, 0X22, 0X33, 0X11, 0X11, 0X33, 0X22, 0X22, 47 | 0X22, 0X22, 0X23, 0X31, 0X13, 0X32, 0X22, 0X22, 48 | 0X22, 0X22, 0X22, 0X33, 0X33, 0X22, 0X22, 0X22, 49 | 0X22, 0X22, 0X22, 0X23, 0X32, 0X22, 0X22, 0X22, 50 | 0X32, 0X22, 0X22, 0X22, 0X22, 0X22, 0X22, 0X23, 51 | 0X33, 0X22, 0X22, 0X22, 0X22, 0X22, 0X22, 0X33, 52 | 0X63, 0X32, 0X22, 0X22, 0X22, 0X22, 0X23, 0X36, 53 | 0X66, 0X33, 0X22, 0X22, 0X22, 0X22, 0X33, 0X66, 54 | 0X66, 0X63, 0X32, 0X22, 0X22, 0X23, 0X36, 0X66, 55 | 0X66, 0X66, 0X33, 0X22, 0X22, 0X33, 0X66, 0X66, 56 | 0X66, 0X66, 0X63, 0X32, 0X23, 0X36, 0X66, 0X66, 57 | 0X66, 0X66, 0X66, 0X33, 0X33, 0X66, 0X66, 0X66, 58 | 0X66, 0X66, 0X66, 0X63, 0X36, 0X66, 0X66, 0X66, 59 | 0X36, 0X66, 0X66, 0X66, 0X66, 0X66, 0X66, 0X63, 60 | 0X33, 0X66, 0X66, 0X66, 0X66, 0X66, 0X66, 0X33, 61 | 0X03, 0X36, 0X66, 0X66, 0X66, 0X66, 0X63, 0X30, 62 | 0X00, 0X33, 0X66, 0X66, 0X66, 0X66, 0X33, 0X00, 63 | 0X00, 0X03, 0X36, 0X66, 0X66, 0X63, 0X30, 0X00, 64 | 0X00, 0X00, 0X33, 0X66, 0X66, 0X33, 0X00, 0X00, 65 | 0X00, 0X00, 0X03, 0X36, 0X63, 0X30, 0X00, 0X00, 66 | 0X00, 0X00, 0X00, 0X33, 0X33, 0X00, 0X00, 0X00, 67 | 0X00, 0X00, 0X00, 0X03, 0X30, 0X00, 0X00, 0X00, 68 | 0X30, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 69 | 0X33, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X33, 70 | 0X43, 0X30, 0X00, 0X00, 0X00, 0X00, 0X03, 0X34, 71 | 0X44, 0X33, 0X00, 0X00, 0X00, 0X00, 0X33, 0X44, 72 | 0X44, 0X43, 0X30, 0X00, 0X00, 0X03, 0X34, 0X44, 73 | 0X44, 0X44, 0X33, 0X00, 0X00, 0X33, 0X44, 0X44, 74 | 0X44, 0X44, 0X43, 0X30, 0X03, 0X34, 0X44, 0X44, 75 | 0X44, 0X44, 0X44, 0X33, 0X33, 0X44, 0X44, 0X44, 76 | 0X44, 0X44, 0X44, 0X43, 0X34, 0X44, 0X44, 0X44 }; 77 | 78 | typedef struct { 79 | uint8_t type; // PALETTE[1,4,8] or TRUECOLOR 80 | line_t lines; // Length of image (in scanlines) 81 | const uint8_t *palette; // -> PROGMEM color table (NULL if truecolor) 82 | const uint8_t *pixels; // -> Pixel data in PROGMEM 83 | } image; 84 | 85 | const image PROGMEM images[] = { 86 | { PALETTE4 , 54, (const uint8_t *)palette00, pixels00 } 87 | }; 88 | 89 | #define NUM_IMAGES (sizeof(images) / sizeof(images[0])) 90 | -------------------------------------------------------------------------------- /convertImages/README.md: -------------------------------------------------------------------------------- 1 | Convert image to hex 2 | ========= 3 | This python script is written by Phil Burgess and I've only made a few adjustments to it. 4 | You need python 2.7 and the library Pillow to run the script. I used pip to install the library on OS X 10.11. 5 | -------------------------------------------------------------------------------- /convertImages/convert.py: -------------------------------------------------------------------------------- 1 | # Image converter script for POV LED poi project. Reads one or more images 2 | # as input, generates tables which can be copied-and-pasted or redirected 3 | # to a .h file, e.g.: 4 | # 5 | # $ python convert.py image1.gif image2.png > graphics.h 6 | # 7 | # Ideal image dimensions are determined by hardware setup, e.g. LED poi 8 | # project uses 16 LEDs, so image height should match. Width is limited 9 | # by AVR PROGMEM capacity -- very limited on Trinket! 10 | # 11 | # Adafruit invests time and resources providing this open source code, 12 | # please support Adafruit and open-source hardware by purchasing 13 | # products from Adafruit! 14 | # 15 | # Written by Phil Burgess / Paint Your Dragon for Adafruit Industries. 16 | # MIT license, all text above must be included in any redistribution. 17 | # See 'COPYING' file for additional notes. 18 | # -------------------------------------------------------------------------- 19 | 20 | from PIL import Image 21 | import sys 22 | 23 | # Establish peak and average current limits - a function of battery 24 | # capacity and desired run time. 25 | 26 | # These you can edit to match your build: 27 | batterySize = 150 # Battery capacity, in milliamp-hours (mAh) 28 | runTime = 1.1 # Est. max run time, in hours (longer = dimmer LEDs) 29 | parallelStrips = 2 # Same data is issued to this many LED strips 30 | 31 | # These probably don't need editing: 32 | mcuCurrent = 20 # Est. current used by microcontrolled board (mA) 33 | wireLimit = 1500 # Ampacity of battery wires (est 26 gauge) (milliamps) 34 | 35 | # Estimate average and peak LED currents, within some safety thresholds: 36 | if(runTime < 1.0): runTime = 1.0 # Don't exceed 1C rate from battery 37 | cl = batterySize - mcuCurrent * runTime # After MCU, charge left for LEDs 38 | if cl < 0: cl = 0 # Must be non-negative 39 | avgC = cl / runTime / parallelStrips 40 | if avgC > wireLimit: avgC = wireLimit # Don't exceed battery wire ampacity 41 | peakC = avgC * 2.2 # Battery+wires OK w/brief peaks 42 | 43 | bR = 1.0 # Can adjust 44 | bG = 1.0 # color balance 45 | bB = 1.0 # for whiter whites! 46 | gamma = 2.7 # For more linear-ish perceived brightness 47 | 48 | # Current estimates are averages measured from strip on LiPoly cell 49 | mA0 = 1.3 # LED current when off (driver logic still needs some) 50 | mAR = 15.2 * bR # + current for 100% red 51 | mAG = 8.7 * bG # + current for 100% green 52 | mAB = 8.0 * bB # + current for 100% blue 53 | 54 | # -------------------------------------------------------------------------- 55 | 56 | cols = 0 # Current column number in output 57 | byteNum = 0 58 | numBytes = 0 59 | 60 | def writeByte(n): 61 | global cols, byteNum, numBytes 62 | 63 | cols += 1 # Increment column # 64 | if cols >= 8: # If max column exceeded... 65 | print # end current line 66 | sys.stdout.write(" ") # and start new one 67 | cols = 0 # Reset counter 68 | sys.stdout.write("{0:#0{1}X}".format(n, 4)) 69 | byteNum += 1 70 | if byteNum < numBytes: 71 | sys.stdout.write(",") 72 | if cols < 7: 73 | sys.stdout.write(" ") 74 | 75 | # -------------------------------------------------------------------------- 76 | 77 | numLEDs = 0 78 | images = [] 79 | 80 | # Initial pass loads each image & tracks tallest size overall 81 | 82 | for name in sys.argv[1:]: # For each image passed to script... 83 | image = Image.open(name) 84 | image.pixels = image.load() 85 | # Determine if image is truecolor vs. colormapped. 86 | image.colors = image.getcolors(256) 87 | if image.colors == None: 88 | image.numColors = 257 # Image is truecolor 89 | else: 90 | # If 256 colors or less, that doesn't necessarily mean 91 | # it's a non-truecolor image yet, just that it has few 92 | # colors. Check the image type and if it's truecolor or 93 | # similar, convert the image to a paletted mode so it can 94 | # be more efficiently stored. Since there are few colors, 95 | # this operation is lossless. 96 | if (image.mode != '1' and image.mode != 'L' and 97 | image.mode != 'P'): 98 | image = image.convert("P", palette="ADAPTIVE") 99 | image.pixels = image.load() 100 | image.colors = image.getcolors(256) 101 | # image.colors is an unsorted list of tuples where each 102 | # item is a pixel count and a color palette index. 103 | # Unused palette indices (0 pixels) are not in list, 104 | # so its length tells us the unique color count... 105 | image.numColors = len(image.colors) 106 | # The image & palette aren't necessarily optimally packed, 107 | # e.g. might have a 216-color 'web safe' palette but only 108 | # use a handful of colors. In order to reduce the palette 109 | # storage requirements, only the colors in use will be 110 | # output. The pixel indices in the image must be remapped 111 | # to this new palette sequence... 112 | remap = [0] * 256 113 | for c in range(image.numColors): # For each color used... 114 | # The original color index (image.colors[c][1]) 115 | # is reassigned to a sequential 'packed' index (c): 116 | remap[image.colors[c][1]] = c 117 | # Every pixel in image is then remapped through this table: 118 | for y in range(image.size[1]): 119 | for x in range(image.size[0]): 120 | image.pixels[x, y] = remap[image.pixels[x, y]] 121 | # The color palette associated with the image is still in 122 | # its unpacked/unoptimal order; image pixel values no longer 123 | # point to correct entries. This is OK and we'll compensate 124 | # for it later in the code. 125 | image.name = name 126 | image.bph = image.size[1] # Byte-padded height (tweaked below) 127 | images.append(image) 128 | 129 | # 1- and 4-bit images are padded to the next byte boundary. 130 | # Image size not fully validated - on purpose - in case of quick 131 | # test with an existing (but non-optimal) file. If too big or too 132 | # small for the LED strip, just wastes some PROGMEM space or some 133 | # LEDs will be lit wrong, usually no biggie. 134 | if image.numColors <= 2: # 1 bit/pixel, use 8-pixel blocks 135 | if image.bph & 7: image.bph += 8 - (image.bph & 7) 136 | elif image.numColors <= 16: # 4 bits/pixel, use 2-pixel blocks 137 | if image.bph & 1: image.bph += 1 138 | 139 | if image.bph > numLEDs: numLEDs = image.bph 140 | 141 | print "// Don't edit this file! It's software-generated." 142 | print "// See convert.py script instead." 143 | print 144 | print "#define PALETTE1 0" 145 | print "#define PALETTE4 1" 146 | print "#define PALETTE8 2" 147 | print "#define TRUECOLOR 3" 148 | print 149 | print "#define NUM_LEDS %d" % numLEDs 150 | print 151 | 152 | # Second pass estimates current of each column, then peak & overall average 153 | 154 | for imgNum, image in enumerate(images): # For each image in list... 155 | #sys.stdout.write("// %s%s\n\n" % (image.name, 156 | sys.stdout.write("// %s%s" % (image.name, 157 | ' '.ljust(73 - len(image.name),'-'))) 158 | if image.numColors <= 256: 159 | # Palette optimization requires some weird shenanigans... 160 | # first, make a duplicate image where width=image.numColors 161 | # and height=1. This will have the same color palette as 162 | # the original image, which may contain many unused entries. 163 | lut = image.resize((image.numColors, 1)) 164 | lut.pixels = lut.load() 165 | # The image.colors[] list contains the original palette 166 | # indices of the colors actually in use. Draw one pixel 167 | # into the 'lut' image for each color index in use, in the 168 | # order they appear in the color list... 169 | for x in range(image.numColors): 170 | lut.pixels[x, 0] = image.colors[x][1] 171 | # ...then convert the lut image to RGB format to provide a 172 | # list of (R,G,B) values representing the packed color list. 173 | lut = list(lut.convert("RGB").getdata()) 174 | 175 | # Estimate current for each element of palette: 176 | paletteCurrent = [] 177 | for i in range(image.numColors): 178 | paletteCurrent.append(mA0 + 179 | pow((lut[i][0] / 255.0), gamma) * mAR + 180 | pow((lut[i][1] / 255.0), gamma) * mAG + 181 | pow((lut[i][2] / 255.0), gamma) * mAB) 182 | 183 | # Estimate peak and average current for each column of image 184 | colMaxC = 0.0 # Maximum column current 185 | colAvgC = 0.0 # Average column current 186 | for x in range(image.size[0]): # For each row... 187 | mA = 0.0 # Sum current of each pixel's palette entry 188 | for y in range(image.size[1]): 189 | if image.numColors <= 256: 190 | mA += paletteCurrent[image.pixels[x, y]] 191 | else: 192 | mA += (mA0 + 193 | pow((image.pixels[x, y][0] / 255.0), 194 | gamma) * mAR + 195 | pow((image.pixels[x, y][1] / 255.0), 196 | gamma) * mAG + 197 | pow((image.pixels[x, y][2] / 255.0), 198 | gamma) * mAB) 199 | colAvgC += mA # Accumulate average (div later) 200 | if mA > colMaxC: colMaxC = mA # Monitor peak 201 | colAvgC /= image.size[0] # Sum div into average 202 | 203 | s1 = peakC / colMaxC # Scaling factor for peak current constraint 204 | s2 = avgC / colAvgC # Scaling factor for average current constraint 205 | if s2 < s1: s1 = s2 # Use smaller of two (so both constraints met), 206 | if s1 > 1.0: s1 = 1.0 # but never increase brightness 207 | 208 | s1 *= 255.0 # (0.0-1.0) -> (0.0-255.0) 209 | bR1 = bR * s1 # Scale color balance values 210 | bG1 = bG * s1 211 | bB1 = bB * s1 212 | 213 | p = 0 # Current pixel number in image 214 | cols = 7 # Force wrap on 1st output 215 | byteNum = 0 216 | 217 | if image.numColors <= 256: 218 | # Output gamma- and brightness-adjusted color palette: 219 | print 220 | print ("const uint8_t palette%02d[][3] = {" % imgNum) 221 | for i in range(image.numColors): 222 | sys.stdout.write(" { %3d, %3d, %3d }" % ( 223 | int(pow((lut[i][0]/255.0),gamma)*bR1+0.5), 224 | int(pow((lut[i][1]/255.0),gamma)*bG1+0.5), 225 | int(pow((lut[i][2]/255.0),gamma)*bB1+0.5))) 226 | if i < (image.numColors - 1): print "," 227 | print " };" 228 | print 229 | 230 | sys.stdout.write( 231 | "const uint8_t pixels%02d[] = {" % imgNum) 232 | 233 | if image.numColors <= 2: 234 | numBytes = image.size[0] * numLEDs / 8 235 | elif image.numColors <= 16: 236 | numBytes = image.size[0] * numLEDs / 2 237 | elif image.numColors <= 256: 238 | numBytes = image.size[0] * numLEDs 239 | else: 240 | numBytes = image.size[0] * numLEDs * 3 241 | 242 | for x in range(image.size[0]): 243 | if image.numColors <= 2: 244 | for y in range(0, numLEDs, 8): 245 | sum = 0 246 | for bit in range(8): 247 | y1 = y + bit 248 | if y1 < image.size[1]: 249 | sum += ( 250 | image.pixels[x, 251 | y1] << bit) 252 | writeByte(sum) 253 | elif image.numColors <= 16: 254 | for y in range(0, numLEDs, 2): 255 | if y < image.size[1]: 256 | p1 = image.pixels[x, y] 257 | else: 258 | p1 = 0 259 | if (y + 1) < image.size[1]: 260 | p2 = image.pixels[x, y + 1] 261 | else: 262 | p2 = 0 263 | writeByte(p1 * 16 + p2) 264 | elif image.numColors <= 256: 265 | for y in range(numLEDs): 266 | if y < image.size[1]: 267 | writeByte(image.pixels[x, y]) 268 | else: 269 | writeByte(0) 270 | else: 271 | for y in range(numLEDs): 272 | if y < image.size[1]: 273 | writeByte(image.pixels[x, y][0]) 274 | writeByte(image.pixels[x, y][1]) 275 | writeByte(image.pixels[x, y][2]) 276 | else: 277 | writeByte(0) 278 | writeByte(0) 279 | writeByte(0) 280 | 281 | else: 282 | sys.stdout.write("const uint8_t palette00[][3] = {};") 283 | # Perform gamma- and brightness-adjustment on pixel data 284 | sys.stdout.write( 285 | "const uint8_t pixels%02d[] = {" % imgNum) 286 | numBytes = image.size[0] * numLEDs * 3 287 | 288 | for x in range(image.size[0]): 289 | for y in range(numLEDs): 290 | if y < image.size[1]: 291 | writeByte(int(pow(( 292 | image.pixels[x, y][0] / 255.0), 293 | gamma) * bR1 + 0.5)) 294 | writeByte(int(pow(( 295 | image.pixels[x, y][1] / 255.0), 296 | gamma) * bG1 + 0.5)) 297 | writeByte(int(pow(( 298 | image.pixels[x, y][2] / 255.0), 299 | gamma) * bB1 + 0.5)) 300 | else: 301 | writeByte(0) 302 | writeByte(0) 303 | writeByte(0) 304 | 305 | print " };" # end pixels[] array 306 | 307 | print 308 | 309 | # Last pass, print table of images... 310 | 311 | # print "typedef struct {" 312 | # print " uint8_t type; // PALETTE[1,4,8] or TRUECOLOR" 313 | # print " line_t lines; // Length of image (in scanlines)" 314 | # print " const uint8_t *palette; // -> PROGMEM color table (NULL if truecolor)" 315 | # print " const uint8_t *pixels; // -> Pixel data in PROGMEM" 316 | # print "} image;" 317 | # print 318 | # print "const image images[] = {" 319 | 320 | for imgNum, image in enumerate(images): # For each image in list... 321 | sys.stdout.write("#define paletteType ") 322 | if image.numColors <= 2: 323 | sys.stdout.write("PALETTE1") 324 | elif image.numColors <= 16: 325 | sys.stdout.write("PALETTE4") 326 | elif image.numColors <= 256: 327 | sys.stdout.write("PALETTE8") 328 | else: 329 | sys.stdout.write("TRUECOLOR ") 330 | 331 | # sys.stdout.write(" %3d, " % image.size[0]) 332 | 333 | # if image.numColors <= 256: 334 | # sys.stdout.write("(const uint8_t *)palette%02d, " % imgNum) 335 | # else: 336 | # sys.stdout.write("NULL , ") 337 | 338 | # sys.stdout.write("pixels%02d }" % imgNum) 339 | 340 | # if imgNum < len(images) - 1: 341 | # print(",") 342 | # else: 343 | # print 344 | 345 | # print "};" 346 | # print 347 | # print "#define NUM_IMAGES (sizeof(images) / sizeof(images[0]))" 348 | -------------------------------------------------------------------------------- /convertImages/forrest.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NBAKH/bikePOVdisplay/97f3e424781e5bafb2d3a1f5a7f55e87a1a3d266/convertImages/forrest.png -------------------------------------------------------------------------------- /convertImages/færrefremmede.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NBAKH/bikePOVdisplay/97f3e424781e5bafb2d3a1f5a7f55e87a1a3d266/convertImages/færrefremmede.png -------------------------------------------------------------------------------- /convertImages/graphics.h: -------------------------------------------------------------------------------- 1 | // Don't edit this file! It's software-generated. 2 | // See convert.py script instead. 3 | 4 | #define PALETTE1 0 5 | #define PALETTE4 1 6 | #define PALETTE8 2 7 | #define TRUECOLOR 3 8 | 9 | #define NUM_LEDS 16 10 | 11 | // adafruit.gif ------------------------------------------------------------ 12 | 13 | const uint8_t PROGMEM palette00[][3] = { 14 | { 0, 0, 0 }, 15 | { 61, 61, 61 } }; 16 | 17 | const uint8_t PROGMEM pixels00[] = { 18 | 0X00, 0X7C, 0XE0, 0XFE, 0XF0, 0XFE, 0X70, 0XE6, 19 | 0X70, 0XC6, 0X30, 0XC6, 0X30, 0X66, 0X70, 0X66, 20 | 0XF0, 0XFF, 0XF0, 0XFF, 0XC0, 0XFF, 0X00, 0X00, 21 | 0XC0, 0X3F, 0XE0, 0X7F, 0XF0, 0XFF, 0X70, 0XE0, 22 | 0X70, 0XE0, 0X70, 0XE0, 0X60, 0X60, 0X60, 0X60, 23 | 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X00, 0X00, 24 | 0X00, 0X30, 0XE0, 0XFC, 0XF0, 0XFE, 0XF0, 0XEE, 25 | 0X70, 0XC6, 0X30, 0XC6, 0X30, 0X46, 0X70, 0X66, 26 | 0XF0, 0XFF, 0XF0, 0XFF, 0XE0, 0XFF, 0X00, 0X00, 27 | 0XFC, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0X77, 0X00, 28 | 0X73, 0X00, 0X73, 0X00, 0X00, 0X00, 0XE0, 0XFF, 29 | 0XF0, 0XFF, 0XF0, 0XFF, 0XE0, 0X00, 0X60, 0X00, 30 | 0X70, 0X00, 0X70, 0X00, 0X00, 0X00, 0X00, 0X00, 31 | 0XF0, 0X7F, 0XF0, 0XFF, 0XF0, 0XFF, 0X00, 0XE0, 32 | 0X00, 0XE0, 0X00, 0XE0, 0X00, 0X60, 0XF0, 0XFF, 33 | 0XF0, 0XFF, 0XF0, 0XFF, 0X00, 0X00, 0X00, 0X00, 34 | 0XF3, 0XFF, 0XF3, 0XFF, 0XF3, 0XFF, 0X00, 0X00, 35 | 0XF8, 0X3F, 0XF8, 0XFF, 0XFC, 0XFF, 0XF8, 0XFF, 36 | 0X70, 0XE0, 0X70, 0XE0, 0X00, 0X00, 0X00, 0X00, 37 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 38 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 39 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 40 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 41 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 42 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 }; 43 | 44 | typedef struct { 45 | uint8_t type; // PALETTE[1,4,8] or TRUECOLOR 46 | line_t lines; // Length of image (in scanlines) 47 | const uint8_t *palette; // -> PROGMEM color table (NULL if truecolor) 48 | const uint8_t *pixels; // -> Pixel data in PROGMEM 49 | } image; 50 | 51 | const image PROGMEM images[] = { 52 | { PALETTE1 , 100, (const uint8_t *)palette00, pixels00 } 53 | }; 54 | 55 | #define NUM_IMAGES (sizeof(images) / sizeof(images[0])) 56 | -------------------------------------------------------------------------------- /convertImages/moth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NBAKH/bikePOVdisplay/97f3e424781e5bafb2d3a1f5a7f55e87a1a3d266/convertImages/moth.png -------------------------------------------------------------------------------- /convertImages/nastywoman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NBAKH/bikePOVdisplay/97f3e424781e5bafb2d3a1f5a7f55e87a1a3d266/convertImages/nastywoman.png -------------------------------------------------------------------------------- /convertImages/pride.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NBAKH/bikePOVdisplay/97f3e424781e5bafb2d3a1f5a7f55e87a1a3d266/convertImages/pride.png -------------------------------------------------------------------------------- /convertImages/runningdollar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NBAKH/bikePOVdisplay/97f3e424781e5bafb2d3a1f5a7f55e87a1a3d266/convertImages/runningdollar.png -------------------------------------------------------------------------------- /convertImages/trump.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NBAKH/bikePOVdisplay/97f3e424781e5bafb2d3a1f5a7f55e87a1a3d266/convertImages/trump.png -------------------------------------------------------------------------------- /pov_bike/README.md: -------------------------------------------------------------------------------- 1 | POV display 2 | ==================== 3 | This is the main sketch for my version of a Persistance of Vision display for bikes 4 | -------------------------------------------------------------------------------- /pov_bike/nasty.h: -------------------------------------------------------------------------------- 1 | // Don't edit this file! It's software-generated. 2 | // See convert.py script instead. 3 | 4 | #define PALETTE1 0 5 | #define PALETTE4 1 6 | #define PALETTE8 2 7 | #define TRUECOLOR 3 8 | 9 | #define NUM_LEDS 32 10 | 11 | // nastywoman.png ---------------------------------------------------------- 12 | const uint8_t palette00[][3] = { 13 | { 0, 0, 40 }, 14 | { 40, 34, 0 }, 15 | { 0, 0, 35 }, 16 | { 0, 1, 22 }, 17 | { 3, 4, 10 }, 18 | { 2, 2, 13 }, 19 | { 0, 0, 30 }, 20 | { 0, 0, 26 }, 21 | { 35, 30, 0 }, 22 | { 1, 1, 17 }, 23 | { 30, 26, 0 }, 24 | { 5, 5, 7 }, 25 | { 10, 9, 3 }, 26 | { 7, 7, 5 }, 27 | { 1, 1, 19 }, 28 | { 27, 23, 0 }, 29 | { 23, 20, 0 }, 30 | { 17, 15, 1 }, 31 | { 3, 3, 12 }, 32 | { 14, 13, 2 }, 33 | { 12, 11, 3 }, 34 | { 20, 18, 1 }, 35 | { 6, 6, 6 } }; 36 | 37 | const uint8_t pixels00[] = { 38 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 39 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 40 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 41 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 42 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 43 | 0X00, 0X00, 0X00, 0X00, 0X02, 0X01, 0X01, 0X01, 44 | 0X01, 0X01, 0X01, 0X01, 0X0E, 0X0E, 0X0E, 0X0E, 45 | 0X02, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 46 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 47 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X13, 0X08, 48 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 49 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X04, 0X07, 0X00, 50 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 51 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X04, 52 | 0X0F, 0X08, 0X01, 0X11, 0X03, 0X03, 0X03, 0X01, 53 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X0C, 0X00, 54 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 55 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 56 | 0X02, 0X03, 0X01, 0X01, 0X0B, 0X06, 0X03, 0X02, 57 | 0X02, 0X02, 0X02, 0X06, 0X03, 0X05, 0X09, 0X00, 58 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 59 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 60 | 0X00, 0X00, 0X02, 0X01, 0X01, 0X01, 0X01, 0X10, 61 | 0X0D, 0X0E, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 62 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 63 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X02, 0X02, 64 | 0X02, 0X02, 0X00, 0X02, 0X02, 0X01, 0X01, 0X01, 65 | 0X01, 0X0A, 0X0C, 0X06, 0X02, 0X00, 0X00, 0X00, 66 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 67 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X12, 0X01, 0X01, 68 | 0X01, 0X01, 0X01, 0X01, 0X00, 0X00, 0X00, 0X00, 69 | 0X01, 0X01, 0X01, 0X01, 0X0F, 0X05, 0X02, 0X00, 70 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 71 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 72 | 0X00, 0X00, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 73 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X05, 0X00, 74 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 75 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X05, 0X01, 0X01, 76 | 0X01, 0X01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 77 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X02, 0X00, 78 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 79 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X01, 0X01, 80 | 0X10, 0X01, 0X01, 0X08, 0X01, 0X01, 0X01, 0X01, 81 | 0X0E, 0X03, 0X07, 0X02, 0X00, 0X00, 0X00, 0X00, 82 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 83 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 84 | 0X02, 0X05, 0X01, 0X01, 0X01, 0X14, 0X0D, 0X01, 85 | 0X01, 0X01, 0X0A, 0X0C, 0X04, 0X05, 0X03, 0X00, 86 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 87 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 88 | 0X00, 0X00, 0X06, 0X01, 0X01, 0X06, 0X00, 0X06, 89 | 0X12, 0X01, 0X01, 0X01, 0X01, 0X01, 0X14, 0X00, 90 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 91 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 92 | 0X00, 0X00, 0X02, 0X0B, 0X01, 0X09, 0X03, 0X03, 93 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X00, 94 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 95 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X01, 0X01, 96 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 97 | 0X01, 0X10, 0X0C, 0X02, 0X00, 0X00, 0X00, 0X00, 98 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 99 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X07, 0X05, 0X09, 100 | 0X09, 0X09, 0X05, 0X05, 0X09, 0X07, 0X06, 0X02, 101 | 0X02, 0X02, 0X02, 0X00, 0X00, 0X00, 0X00, 0X00, 102 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 103 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X01, 0X01, 104 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 105 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X0F, 0X0D, 0X00, 106 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 107 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X05, 0X10, 0X0F, 108 | 0X0A, 0X08, 0X08, 0X01, 0X01, 0X01, 0X01, 0X01, 109 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X00, 110 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 111 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X06, 0X07, 112 | 0X03, 0X03, 0X03, 0X03, 0X09, 0X0B, 0X14, 0X08, 113 | 0X01, 0X01, 0X01, 0X0D, 0X0E, 0X00, 0X02, 0X00, 114 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 115 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X02, 0X00, 116 | 0X00, 0X07, 0X05, 0X05, 0X0D, 0X01, 0X01, 0X01, 117 | 0X01, 0X12, 0X06, 0X00, 0X00, 0X00, 0X00, 0X00, 118 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 119 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X04, 0X0F, 0X11, 120 | 0X13, 0X01, 0X01, 0X01, 0X01, 0X01, 0X16, 0X02, 121 | 0X02, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 122 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 123 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X04, 0X04, 124 | 0X04, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X13, 125 | 0X0C, 0X05, 0X09, 0X03, 0X00, 0X00, 0X00, 0X00, 126 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 127 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X02, 0X00, 128 | 0X00, 0X02, 0X03, 0X00, 0X00, 0X00, 0X01, 0X01, 129 | 0X01, 0X08, 0X08, 0X15, 0X0C, 0X0C, 0X05, 0X00, 130 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 131 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X0B, 0X01, 0X01, 132 | 0X01, 0X01, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 133 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X08, 0X0B, 0X00, 134 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 135 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X12, 0X01, 0X01, 136 | 0X01, 0X01, 0X0A, 0X0A, 0X0F, 0X01, 0X01, 0X01, 137 | 0X01, 0X01, 0X01, 0X01, 0X0C, 0X0B, 0X06, 0X00, 138 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 139 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X07, 140 | 0X04, 0X0B, 0X0B, 0X0B, 0X0B, 0X0B, 0X0B, 0X0B, 141 | 0X0D, 0X0D, 0X0C, 0X0B, 0X07, 0X02, 0X00, 0X00, 142 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 143 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X07, 0X0B, 0X11, 144 | 0X01, 0X08, 0X0A, 0X08, 0X0A, 0X0A, 0X0A, 0X0A, 145 | 0X0A, 0X0F, 0X10, 0X08, 0X08, 0X11, 0X03, 0X00, 146 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 147 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X0D, 0X01, 0X08, 148 | 0X0D, 0X09, 0X03, 0X0E, 0X03, 0X03, 0X03, 0X03, 149 | 0X03, 0X07, 0X06, 0X05, 0X15, 0X01, 0X0D, 0X00, 150 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 151 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X0C, 0X01, 0X0B, 152 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 153 | 0X00, 0X00, 0X00, 0X00, 0X04, 0X01, 0X11, 0X00, 154 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 155 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X0C, 0X01, 0X10, 156 | 0X0E, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 157 | 0X00, 0X00, 0X02, 0X03, 0X13, 0X01, 0X0D, 0X00, 158 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 159 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X0A, 0X01, 160 | 0X0A, 0X0D, 0X04, 0X12, 0X12, 0X04, 0X04, 0X12, 161 | 0X04, 0X04, 0X0C, 0X08, 0X08, 0X0C, 0X06, 0X00, 162 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 163 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X07, 0X05, 164 | 0X04, 0X0C, 0X08, 0X0A, 0X0A, 0X0A, 0X0F, 0X0F, 165 | 0X0F, 0X0F, 0X0A, 0X13, 0X04, 0X07, 0X02, 0X00, 166 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 167 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 168 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X06, 0X03, 169 | 0X03, 0X03, 0X03, 0X04, 0X10, 0X01, 0X01, 0X00, 170 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 171 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X0B, 0X01, 172 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 173 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X0D, 0X12, 0X00, 174 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 175 | 0X00, 0X00, 0X00, 0X00, 0X02, 0X04, 0X08, 0X01, 176 | 0X01, 0X01, 0X01, 0X08, 0X00, 0X00, 0X00, 0X00, 177 | 0X00, 0X00, 0X00, 0X00, 0X02, 0X00, 0X00, 0X00, 178 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 179 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 180 | 0X00, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 181 | 0X00, 0X00, 0X00, 0X00, 0X03, 0X03, 0X02, 0X00, 182 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 183 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 184 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X01, 185 | 0X01, 0X08, 0X08, 0X01, 0X01, 0X08, 0X04, 0X00, 186 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 187 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X05, 0X0E, 188 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 189 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X05, 0X07, 0X00, 190 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 191 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X0C, 0X01, 0X01, 192 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 193 | 0X01, 0X01, 0X14, 0X07, 0X00, 0X00, 0X00, 0X00, 194 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 195 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X04, 0X01, 196 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X00, 0X00, 197 | 0X00, 0X00, 0X09, 0X09, 0X09, 0X09, 0X02, 0X00, 198 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 199 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 200 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X01, 0X01, 0X01, 201 | 0X01, 0X01, 0X0A, 0X0A, 0X08, 0X08, 0X0C, 0X00, 202 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 203 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 204 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X06, 205 | 0X07, 0X03, 0X07, 0X03, 0X0D, 0X15, 0X16, 0X00, 206 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 207 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 208 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 209 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 210 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 211 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 212 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 213 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 214 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 215 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 216 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 217 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 218 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 219 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 220 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 221 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 222 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 223 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 224 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 225 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 226 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 227 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 228 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 229 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 230 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 231 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 232 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 233 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 234 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 235 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 236 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 237 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X02, 0X00, 238 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 239 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 240 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 241 | 0X00, 0X00, 0X00, 0X02, 0X01, 0X01, 0X01, 0X00, 242 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 243 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 244 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X07, 0X03, 245 | 0X09, 0X0D, 0X01, 0X01, 0X01, 0X08, 0X11, 0X00, 246 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 247 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X04, 0X01, 0X01, 248 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X0A, 249 | 0X01, 0X01, 0X01, 0X10, 0X0C, 0X09, 0X03, 0X00, 250 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 251 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X04, 0X01, 0X01, 252 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 253 | 0X01, 0X05, 0X06, 0X02, 0X00, 0X00, 0X00, 0X00, 254 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 255 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X00, 0X00, 256 | 0X00, 0X00, 0X00, 0X02, 0X06, 0X09, 0X01, 0X01, 257 | 0X01, 0X01, 0X01, 0X01, 0X07, 0X06, 0X02, 0X00, 258 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 259 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 260 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X02, 261 | 0X05, 0X01, 0X01, 0X01, 0X01, 0X01, 0X0B, 0X00, 262 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 263 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 264 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 265 | 0X00, 0X00, 0X00, 0X06, 0X0C, 0X01, 0X01, 0X00, 266 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 267 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X09, 0X13, 0X14, 268 | 0X0C, 0X0D, 0X0B, 0X04, 0X04, 0X05, 0X05, 0X09, 269 | 0X0E, 0X03, 0X03, 0X03, 0X04, 0X0A, 0X01, 0X00, 270 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 271 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X05, 0X01, 0X01, 272 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 273 | 0X01, 0X01, 0X01, 0X08, 0X08, 0X01, 0X01, 0X00, 274 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 275 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X01, 0X01, 276 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 277 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X00, 278 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 279 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 280 | 0X02, 0X03, 0X03, 0X02, 0X00, 0X00, 0X00, 0X00, 281 | 0X00, 0X00, 0X00, 0X00, 0X09, 0X08, 0X0A, 0X00, 282 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 283 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X06, 284 | 0X05, 0X01, 0X01, 0X01, 0X04, 0X06, 0X00, 0X00, 285 | 0X00, 0X00, 0X00, 0X00, 0X06, 0X01, 0X01, 0X00, 286 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 287 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X07, 0X04, 0X01, 288 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X07, 0X00, 289 | 0X00, 0X00, 0X00, 0X00, 0X05, 0X14, 0X03, 0X00, 290 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 291 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X05, 0X01, 0X01, 292 | 0X01, 0X06, 0X00, 0X00, 0X09, 0X01, 0X01, 0X07, 293 | 0X00, 0X00, 0X00, 0X00, 0X04, 0X01, 0X15, 0X00, 294 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 295 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X05, 0X01, 0X04, 296 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X06, 0X01, 0X01, 297 | 0X01, 0X02, 0X00, 0X00, 0X01, 0X01, 0X01, 0X00, 298 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 299 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X01, 0X09, 300 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X06, 0X11, 301 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X05, 0X00, 302 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 303 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X07, 0X04, 0X0B, 304 | 0X0E, 0X02, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 305 | 0X03, 0X01, 0X01, 0X01, 0X01, 0X01, 0X02, 0X00, 306 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 307 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X05, 0X01, 0X01, 308 | 0X01, 0X01, 0X01, 0X01, 0X0D, 0X02, 0X00, 0X00, 309 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 310 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 311 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X07, 0X07, 312 | 0X09, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 313 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X00, 0X00, 0X00, 314 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 315 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 316 | 0X00, 0X00, 0X02, 0X01, 0X01, 0X07, 0X00, 0X00, 317 | 0X00, 0X00, 0X00, 0X01, 0X01, 0X01, 0X01, 0X00, 318 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 319 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 320 | 0X00, 0X00, 0X02, 0X01, 0X01, 0X02, 0X00, 0X09, 321 | 0X00, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X00, 322 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 323 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X02, 0X07, 324 | 0X0D, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 325 | 0X01, 0X01, 0X03, 0X02, 0X00, 0X00, 0X00, 0X00, 326 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 327 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X01, 0X01, 328 | 0X01, 0X01, 0X10, 0X13, 0X0E, 0X02, 0X03, 0X02, 329 | 0X00, 0X00, 0X00, 0X00, 0X02, 0X06, 0X06, 0X00, 330 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 331 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X07, 0X00, 332 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 333 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X00, 334 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 335 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X0E, 0X05, 336 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 337 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X00, 338 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 339 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X03, 0X11, 0X01, 340 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X0B, 0X05, 0X03, 341 | 0X06, 0X02, 0X06, 0X02, 0X02, 0X02, 0X02, 0X00, 342 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 343 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X07, 0X04, 344 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X04, 345 | 0X0E, 0X03, 0X02, 0X00, 0X00, 0X00, 0X00, 0X00, 346 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 347 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 348 | 0X00, 0X02, 0X06, 0X07, 0X01, 0X01, 0X01, 0X01, 349 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X0C, 0X00, 350 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 351 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X02, 0X00, 352 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X01, 353 | 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X00, 354 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 355 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X06, 0X01, 0X0A, 356 | 0X08, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 0X01, 357 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 358 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 359 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X07, 0X01, 0X01, 360 | 0X01, 0X0B, 0X05, 0X0E, 0X03, 0X06, 0X02, 0X02, 361 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 362 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 363 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 364 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 365 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 366 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 367 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 368 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 369 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 370 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 371 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 372 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 373 | 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 }; 374 | 375 | #define paletteType PALETTE8 -------------------------------------------------------------------------------- /pov_bike/pov_bike.ino: -------------------------------------------------------------------------------- 1 | #include "nasty.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | Ticker draw; 8 | 9 | #define DATAPIN MOSI 10 | #define CLOCKPIN SCK 11 | 12 | Adafruit_DotStar strip = Adafruit_DotStar(NUM_LEDS+1, DATAPIN, CLOCKPIN); 13 | 14 | //global stuff i've stolen 15 | uint8_t imageType, // Image type: PALETTE[1,4,8] or TRUECOLOR 16 | imagePalette, // -> palette data in PROGMEM 17 | imagePixels, // -> pixel data in PROGMEM 18 | imageLines, // Number of lines in active image2 19 | imageLine; // Current line number in image 20 | 21 | const int interruptPin = D2; 22 | unsigned long time1; 23 | unsigned long animationTime; 24 | unsigned long wheelTime; 25 | unsigned long animationResult; 26 | unsigned long wheelResult; 27 | unsigned long delayTime; 28 | 29 | void initializePhoto(){ 30 | imageType = paletteType; 31 | switch (imageType) { 32 | case 0: 33 | imageLines = sizeof(pixels00)*8/NUM_LEDS; 34 | break; 35 | case 1: 36 | imageLines = sizeof(pixels00)*2/NUM_LEDS; 37 | break; 38 | case 2: 39 | imageLines = sizeof(pixels00)/NUM_LEDS; 40 | break; 41 | case 3: 42 | imageLines = sizeof(pixels00)/NUM_LEDS/3; 43 | Serial.print("Image lines: "); 44 | Serial.println(imageLines); 45 | 46 | } 47 | imageLine = 0; 48 | } 49 | 50 | void tickerTime(){ 51 | time1 = micros(); 52 | if(animationResult+5000> 4; 76 | p2 &= 0x0F; 77 | strip.setPixelColor(1+pixelNum++, 78 | palette00[p1][0],palette00[p1][1],palette00[p1][2]); 79 | 80 | strip.setPixelColor(1+pixelNum++, 81 | palette00[p2][0],palette00[p2][1],palette00[p2][2]); 82 | } 83 | imageLine++; 84 | if(imageLine>=imageLines) imageLine=0; 85 | strip.show(); 86 | break; 87 | case 2: 88 | uint16_t o; 89 | for(int pixelNum = 0; pixelNum=imageLines){ 96 | imageLine=0; 97 | } 98 | strip.show(); 99 | break; 100 | case 3: 101 | uint8_t p, r, g, b; 102 | p = 0; 103 | for(int pixelNum = 0; pixelNumimageLines){ 110 | p==0; 111 | } 112 | } 113 | break; 114 | } 115 | } 116 | 117 | void timeCalc(){ 118 | animationTime=micros(); 119 | while(imageLine<=imageLines){ 120 | switch (imageType) { 121 | case 0: 122 | 123 | break; 124 | case 1: 125 | uint8_t p1, p2, pixelNum; 126 | for(pixelNum = 0; pixelNum> 4; 129 | p2 &= 0x0F; 130 | strip.setPixelColor(1+pixelNum++, 131 | palette00[p1][0],palette00[p1][1],palette00[p1][2]); 132 | 133 | strip.setPixelColor(1+pixelNum++, 134 | palette00[p2][0],palette00[p2][1],palette00[p2][2]); 135 | } 136 | imageLine++; 137 | if(imageLine>=imageLines) imageLine=0; 138 | strip.show(); 139 | break; 140 | case 2: 141 | uint16_t o; 142 | for(int pixelNum = 0; pixelNumimageLines){ 160 | p==0; 161 | } 162 | } 163 | break; 164 | } 165 | } 166 | imageLine=0; 167 | strip.clear(); 168 | time1=micros(); 169 | animationResult = time1-animationTime; 170 | Serial.print("one cycle: "); 171 | Serial.println(animationResult); 172 | animationTime= time1; 173 | } 174 | 175 | void setup() { 176 | Serial.begin(115200); 177 | Serial.println("Begin strip"); 178 | strip.begin(); 179 | Serial.println("Begin show"); 180 | strip.show(); 181 | initializePhoto(); 182 | time1 = micros(); 183 | animationTime = time1; 184 | wheelTime = time1; 185 | pinMode(interruptPin, INPUT); 186 | attachInterrupt(interruptPin, tickerTime, FALLING); 187 | timeCalc(); 188 | draw.attach_ms(1000, animation); 189 | } 190 | 191 | void loop() { 192 | //Everything is controlled by tickers so there's nothing in the loop 193 | } 194 | --------------------------------------------------------------------------------