1
/* STAR_momentary version 1.4
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
17
* Star 4 -| |- Voltage ADC
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)
27
* For more details on these settings, visit http://github.com/JCapSolutions/blf-firmware/wiki/PWM-Frequency
31
* Star 3 = H-L if connected, L-H if not
32
* Star 4 = Switch input
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
40
* Vd (~.25 v drop from protection diode)
42
* 1912 (R1 19,100 ohms)
46
* 4701 (R2 4,700 ohms)
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 )
54
* Well 125 and 121 were too close, so it shut off right after lowering to low mode, so I went with
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)
1
61
#define F_CPU 4800000UL
64
#define PHASE 0b00000001
65
#define FAST 0b00000011
4
68
* =========================================================================
5
69
* Settings to modify per driver
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)
86
#define MOM_ENTER_DUR 128 // .16ms each. Comment out to disable this feature
87
#define MOM_EXIT_DUR 128 // .16ms each
89
#define MOM_MODE_IDX 4 // The index of the mode to use in MODES above, starting at index of 0
21
92
* =========================================================================
30
101
#include <avr/sleep.h>
31
102
//#include <avr/power.h>
33
#define STAR2_PIN PB0 // If not connected, will cycle L-H. Connected, H-L
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
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
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
47
119
// Switch handling
48
120
#define LONG_PRESS_DUR 32 // How many WDT ticks until we consider a press a long press
121
// 32 is roughly .5 s
52
124
* The actual program
57
129
* global variables
59
PROGMEM const uint8_t modes[] = { MODES };
131
const uint8_t modes[] = { MODES };
133
const uint8_t alt_modes[] = { ALT_MODES };
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;
64
141
// Debounced switch press value
240
346
// Set all ports to input, and turn pull-up resistors on for the inputs we are using
242
PORTB = (1 << SWITCH_PIN) | (1 << STAR2_PIN) | (1 << STAR3_PIN);
348
PORTB = (1 << SWITCH_PIN) | (1 << STAR3_PIN);
244
350
// Set the switch as an interrupt for when we turn pin change interrupts on
245
351
PCMSK = (1 << SWITCH_PIN);
247
353
// Set PWM pin to output
248
DDRB = (1 << PWM_PIN);
355
DDRB = (1 << PWM_PIN) | (1 << ALT_PWM_PIN);
357
DDRB = (1 << PWM_PIN);
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...)
254
364
// Turn features on or off as needed
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.
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]) {
397
TCCR0A = mode_pwm[mode_idx] | 0b10100000; // Use both outputs
399
TCCR0A = mode_pwm[mode_idx] | 0b00100000; // Only use the normal output
403
PWM_LVL = modes[mode_idx];
405
ALT_PWM_LVL = alt_modes[mode_idx];
281
407
last_mode_idx = mode_idx;
282
// The WDT changed the mode.
283
PWM_LVL = pgm_read_byte(&modes[mode_idx]);
409
if (modes[mode_idx] == 0 && alt_modes[mode_idx] == 0) {
411
if (modes[mode_idx] == 0) {
285
413
_delay_ms(1); // Need this here, maybe instructions for PWM output not getting executed before shutdown?
287
415
sleep_until_switch_press();