1
//v0 5/1/2014 by Everett
3
//simple flashlight controller. mode change on power cycle
4
//v1 5/3/2014 by Everett
5
//adapted to momentary switch
6
//v2 5/6/2014 by Everett
7
//ported to Attiny10 device
13
#include <avr/interrupt.h>
14
#include <util/delay.h>
15
#include <avr/sleep.h>
25
#define default_mode 0
29
#define voltage_rate 100 //milliseconds
34
unsigned char isr_prescale;
37
unsigned char read_voltage(void);
38
void initialize_mode(void);
42
ISR(TIM0_OVF_vect) //fires at 4kHz
45
if(isr_prescale>=4){ //prescale since timer only has the 4kHz option
48
if(++v_timer==voltage_rate){v_timer=0; v_sample=1;}
54
//no action, but ISR must be included since it will execute upon waking
60
configure(); //set up hardware peripherals
64
pressed=0; new_press=0; switch_count=10;
65
sei(); //turn on interrupts
71
if(mode==max){ //if battery goes below threshold in max mode, force down to medium mode
72
if(read_voltage()<100){ //set threshold for external voltage here
82
if(mode>max_mode) mode=0;
88
shutdown(); //shutdown will lock up here until a press wakes the device
96
TIMSK0=0; //stop timer interrupt
98
TCCR0A=0; //turn off pwm
102
PORTB=0; //ensure pin is low
105
PRR=3; //power reduce on adc and timer0
107
while(1) //make this a loop so we stay here until sure the switch went down
112
}while(pressed); //ensure switch is up
114
EICRA=0; //interrupt on low level of int0
116
SMCR=0b00000101; //enable sleep
119
SMCR=0b00000100; //disable sleep
121
pressed=0; switch_count=10;
122
for(char i=0; i<40; i++){ //watch for up to 40ms for a solid press
125
if(pressed) break; //if pressed break out of for loop
127
if(pressed) break; //if pressed break out of sleep loop
130
configure(); //set up hardware for operation
136
static char port_copy=0xff;
137
#define switch_mask 0b00000001 //this selects PB0 as the switch
139
if((PINB&switch_mask)==port_copy) //if the current state matches previous state
141
if(--switch_count==0) //count down samples. if 10 consecutive samples matched
143
switch_count=10; //reset sample counter
144
if(PINB&switch_mask) pressed=0; //if the state is high, switch is up
145
else //else switch is down. check for new press
147
if(pressed==0) new_press=1; //if last state of pressed was 0, this is a new press
148
pressed=1; //switch is now down
152
else //state doesn't match,
154
switch_count=10; //reset sample counter
155
port_copy=(PINB&switch_mask); //get new sample
159
void initialize_mode(void)
161
switch(mode){ //initialize current mode
178
unsigned char read_voltage(void)
181
while(ADCSRA&(1<<ADSC));
189
TIMSK0=0b00000001; //interrupt on t0 overflow
192
TCCR0A=0b00110001; //output B inverted
194
TCCR0A=0b00100001; //output B on, not inverted, 8bit pwm,
196
TCCR0B=0b00001001; //no prescale for 3906Hz pwm and interrupt
200
DDRB=0b00000010; //PB1 output
201
DIDR0=0b00000100; //PB2 analog
202
PUEB=0b11111001; //pull up switch and reset
205
ADCSRA=0b10000011; //
207
SMCR=0b00000100; //enable power down mode