1 | /*********************************************
|
2 | * Chip type : ATtiny13
|
3 | * Clock frequency : Internal clock 1 Mhz (factory default)
|
4 | *********************************************/
|
5 | #define F_CPU 1000000UL // 1 MHz
|
6 | #include <avr/io.h>
|
7 | #include <avr/sleep.h>
|
8 | #include <inttypes.h>
|
9 | #include <avr/delay.h>
|
10 | #include <avr/interrupt.h>
|
11 | #include <avr/signal.h>
|
12 |
|
13 |
|
14 | //Hardware definitions
|
15 | #define PORT PORTB
|
16 | #define PIN PINB
|
17 | #define DDR DDRB
|
18 | #define REDLED PB2
|
19 | #define GREENLED PB1
|
20 | #define BLUELED PB0
|
21 | #define BTN PB3
|
22 |
|
23 | //Fading States
|
24 | #define REDtoYELLOW 0
|
25 | #define YELLOWtoGREEN 1
|
26 | #define GREENtoCYAN 2
|
27 | #define CYANtoBLUE 3
|
28 | #define BLUEtoVIOLET 4
|
29 | #define VIOLETtoRED 5
|
30 |
|
31 | //Less Typing of _
|
32 | #define BV _BV
|
33 |
|
34 | //Maximim value for led brightness
|
35 | #define V_MAX 255
|
36 |
|
37 | char mode=0;
|
38 | char state; //Counter for each mode. Reset to 0 while changing modes
|
39 |
|
40 | //Current color values
|
41 | unsigned char red;
|
42 | unsigned char green;
|
43 | unsigned char blue;
|
44 |
|
45 | //Predefine function
|
46 | void button(void);
|
47 |
|
48 | char state2; //State in the rainbow fade progress
|
49 | void rainbowfade(int n){
|
50 | //Go one step through a state machine that fades through the rainbow
|
51 | //n sets the step increment
|
52 | //255%n must equal 0
|
53 | if (state2==REDtoYELLOW) green+=n;
|
54 | if (state2==YELLOWtoGREEN) red-=n;
|
55 | if (state2==GREENtoCYAN) blue+=n;
|
56 | if (state2==CYANtoBLUE) green-=n;
|
57 | if (state2==BLUEtoVIOLET) red+=n;
|
58 | if (state2==VIOLETtoRED) blue-=n;
|
59 | if (red==V_MAX || green==V_MAX || blue==V_MAX || red==0 || green==0 || blue==0){
|
60 | //Finished fading a color; move on to the next
|
61 | state2++;
|
62 | state2%=6;
|
63 | }
|
64 | }
|
65 |
|
66 | void mode1(void){
|
67 | rainbowfade(1); //Fade 1 step per PWM Cycle
|
68 | }
|
69 |
|
70 | void mode2(void){
|
71 | state++;
|
72 | if (state%128==0){//Every 128 PWM cycles
|
73 | //Save old colors
|
74 | char r=red;
|
75 | char g=green;
|
76 | char b=blue;
|
77 | //Rotate colors
|
78 | red=g;
|
79 | green=b;
|
80 | blue=r;
|
81 | }
|
82 | }
|
83 |
|
84 | void mode3(void){
|
85 | state++;
|
86 | if (state%128==0){ //Every 128 PWM Cycles
|
87 | rainbowfade(255); //Skip to the next color
|
88 | }
|
89 | }
|
90 |
|
91 | void mode0(void);
|
92 |
|
93 | #define NUM_MODES 4
|
94 |
|
95 | //Array of mode function pointers
|
96 | typedef void(*modefn)(void);
|
97 | modefn modefns[NUM_MODES]={
|
98 | mode0,
|
99 | mode1,
|
100 | mode2,
|
101 | mode3,
|
102 | };
|
103 | modefn current; //Function pointer for current mode
|
104 |
|
105 | void setmode(char m){
|
106 | //Switch mode to m
|
107 | mode=m;
|
108 |
|
109 | //Reset state
|
110 | red=255;
|
111 | green=0;
|
112 | blue=0;
|
113 | state=0;
|
114 | state2=0;
|
115 |
|
116 | //Set function pointer
|
117 | current=modefns[(int)mode];
|
118 | }
|
119 |
|
120 | void button(){ //Called when the button is pressed
|
121 | setmode((mode+1)%NUM_MODES);
|
122 | }
|
123 |
|
124 | void mode0(void){
|
125 | PORT|=BV(PB4); //Turn on debug LED
|
126 | PORT|=(BV(REDLED)| BV(BLUELED)| BV(GREENLED)); //Turn off LEDs
|
127 |
|
128 | unsigned char n=10;
|
129 | while (n--) _delay_ms(255); //Wait for a bit so it doesn't wake up while
|
130 | //the button is still down
|
131 |
|
132 | PORT&=~BV(PB4); //Turn off debug LED
|
133 |
|
134 | //Enter Sleep Mode
|
135 | set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
136 | PCMSK=BV(PCINT3);
|
137 | GIMSK|=BV(PCIE); //Enable PCINTs
|
138 | GIFR|=BV(PCIF);//Clear flags
|
139 | sei();
|
140 | sleep_mode();
|
141 |
|
142 | //Now, after awakening...
|
143 |
|
144 | cli(); // Turn off interrupts
|
145 |
|
146 | setmode(1); //Switch to mode 1
|
147 | while (n>250){ //wait until button is released
|
148 | if ((PIN&BV(BTN))!=0){
|
149 | n++;
|
150 | }else n=0;
|
151 | _delay_ms(25);
|
152 | }
|
153 | }
|
154 |
|
155 | SIGNAL(SIG_PIN_CHANGE0){ //Button change, used to wake from sleep, not while running
|
156 | PORT|=BV(PB4);
|
157 | }
|
158 |
|
159 | void timer(void){ //Called once per PWM Cycle
|
160 | current(); //Let the current mode update colors
|
161 | }
|
162 |
|
163 | int main(void){
|
164 | unsigned char i=0;
|
165 |
|
166 | //Set pins to output
|
167 | DDR|= BV(DDB2);
|
168 | DDR|= BV(DDB1);
|
169 | DDR|= BV(DDB0);
|
170 | DDR|= BV(DDB4);
|
171 |
|
172 | DDRB&=~BV(DDB3); //Set button to input
|
173 |
|
174 | unsigned char debounce=0;
|
175 | setmode(1); //Start with mode 1
|
176 | timer(); //Let mode set initial color
|
177 |
|
178 | while (1) {
|
179 | //Software PWM
|
180 | if (i<red){
|
181 | PORT &=~ BV(REDLED);
|
182 | }else{
|
183 | PORT|=BV(REDLED);
|
184 | }
|
185 | if (i<green){
|
186 | PORT &=~ BV(GREENLED);
|
187 | }else{
|
188 | PORT|=BV(GREENLED);
|
189 | }
|
190 | if (i<blue){
|
191 | PORT &=~ BV(BLUELED);
|
192 | }else{
|
193 | PORT|=BV(BLUELED);
|
194 | }
|
195 |
|
196 | if (i==0){ //After blinking LEDs 255 times
|
197 | if ((PIN&BV(BTN))==0 && debounce==0){ //Is button down?
|
198 | button();
|
199 | debounce=1; //Wait for release
|
200 | }
|
201 | if (debounce) debounce++; //Will wrap to 0 and stop counting
|
202 | timer();
|
203 | }
|
204 | i++;
|
205 | }
|
206 | return 0; //Will never get here
|
207 | }
|