|
| 1 | +// SPDX-FileCopyrightText: 2018 Mikey Sklar for Adafruit Industries |
| 2 | +// |
| 3 | +// SPDX-License-Identifier: MIT |
| 4 | + |
| 5 | +// Trinket/Gemma + LED matrix backpack jewelry. Plays animated |
| 6 | +// sequence on LED matrix. Press reset button to display again, |
| 7 | +// or add optional momentary button between pin #1 and +V. |
| 8 | +// THERE IS NO ANIMATION DATA IN THIS SOURCE FILE, you should |
| 9 | +// rarely need to change anything here. EDIT anim.h INSTEAD. |
| 10 | + |
| 11 | +#define BRIGHTNESS 12 // 0=min, 15=max |
| 12 | +#define I2C_ADDR 0x70 // Edit if backpack A0/A1 jumpers set |
| 13 | + |
| 14 | +#include <Wire.h> |
| 15 | +#include <avr/power.h> |
| 16 | +#include <avr/sleep.h> |
| 17 | +#include "anim.h" // Animation data is located here |
| 18 | + |
| 19 | +static const uint8_t PROGMEM reorder[] = { // Column-reordering table |
| 20 | + 0x00,0x40,0x20,0x60,0x10,0x50,0x30,0x70,0x08,0x48,0x28,0x68,0x18,0x58,0x38,0x78, |
| 21 | + 0x04,0x44,0x24,0x64,0x14,0x54,0x34,0x74,0x0c,0x4c,0x2c,0x6c,0x1c,0x5c,0x3c,0x7c, |
| 22 | + 0x02,0x42,0x22,0x62,0x12,0x52,0x32,0x72,0x0a,0x4a,0x2a,0x6a,0x1a,0x5a,0x3a,0x7a, |
| 23 | + 0x06,0x46,0x26,0x66,0x16,0x56,0x36,0x76,0x0e,0x4e,0x2e,0x6e,0x1e,0x5e,0x3e,0x7e, |
| 24 | + 0x01,0x41,0x21,0x61,0x11,0x51,0x31,0x71,0x09,0x49,0x29,0x69,0x19,0x59,0x39,0x79, |
| 25 | + 0x05,0x45,0x25,0x65,0x15,0x55,0x35,0x75,0x0d,0x4d,0x2d,0x6d,0x1d,0x5d,0x3d,0x7d, |
| 26 | + 0x03,0x43,0x23,0x63,0x13,0x53,0x33,0x73,0x0b,0x4b,0x2b,0x6b,0x1b,0x5b,0x3b,0x7b, |
| 27 | + 0x07,0x47,0x27,0x67,0x17,0x57,0x37,0x77,0x0f,0x4f,0x2f,0x6f,0x1f,0x5f,0x3f,0x7f, |
| 28 | + 0x80,0xc0,0xa0,0xe0,0x90,0xd0,0xb0,0xf0,0x88,0xc8,0xa8,0xe8,0x98,0xd8,0xb8,0xf8, |
| 29 | + 0x84,0xc4,0xa4,0xe4,0x94,0xd4,0xb4,0xf4,0x8c,0xcc,0xac,0xec,0x9c,0xdc,0xbc,0xfc, |
| 30 | + 0x82,0xc2,0xa2,0xe2,0x92,0xd2,0xb2,0xf2,0x8a,0xca,0xaa,0xea,0x9a,0xda,0xba,0xfa, |
| 31 | + 0x86,0xc6,0xa6,0xe6,0x96,0xd6,0xb6,0xf6,0x8e,0xce,0xae,0xee,0x9e,0xde,0xbe,0xfe, |
| 32 | + 0x81,0xc1,0xa1,0xe1,0x91,0xd1,0xb1,0xf1,0x89,0xc9,0xa9,0xe9,0x99,0xd9,0xb9,0xf9, |
| 33 | + 0x85,0xc5,0xa5,0xe5,0x95,0xd5,0xb5,0xf5,0x8d,0xcd,0xad,0xed,0x9d,0xdd,0xbd,0xfd, |
| 34 | + 0x83,0xc3,0xa3,0xe3,0x93,0xd3,0xb3,0xf3,0x8b,0xcb,0xab,0xeb,0x9b,0xdb,0xbb,0xfb, |
| 35 | + 0x87,0xc7,0xa7,0xe7,0x97,0xd7,0xb7,0xf7,0x8f,0xcf,0xaf,0xef,0x9f,0xdf,0xbf,0xff }; |
| 36 | + |
| 37 | +void ledCmd(uint8_t x) { // Issue command to LED backback driver |
| 38 | + Wire.beginTransmission(I2C_ADDR); |
| 39 | + Wire.write(x); |
| 40 | + Wire.endTransmission(); |
| 41 | +} |
| 42 | + |
| 43 | +void clear(void) { // Clear display buffer |
| 44 | + Wire.beginTransmission(I2C_ADDR); |
| 45 | + for(uint8_t i=0; i<17; i++) Wire.write(0); |
| 46 | + Wire.endTransmission(); |
| 47 | +} |
| 48 | + |
| 49 | +void setup() { |
| 50 | + power_timer1_disable(); // Disable unused peripherals |
| 51 | + power_adc_disable(); // to save power |
| 52 | + PCMSK |= _BV(PCINT1); // Set change mask for pin 1 |
| 53 | + Wire.begin(); // I2C init |
| 54 | + clear(); // Blank display |
| 55 | + ledCmd(0x21); // Turn on oscillator |
| 56 | + ledCmd(0xE0 | BRIGHTNESS); // Set brightness |
| 57 | + ledCmd(0x81); // Display on, no blink |
| 58 | +} |
| 59 | + |
| 60 | +uint8_t rep = REPS; |
| 61 | + |
| 62 | +void loop() { |
| 63 | + |
| 64 | + for(int i=0; i<sizeof(anim); i) { // For each frame... |
| 65 | + Wire.beginTransmission(I2C_ADDR); |
| 66 | + Wire.write(0); // Start address |
| 67 | + for(uint8_t j=0; j<8; j++) { // 8 rows... |
| 68 | + Wire.write(pgm_read_byte(&reorder[pgm_read_byte(&anim[i++])])); |
| 69 | + Wire.write(0); |
| 70 | + } |
| 71 | + Wire.endTransmission(); |
| 72 | + delay(pgm_read_byte(&anim[i++]) * 10); |
| 73 | + } |
| 74 | + |
| 75 | + if(!--rep) { // If last cycle... |
| 76 | + ledCmd(0x20); // LED matrix in standby mode |
| 77 | + GIMSK = _BV(PCIE); // Enable pin change interrupt |
| 78 | + power_all_disable(); // All peripherals off |
| 79 | + set_sleep_mode(SLEEP_MODE_PWR_DOWN); |
| 80 | + sleep_enable(); |
| 81 | + sei(); // Keep interrupts enabled |
| 82 | + sleep_mode(); // Power down CPU (pin 1 will wake) |
| 83 | + // Execution resumes here on wake. |
| 84 | + GIMSK = 0; // Disable pin change interrupt |
| 85 | + rep = REPS; // Reset animation counter |
| 86 | + power_timer0_enable(); // Re-enable timer |
| 87 | + power_usi_enable(); // Re-enable USI |
| 88 | + Wire.begin(); // Re-init I2C |
| 89 | + clear(); // Blank display |
| 90 | + ledCmd(0x21); // Re-enable matrix |
| 91 | + } |
| 92 | +} |
| 93 | + |
| 94 | +ISR(PCINT0_vect) {} // Button tap |
0 commit comments