~toykeeper/flashlight-firmware/trunk

« back to all changes in this revision

Viewing changes to JonnyC/STAR/STAR_momentary/STAR_momentary.c

  • Committer: Selene Scriven
  • Date: 2014-11-10 21:44:25 UTC
  • mto: This revision was merged to the branch mainline in revision 71.
  • Revision ID: ubuntu@toykeeper.net-20141110214425-h071pac1ulayazsf
JCapSolutions   2014-10-07 [merge]
git commit: fed8251a4b977f18c55acfbb1ed40c702008dde8
Merge branch 'dual_pwm'

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* STAR_momentary version 1.4
 
2
 *
 
3
 * Changelog
 
4
 *
 
5
 * 1.0 Initial version
 
6
 * 1.1 Added ability for star 2 to change mode order
 
7
 * 1.2 Fix for newer version of AVR Studio
 
8
 * 1.3 Added support for dual PWM outputs and selection of PWM mode per output level
 
9
 * 1.4 Added ability to switch to a momentary mode
 
10
 *
 
11
 */
 
12
 
 
13
/*
 
14
 * NANJG 105C Diagram
 
15
 *           ---
 
16
 *         -|   |- VCC
 
17
 *  Star 4 -|   |- Voltage ADC
 
18
 *  Star 3 -|   |- PWM
 
19
 *     GND -|   |- Star 2
 
20
 *           ---
 
21
 *
 
22
 * FUSES
 
23
 *              I use these fuse settings
 
24
 *              Low:  0x75      (4.8MHz CPU without 8x divider, 9.4kHz phase-correct PWM or 18.75kHz fast-PWM)
 
25
 *              High: 0xff
 
26
 *
 
27
 *      For more details on these settings, visit http://github.com/JCapSolutions/blf-firmware/wiki/PWM-Frequency
 
28
 *
 
29
 * STARS
 
30
 *              Star 2 = Not used
 
31
 *              Star 3 = H-L if connected, L-H if not
 
32
 *              Star 4 = Switch input
 
33
 *
 
34
 * VOLTAGE
 
35
 *              Resistor values for voltage divider (reference BLF-VLD README for more info)
 
36
 *              Reference voltage can be anywhere from 1.0 to 1.2, so this cannot be all that accurate
 
37
 *
 
38
 *           VCC
 
39
 *            |
 
40
 *           Vd (~.25 v drop from protection diode)
 
41
 *            |
 
42
 *          1912 (R1 19,100 ohms)
 
43
 *            |
 
44
 *            |---- PB2 from MCU
 
45
 *            |
 
46
 *          4701 (R2 4,700 ohms)
 
47
 *            |
 
48
 *           GND
 
49
 *
 
50
 *              ADC = ((V_bat - V_diode) * R2   * 255) / ((R1    + R2  ) * V_ref)
 
51
 *              125 = ((3.0   - .25    ) * 4700 * 255) / ((19100 + 4700) * 1.1  )
 
52
 *              121 = ((2.9   - .25    ) * 4700 * 255) / ((19100 + 4700) * 1.1  )
 
53
 *
 
54
 *              Well 125 and 121 were too close, so it shut off right after lowering to low mode, so I went with
 
55
 *              130 and 120
 
56
 *
 
57
 *              To find out what value to use, plug in the target voltage (V) to this equation
 
58
 *                      value = (V * 4700 * 255) / (23800 * 1.1)
 
59
 *      
 
60
 */
1
61
#define F_CPU 4800000UL
2
62
 
 
63
// PWM Mode
 
64
#define PHASE 0b00000001
 
65
#define FAST  0b00000011
 
66
 
3
67
/*
4
68
 * =========================================================================
5
69
 * Settings to modify per driver
6
70
 */
7
71
 
8
72
#define VOLTAGE_MON                     // Comment out to disable - ramp down and eventual shutoff when battery is low
9
 
#define MODES                   0,16,32,125,255 // Must be low to high, and must start with 0
 
73
#define MODES                   0,8,32,125,255          // Must be low to high, and must start with 0
 
74
#define ALT_MODES               0,2,32,125,255          // Must be low to high, and must start with 0, the defines the level for the secondary output. Comment out if no secondary output
 
75
#define MODE_PWM                0,PHASE,FAST,FAST,FAST          // Define one per mode above, 0 for phase-correct, 1 for fast-PWM
10
76
#define TURBO                           // Comment out to disable - full output with a step down after n number of seconds
11
77
                                                        // If turbo is enabled, it will be where 255 is listed in the modes above
12
78
#define TURBO_TIMEOUT   5625 // How many WTD ticks before before dropping down (.016 sec each)
17
83
#define ADC_CRIT                120 // When do we shut the light off
18
84
#define ADC_DELAY               188     // Delay in ticks between low-bat rampdowns (188 ~= 3s)
19
85
 
 
86
#define MOM_ENTER_DUR   128 // .16ms each.  Comment out to disable this feature
 
87
#define MOM_EXIT_DUR    128 // .16ms each
 
88
 
 
89
#define MOM_MODE_IDX    4   // The index of the mode to use in MODES above, starting at index of 0
 
90
 
20
91
/*
21
92
 * =========================================================================
22
93
 */
30
101
#include <avr/sleep.h>
31
102
//#include <avr/power.h>
32
103
 
33
 
#define STAR2_PIN   PB0         // If not connected, will cycle L-H.  Connected, H-L
34
 
#define STAR3_PIN   PB4
 
104
#define STAR3_PIN   PB4     // If not connected, will cycle L-H.  Connected, H-L
35
105
#define SWITCH_PIN  PB3         // what pin the switch is connected to, which is Star 4
36
106
#define PWM_PIN     PB1
 
107
#define ALT_PWM_PIN PB0
37
108
#define VOLTAGE_PIN PB2
38
109
#define ADC_CHANNEL 0x01        // MUX 01 corresponds with PB2
39
110
#define ADC_DIDR        ADC1D   // Digital input disable bit corresponding with PB2
40
111
#define ADC_PRSCL   0x06        // clk/64
41
112
 
42
 
#define PWM_LVL OCR0B       // OCR0B is the output compare register for PB1
 
113
#define PWM_LVL     OCR0B   // OCR0B is the output compare register for PB1
 
114
#define ALT_PWM_LVL OCR0A   // OCR0A is the output compare register for PB0
43
115
 
44
116
#define DB_REL_DUR 0b00001111 // time before we consider the switch released after
45
117
                                                          // each bit of 1 from the right equals 16ms, so 0x0f = 64ms
46
118
 
47
119
// Switch handling
48
120
#define LONG_PRESS_DUR   32 // How many WDT ticks until we consider a press a long press
49
 
                            // 32 is roughly .5 s       
 
121
                            // 32 is roughly .5 s
50
122
 
51
123
/*
52
124
 * The actual program
56
128
/*
57
129
 * global variables
58
130
 */
59
 
PROGMEM  const uint8_t modes[] = { MODES };
 
131
const uint8_t modes[]     = { MODES    };
 
132
#ifdef ALT_MODES
 
133
const uint8_t alt_modes[] = { ALT_MODES };
 
134
#endif
 
135
const uint8_t mode_pwm[] = { MODE_PWM };
60
136
volatile uint8_t mode_idx = 0;
61
137
volatile uint8_t press_duration = 0;
62
138
volatile uint8_t low_to_high = 0;
 
139
volatile uint8_t in_momentary = 0;
63
140
 
64
141
// Debounced switch press value
65
142
int is_pressed()
169
246
                        press_duration++;
170
247
                }
171
248
                
 
249
                #ifdef MOM_ENTER_DUR
 
250
                if (in_momentary) {
 
251
                        // Turn on full output
 
252
                        mode_idx = MOM_MODE_IDX;
 
253
                        if (press_duration == MOM_EXIT_DUR) {
 
254
                                // Turn light off and disable momentary
 
255
                                mode_idx = 0;
 
256
                                in_momentary = 0;
 
257
                        }
 
258
                        return;
 
259
                }
 
260
                #endif  
 
261
 
172
262
                if (press_duration == LONG_PRESS_DUR) {
173
263
                        // Long press
174
264
                        if (low_to_high) {
177
267
                                next_mode();
178
268
                        }                       
179
269
                }
 
270
                #ifdef MOM_ENTER_DUR
 
271
                if (press_duration == MOM_ENTER_DUR) {
 
272
                        in_momentary = 1;
 
273
                        press_duration = 0;
 
274
                }
 
275
                #endif
180
276
                // Just always reset turbo timer whenever the button is pressed
181
277
                turbo_ticks = 0;
182
278
                // Same with the ramp down delay
183
279
                adc_ticks = ADC_DELAY;
 
280
        
184
281
        } else {
 
282
                
 
283
                #ifdef MOM_ENTER_DUR
 
284
                if (in_momentary) {
 
285
                        // Turn off the light
 
286
                        mode_idx = 0;
 
287
                        return;
 
288
                }
 
289
                #endif
 
290
                
185
291
                // Not pressed
186
292
                if (press_duration > 0 && press_duration < LONG_PRESS_DUR) {
187
293
                        // Short press
193
299
                } else {
194
300
                        // Only do turbo check when switch isn't pressed
195
301
                #ifdef TURBO
196
 
                        if (pgm_read_byte(&modes[mode_idx]) == 255) {
 
302
                        if (modes[mode_idx] == 255) {
197
303
                                turbo_ticks++;
198
304
                                if (turbo_ticks > TURBO_TIMEOUT) {
199
305
                                        // Go to the previous mode
239
345
{       
240
346
        // Set all ports to input, and turn pull-up resistors on for the inputs we are using
241
347
        DDRB = 0x00;
242
 
        PORTB = (1 << SWITCH_PIN) | (1 << STAR2_PIN) | (1 << STAR3_PIN);
 
348
        PORTB = (1 << SWITCH_PIN) | (1 << STAR3_PIN);
243
349
 
244
350
        // Set the switch as an interrupt for when we turn pin change interrupts on
245
351
        PCMSK = (1 << SWITCH_PIN);
246
352
        
247
353
    // Set PWM pin to output
248
 
    DDRB = (1 << PWM_PIN);
 
354
        #ifdef ALT_MODES
 
355
    DDRB = (1 << PWM_PIN) | (1 << ALT_PWM_PIN);
 
356
        #else
 
357
        DDRB = (1 << PWM_PIN);
 
358
        #endif
249
359
 
250
360
    // Set timer to do PWM for correct output pin and set prescaler timing
251
 
    TCCR0A = 0x23; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
 
361
    //TCCR0A = 0x23; // phase corrected PWM is 0x21 for PB1, fast-PWM is 0x23
252
362
    TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
253
363
        
254
364
        // Turn features on or off as needed
259
369
        #endif
260
370
        ACSR   |=  (1<<7); //AC off
261
371
        
262
 
        // Determine if we are going L-H, or H-L based on STAR 2
263
 
        if ((PINB & (1 << STAR2_PIN)) == 0) {
 
372
        // Determine if we are going L-H, or H-L based on Star 3
 
373
        if ((PINB & (1 << STAR3_PIN)) == 0) {
264
374
                // High to Low
265
375
                low_to_high = 0;
266
376
        } else {
278
388
                // will change the mode if needed.  If this loop detects that the mode has changed, run the
279
389
                // logic for that mode while continuing to check for a mode change.
280
390
                if (mode_idx != last_mode_idx) {
 
391
                        // The WDT changed the mode.
 
392
                        if (mode_idx > 0) {
 
393
                                // No need to change the mode if we are just turning the light off
 
394
                                // Check if the PWM mode is different
 
395
                                if (mode_pwm[last_mode_idx] != mode_pwm[mode_idx]) {
 
396
                                        #ifdef ALT_MODES
 
397
                                        TCCR0A = mode_pwm[mode_idx] | 0b10100000;  // Use both outputs
 
398
                                        #else
 
399
                                        TCCR0A = mode_pwm[mode_idx] | 0b00100000;  // Only use the normal output
 
400
                                        #endif
 
401
                                }
 
402
                        }
 
403
                        PWM_LVL     = modes[mode_idx];
 
404
                        #ifdef ALT_MODES
 
405
                        ALT_PWM_LVL = alt_modes[mode_idx];
 
406
                        #endif
281
407
                        last_mode_idx = mode_idx;
282
 
                        // The WDT changed the mode.
283
 
                        PWM_LVL = pgm_read_byte(&modes[mode_idx]);
284
 
                        if (PWM_LVL == 0) {
 
408
                        #ifdef ALT_MODES
 
409
                        if (modes[mode_idx] == 0 && alt_modes[mode_idx] == 0) {
 
410
                        #else
 
411
                        if (modes[mode_idx] == 0) {
 
412
                        #endif
285
413
                                _delay_ms(1); // Need this here, maybe instructions for PWM output not getting executed before shutdown?
286
414
                                // Go to sleep
287
415
                                sleep_until_switch_press();