aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--spaghetti-monster/anduril/anduril.c13
-rw-r--r--spaghetti-monster/baton/baton-simpler.c8
-rw-r--r--spaghetti-monster/baton/baton.c3
-rw-r--r--spaghetti-monster/darkhorse/darkhorse.c13
-rw-r--r--spaghetti-monster/fsm-events.c4
-rw-r--r--spaghetti-monster/fsm-main.c89
-rw-r--r--spaghetti-monster/fsm-misc.c2
-rw-r--r--spaghetti-monster/fsm-standby.h7
-rw-r--r--spaghetti-monster/fsm-states.c11
-rw-r--r--spaghetti-monster/fsm-states.h2
-rw-r--r--spaghetti-monster/momentary/momentary.c4
-rw-r--r--spaghetti-monster/ramping-ui/ramping-ui.c3
-rw-r--r--tk-attiny.h18
13 files changed, 91 insertions, 86 deletions
diff --git a/spaghetti-monster/anduril/anduril.c b/spaghetti-monster/anduril/anduril.c
index 998c0c5..c27ca68 100644
--- a/spaghetti-monster/anduril/anduril.c
+++ b/spaghetti-monster/anduril/anduril.c
@@ -114,9 +114,6 @@ uint8_t pseudo_rand();
// beacon timing
volatile uint8_t beacon_seconds = 2;
-// deferred "off" so we won't suspend in a weird state
-volatile uint8_t go_to_standby = 0;
-
uint8_t off_state(EventPtr event, uint16_t arg) {
// turn emitter off when entering state
@@ -452,8 +449,8 @@ uint8_t goodnight_state(EventPtr event, uint16_t arg) {
static uint16_t ticks_since_stepdown = 0;
// blink on start
if (event == EV_enter_state) {
- blink_confirm(4);
ticks_since_stepdown = 0;
+ blink_confirm(2);
set_level(GOODNIGHT_LEVEL);
return MISCHIEF_MANAGED;
}
@@ -871,14 +868,6 @@ void setup() {
void loop() {
- // deferred "off" so we won't suspend in a weird state
- // (like... during the middle of a strobe pulse)
- if (go_to_standby) {
- go_to_standby = 0;
- set_level(0);
- standby_mode();
- }
-
if (current_state == strobe_state) {
// party / tactical strobe
if (strobe_type < 2) {
diff --git a/spaghetti-monster/baton/baton-simpler.c b/spaghetti-monster/baton/baton-simpler.c
index a6ddf36..96b0ea7 100644
--- a/spaghetti-monster/baton/baton-simpler.c
+++ b/spaghetti-monster/baton/baton-simpler.c
@@ -36,9 +36,6 @@ uint8_t actual_level = 0;
uint8_t target_level = 0;
#endif
-// deferred "off" so we won't suspend in a weird state
-volatile uint8_t go_to_standby = 0;
-
// moon + ../../bin/level_calc.py 2 6 7135 18 10 150 FET 1 10 1500
uint8_t pwm1_levels[] = { 3, 18, 110, 255, 255, 255, 0, };
uint8_t pwm2_levels[] = { 0, 0, 0, 9, 58, 138, 255, };
@@ -194,9 +191,4 @@ void setup() {
}
void loop() {
- if (go_to_standby) {
- go_to_standby = 0;
- PWM1_LVL = 0; PWM2_LVL = 0;
- standby_mode();
- }
}
diff --git a/spaghetti-monster/baton/baton.c b/spaghetti-monster/baton/baton.c
index 515f2d0..1266ddd 100644
--- a/spaghetti-monster/baton/baton.c
+++ b/spaghetti-monster/baton/baton.c
@@ -56,8 +56,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) {
PWM1_LVL = 0;
PWM2_LVL = 0;
// sleep while off (lower power use)
- //empty_event_sequence(); // just in case (but shouldn't be needed)
- standby_mode();
+ go_to_standby = 1;
return 0;
}
// hold (initially): go to lowest level, but allow abort for regular click
diff --git a/spaghetti-monster/darkhorse/darkhorse.c b/spaghetti-monster/darkhorse/darkhorse.c
index 2aa3e90..97053b5 100644
--- a/spaghetti-monster/darkhorse/darkhorse.c
+++ b/spaghetti-monster/darkhorse/darkhorse.c
@@ -55,7 +55,7 @@ uint8_t L2 = 1;
uint8_t M2 = 1;
uint8_t H2 = 1;
// mode groups, ish
-uint8_t low_modes[] = {12, 1, 4, 9}; // 3.3 lm, 2.0 lm, 0.8 lm, 0.3 lm
+uint8_t low_modes[] = {12, 3, 5, 9}; // 3.3 lm, 2.0 lm, 0.8 lm, 0.3 lm
uint8_t med_modes[] = {56, 21, 29, 37}; // 101 lm, 35 lm, 20 lm, 10 lm
uint8_t hi_modes[] = {MAX_LEVEL, 81, 96, 113}; // 1500 lm, 678 lm, 430 lm, 270 lm
// strobe/beacon modes:
@@ -65,9 +65,6 @@ uint8_t hi_modes[] = {MAX_LEVEL, 81, 96, 113}; // 1500 lm, 678 lm, 430 lm, 270
// 3: 19 Hz strobe at H1
uint8_t strobe_beacon_mode = 0;
-// deferred "off" so we won't suspend in a weird state
-volatile uint8_t go_to_standby = 0;
-
#ifdef USE_THERMAL_REGULATION
// brightness before thermal step-down
uint8_t target_level = 0;
@@ -337,14 +334,6 @@ void setup() {
}
void loop() {
- // deferred "off" so we won't suspend in a weird state
- // (like... during the middle of a strobe pulse)
- if (go_to_standby) {
- go_to_standby = 0;
- set_level(0);
- standby_mode();
- }
-
if (current_state == strobe_beacon_state) {
switch(strobe_beacon_mode) {
// 0.2 Hz beacon at L1
diff --git a/spaghetti-monster/fsm-events.c b/spaghetti-monster/fsm-events.c
index 99a6a72..5448feb 100644
--- a/spaghetti-monster/fsm-events.c
+++ b/spaghetti-monster/fsm-events.c
@@ -170,8 +170,4 @@ void emit_current_event(uint16_t arg) {
//return err;
}
-// TODO? add events to a queue when inside an interrupt
-// instead of calling the event functions directly?
-// (then empty the queue in main loop?)
-
#endif
diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c
index 9505322..d526455 100644
--- a/spaghetti-monster/fsm-main.c
+++ b/spaghetti-monster/fsm-main.c
@@ -22,6 +22,20 @@
#include "fsm-main.h"
+#if PWM_CHANNELS == 4
+// 4th PWM channel requires manually turning the pin on/off via interrupt :(
+ISR(TIMER1_OVF_vect) {
+ //bitClear(PORTB, 3);
+ PORTB &= 0b11110111;
+ //PORTB |= 0b00001000;
+}
+ISR(TIMER1_COMPA_vect) {
+ //if (!bitRead(TIFR,TOV1)) bitSet(PORTB, 3);
+ if (! (TIFR & (1<<TOV1))) PORTB |= 0b00001000;
+ //if (! (TIFR & (1<<TOV1))) PORTB &= 0b11110111;
+}
+#endif
+
int main() {
// Don't allow interrupts while booting
cli();
@@ -29,49 +43,39 @@ int main() {
//PCINT_off();
// configure PWM channels
- #if PWM_CHANNELS == 1
+ #if PWM_CHANNELS >= 1
DDRB |= (1 << PWM1_PIN);
TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
TCCR0A = PHASE;
- #elif PWM_CHANNELS == 2
- DDRB |= (1 << PWM1_PIN);
- DDRB |= (1 << PWM2_PIN);
- TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
- TCCR0A = PHASE;
- #elif PWM_CHANNELS == 3
- DDRB |= (1 << PWM1_PIN);
- DDRB |= (1 << PWM2_PIN);
- TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
- TCCR0A = PHASE;
- // Second PWM counter is ... weird
- DDRB |= (1 << PWM3_PIN);
- TCCR1 = _BV (CS10);
- GTCCR = _BV (COM1B1) | _BV (PWM1B);
- OCR1C = 255; // Set ceiling value to maximum
- #elif PWM_CHANNELS == 4
- DDRB |= (1 << PWM1_PIN);
+ #endif
+ #if PWM_CHANNELS >= 2
DDRB |= (1 << PWM2_PIN);
- TCCR0B = 0x01; // pre-scaler for timer (1 => 1, 2 => 8, 3 => 64...)
- TCCR0A = PHASE;
+ #endif
+ #if PWM_CHANNELS >= 3
// Second PWM counter is ... weird
DDRB |= (1 << PWM3_PIN);
- // FIXME: How exactly do we do PWM on channel 4?
TCCR1 = _BV (CS10);
GTCCR = _BV (COM1B1) | _BV (PWM1B);
OCR1C = 255; // Set ceiling value to maximum
+ #endif
+ #if PWM_CHANNELS >= 4
+ // 4th PWM channel is ... not actually supported in hardware :(
DDRB |= (1 << PWM4_PIN);
+ //OCR1C = 255; // Set ceiling value to maximum
+ TCCR1 = 1<<CTC1 | 1<<PWM1A | 3<<COM1A0 | 2<<CS10;
+ GTCCR = (2<<COM1B0) | (1<<PWM1B);
+ // set up an interrupt to control PWM4 pin
+ TIMSK |= (1<<OCIE1A) | (1<<TOIE1);
#endif
- // TODO: turn on ADC?
// configure e-switch
PORTB = (1 << SWITCH_PIN); // e-switch is the only input
PCMSK = (1 << SWITCH_PIN); // pin change interrupt uses this pin
- // TODO: configure sleep mode
+ // configure sleep mode
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
// Read config values and saved state
- // restore_state(); // TODO
// TODO: handle long press vs short press (or even medium press)?
@@ -85,9 +89,6 @@ int main() {
ADC_on();
sei();
- // fallback for handling a few things
- push_state(default_state, 0);
-
// in case any spurious button presses were detected at boot
#ifdef USE_DELAY_MS
delay_ms(1);
@@ -96,17 +97,43 @@ int main() {
#endif
empty_event_sequence();
+ // fallback for handling a few things
+ #ifndef DONT_USE_DEFAULT_STATE
+ push_state(default_state, 0);
+ #endif
+
// call recipe's setup
setup();
// main loop
while (1) {
- // TODO: update e-switch press state?
- // TODO: check voltage?
- // TODO: check temperature?
- // if event queue not empty, process and pop first item in queue?
+ // if event queue not empty, empty it
process_emissions();
+ // enter standby mode if requested
+ // (works better if deferred like this)
+ if (go_to_standby) {
+ go_to_standby = 0;
+ #ifdef USE_RAMPING
+ set_level(0);
+ #else
+ #if PWM_CHANNELS >= 1
+ PWM1_LVL = 0;
+ #endif
+ #if PWM_CHANNELS >= 2
+ PWM2_LVL = 0;
+ #endif
+ #if PWM_CHANNELS >= 3
+ PWM3_LVL = 0;
+ #endif
+ #if PWM_CHANNELS >= 4
+ PWM4_LVL = 255; // inverted :(
+ #endif
+ #endif
+ standby_mode();
+ }
+
+ // give the recipe some time slices
loop();
}
}
diff --git a/spaghetti-monster/fsm-misc.c b/spaghetti-monster/fsm-misc.c
index 7322a59..5d28002 100644
--- a/spaghetti-monster/fsm-misc.c
+++ b/spaghetti-monster/fsm-misc.c
@@ -30,7 +30,7 @@ uint8_t blink_digit(uint8_t num) {
for (; num>0; num--) {
set_level(BLINK_BRIGHTNESS);
- if (! nice_delay_ms(ontime)) { set_level(0); return 0; }
+ if (! nice_delay_ms(ontime)) { return 0; }
set_level(0);
//if (current_state != old_state) return 0;
if (! nice_delay_ms(400)) return 0;
diff --git a/spaghetti-monster/fsm-standby.h b/spaghetti-monster/fsm-standby.h
index baeb6af..a23bd0c 100644
--- a/spaghetti-monster/fsm-standby.h
+++ b/spaghetti-monster/fsm-standby.h
@@ -20,7 +20,14 @@
#ifndef FSM_STANDBY_H
#define FSM_STANDBY_H
+// deferred "off" so we won't suspend in a weird state
+// (like... during the middle of a strobe pulse)
+// set this to nonzero to enter standby mode next time the system is idle
+volatile uint8_t go_to_standby = 0;
+
#define standby_mode sleep_until_eswitch_pressed
void sleep_until_eswitch_pressed();
+// TODO: half-sleep "twilight" mode with WDT on but running slowly
+
#endif
diff --git a/spaghetti-monster/fsm-states.c b/spaghetti-monster/fsm-states.c
index 2939475..09ae804 100644
--- a/spaghetti-monster/fsm-states.c
+++ b/spaghetti-monster/fsm-states.c
@@ -67,26 +67,28 @@ StatePtr pop_state() {
if (state_stack_len > 0) {
new_state = state_stack[state_stack_len-1];
}
- // FIXME: what should 'arg' be?
+ // FIXME: what should 'arg' be? (maybe re-entry should be entry with arg+1?)
_set_state(new_state, 0, EV_leave_state, EV_reenter_state);
return old_state;
}
uint8_t set_state(StatePtr new_state, uint16_t arg) {
// FIXME: this calls exit/enter hooks it shouldn't
+ // (for the layer underneath the top)
pop_state();
return push_state(new_state, arg);
}
+#ifndef DONT_USE_DEFAULT_STATE
// bottom state on stack
// handles default actions for LVP, thermal regulation, etc
uint8_t default_state(EventPtr event, uint16_t arg) {
- if (0) {}
+ if (0) {} // this should get compiled out
#ifdef USE_LVP
else if (event == EV_voltage_low) {
low_voltage();
- return 0;
+ return EVENT_HANDLED;
}
#endif
@@ -105,7 +107,8 @@ uint8_t default_state(EventPtr event, uint16_t arg) {
#endif
// event not handled
- return 1;
+ return EVENT_NOT_HANDLED;
}
+#endif
#endif
diff --git a/spaghetti-monster/fsm-states.h b/spaghetti-monster/fsm-states.h
index f92abba..6e4a2a0 100644
--- a/spaghetti-monster/fsm-states.h
+++ b/spaghetti-monster/fsm-states.h
@@ -40,6 +40,8 @@ void _set_state(StatePtr new_state, uint16_t arg,
int8_t push_state(StatePtr new_state, uint16_t arg);
StatePtr pop_state();
uint8_t set_state(StatePtr new_state, uint16_t arg);
+#ifndef DONT_USE_DEFAULT_STATE
uint8_t default_state(EventPtr event, uint16_t arg);
+#endif
#endif
diff --git a/spaghetti-monster/momentary/momentary.c b/spaghetti-monster/momentary/momentary.c
index 6b049f4..d4ac1db 100644
--- a/spaghetti-monster/momentary/momentary.c
+++ b/spaghetti-monster/momentary/momentary.c
@@ -52,7 +52,7 @@ uint8_t momentary_state(EventPtr event, uint16_t arg) {
else if (event == EV_release) {
light_off();
empty_event_sequence(); // don't attempt to parse multiple clicks
- standby_mode(); // sleep while light is off
+ go_to_standby = 1; // sleep while light is off
return 0;
}
@@ -68,7 +68,7 @@ void low_voltage() {
} else {
debug_blink(8);
light_off();
- standby_mode();
+ go_to_standby = 1;
}
}
diff --git a/spaghetti-monster/ramping-ui/ramping-ui.c b/spaghetti-monster/ramping-ui/ramping-ui.c
index 527a824..e6f571d 100644
--- a/spaghetti-monster/ramping-ui/ramping-ui.c
+++ b/spaghetti-monster/ramping-ui/ramping-ui.c
@@ -59,8 +59,7 @@ uint8_t off_state(EventPtr event, uint16_t arg) {
if (event == EV_enter_state) {
set_level(0);
// sleep while off (lower power use)
- //empty_event_sequence(); // just in case (but shouldn't be needed)
- standby_mode();
+ go_to_standby = 1;
return MISCHIEF_MANAGED;
}
// hold (initially): go to lowest level, but allow abort for regular click
diff --git a/tk-attiny.h b/tk-attiny.h
index 7939ccc..887a151 100644
--- a/tk-attiny.h
+++ b/tk-attiny.h
@@ -188,6 +188,7 @@
#define PWM2_PIN PB1 // pin 6, FET PWM
#define PWM2_LVL OCR0B // OCR0B is the output compare register for PB1
+// (FIXME: remove? not used?)
#define VOLTAGE_PIN PB2 // pin 7, voltage ADC
#define ADC_CHANNEL 0x01 // MUX 01 corresponds with PB2
#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2
@@ -208,7 +209,7 @@
* ----
* Reset -|1 8|- VCC
* PWM 4 (A) -|2 7|- e-switch
- * PWM 3 (B) -|3 6|- PWM 2 (G)
+ * PWM 3 (G) -|3 6|- PWM 2 (B)
* GND -|4 5|- PWM 1 (R)
* ----
*/
@@ -221,17 +222,18 @@
#define PWM3_PIN PB4 // pin 3
#define PWM3_LVL OCR1B
#define PWM4_PIN PB3 // pin 2
-#define PWM4_LVL OCR1A // FIXME: does this work?
+#define PWM4_LVL OCR1A
-#define SWITCH_PIN PB2 // pin 7
+#define SWITCH_PIN PB2 // pin 7
#define SWITCH_PCINT PCINT2 // pin 7 pin change interrupt
-#define ADC_PRSCL 0x07 // clk/128 (no need to be super fast)
-// FIXME: What is the DIDR for pin 8?
-//#define ADC_DIDR ADC1D // Digital input disable bit corresponding with PB2
+#define ADC_PRSCL 0x06 // clk/64 (no need to be super fast)
-#define FAST 0xA3 // fast PWM both channels
-#define PHASE 0xA1 // phase-correct PWM both channels
+//#define TEMP_DIDR ADC4D
+#define TEMP_CHANNEL 0b00001111
+
+#define FAST 0xA3 // fast PWM both channels
+#define PHASE 0xA1 // phase-correct PWM both channels
#endif // TKSABER_DRIVER