ATtiny402 Christmas tree with motion

23 LED Christmas Tree, Lights up with PIR and lasts for a long time on a Lipo battery.


/* * ATtiny402-Motion-Christmas-tree.c * WORKS :) * Created: 3/23/2023 10:13:50 * Author : Sherman Stebbins */ 
#define F_CPU 10000000UL#include <avr/io.h>#include <util/delay.h>#include <avr/interrupt.h>//#include <avr/common.h> //for random(); from arduino.. failed#include <stdlib.h> //for rand(); works
#define PA PIN3_bm#define PB PIN6_bm#define PC PIN7_bm#define PD PIN1_bm
#define ModeMax 8#define STAR 0//#define DEBG
const uint8_t led_dir[12] = { ( PA | PB), //LED 0 1 ( PA | PB), //LED 0 1 ( PC | PA), //LED 2 3 ( PC | PA), //LED 2 3 ( PD | PA), //LED 4 5 ( PD | PA), //LED 4 5 ( PB | PC), //LED 6 7 ( PB | PC), //LED 6 7 ( PB | PD), //LED 8 9 ( PB | PD), //LED 8 9 ( PD | PC), //LED 10 11 ( PD | PC)  //LED 10 11  };
const uint8_t led[12] = { ( PB ), //LED 0 ( PA ), //LED 1 ( PA ), //LED 2 ( PC ), //LED 3 ( PA ), //LED 4 ( PD ), //LED 5 ( PC ), //LED 6 ( PB ), //LED 7 ( PD ), //LED 8 ( PB ), //LED 9 ( PC ), //LED 10( PD) }; //LED 11
const uint8_t red[3] = {1,8,10};const uint8_t blue[3] = {3,4,11};const uint8_t yellow[2] = {7,9};const uint8_t green[3] = {2,5,6};

static volatile uint8_t sleepstate = 0;static volatile uint8_t mode = 0;uint8_t randLoops;

void gotosleep(void);void ledOn(uint8_t);void ledOff(void);void allLedOn(uint16_t);void rainDrop(uint8_t, uint8_t);void randRainDrops(uint8_t);void upDown(uint8_t, uint8_t);void twinkleLeds(uint8_t);void diag(void);void startUp(uint8_t loops);void redGreenThenYellowBlue(uint8_t speed,uint8_t loops);void fade (uint8_t color, uint8_t speed, uint8_t loops);
int main(void){ CCP = 0xD8; CLKCTRL_MCLKCTRLB = 0b00000001; // long tt = random(10,20);// PORTA.DIRSET = 0;// ledOn(0);// _delay_ms(5000);// ledOff(); startUp(15); //about 20 sec for number 30// diag();// redGreenThenYellowBlue(1,5);// fade(STAR,15,200); //pull up pin 2 and set it to trigger int on falling edge: PORTA.PIN2CTRL = PORT_ISC_RISING_gc; //this was my fix for changing current draw sei(); //Set enable interrupt //set sleep to power down //SLPCTRL.CTRLA = 0b00000101; //sherms way SLPCTRL.CTRLA = SLPCTRL_SMODE_PDOWN_gc | SLPCTRL_SEN_bm; //Microchip studio showed this gotosleep(); //sleep //asm("sleep"); //sleep
while (1){ randLoops = (rand() % 100)+10;//3; //random 3-12 loops for display // mode=3; switch(mode){ case 0: upDown(150,randLoops); //150 break; case 1: //randLeds(randLoops); twinkleLeds(randLoops+10); break; case 2: allLedOn(80); //about 1min per 100 (250 max). break; case 3: redGreenThenYellowBlue(5,randLoops); //speed,loops break; case 4: rainDrop(100,randLoops); break; case 5: randRainDrops(randLoops); break; case 6: startUp(100); break; case 7: allLedOn(randLoops); break; case 8: allLedOn(100); break;
default: break; } #ifdef DEBG ledOn(mode); _delay_ms(50); ledOff(); #endif// mode=3; mode= (rand() % ModeMax); //Randomly select next mode/* if(mode++ > ModeMax-1){ mode=0; }*/ gotosleep(); }}
void startUp(uint8_t loops){ for(uint8_t j=0;j<loops;j++){ for(uint8_t i=0;i<12;i++){ for (uint8_t k=0;k<10;k++){ ledOn(i); _delay_us(500); ledOff(); _delay_us(500); ledOn(STAR); _delay_us(500); ledOff(); if(i>0){ ledOn(i-1); for(uint8_t dly=j;dly>1;dly--){ _delay_us(300); } ledOff(); _delay_us(700); } } } }}
void diag(void){ for(uint8_t i =0; i<12;i++){ ledOn(i); _delay_ms(2000); ledOff(); _delay_ms(500); }}void rainDrop(uint8_t speed,  uint8_t loops){ ledOff(); for(uint8_t l=0;l<loops;l++){ for(uint8_t i=0;i<12;i++){ for (uint8_t k=0;k<speed;k++){ ledOn(i); _delay_us(50); ledOff(); _delay_us(20); if(i>0){ ledOn(i-1); _delay_us(50); ledOff(); _delay_us(20); } if(i>1){ ledOn(i-2); _delay_us(50); ledOff(); _delay_us(20); } } } for(int i=0;i<5;i++){ ledOn(STAR); _delay_ms(10); ledOff(); _delay_ms(10); } }}
void randRainDrops(uint8_t loops){ ledOff(); int randNum; for(uint8_t l=0;l<loops;l++){ randNum = (rand() % 205)+10; for(uint8_t i=0;i<12;i++){ for (int k=0;k<randNum;k++){ ledOn(i); _delay_us(50); ledOff(); _delay_us(50); if(i>0){ ledOn(i-1); _delay_us(50); ledOff(); _delay_us(50); } } } for(int i=0;i<5;i++){ ledOn(STAR); _delay_ms(10); ledOff(); _delay_ms(10); } }}
void upDown(uint8_t speed, uint8_t loops){ ledOff(); uint8_t j; for(uint8_t h=0;h<loops;h++){ for(uint8_t i=0;i<12;i++){ for (uint8_t k=0;k<speed;k++){ ledOn(i); _delay_us(50); ledOff(); _delay_us(20); ledOff(); _delay_us(1); ledOn(STAR); _delay_us(1); } } for(uint8_t i=12;i>0;i--){ j=i-1; for (uint8_t k=0;k<speed;k++){ ledOn(j); _delay_us(50); ledOff(); _delay_us(20);
} } }}
void twinkleLeds(uint8_t loops){ uint8_t randLight; uint8_t randTime; for(uint8_t i=0;i<loops;i++){ for (uint8_t k=0;k<48;k++){ randLight = rand() % 12; ledOn(randLight); randTime = (rand() % 180) + 10; for(uint8_t l=0;l<randTime;l++){ _delay_us(200); ledOff(); _delay_us(1); } ledOn(STAR); _delay_us(10); ledOff(); } }}
void ledOn(uint8_t light){ PORTA.DIRSET = led_dir[light]; PORTA.OUT = led[light];}
void allLedOn(uint16_t loops){ for (uint16_t j=0;j<loops*250;j++){ for(uint8_t k=0;k<15;k++){ for (uint8_t i = 0; i<12 ; i++) { ledOn(i); ledOff(); } } }}void redGreenThenYellowBlue(uint8_t speed,uint8_t loops){ for(uint8_t lp=0;lp<loops;lp++){ for (uint16_t j=0;j<speed*20;j++){ for (uint8_t i = 0; i<3 ; i++) { ledOn(red[i]); _delay_ms(1); ledOff(); } ledOn(STAR); _delay_ms(1); ledOff(); for (uint8_t i = 0; i<3 ; i++) { ledOn(green[i]); _delay_ms(1); ledOff(); } ledOn(STAR); _delay_ms(1); ledOff(); } for (uint16_t j=0;j<speed*20;j++){ for (uint8_t i = 0; i<3 ; i++) { ledOn(blue[i]); _delay_ms(1); ledOff(); } ledOn(STAR); _delay_ms(1); ledOff(); for (uint8_t i = 0; i<2 ; i++) { ledOn(yellow[i]); _delay_ms(1); ledOff(); } ledOn(STAR); _delay_ms(1); ledOff(); } }}

void ledOff(void){ PORTA.DIRCLR = (PA|PB|PC|PD);}
void gotosleep(void){ PORTA.DIRSET = 0b00000000;
PORTA.PIN3CTRL = PORT_PULLUPEN_bm; PORTA.PIN1CTRL = PORT_PULLUPEN_bm; PORTA.PIN7CTRL = PORT_PULLUPEN_bm; PORTA.PIN6CTRL = PORT_PULLUPEN_bm;
sei(); SLPCTRL.CTRLA = 0b00000101; //set power down and sleep enable asm("sleep"); //sleep //turn off pull ups after sleep PORTA.PIN3CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN1CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN7CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN6CTRL &= ~(PORT_PULLUPEN_bm);
}
ISR(PORTA_PORT_vect){ if(sleepstate){ sleepstate=0; } //PORTA.INTFLAGS = 0x04; //clear int flag, from Ben Heck.. PORTA.INTFLAGS = PORT_INT2_bm; //not tested, got from iotn402.h}