aboutsummaryrefslogtreecommitdiff
path: root/spaghetti-monster
diff options
context:
space:
mode:
authorSelene ToyKeeper2017-09-03 14:58:22 -0600
committerSelene ToyKeeper2017-09-03 14:58:22 -0600
commita419850e536f00549120255a627137faffded47a (patch)
tree60976f561f189d6e5e08a581bdc3824f163f65be /spaghetti-monster
parentAdded UI2. UI2 is weird. (diff)
downloadanduril-a419850e536f00549120255a627137faffded47a.tar.gz
anduril-a419850e536f00549120255a627137faffded47a.tar.bz2
anduril-a419850e536f00549120255a627137faffded47a.zip
Got the 4th PWM channel to work, ish. (channel 4 is inverted though)
Moved go_to_suspend thing into main() instead of making each UI handle that during loop(). Made default_state() optional. Fixed bug where battcheck and other number readouts could interfere with the state which interrupted them. (they would sometimes turn the LED off after the new state had already started) Updated darkhorse's moon levels to match new ramp on D4 hardware.
Diffstat (limited to 'spaghetti-monster')
-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
12 files changed, 81 insertions, 78 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