/*Christmas tree illumination Low current consumption type (using delayWDT) Lights 17 LEDs using CPU pull-up resistors. 8MHz internal CR oscillator, contents written on leg extension chip. Add shooting star 2019/12/13 Radiopench http://radiopench.blog96.fc2.com/ This English comment version is same code as 20191213XmassIllumi.txt */ #include // use sleep mode #include // watch dog timer unsigned long data = 0; int i, n; unsigned long fS[4][12] = { // shooting star pattern def. { 0b00000000000000000, // trace0 0b00000000100000000, 0b00000000100000000, 0b00000000110000000, 0b00000000010000000, 0b00000000010100000, 0b00000000000100000, 0b00000000000101000, 0b00000000000001000, 0b00000000000001010, 0b00000000000000010, 0b00000000000000010 }, { 0b00000000000000000, // trace1 0b00000000100000000, 0b00000000100000000, 0b00000000101000000, 0b00000000001000000, 0b00000000001010000, 0b00000000000010000, 0b00000000000010100, 0b00000000000000100, 0b00000000000000101, 0b00000000000000001, 0b00000000000000001 }, { 0b00000000000000000, // trace2 0b00000000100000000, 0b00000000100000000, 0b00000001100000000, 0b00000001000000000, 0b00000101000000000, 0b00000100000000000, 0b00010100000000000, 0b00010000000000000, 0b01010000000000000, 0b01000000000000000, 0b01000000000000000, }, { 0b00000000000000000, // trace3 0b00000000100000000, 0b00000000100000000, 0b00000010100000000, 0b00000010000000000, 0b00001010000000000, 0b00001000000000000, 0b00101000000000000, 0b00100000000000000, 0b10100000000000000, 0b10000000000000000, 0b10000000000000000 } }; void setup() { allOn1000(); // start display } // All input pin (No pinMode command) void loop() { // mail loop for (int j = 0; j < 245; j++) { // Aprox 6 hours (88sec*245=6Hours) allOn1000(); // display loop start singleR(1); // single right turn singleL(1); // single left turn waveR(1); // wave right waveL(1); // wave left x_rotate(2); // single waveSimultaneous left and right allOn5000(); // all ON 5sec. Vcross(2); // reverse V Hline(2); VrotateR(3); // vartical line move right fullRotateR(3); // wipe rigth VrotateL(3); // vartical line move left fullRotateL(3); // wipe left wipeUpDown(2); // wipe up/down shootingStars(); // shootong star (falling rain) randomFlash(75); // random flash } timeUp(); // Stopped display after specified time (Center LED flash) } void allOn1000() { led(0); // all off delayWDT(5); // wait 0.5sec. led(0x1FFFF); // all on delayWDT(6); led(0); delayWDT(4); // 256ms } void allOn5000() { led(0); // all off delayWDT(5); // 0.5sec. led(0x1FFFF); // all on delayWDT(8); // 4sec. delayWDT(6); // 1sec led(0); // all off delayWDT(5); // wait 0.5sec. } void singleR(int count) { // single right turn for (i = 1; i <= count; i++) { data = 0x01; // prepare seed for (n = 0; n <= 18; n++) { // execute till seed go out led(data); // display LED data = data << 1; // shift left delayWDT(2); // 64ms } delayWDT(3); // 128ms } } void singleL(int count) { // single left turn for (i = 1; i <= count; i++) { data = 0x10000; // prepare seed for (n = 0; n <= 18; n++) { // execute till seed go out led(data); // display LED data = data >> 1; // shift right delayWDT(2); // 64ms } delayWDT(3); // 128ms } } void waveR(int count) { // display like a wave(clockwise) for (i = 1; i <= count; i++) { for (n = 0; n <= 16; n++) { data |= 0x01; // add 1 bit at bottom led(data); // disp. LED data = data << 1; // shift left delayWDT(2); // 64ms } for (n = 0; n <= 16; n++) { data = data & 0x1FFFE; // erase bottom 1 bit led(data); // display LED data = data << 1; // shift left delayWDT(2); // 64ms } } } void waveL(int count) { // display like a wave (ccw) for (i = 1; i <= count; i++) { for (n = 0; n <= 16; n++) { data |= 0x10000; // add 1 bit at bottom led(data); // display LED data = data >> 1; // shift right delayWDT(2); // 64ms } for (n = 0; n <= 16; n++) { data = data & 0x0FFF; // erase end bit led(data); // display LED data = data >> 1; // shift right delayWDT(2); // 64ms } } } void x_rotate(int count) { // cross rotation unsigned long a, b; for (i = 1; i <= count; i++) { a = 0x00001; // lower side seed b = 0x10000; // upper side seed for (n = 0; n <= 17; n++) { data = a | b; // composit upeer/lower led(data); // display a = a << 1; // left move lower seed b = b >> 1; // right move upper seed delayWDT(2); // 64ms; } } } void Vcross(int count) { // V cross for (i = 1; i <= count; i++) { led(0b00000000000000001); delayWDT(2); // 64ms led(0b00000000000000101); delayWDT(2); // 64ms led(0b00000000000010101); delayWDT(2); // 64ms led(0b00000000001010101); delayWDT(2); // 64ms led(0b00000000101010101); delayWDT(2); // 64ms center position led(0b00000001101010101); delayWDT(2); // 64ms led(0b00000101101010101); delayWDT(2); // 648ms led(0b00010101101010101); delayWDT(2); // 64ms led(0b01010101101010101); delayWDT(2); // 64ms led(0b11010101101010101); delayWDT(2); // 64ms led(0b11110101101010101); delayWDT(2); // 64ms led(0b11111101101010101); delayWDT(2); // 64ms led(0b11111111101010101); delayWDT(2); // 64ms led(0b11111111101010101); delayWDT(2); // 64ms center position led(0b11111111111010101); delayWDT(2); // 64ms led(0b11111111111110101); delayWDT(2); // 64ms led(0b11111111111111101); delayWDT(2); // 64ms led(0b11111111111111111); delayWDT(2); // 64ms led(0b11111111111111110); delayWDT(2); // 64ms led(0b11111111111111010); delayWDT(2); // 64ms led(0b11111111111101010); delayWDT(2); // 64ms led(0b11111111110101010); delayWDT(2); // 64ms led(0b11111111110101010); delayWDT(2); // 64ms center position led(0b11111110110101010); delayWDT(2); // 64ms led(0b11111010110101010); delayWDT(2); // 64ms led(0b11101010110101010); delayWDT(2); // 64ms led(0b10101010110101010); delayWDT(2); // 64ms led(0b00101010110101010); delayWDT(2); // 64ms led(0b00001010110101010); delayWDT(2); // 64ms led(0b00000010110101010); delayWDT(2); // 64ms led(0b00000000110101010); delayWDT(2); // 64ms led(0b00000000010101010); delayWDT(2); // 64ms center position(off) led(0b00000000000101010); delayWDT(2); // 64ms led(0b00000000000001010); delayWDT(2); // 64ms led(0b00000000000000010); delayWDT(2); // 64ms led(0b00000000000000000); delayWDT(2); // 64ms } } void Hline(int count) { // horizontal line for (i = 1; i <= count; i++) { led(0b00000000000000000); delayWDT(2); // 64ms led(0b00000000000000010); delayWDT(2); // 64ms led(0b00000000000000001); delayWDT(2); // 64ms led(0b10000000000000000); delayWDT(2); // 64ms led(0b01000000000000000); delayWDT(2); // 64ms led(0b00000000000000000); delayWDT(2); // 64ms led(0b00000000000001000); delayWDT(2); // 64ms led(0b00000000000000100); delayWDT(2); // 64ms led(0b00100000000000000); delayWDT(2); // 64ms led(0b00010000000000000); delayWDT(2); // 64ms led(0b00000000000000000); delayWDT(2); // 64ms led(0b00000000000100000); delayWDT(2); // 64ms led(0b00000000000010000); delayWDT(2); // 64ms led(0b00001000000000000); delayWDT(2); // 64ms led(0b00000100000000000); delayWDT(2); // 64ms led(0b00000000000000000); delayWDT(2); // 64ms led(0b00000000010000000); delayWDT(2); // 64ms led(0b00000000001000000); delayWDT(2); // 64ms led(0b00000010000000000); delayWDT(2); // 64ms led(0b00000001000000000); delayWDT(2); // 64ms led(0b00000000100000000); delayWDT(3); // 128ms center ON } } void VrotateR(int count) { // Vartival line rotate right for (i = 1; i <= count; i++) { led(0b00000000110101010); delayWDT(3); // 128ms led(0b00000000101010101); delayWDT(3); // 128ms led(0b10101010100000000); delayWDT(3); // 128ms led(0b01010101100000000); delayWDT(3); // 128ms led(0b00000000100000000); delayWDT(3); // 128ms } } void fullRotateR(int count) { // full rotation right for (i = 1; i <= count; i++) { led(0b00000000110101010); delayWDT(3); // 128ms led(0b00000000111111111); delayWDT(3); // 128ms led(0b10101010111111111); delayWDT(3); // 128ms led(0b11111111111111111); delayWDT(4); // 250ms <- little bit long time led(0b11111111101010101); delayWDT(3); // 128ms led(0b11111111100000000); delayWDT(3); // 128ms led(0b10101010100000000); delayWDT(3); // 128ms led(0b00000000100000000); delayWDT(3); // 128ms } } void VrotateL(int count) { // vertical lines move left for (i = 1; i <= count; i++) { led(0b01010101100000000); delayWDT(3); // 128ms led(0b10101010100000000); delayWDT(3); // 128ms led(0b00000000101010101); delayWDT(3); // 128ms led(0b00000000110101010); delayWDT(3); // 128ms led(0b00000000100000000); delayWDT(3); // 128ms } } void fullRotateL(int count) { //full rotation left for (i = 1; i <= count; i++) { led(0b01010101100000000); delayWDT(3); // 128ms led(0b11111111100000000); delayWDT(3); // 128ms led(0b11111111101010101); delayWDT(3); // 128ms led(0b11111111111111111); delayWDT(4); // 250ms <- little bit long time led(0b10101010111111111); delayWDT(3); // 128ms led(0b00000000111111111); delayWDT(3); // 128ms led(0b00000000110101010); delayWDT(3); // 128ms led(0b00000000100000000); delayWDT(3); // 128ms } } void wipeUpDown(int count) { // wipe up down. ON from bottom to top, OFF revwrse order unsigned long a, b; for (i = 1; i <= count; i++) { a = 0; b = 0; for (n = 0; n <= 9; n++) { // ON from bottom to top data = a | b; // synthesize rigfr and left seed led(data); // display LED a = a << 1; // move up upper part a |= 0x01; // fill 1 at bottom b = b >> 1; // move down upper part b |= 0x10000; // fill 1 at top delayWDT(2); // 64ms } delayWDT(4); // all ON, wait 250ms for (n = 0; n <= 8; n++) { // OFF from bottom to top 下から上に消灯 data = a | b; // synthesize rigfr and left seed led(data); // display LED a = a << 1; // move up upper part a &= 0x1FF; b = b >> 1; // move down upper part b &= 0x1FF00; delayWDT(2); // 64ms } delayWDT(3); // 128ms for (n = 0; n <= 8; n++) { // ON from upper to lower data = a | b; // synthesize rigfr and left seed data |= 0x100; led(data); // display LED a = a >> 1; // a |= 0x180; b = b << 1; // b |= 0x300; delayWDT(2); // 64ms } for (n = 0; n <= 9; n++) { // ON from upper to lower data = a | b; // synthesize rigfr and left seed led(data); // display LED a = a >> 1; // a &= 0x0FF; b = b << 1; // b &= 0x1FE00; delayWDT(2); // 64ms } delayWDT(4); // 250ms } } void shootingStars() { // many shooting stars (falling rain) int x; unsigned int pixP[4]; // pix positoin buffer. 4lines * 12positios. move start fron LSB unsigned int bP; // bit manipulation pointer unsigned long pLED; // display position buffer for (int i = 0; i < 4; i++) { // clear buffer pixP[i] = 0; } for (int c = 1000; c > 0; c--) { // loop 1000 times for (int i = 0; i < 4; i++) { // against 4 lines, pixP[i] = pixP[i] << 1; // advance pixel position } x = random(0, c / 100); // random number range is inversely proportional to the number of loops if (x == 0) { // if the number is 0 x = random(0, 4); // select any of the four tracks pixP[x] |= 0x0001; // inject new seed to the selected track } pLED = 0; // clear LED buffer for (int n = 0; n < 4; n++) { // 4 lines one by one bP = 0x01; // initialize bit position pointer for (int m = 0; m < 12; m++) { // Check 12 bits from the beginning if ((pixP[n] & bP) != 0) { // If seed is existing pLED |= fS[n][m]; // over write display pattern } bP = bP << 1; // advance bit pointer for next process } } led(pLED); // display LED delayWDT(1); } led(0x1FFFF); // last time, all ON delayWDT(7); // 2 sec. } void randomFlash(int count) { // randam flash for (i = 1; i <= count; i++) { data = random(0, 0x20000); // genarate random bit pattern from 0 to 0x1FFFF if ((i % 5) == 0) { // once in 5 times data |= 0x100; // center LED ON } else { data &= 0x1FEFF; // center LED OFF } led(data); // display LED delayWDT(3); // wait 128ms } } void timeUp() { for (;;) { led(0x100); // only center(top) top LED delayWDT(2); // flash 64ms led(0); // all turn off delayWDT(8); // 4sec. } } void led(unsigned long x) { // displa LED routine /* Lights the LED of the bit corresponding to the argument. * write 1 with the input pin assigned, the pull-up resistor is enabled and the LED lights up. * Data is 17 bits, correspondence with port is as follows * data x xxxx xxxx xxxx xxxx PORTD 76 5432 digita 2-7 PORTB 432 10 digital 8-12 PORTC 5 4321 0 A 0-5 (digital 14-19) digital 0, 1, 13 are not used (Arduino IDE use those) bit location vs fisical tree location 8 ← top (0x100) 7 9 6 10 5 11 4 12 3 13 2 14 1 15 0 17 */ byte d; x = x & 0x1FFFF; // delete un-defined range value // bottom 6 bits -> digital 2-7 d = (x << 2) & B11111100; PORTD = d; // 5 bits from bit 6 -> digital 8-12 d = (x >> 6) & B00011111; PORTB = d; // 6 bits from bit 11 -> analog0-5(digital 14-19) d = (x >> 11) & B00111111; PORTC = d; } void delayWDT(unsigned long t) { // delay using watch dog timer (very low power during waiting) delayWDT_setup(t); // set watch dog timer interrupt ADCSRA &= ~(1 << ADEN); // ADC power off (clear ADEN bit). eliminated 120μA set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is powder down mode sleep_enable(); sleep_mode(); // enter sleep here (power current 28 uA during sleep) sleep_disable(); // when WDT time up, resume here ADCSRA |= (1 << ADEN); // ADC power ON } void delayWDT_setup(unsigned int ii) { // setting watch dog timer // argument vs wait time is follows // 0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms // 6=1sec, 7=2sec, 8=4sec, 9=8sec byte bb; if (ii > 9 ) { // remode un defined value ii = 9; } bb = ii & 7; // copy bottom 3 bits to bb if (ii > 7) { // if more than 8 bb |= (1 << 5); // set 1, bit 5 of bb } bb |= ( 1 << WDCE ); MCUSR &= ~(1 << WDRF); // Watchdog Reset Flag ->0 at MCU Status Reg. // start timed sequence WDTCSR |= (1 << WDCE) | (1 << WDE); // request watch dog register change // set new watchdog timeout value WDTCSR = bb; // set controle register WDTCSR |= _BV(WDIE); } ISR(WDT_vect) { // watch dog timer interrupt routin // wdt_cycle++; // write code if necessary }