~toykeeper/flashlight-firmware/trunk

« back to all changes in this revision

Viewing changes to odd/MGdriver/MGdriver.c

  • Committer: Selene Scriven
  • Date: 2015-07-18 20:54:25 UTC
  • Revision ID: ubuntu@toykeeper.net-20150718205425-yu8ul1ny00v1go7c
Added MGdriver by odd.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * MGdriver -  Off-time MultiGroup Driver by odd, based on luxdrv030 by DrJones
 
4
 *
 
5
 *
 
6
 * License: CC-BY-NC-SA (non-commercial use only, derivative works must be under the same license)
 
7
 *
 
8
 *
 
9
 *  Main differences to luxdrvß30:
 
10
 *  - REMOVED: Ramping mode
 
11
 *  - REMOVED: Wear leveling
 
12
 *  - CHANGED: OFFTime memory instead of ONTime memory
 
13
 *  - ADDED: Multiple groups
 
14
 *  - ADDED: Memory or nomemory selectable for each group
 
15
 *  - ADDED: Simple UI for switching groups
 
16
 */
 
17
 
 
18
 
 
19
#include <avr/pgmspace.h>
 
20
#include <avr/io.h>
 
21
#include <util/delay_basic.h>
 
22
#include <avr/interrupt.h>
 
23
#include <avr/sleep.h>
 
24
#include <avr/eeprom.h>
 
25
 
 
26
#define F_CPU                   4800000
 
27
#define byte                    uint8_t
 
28
#define word                    uint16_t
 
29
#define NOMEM                   0
 
30
#define MEM                     1
 
31
#define NOINIT                  __attribute__ ((section (".noinit")))
 
32
#define STROBE                  253
 
33
#define BEACON                  252
 
34
#define MODES_0                 NOMEM,  255, 0 , 0, 0 , 0                       // Fill unused modes with pwm level 0
 
35
#define MODES_1                 MEM,    25,     255 , 0 , 0 , 0
 
36
#define MODES_2                 NOMEM,  25,     255 , 0 , 0 , 0
 
37
#define MODES_3                 MEM,    255, 25 , 0 , 0 , 0
 
38
#define MODES_4                 NOMEM,  255, 25 , 0 , 0 , 0
 
39
#define MODES_5                 MEM,    25, 64 , 255 , 0 , 0
 
40
#define MODES_6                 NOMEM,  25, 64 , 255 , 0 , 0
 
41
#define MODES_7                 MEM,    255, 64 , 25 , 0 , 0
 
42
#define MODES_8                 NOMEM,  255, 64 , 25 , 0 , 0
 
43
#define MODES_9                 NOMEM,  6, 25 , 64 , 255 , 0
 
44
#define MODES_10                NOMEM,  25, 64 , 255 , STROBE , 0
 
45
#define MODES_11                NOMEM,  6 , 25 , 64 ,BEACON, STROBE
 
46
#define LENGTH_MODES    6                                                                       // 5 modes per group +1 for memory seletion
 
47
#define NUM_GROUPS              12                                                                      // 12 groups
 
48
PROGMEM const byte groups[NUM_GROUPS][LENGTH_MODES]={   
 
49
                                                        {MODES_0} , {MODES_1} , //delete or add groups here
 
50
                                                        {MODES_2} , {MODES_3} ,
 
51
                                                        {MODES_4} , {MODES_5} ,
 
52
                                                        {MODES_6} , {MODES_7} ,
 
53
                                                        {MODES_8} , {MODES_9} ,
 
54
                                                        {MODES_10}, {MODES_11} };
 
55
 
 
56
#define RESETTIME 12
 
57
#define BATTMON  129
 
58
 
 
59
#define outpin 1
 
60
#define PWM OCR0B
 
61
#define adcpin 2
 
62
#define adcchn 1
 
63
#define portinit() do{ DDRB=(1<<outpin); PORTB=0xff-(1<<outpin)-(1<<adcpin);  }while(0)
 
64
 
 
65
#define WDTIME 0b01000011  //125ms
 
66
 
 
67
#define sleepinit() do{ WDTCR=WDTIME; sei(); MCUCR=(MCUCR &~0b00111000)|0b00100000; }while(0)
 
68
 
 
69
#define SLEEP asm volatile ("SLEEP")
 
70
 
 
71
#define pwminit() do{ TCCR0A=0b00100001; TCCR0B=0b00000001; }while(0)
 
72
 
 
73
#define adcinit() do{ ADMUX =0b01100000|adcchn; ADCSRA=0b11000100; }while(0)
 
74
#define adcread() do{ ADCSRA|=64; while (ADCSRA&64); }while(0)
 
75
#define adcresult ADCH
 
76
 
 
77
#define ADCoff ADCSRA&=~(1<<7)
 
78
#define ADCon  ADCSRA|=(1<<7)
 
79
#define ACoff  ACSR|=(1<<7)
 
80
#define ACon   ACSR&=~(1<<7)
 
81
 
 
82
 
 
83
EEMEM byte eemode = 1;                          //Saving mode and group in EEPROM, no wear leveling
 
84
EEMEM byte eegroup = 1;
 
85
byte mypwm = 0;
 
86
volatile byte ticks = 0;
 
87
byte mode = 1;
 
88
byte pmode = 50;
 
89
byte group= 0 ;
 
90
byte memory = 0;
 
91
byte i = 0;
 
92
byte decay NOINIT;                                      //Using the NOINIT section of the RAM
 
93
byte shortcounter NOINIT;
 
94
byte lowbattcounter = 0;
 
95
 
 
96
ISR(WDT_vect) {
 
97
        if (ticks < 255)
 
98
                ticks++;
 
99
        if (ticks == RESETTIME)
 
100
                shortcounter=0;                         // Setting back the counter for repeated shortpresses, so we
 
101
                                                                        // never enter programming mode by accident
 
102
 
 
103
 
 
104
#ifdef BATTMON
 
105
        adcread()
 
106
        ;
 
107
        if (adcresult < BATTMON) {
 
108
                if (++lowbattcounter > 40) {
 
109
                        mypwm = (mypwm >> 1) + 3;
 
110
                        lowbattcounter = 0;
 
111
                }
 
112
        } else
 
113
                lowbattcounter = 0;
 
114
#endif
 
115
}
 
116
 
 
117
 
 
118
void _delay_ms(uint16_t n) {
 
119
 
 
120
    while(n-- > 0) _delay_loop_2(950);
 
121
}
 
122
 
 
123
 
 
124
inline void getmode(void) {
 
125
 
 
126
        mode=eeprom_read_byte(&eemode);                                         //reading mode and group from EEPROM
 
127
        group=eeprom_read_byte(&eegroup);
 
128
        memory=pgm_read_byte(&groups[group][0]);                        // reading memory from the 2D-array stored in flash
 
129
        if (!decay) {                                                                           // fast press
 
130
                mode++;
 
131
                                                                        //wrap around if it is last mode of the group or a unused mode
 
132
            if ((mode > LENGTH_MODES) || (!(pgm_read_byte(&groups[group][mode]))))
 
133
                mode = 1;
 
134
 
 
135
                shortcounter += 1;                                                      //count number of short-presses
 
136
                }
 
137
                else {                                                                                  // long press
 
138
                        if (memory == NOMEM) {
 
139
                          mode=1;  //NOMEM
 
140
 
 
141
                }
 
142
                shortcounter = 0;                                                               //Set back the counter for repeated shortpresses
 
143
                }
 
144
          decay=0;                                                                                      //Set back decay for long/shortpress detection
 
145
 
 
146
          eeprom_write_byte(&eemode, mode);
 
147
}
 
148
 
 
149
 
 
150
int main(void) {
 
151
 
 
152
 
 
153
        portinit();
 
154
 
 
155
        sleepinit();
 
156
 
 
157
        ACoff;
 
158
 
 
159
#ifdef BATTMON
 
160
        adcinit();
 
161
#else
 
162
        ADCoff;
 
163
#endif
 
164
 
 
165
        pwminit();
 
166
 
 
167
        getmode();
 
168
 
 
169
        pmode= pgm_read_byte(&groups[group][mode]);
 
170
 
 
171
        if (shortcounter>15) {                                                          // 15 or more short presses, enter programming mode
 
172
 
 
173
                PWM = 25;
 
174
                _delay_ms(2000);                                                                // to switch to the next group, press switch when light
 
175
                shortcounter = 0;                                                               // goes off after 2sec, or wait until it turn on again to cancel
 
176
                                                                                                                // switching the group
 
177
                group++;
 
178
                if (group >= NUM_GROUPS)
 
179
                        group = 0;
 
180
                shortcounter = 0;
 
181
                eeprom_write_byte(&eegroup, group);
 
182
                eeprom_write_byte(&eemode, 1);
 
183
                PWM = 0;
 
184
                _delay_ms(2000);
 
185
                if (!group)
 
186
                        group--;
 
187
                else
 
188
                        group = (NUM_GROUPS-1);
 
189
                eeprom_write_byte(&eegroup, group);
 
190
                while (1) {
 
191
                        PWM = 25;
 
192
                }
 
193
 
 
194
                }
 
195
 
 
196
        else {
 
197
 
 
198
                        switch (pmode) {
 
199
 
 
200
                #ifdef STROBE
 
201
                        case STROBE:
 
202
                                mypwm = 255;
 
203
                                while (1) {
 
204
                                        PWM = mypwm;
 
205
                                        _delay_ms(20);
 
206
                                        PWM = 0;
 
207
                                        _delay_ms(60);
 
208
                                }
 
209
                                break; //strobe 12.5Hz  //+48
 
210
                #endif
 
211
 
 
212
                #ifdef BEACON
 
213
                        case BEACON:
 
214
                #ifdef BATTMON
 
215
 
 
216
                                adcread();
 
217
                                i = adcresult;
 
218
                                while (i > BATTMON) {
 
219
                                        PWM = 8;
 
220
                                        SLEEP;                                  //SLEEP instead of delay_ms saves a few bytes here
 
221
                                        SLEEP;
 
222
                                        SLEEP;
 
223
                                        PWM = 0;
 
224
                                        SLEEP;
 
225
                                        SLEEP;
 
226
                                        i -= 5;
 
227
                                }
 
228
                                SLEEP;
 
229
                                SLEEP;
 
230
                                SLEEP;
 
231
                #endif
 
232
                                mypwm = 255;
 
233
                                while (1) {
 
234
                                        PWM = mypwm;
 
235
                                        _delay_ms(20);
 
236
                                        PWM = 0;
 
237
                                        _delay_ms(9880);
 
238
                                }
 
239
                                break;  //beacon 10s //+48
 
240
                #endif
 
241
 
 
242
                        default:
 
243
                                mypwm = pmode;
 
244
                                while (1) {
 
245
                                        PWM = mypwm;
 
246
                                        SLEEP;
 
247
                                }
 
248
                        }
 
249
}
 
250
                return 0;
 
251
}
 
 
b'\\ No newline at end of file'