ATtiny414 Ugly Runway Sweater

ATtiny414 Ugly Sweater Runway lights

Ugly Runway Sweater Guarded by the Black Panther

Charlie Plexing diagram how layed out on sweater

Diagram of how running lights are Charlie Plexed on sweater. To make easier for code.

20221113_154747.mp4

USB C Charge port.

Control Box, 3d printed on Ender3

ATtiny-runway-ugly-sweater-high.flv

Over 400 lines of code:

//Code in C with Microchip Studio
/* * ATtiny414-Runway-lights.c * v1.3 2022-11-13 * Created: 10/26/2022 16:27:03 * Author : Sherman Stebbins * Used Micro Chip Studio 7 * Updated 2022-11-13 - worked on modes * Updated 2022-11-17 - Fixed SOS mode. */ 
#define F_CPU 10000000UL#include <avr/io.h>#include <util/delay.h>#include <avr/interrupt.h>#include <stdlib.h> //for rand(); works
#define PA PIN4_bm#define PB PIN5_bm#define PC PIN6_bm#define PD PIN7_bm
#define ModeMax 6//#define DEBG 
const uint8_t led_dir[12] = { ( PA | PB), //LED 0 1 ( PA | PB), //LED 0 1 ( PC | PB), //LED 2 3 ( PC | PB), //LED 2 3 ( PC | PA), //LED 4 5 ( PC | PA), //LED 4 5 ( PA | PD), //LED 6 7 ( PA | PD), //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] = { ( PA ), //LED 0 ( PB ), //LED 1 ( PC ), //LED 2 ( PB ), //LED 3 ( PC ), //LED 4 ( PA ), //LED 5 ( PA ), //LED 6 ( PD ), //LED 7 ( PB ), //LED 8 ( PD ), //LED 9 ( PC ), //LED 10    ( PD) }; //LED 11
static volatile uint8_t sleepstate = 0;static volatile uint8_t mode = 5;static volatile uint8_t modeChange=0;uint8_t randLoops;
void sos(void);void newDot(void);void newDash(void);void whiteOn(void);void redOn(void);void greenOn(void);void whiteOff(void);void redOff(void);void greenOff(void);void allColorLedOn(void);void allColorLedOff(void);void gotosleep(void);void ledOn(uint8_t);void ledOff(void);void allLedOn(uint8_t);void rainDrop(uint8_t, uint8_t);void randRainDrops(uint8_t);void upDown(uint8_t, uint8_t);void randLeds(uint8_t);
void flashTest(void){ //for(uint8_t i = mode;i>=0;i--){ PORTB_OUT &= ~(PIN2_bm); _delay_ms(100); PORTB_OUT = PIN2_bm; //}}void changeMode(void){ flashTest(); mode++; if(mode>=ModeMax){ mode=0; } modeChange=0;}ISR(PORTB_PORT_vect){ if(~PORTB_IN & PIN3_bm){ } if(~PORTB.INTFLAGS & PIN3_bm){ while(PORTB.IN & PIN3_bm){ } } PORTB.INTFLAGS = 0b11111111;// PORTB.INTFLAGS = PORT_INT3_bm; modeChange=1; _delay_ms(50); // mode++; // if(mode > ModeMax-1){ // mode=0; // }}
int main(void){ CCP = 0xD8; CLKCTRL_MCLKCTRLB = 0b00000001; //set at max speed div by 2 so 10mhz while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm){;} //wait for clock sync.// long tt = random(10,20); //PORTA.OUTSET = (1<<) PORTA.DIRSET = 0; PORTB.DIRSET = PIN0_bm|PIN1_bm|PIN2_bm; PORTA.DIRSET = PIN1_bm|PIN2_bm; PORTB.DIRSET &= ~(PIN3_bm); PORTB.PIN3CTRL = PORT_PULLUPEN_bm |  PORT_ISC_FALLING_gc|PORT_INVEN_bm; PORTA_OUT = PIN2_bm; PORTB_OUT = PIN2_bm; _delay_ms(100); //pull up pin 2 and set it to trigger int on falling edge: PORTB.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// allColorLedOn(); while (1){ // allColorLedOn(); if(modeChange){ changeMode();} // mode=5; switch(mode){     case 0: allColorLedOn(); for(uint8_t i=0;i<12;i++){ ledOn(i); _delay_ms(70); ledOff(); } ledOff(); _delay_ms(70);         break; case 1: allColorLedOn(); rainDrop(250,1); break; case 2: allColorLedOn(); upDown(150,1); break; case 3: allColorLedOn(); randLeds(1); break; case 4: allColorLedOn(); allLedOn(1); //about 1min per 100 (250 max). break; case 5: sos(); break; default: break; } #ifdef DEBG ledOn(mode); _delay_ms(50); ledOff(); #endif // gotosleep(); }}void ledOn(uint8_t light){ PORTA.DIR = led_dir[light]; PORTA.OUT = led[light]; greenOn();}void ledOff(void){ //PORTA.DIRCLR = (PA|PB|PC|PD); PORTA.DIR &= ~(PA|PB|PC|PD); //same}
void whiteOn(void){// PORTB.DIRSET = PIN0_bm; PORTB.OUTSET = PIN1_bm;}
void redOn(void){// PORTB.DIRSET = PIN1_bm; PORTA.OUTSET = PIN1_bm;}void greenOn(void){ PORTA.DIRSET = PIN2_bm; PORTA.OUTSET = PIN2_bm;// PORTA.DIR = PIN2_bm;// PORTA.OUT = PIN2_bm;}void whiteOff(void){ PORTB_OUT &= ~PIN1_bm;}void redOff(void){ PORTA.OUTCLR= PIN1_bm;}void greenOff(void){ PORTA.OUTCLR = PIN2_bm;}void allColorLedOn(void){ PORTB_DIRSET = PIN0_bm; PORTB_OUTSET = PIN0_bm; whiteOn(); redOn(); greenOn();}
void allColorLedOff(){ PORTB_OUTCLR = PIN0_bm; whiteOff(); redOff(); greenOff();}void newDot(){ PORTB.OUTSET = PIN1_bm; PORTA.OUTSET = PIN2_bm; _delay_ms(400); PORTB.OUTCLR = PIN1_bm; PORTA_OUT &= ~PIN2_bm; _delay_ms(300);}void newDash(){ PORTB_OUTSET = PIN1_bm; PORTA.OUTSET = PIN2_bm; _delay_ms(800); PORTB_OUTCLR = PIN1_bm; PORTA_OUTCLR = PIN2_bm; _delay_ms(300);}void sos(){    //..-. ..- -.-. -.- / ..-  //fuck u    //..-. / ..- //f u newDot(); newDot(); newDash(); newDot(); _delay_ms(500); newDot(); newDot(); newDash(); _delay_ms(1000);}
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++){ // if(modeChange){ // changeMode(); // return;} ledOn(i); _delay_us(50); ledOff(); _delay_us(20); if(i>0){ ledOn(i-1); _delay_us(50); ledOff(); _delay_us(20); }/* // unremark if you want 3 lines of lights running instead of 2 if(i>1){ ledOn(i-2); _delay_us(50); ledOff(); _delay_us(20); }*/ } } for(int i=0;i<3;i++){ ledOn(11); _delay_ms(40); ledOff(); _delay_ms(40); } }}
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++){ // if(modeChange){ // changeMode(); // return;}
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(11); _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++){ // if(modeChange){ // changeMode(); // return;}
ledOn(i); _delay_us(50); ledOff(); _delay_us(20); } } 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 randLeds(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++){ // if(modeChange){ // changeMode(); // return;}
randLight = rand() % 12; ledOn(randLight); randTime = (rand() % 80) + 10; for(uint8_t l=0;l<randTime;l++){ _delay_us(200); } ledOff(); } }}

void allLedOn(uint8_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++) { // if(modeChange){ // changeMode(); // return;}
ledOn(i); ledOff(); } } }}

void gotosleep(void){ PORTA.DIRSET = 0b00000000; PORTB.PIN0CTRL = PORT_PULLUPEN_bm; PORTB.PIN1CTRL = PORT_PULLUPEN_bm;    PORTA.PIN1CTRL = PORT_PULLUPEN_bm; PORTA.PIN4CTRL = PORT_PULLUPEN_bm; PORTA.PIN5CTRL = PORT_PULLUPEN_bm; PORTA.PIN6CTRL = PORT_PULLUPEN_bm; PORTA.PIN7CTRL = PORT_PULLUPEN_bm;
sei(); SLPCTRL.CTRLA = 0b00000101; //set power down and sleep enable asm("sleep"); //sleep //turn off pull ups after sleep PORTB.PIN0CTRL &= ~(PORT_PULLUPEN_bm); PORTB.PIN1CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN1CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN4CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN5CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN6CTRL &= ~(PORT_PULLUPEN_bm); PORTA.PIN7CTRL &= ~(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}