~gabe/flashlight-firmware/anduril2

« back to all changes in this revision

Viewing changes to tterev3/attiny10_starter_code/attiny10-eswitch.c

  • Committer: Selene Scriven
  • Date: 2015-03-20 03:56:13 UTC
  • mto: This revision was merged to the branch mainline in revision 125.
  • Revision ID: ubuntu@toykeeper.net-20150320035613-ukmszeabb5vglddu
minor top-level doc updates

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//v0 5/1/2014 by Everett
 
2
        //initial version
 
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
 
8
 
 
9
#define F_CPU 1000000
 
10
#define pwm OCR0BL
 
11
#define pwm_invert
 
12
#include <avr/io.h>
 
13
#include <avr/interrupt.h>
 
14
#include <util/delay.h>
 
15
#include <avr/sleep.h>
 
16
 
 
17
unsigned char mode;
 
18
enum mode{
 
19
        max=0,
 
20
        med=1,
 
21
        low=2,
 
22
        off=3,
 
23
};
 
24
#define max_mode 3
 
25
#define default_mode 0
 
26
 
 
27
unsigned int v_timer;
 
28
char v_sample;
 
29
#define voltage_rate 100 //milliseconds
 
30
 
 
31
char pressed;
 
32
char new_press;
 
33
char switch_count;
 
34
unsigned char isr_prescale;
 
35
 
 
36
void configure(void);
 
37
unsigned char read_voltage(void);
 
38
void initialize_mode(void);
 
39
void debounce(void);
 
40
void shutdown(void);
 
41
 
 
42
ISR(TIM0_OVF_vect) //fires at 4kHz
 
43
{
 
44
        isr_prescale++;
 
45
        if(isr_prescale>=4){    //prescale since timer only has the 4kHz option
 
46
                isr_prescale=0;
 
47
                debounce();
 
48
                if(++v_timer==voltage_rate){v_timer=0; v_sample=1;}
 
49
        }
 
50
}
 
51
 
 
52
ISR(INT0_vect)
 
53
{
 
54
        //no action, but ISR must be included since it will execute upon waking
 
55
}
 
56
 
 
57
 
 
58
int main(void)
 
59
{
 
60
        configure();    //set up hardware peripherals
 
61
        
 
62
        mode=default_mode;
 
63
        initialize_mode();
 
64
        pressed=0; new_press=0; switch_count=10;
 
65
        sei();  //turn on interrupts
 
66
 
 
67
        while(1){
 
68
                
 
69
                if(v_sample){
 
70
                        v_sample=0;
 
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
 
73
                                        mode=med;
 
74
                                        initialize_mode();
 
75
                                }
 
76
                        }
 
77
                }
 
78
                
 
79
                if(new_press){
 
80
                        new_press=0;
 
81
                        mode++;
 
82
                        if(mode>max_mode) mode=0;
 
83
                        initialize_mode();
 
84
                }
 
85
                
 
86
                if(mode==off)
 
87
                {
 
88
                        shutdown();     //shutdown will lock up here until a press wakes the device
 
89
                }
 
90
                
 
91
        }
 
92
}
 
93
 
 
94
void shutdown(void)
 
95
{
 
96
        TIMSK0=0;       //stop timer interrupt
 
97
        pwm=0;  //zero output
 
98
        TCCR0A=0; //turn off pwm
 
99
        #ifdef pwm_invert
 
100
        PORTB|=0b00000010;
 
101
        #else
 
102
        PORTB=0;                //ensure pin is low
 
103
        #endif
 
104
        ADCSRA=0;       //adc off
 
105
        PRR=3;  //power reduce on adc and timer0
 
106
        
 
107
        while(1)        //make this a loop so we stay here until sure the switch went down
 
108
        {
 
109
                do{
 
110
                        debounce();
 
111
                        _delay_ms((char)1);
 
112
                }while(pressed);        //ensure switch is up
 
113
                
 
114
                EICRA=0;        //interrupt on low level of int0
 
115
                EIMSK=1;        
 
116
                SMCR=0b00000101;        //enable sleep
 
117
                sleep_cpu();
 
118
                EIMSK=0;
 
119
                SMCR=0b00000100;        //disable sleep 
 
120
                
 
121
                pressed=0; switch_count=10;
 
122
                for(char i=0; i<40; i++){       //watch for up to 40ms for a solid press
 
123
                        debounce();
 
124
                        _delay_ms((char)1);
 
125
                        if(pressed) break;      //if pressed break out of for loop
 
126
                }
 
127
                if(pressed) break;      //if pressed break out of sleep loop
 
128
        }
 
129
        
 
130
        configure();    //set up hardware for operation
 
131
        
 
132
}
 
133
 
 
134
void debounce(void)
 
135
{
 
136
        static char port_copy=0xff;
 
137
        #define switch_mask 0b00000001  //this selects PB0 as the switch
 
138
        
 
139
        if((PINB&switch_mask)==port_copy)       //if the current state matches previous state
 
140
        {
 
141
                if(--switch_count==0)   //count down samples. if 10 consecutive samples matched
 
142
                {
 
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
 
146
                        {
 
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
 
149
                        }
 
150
                }
 
151
        }
 
152
        else    //state doesn't match,
 
153
        {
 
154
                switch_count=10;        //reset sample counter
 
155
                port_copy=(PINB&switch_mask);   //get new sample
 
156
        }
 
157
}
 
158
 
 
159
void initialize_mode(void)
 
160
{
 
161
        switch(mode){   //initialize current mode
 
162
                default:
 
163
                case max:
 
164
                pwm=255;
 
165
                break;
 
166
                case med:
 
167
                pwm=25;
 
168
                break;
 
169
                case low:
 
170
                pwm=1;
 
171
                break;
 
172
                case off:
 
173
                pwm=0;
 
174
                break;
 
175
        }
 
176
}
 
177
 
 
178
unsigned char read_voltage(void)
 
179
{
 
180
        ADCSRA|=(1<<ADSC);      
 
181
        while(ADCSRA&(1<<ADSC));
 
182
        return ADCL;
 
183
}
 
184
 
 
185
 
 
186
void configure(void)
 
187
{
 
188
        PRR=0;
 
189
        TIMSK0=0b00000001;      //interrupt on t0 overflow
 
190
        pwm=0;
 
191
        #ifdef pwm_invert
 
192
        TCCR0A=0b00110001;      //output B inverted
 
193
        #else
 
194
        TCCR0A=0b00100001;      //output B on, not inverted, 8bit pwm,
 
195
        #endif
 
196
        TCCR0B=0b00001001;      //no prescale for 3906Hz pwm and interrupt
 
197
        GTCCR=0;
 
198
        
 
199
        PORTB=0;
 
200
        DDRB=0b00000010;        //PB1 output
 
201
        DIDR0=0b00000100;       //PB2 analog
 
202
        PUEB=0b11111001;        //pull up switch and reset
 
203
 
 
204
        ADMUX=2;        //PB2
 
205
        ADCSRA=0b10000011;      // 
 
206
 
 
207
        SMCR=0b00000100;        //enable power down mode
 
208
}