From 8d2f442317fd3678213a14307f95d2f5b54c5623 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Sat, 19 Aug 2017 12:17:58 -0600
Subject: Renamed from RoundTable to SpaghettiMonster (FSM).
---
spaghetti-monster/spaghetti-monster.h | 737 ++++++++++++++++++++++++++++++++++
1 file changed, 737 insertions(+)
create mode 100644 spaghetti-monster/spaghetti-monster.h
(limited to 'spaghetti-monster/spaghetti-monster.h')
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
new file mode 100644
index 0000000..af6d828
--- /dev/null
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -0,0 +1,737 @@
+/*
+ * SpaghettiMonster: Generic foundation code for e-switch flashlights.
+ * Other possible names:
+ * - FSM
+ * - RoundTable
+ * - Mostly Harmless
+ * - ...
+ *
+ * Copyright (C) 2017 Selene ToyKeeper
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "tk-attiny.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// typedefs
+typedef PROGMEM const uint8_t Event;
+typedef Event * EventPtr;
+typedef uint8_t (*EventCallbackPtr)(EventPtr event, uint16_t arg);
+typedef uint8_t EventCallback(EventPtr event, uint16_t arg);
+typedef uint8_t State(EventPtr event, uint16_t arg);
+typedef State * StatePtr;
+typedef struct Emission {
+ EventPtr event;
+ uint16_t arg;
+} Emission;
+
+volatile StatePtr current_state;
+#define EV_MAX_LEN 16
+uint8_t current_event[EV_MAX_LEN];
+// at 0.016 ms per tick, 255 ticks = 4.08 s
+// TODO: 16 bits?
+static volatile uint8_t ticks_since_last_event = 0;
+
+#ifdef USE_LVP
+// volts * 10
+#define VOLTAGE_LOW 30
+// MCU sees voltage 0.X volts lower than actual, add X to readings
+#define VOLTAGE_FUDGE_FACTOR 2
+volatile uint8_t voltage;
+void low_voltage();
+#endif
+#ifdef USE_THERMAL_REGULATION
+volatile int16_t temperature;
+void low_temperature();
+void high_temperature();
+#endif
+
+#ifdef USE_DEBUG_BLINK
+#define OWN_DELAY
+#define USE_DELAY_4MS
+#include "tk-delay.h"
+#define DEBUG_FLASH PWM1_LVL = 64; delay_4ms(2); PWM1_LVL = 0;
+void debug_blink(uint8_t num) {
+ for(; num>0; num--) {
+ PWM1_LVL = 32;
+ delay_4ms(100/4);
+ PWM1_LVL = 0;
+ delay_4ms(100/4);
+ }
+}
+#endif
+
+#define A_ENTER_STATE 1
+#define A_LEAVE_STATE 2
+#define A_TICK 3
+#define A_PRESS 4
+#define A_HOLD_START 5
+#define A_HOLD_TICK 6
+#define A_RELEASE 7
+#define A_RELEASE_TIMEOUT 8
+// TODO: add events for over/under-heat conditions (with parameter for severity)
+#define A_OVERHEATING 9
+#define A_UNDERHEATING 10
+// TODO: add events for low voltage conditions
+#define A_VOLTAGE_LOW 11
+//#define A_VOLTAGE_CRITICAL 12
+#define A_DEBUG 255 // test event for debugging
+
+// TODO: maybe compare events by number instead of pointer?
+// (number = index in event types array)
+// (comparison would use full event content, but send off index to callbacks)
+// (saves space by using uint8_t instead of a pointer)
+// (also eliminates the need to duplicate single-entry events like for voltage or timer tick)
+
+// Event types
+Event EV_debug[] = {
+ A_DEBUG,
+ 0 } ;
+Event EV_enter_state[] = {
+ A_ENTER_STATE,
+ 0 } ;
+Event EV_leave_state[] = {
+ A_LEAVE_STATE,
+ 0 } ;
+Event EV_tick[] = {
+ A_TICK,
+ 0 } ;
+#ifdef USE_LVP
+Event EV_voltage_low[] = {
+ A_VOLTAGE_LOW,
+ 0 } ;
+#endif
+#ifdef USE_THERMAL_REGULATION
+Event EV_temperature_high[] = {
+ A_OVERHEATING,
+ 0 } ;
+Event EV_temperature_low[] = {
+ A_UNDERHEATING,
+ 0 } ;
+#endif
+Event EV_click1_press[] = {
+ A_PRESS,
+ 0 };
+// shouldn't normally happen, but UI might reset event while button is down
+// so a release with no recorded prior hold could be possible
+Event EV_release[] = {
+ A_RELEASE,
+ 0 };
+Event EV_click1_release[] = {
+ A_PRESS,
+ A_RELEASE,
+ 0 };
+#define EV_1click EV_click1_complete
+Event EV_click1_complete[] = {
+ A_PRESS,
+ A_RELEASE,
+ A_RELEASE_TIMEOUT,
+ 0 };
+#define EV_hold EV_click1_hold
+// FIXME: Should holds use "start+tick" or just "tick" with a tick number?
+// Or "start+tick" with a tick number?
+Event EV_click1_hold[] = {
+ A_PRESS,
+ A_HOLD_START,
+ 0 };
+Event EV_click1_hold_release[] = {
+ A_PRESS,
+ A_HOLD_START,
+ A_RELEASE,
+ 0 };
+Event EV_click2_press[] = {
+ A_PRESS,
+ A_RELEASE,
+ A_PRESS,
+ 0 };
+Event EV_click2_release[] = {
+ A_PRESS,
+ A_RELEASE,
+ A_PRESS,
+ A_RELEASE,
+ 0 };
+#define EV_2clicks EV_click2_complete
+Event EV_click2_complete[] = {
+ A_PRESS,
+ A_RELEASE,
+ A_PRESS,
+ A_RELEASE,
+ A_RELEASE_TIMEOUT,
+ 0 };
+Event EV_click3_press[] = {
+ A_PRESS,
+ A_RELEASE,
+ A_PRESS,
+ A_RELEASE,
+ A_PRESS,
+ 0 };
+Event EV_click3_release[] = {
+ A_PRESS,
+ A_RELEASE,
+ A_PRESS,
+ A_RELEASE,
+ A_PRESS,
+ A_RELEASE,
+ 0 };
+#define EV_3clicks EV_click3_complete
+Event EV_click3_complete[] = {
+ A_PRESS,
+ A_RELEASE,
+ A_PRESS,
+ A_RELEASE,
+ A_PRESS,
+ A_RELEASE,
+ A_RELEASE_TIMEOUT,
+ 0 };
+// ... and so on
+
+// A list of event types for easy iteration
+EventPtr event_sequences[] = {
+ EV_click1_press,
+ EV_release,
+ EV_click1_release,
+ EV_click1_complete,
+ EV_click1_hold,
+ EV_click1_hold_release,
+ EV_click2_press,
+ EV_click2_release,
+ EV_click2_complete,
+ EV_click3_press,
+ EV_click3_release,
+ EV_click3_complete,
+ // ...
+};
+
+#define events_match(a,b) compare_event_sequences(a,b)
+// return 1 if (a == b), 0 otherwise
+uint8_t compare_event_sequences(uint8_t *a, const uint8_t *b) {
+ for(uint8_t i=0; (i=0; i--) {
+ uint8_t err = state_stack[i](event, arg);
+ if (! err) return 0;
+ }
+ return 1; // event not handled
+}
+
+void emit(EventPtr event, uint16_t arg) {
+ // add this event to the queue for later,
+ // so we won't use too much time during an interrupt
+ append_emission(event, arg);
+}
+
+// Search the pre-defined event list for one matching what the user just did,
+// and emit it if one was found.
+void emit_current_event(uint16_t arg) {
+ //uint8_t err = 1;
+ for (uint8_t i=0; i<(sizeof(event_sequences)/sizeof(EventPtr)); i++) {
+ if (events_match(current_event, event_sequences[i])) {
+ //DEBUG_FLASH;
+ //err = emit(event_sequences[i], arg);
+ //return err;
+ emit(event_sequences[i], arg);
+ return;
+ }
+ }
+ //return err;
+}
+
+void _set_state(StatePtr new_state) {
+ // call old state-exit hook (don't use stack)
+ if (current_state != NULL) current_state(EV_leave_state, 0);
+ // set new state
+ current_state = new_state;
+ // call new state-enter hook (don't use stack)
+ if (new_state != NULL) current_state(EV_enter_state, 0);
+}
+
+int8_t push_state(StatePtr new_state) {
+ if (state_stack_len < STATE_STACK_SIZE) {
+ // TODO: call old state's exit hook?
+ // new hook for non-exit recursion into child?
+ state_stack[state_stack_len] = new_state;
+ state_stack_len ++;
+ _set_state(new_state);
+ return state_stack_len;
+ } else {
+ // TODO: um... how is a flashlight supposed to handle a recursion depth error?
+ return -1;
+ }
+}
+
+StatePtr pop_state() {
+ // TODO: how to handle pop from empty stack?
+ StatePtr old_state = NULL;
+ StatePtr new_state = NULL;
+ if (state_stack_len > 0) {
+ state_stack_len --;
+ old_state = state_stack[state_stack_len];
+ }
+ if (state_stack_len > 0) {
+ new_state = state_stack[state_stack_len-1];
+ }
+ _set_state(new_state);
+ return old_state;
+}
+
+uint8_t set_state(StatePtr new_state) {
+ // FIXME: this calls exit/enter hooks it shouldn't
+ pop_state();
+ return push_state(new_state);
+}
+
+// TODO? add events to a queue when inside an interrupt
+// instead of calling the event functions directly?
+// (then empty the queue in main loop?)
+
+// TODO? new delay() functions which handle queue consumption?
+// TODO? new interruptible delay() functions?
+
+
+//static volatile uint8_t button_was_pressed;
+#define BP_SAMPLES 16
+uint8_t button_is_pressed() {
+ // debounce a little
+ uint8_t highcount = 0;
+ // measure for 16/64ths of a ms
+ for(uint8_t i=0; i (BP_SAMPLES/2));
+ //button_was_pressed = result;
+ return result;
+}
+
+//void button_change_interrupt() {
+ISR(PCINT0_vect) {
+
+ //DEBUG_FLASH;
+
+ // something happened
+ //ticks_since_last_event = 0;
+
+ // add event to current sequence
+ if (button_is_pressed()) {
+ push_event(A_PRESS);
+ } else {
+ push_event(A_RELEASE);
+ }
+
+ // check if sequence matches any defined sequences
+ // if so, send event to current state callback
+ emit_current_event(0);
+}
+
+// TODO: implement
+ISR(WDT_vect) {
+ /*
+ // TODO? safety net for PCINT, in case it misses a press or release
+ uint8_t bp = button_is_pressed();
+ if (bp != button_was_pressed) {
+ // TODO: handle missed button event
+ if (bp) {
+ push_event(A_PRESS);
+ } else {
+ push_event(A_RELEASE);
+ }
+ emit_current_event(0);
+ }
+ */
+
+ //timer ++; // Is this needed at all?
+
+ /*
+ if (ticks_since_last_event & 0b00000111 ) {
+ DEBUG_FLASH;
+ }
+ */
+
+ //if (ticks_since_last_event < 0xff) ticks_since_last_event ++;
+ // increment, but loop from 255 back to 128
+ ticks_since_last_event = (ticks_since_last_event + 1) \
+ | (ticks_since_last_event & 0x80);
+
+ //static uint8_t hold_ticks = 0; // TODO: 16 bits?
+
+ // callback on each timer tick
+ emit(EV_tick, ticks_since_last_event);
+
+ // if time since last event exceeds timeout,
+ // append timeout to current event sequence, then
+ // send event to current state callback
+ // //hold_event(ticks)
+ // //emit(EV_press_hold, hold_ticks);
+ // emit_current_event(hold_ticks);
+ // or
+ // //release_timeout()
+ // //emit(EV_press_release_timeout, 0);
+ // emit_current_event(0);
+
+ #if defined(USE_LVP) || defined(USE_THERMAL_REGULATION)
+ // start a new ADC measurement every 4 ticks
+ static uint8_t adc_trigger = 0;
+ adc_trigger ++;
+ if (adc_trigger > 3) {
+ adc_trigger = 0;
+ ADCSRA |= (1 << ADSC) | (1 << ADIE);
+ }
+ #endif
+}
+
+// TODO: implement? (or is it better done in main()?)
+ISR(ADC_vect) {
+ static uint8_t adc_step = 0;
+ #ifdef USE_LVP
+ #ifdef USE_LVP_AVG
+ #define NUM_VOLTAGE_VALUES 4
+ static int16_t voltage_values[NUM_VOLTAGE_VALUES];
+ #endif
+ static uint8_t lvp_timer = 0;
+ static uint8_t lvp_lowpass = 0;
+ #define LVP_TIMER_START 50 // ticks between LVP warnings
+ #define LVP_LOWPASS_STRENGTH 4
+ #endif
+
+ #ifdef USE_THERMAL_REGULATION
+ #define NUM_THERMAL_VALUES 4
+ #define ADC_STEPS 4
+ static int16_t temperature_values[NUM_THERMAL_VALUES];
+ #else
+ #define ADC_STEPS 2
+ #endif
+
+ uint16_t measurement = ADC; // latest 10-bit ADC reading
+
+ adc_step = (adc_step + 1) & (ADC_STEPS-1);
+
+ #ifdef USE_LVP
+ // voltage
+ if (adc_step == 1) {
+ #ifdef USE_LVP_AVG
+ // prime on first execution
+ if (voltage == 0) {
+ for(uint8_t i=0; i> 2;
+
+ voltage = (uint16_t)(1.1*1024*10)/total + VOLTAGE_FUDGE_FACTOR;
+ }
+ #else // no USE_LVP_AVG
+ // calculate actual voltage: volts * 10
+ // ADC = 1.1 * 1024 / volts
+ // volts = 1.1 * 1024 / ADC
+ voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR;
+ #endif
+ // if low, callback EV_voltage_low / EV_voltage_critical
+ // (but only if it has been more than N ticks since last call)
+ if (lvp_timer) {
+ lvp_timer --;
+ } else { // it has been long enough since the last warning
+ if (voltage < VOLTAGE_LOW) {
+ if (lvp_lowpass < LVP_LOWPASS_STRENGTH) {
+ lvp_lowpass ++;
+ } else {
+ // try to send out a warning
+ //uint8_t err = emit(EV_voltage_low, 0);
+ //uint8_t err = emit_now(EV_voltage_low, 0);
+ emit(EV_voltage_low, 0);
+ //if (!err) {
+ // on successful warning, reset counters
+ lvp_timer = LVP_TIMER_START;
+ lvp_lowpass = 0;
+ //}
+ }
+ } else {
+ // voltage not low? reset count
+ lvp_lowpass = 0;
+ }
+ }
+ }
+ #endif // ifdef USE_LVP
+
+ // TODO: temperature
+
+ // start another measurement for next time
+ #ifdef USE_THERMAL_REGULATION
+ #ifdef USE_LVP
+ if (adc_step < 2) ADMUX = ADMUX_VCC;
+ else ADMUX = ADMUX_THERM;
+ #else
+ ADMUX = ADMUX_THERM;
+ #endif
+ #else
+ #ifdef USE_LVP
+ ADMUX = ADMUX_VCC;
+ #endif
+ #endif
+}
+
+inline void ADC_on()
+{
+ // read voltage on VCC by default
+ // disable digital input on VCC pin to reduce power consumption
+ //DIDR0 |= (1 << ADC_DIDR); // FIXME: unsure how to handle for VCC pin
+ // VCC / 1.1V reference
+ ADMUX = ADMUX_VCC;
+ // enable, start, prescale
+ ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL;
+}
+
+inline void ADC_off() {
+ ADCSRA &= ~(1<= 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 << PWM2_PIN);
+ #elif PWM_CHANNELS >= 3
+ DDRB |= (1 << PWM3_PIN);
+ // Second PWM counter is ... weird
+ TCCR1 = _BV (CS10);
+ GTCCR = _BV (COM1B1) | _BV (PWM1B);
+ OCR1C = 255; // Set ceiling value to maximum
+ #elif PWM_CHANNELS == 4
+ // FIXME: How exactly do we do PWM on channel 4?
+ DDRB |= (1 << PWM4_PIN);
+ #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
+ 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)?
+
+ #ifdef USE_DEBUG_BLINK
+ //debug_blink(1);
+ #endif
+
+ // all booted -- turn interrupts back on
+ PCINT_on();
+ WDT_on();
+ ADC_on();
+ sei();
+
+ // fallback for handling a few things
+ push_state(default_state);
+
+ // 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 (emissions[0].event != NULL) {
+ emit_now(emissions[0].event, emissions[0].arg);
+ delete_first_emission();
+ }
+ }
+}
--
cgit v1.2.3
From 65167c016935885552035bf983f4a5b739048f61 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Sat, 19 Aug 2017 14:56:39 -0600
Subject: Added unfinished UI similar to Olight Baton series. Fixed 2nd PWM
channel init. May have fixed 3rd and 4th too. Added handling for complete
normal clicks, but it's kind of flaky so far. Added handling for sustained
button holds. Added missing 'arg' to state change functions.
---
spaghetti-monster/spaghetti-monster.h | 162 +++++++++++++++++++++-------------
1 file changed, 103 insertions(+), 59 deletions(-)
(limited to 'spaghetti-monster/spaghetti-monster.h')
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
index af6d828..e51416a 100644
--- a/spaghetti-monster/spaghetti-monster.h
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -49,7 +49,7 @@ volatile StatePtr current_state;
uint8_t current_event[EV_MAX_LEN];
// at 0.016 ms per tick, 255 ticks = 4.08 s
// TODO: 16 bits?
-static volatile uint8_t ticks_since_last_event = 0;
+static volatile uint16_t ticks_since_last_event = 0;
#ifdef USE_LVP
// volts * 10
@@ -80,20 +80,23 @@ void debug_blink(uint8_t num) {
}
#endif
+// timeout durations in ticks (each tick 1/60th s)
+#define HOLD_TIMEOUT 24
+#define RELEASE_TIMEOUT 24
+
#define A_ENTER_STATE 1
#define A_LEAVE_STATE 2
#define A_TICK 3
#define A_PRESS 4
-#define A_HOLD_START 5
-#define A_HOLD_TICK 6
-#define A_RELEASE 7
-#define A_RELEASE_TIMEOUT 8
+#define A_HOLD 5
+#define A_RELEASE 6
+#define A_RELEASE_TIMEOUT 7
// TODO: add events for over/under-heat conditions (with parameter for severity)
-#define A_OVERHEATING 9
-#define A_UNDERHEATING 10
+#define A_OVERHEATING 8
+#define A_UNDERHEATING 9
// TODO: add events for low voltage conditions
-#define A_VOLTAGE_LOW 11
-//#define A_VOLTAGE_CRITICAL 12
+#define A_VOLTAGE_LOW 10
+//#define A_VOLTAGE_CRITICAL 11
#define A_DEBUG 255 // test event for debugging
// TODO: maybe compare events by number instead of pointer?
@@ -151,11 +154,11 @@ Event EV_click1_complete[] = {
// Or "start+tick" with a tick number?
Event EV_click1_hold[] = {
A_PRESS,
- A_HOLD_START,
+ A_HOLD,
0 };
Event EV_click1_hold_release[] = {
A_PRESS,
- A_HOLD_START,
+ A_HOLD,
A_RELEASE,
0 };
Event EV_click2_press[] = {
@@ -248,7 +251,25 @@ void push_event(uint8_t ev_type) {
}
}
-#define EMISSION_QUEUE_LEN 8
+// find and return last action in the current event sequence
+/*
+uint8_t last_event(uint8_t offset) {
+ uint8_t i;
+ for(i=0; current_event[i] && (i= offset) return current_event[i-offset];
+ return 0;
+}
+*/
+
+inline uint8_t last_event_num() {
+ uint8_t i;
+ for(i=0; current_event[i] && (i 0) {
new_state = state_stack[state_stack_len-1];
}
- _set_state(new_state);
+ // FIXME: what should 'arg' be?
+ // FIXME: do we need a EV_reenter_state?
+ _set_state(new_state, 0);
return old_state;
}
-uint8_t set_state(StatePtr new_state) {
+uint8_t set_state(StatePtr new_state, uint16_t arg) {
// FIXME: this calls exit/enter hooks it shouldn't
pop_state();
- return push_state(new_state);
+ return push_state(new_state, arg);
}
// TODO? add events to a queue when inside an interrupt
@@ -412,36 +435,12 @@ ISR(PCINT0_vect) {
emit_current_event(0);
}
-// TODO: implement
+// clock tick -- this runs every 16ms (62.5 fps)
ISR(WDT_vect) {
- /*
- // TODO? safety net for PCINT, in case it misses a press or release
- uint8_t bp = button_is_pressed();
- if (bp != button_was_pressed) {
- // TODO: handle missed button event
- if (bp) {
- push_event(A_PRESS);
- } else {
- push_event(A_RELEASE);
- }
- emit_current_event(0);
- }
- */
-
- //timer ++; // Is this needed at all?
-
- /*
- if (ticks_since_last_event & 0b00000111 ) {
- DEBUG_FLASH;
- }
- */
-
//if (ticks_since_last_event < 0xff) ticks_since_last_event ++;
- // increment, but loop from 255 back to 128
+ // increment, but loop from max back to half
ticks_since_last_event = (ticks_since_last_event + 1) \
- | (ticks_since_last_event & 0x80);
-
- //static uint8_t hold_ticks = 0; // TODO: 16 bits?
+ | (ticks_since_last_event & 0x8000);
// callback on each timer tick
emit(EV_tick, ticks_since_last_event);
@@ -449,13 +448,42 @@ ISR(WDT_vect) {
// if time since last event exceeds timeout,
// append timeout to current event sequence, then
// send event to current state callback
- // //hold_event(ticks)
- // //emit(EV_press_hold, hold_ticks);
- // emit_current_event(hold_ticks);
- // or
- // //release_timeout()
- // //emit(EV_press_release_timeout, 0);
- // emit_current_event(0);
+
+ // preload recent events
+ uint8_t le_num = last_event_num();
+ uint8_t last_event = 0;
+ uint8_t prev_event = 0;
+ if (le_num >= 1) last_event = current_event[le_num-1];
+ if (le_num >= 2) prev_event = current_event[le_num-2];
+
+ // user held button long enough to count as a long click?
+ if (last_event == A_PRESS) {
+ if (ticks_since_last_event == HOLD_TIMEOUT) {
+ push_event(A_HOLD);
+ emit_current_event(0);
+ }
+ }
+
+ // user is still holding button, so tick
+ else if (last_event == A_HOLD) {
+ emit_current_event(ticks_since_last_event);
+ }
+
+ // detect completed button presses with expired timeout
+ else if (last_event == A_RELEASE) {
+ // no timeout required when releasing a long-press
+ // TODO? move this logic to PCINT() and simplify things here?
+ if (prev_event == A_HOLD) {
+ //emit_current_event(0); // should have been emitted by PCINT
+ empty_event_sequence();
+ }
+ // end and clear event after release timeout
+ else if (ticks_since_last_event == RELEASE_TIMEOUT) {
+ push_event(A_RELEASE_TIMEOUT);
+ emit_current_event(0);
+ empty_event_sequence();
+ }
+ }
#if defined(USE_LVP) || defined(USE_THERMAL_REGULATION)
// start a new ADC measurement every 4 ticks
@@ -677,20 +705,36 @@ 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 >= 2
+ #elif PWM_CHANNELS == 3
+ DDRB |= (1 << PWM1_PIN);
DDRB |= (1 << PWM2_PIN);
- #elif PWM_CHANNELS >= 3
- DDRB |= (1 << PWM3_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);
+ 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);
// 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
DDRB |= (1 << PWM4_PIN);
#endif
@@ -718,7 +762,7 @@ int main() {
sei();
// fallback for handling a few things
- push_state(default_state);
+ push_state(default_state, 0);
// call recipe's setup
setup();
--
cgit v1.2.3
From ef05435261fac31790303dbff16bcc194e9e5cb5 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Sat, 19 Aug 2017 15:33:33 -0600
Subject: Fixed unreliability of short-click detection. (it was doing stuff
like "press, release, release, timeout" so it didn't match "press, release,
timeout") (it may have also been missing the exact tick it needed, so I made
it use >= instead of ==, but this is theoretical and harmless if I was wrong)
Made baton mode memory work a bit better for both regular and strobe modes.
Made baton fast strobe pulses shorter for better motion freezing. Added
USE_DELAY_ZERO option as an alternate for USE_FINE_DELAY.
---
spaghetti-monster/spaghetti-monster.h | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
(limited to 'spaghetti-monster/spaghetti-monster.h')
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
index e51416a..cfabea8 100644
--- a/spaghetti-monster/spaghetti-monster.h
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -243,8 +243,10 @@ void empty_event_sequence() {
void push_event(uint8_t ev_type) {
ticks_since_last_event = 0; // something happened
uint8_t i;
- for(i=0; current_event[i] && (i= HOLD_TIMEOUT) {
push_event(A_HOLD);
emit_current_event(0);
}
@@ -478,7 +487,7 @@ ISR(WDT_vect) {
empty_event_sequence();
}
// end and clear event after release timeout
- else if (ticks_since_last_event == RELEASE_TIMEOUT) {
+ else if (ticks_since_last_event >= RELEASE_TIMEOUT) {
push_event(A_RELEASE_TIMEOUT);
emit_current_event(0);
empty_event_sequence();
--
cgit v1.2.3
From 9a6965d62578bc7260c7ba1d4860152721c12ea9 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Sat, 19 Aug 2017 16:25:39 -0600
Subject: Extra debouncing in PCINT (don't emit event if push was rejected).
Fixed memory error in Baton -- long-press from off didn't restart at moon.
Made Momentary and Baton go to sleep while light is off.
---
spaghetti-monster/spaghetti-monster.h | 20 +++++++-------------
1 file changed, 7 insertions(+), 13 deletions(-)
(limited to 'spaghetti-monster/spaghetti-monster.h')
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
index cfabea8..fe5e939 100644
--- a/spaghetti-monster/spaghetti-monster.h
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -240,7 +240,7 @@ void empty_event_sequence() {
for(uint8_t i=0; i
-#include
-#include
-#include
#include
-#include
-#include
-// typedefs
-typedef PROGMEM const uint8_t Event;
-typedef Event * EventPtr;
-typedef uint8_t (*EventCallbackPtr)(EventPtr event, uint16_t arg);
-typedef uint8_t EventCallback(EventPtr event, uint16_t arg);
-typedef uint8_t State(EventPtr event, uint16_t arg);
-typedef State * StatePtr;
-typedef struct Emission {
- EventPtr event;
- uint16_t arg;
-} Emission;
-
-volatile StatePtr current_state;
-#define EV_MAX_LEN 16
-uint8_t current_event[EV_MAX_LEN];
-// at 0.016 ms per tick, 255 ticks = 4.08 s
-// TODO: 16 bits?
-static volatile uint16_t ticks_since_last_event = 0;
-
-#ifdef USE_LVP
-// volts * 10
-#define VOLTAGE_LOW 30
-// MCU sees voltage 0.X volts lower than actual, add X to readings
-#define VOLTAGE_FUDGE_FACTOR 2
-volatile uint8_t voltage;
-void low_voltage();
-#endif
-#ifdef USE_THERMAL_REGULATION
-volatile int16_t temperature;
-void low_temperature();
-void high_temperature();
-#endif
+// include project definitions to help with recognizing symbols
+#include "fsm-events.h"
+#include "fsm-states.h"
+#include "fsm-adc.h"
+#include "fsm-wdt.h"
+#include "fsm-pcint.h"
+#include "fsm-standby.h"
+#include "fsm-main.h"
#ifdef USE_DEBUG_BLINK
#define OWN_DELAY
@@ -80,705 +50,18 @@ void debug_blink(uint8_t num) {
}
#endif
-// timeout durations in ticks (each tick 1/60th s)
-#define HOLD_TIMEOUT 24
-#define RELEASE_TIMEOUT 24
-
-#define A_ENTER_STATE 1
-#define A_LEAVE_STATE 2
-#define A_TICK 3
-#define A_PRESS 4
-#define A_HOLD 5
-#define A_RELEASE 6
-#define A_RELEASE_TIMEOUT 7
-// TODO: add events for over/under-heat conditions (with parameter for severity)
-#define A_OVERHEATING 8
-#define A_UNDERHEATING 9
-// TODO: add events for low voltage conditions
-#define A_VOLTAGE_LOW 10
-//#define A_VOLTAGE_CRITICAL 11
-#define A_DEBUG 255 // test event for debugging
-
-// TODO: maybe compare events by number instead of pointer?
-// (number = index in event types array)
-// (comparison would use full event content, but send off index to callbacks)
-// (saves space by using uint8_t instead of a pointer)
-// (also eliminates the need to duplicate single-entry events like for voltage or timer tick)
-
-// Event types
-Event EV_debug[] = {
- A_DEBUG,
- 0 } ;
-Event EV_enter_state[] = {
- A_ENTER_STATE,
- 0 } ;
-Event EV_leave_state[] = {
- A_LEAVE_STATE,
- 0 } ;
-Event EV_tick[] = {
- A_TICK,
- 0 } ;
-#ifdef USE_LVP
-Event EV_voltage_low[] = {
- A_VOLTAGE_LOW,
- 0 } ;
-#endif
-#ifdef USE_THERMAL_REGULATION
-Event EV_temperature_high[] = {
- A_OVERHEATING,
- 0 } ;
-Event EV_temperature_low[] = {
- A_UNDERHEATING,
- 0 } ;
-#endif
-Event EV_click1_press[] = {
- A_PRESS,
- 0 };
-// shouldn't normally happen, but UI might reset event while button is down
-// so a release with no recorded prior hold could be possible
-Event EV_release[] = {
- A_RELEASE,
- 0 };
-Event EV_click1_release[] = {
- A_PRESS,
- A_RELEASE,
- 0 };
-#define EV_1click EV_click1_complete
-Event EV_click1_complete[] = {
- A_PRESS,
- A_RELEASE,
- A_RELEASE_TIMEOUT,
- 0 };
-#define EV_hold EV_click1_hold
-// FIXME: Should holds use "start+tick" or just "tick" with a tick number?
-// Or "start+tick" with a tick number?
-Event EV_click1_hold[] = {
- A_PRESS,
- A_HOLD,
- 0 };
-Event EV_click1_hold_release[] = {
- A_PRESS,
- A_HOLD,
- A_RELEASE,
- 0 };
-Event EV_click2_press[] = {
- A_PRESS,
- A_RELEASE,
- A_PRESS,
- 0 };
-Event EV_click2_release[] = {
- A_PRESS,
- A_RELEASE,
- A_PRESS,
- A_RELEASE,
- 0 };
-#define EV_2clicks EV_click2_complete
-Event EV_click2_complete[] = {
- A_PRESS,
- A_RELEASE,
- A_PRESS,
- A_RELEASE,
- A_RELEASE_TIMEOUT,
- 0 };
-Event EV_click3_press[] = {
- A_PRESS,
- A_RELEASE,
- A_PRESS,
- A_RELEASE,
- A_PRESS,
- 0 };
-Event EV_click3_release[] = {
- A_PRESS,
- A_RELEASE,
- A_PRESS,
- A_RELEASE,
- A_PRESS,
- A_RELEASE,
- 0 };
-#define EV_3clicks EV_click3_complete
-Event EV_click3_complete[] = {
- A_PRESS,
- A_RELEASE,
- A_PRESS,
- A_RELEASE,
- A_PRESS,
- A_RELEASE,
- A_RELEASE_TIMEOUT,
- 0 };
-// ... and so on
-
-// A list of event types for easy iteration
-EventPtr event_sequences[] = {
- EV_click1_press,
- EV_release,
- EV_click1_release,
- EV_click1_complete,
- EV_click1_hold,
- EV_click1_hold_release,
- EV_click2_press,
- EV_click2_release,
- EV_click2_complete,
- EV_click3_press,
- EV_click3_release,
- EV_click3_complete,
- // ...
-};
-
-#define events_match(a,b) compare_event_sequences(a,b)
-// return 1 if (a == b), 0 otherwise
-uint8_t compare_event_sequences(uint8_t *a, const uint8_t *b) {
- for(uint8_t i=0; (i= offset) return current_event[i-offset];
- return 0;
-}
-*/
-
-inline uint8_t last_event_num() {
- uint8_t i;
- for(i=0; current_event[i] && (i=0; i--) {
- uint8_t err = state_stack[i](event, arg);
- if (! err) return 0;
- }
- return 1; // event not handled
-}
-
-void emit(EventPtr event, uint16_t arg) {
- // add this event to the queue for later,
- // so we won't use too much time during an interrupt
- append_emission(event, arg);
-}
-
-// Search the pre-defined event list for one matching what the user just did,
-// and emit it if one was found.
-void emit_current_event(uint16_t arg) {
- //uint8_t err = 1;
- for (uint8_t i=0; i<(sizeof(event_sequences)/sizeof(EventPtr)); i++) {
- if (events_match(current_event, event_sequences[i])) {
- //DEBUG_FLASH;
- //err = emit(event_sequences[i], arg);
- //return err;
- emit(event_sequences[i], arg);
- return;
- }
- }
- //return err;
-}
-
-void _set_state(StatePtr new_state, uint16_t arg) {
- // call old state-exit hook (don't use stack)
- if (current_state != NULL) current_state(EV_leave_state, arg);
- // set new state
- current_state = new_state;
- // call new state-enter hook (don't use stack)
- if (new_state != NULL) current_state(EV_enter_state, arg);
-}
-
-int8_t push_state(StatePtr new_state, uint16_t arg) {
- if (state_stack_len < STATE_STACK_SIZE) {
- // TODO: call old state's exit hook?
- // new hook for non-exit recursion into child?
- state_stack[state_stack_len] = new_state;
- state_stack_len ++;
- _set_state(new_state, arg);
- return state_stack_len;
- } else {
- // TODO: um... how is a flashlight supposed to handle a recursion depth error?
- return -1;
- }
-}
-
-StatePtr pop_state() {
- // TODO: how to handle pop from empty stack?
- StatePtr old_state = NULL;
- StatePtr new_state = NULL;
- if (state_stack_len > 0) {
- state_stack_len --;
- old_state = state_stack[state_stack_len];
- }
- if (state_stack_len > 0) {
- new_state = state_stack[state_stack_len-1];
- }
- // FIXME: what should 'arg' be?
- // FIXME: do we need a EV_reenter_state?
- _set_state(new_state, 0);
- return old_state;
-}
-
-uint8_t set_state(StatePtr new_state, uint16_t arg) {
- // FIXME: this calls exit/enter hooks it shouldn't
- pop_state();
- return push_state(new_state, arg);
-}
-
-// TODO? add events to a queue when inside an interrupt
-// instead of calling the event functions directly?
-// (then empty the queue in main loop?)
-
// TODO? new delay() functions which handle queue consumption?
// TODO? new interruptible delay() functions?
-
-//static volatile uint8_t button_was_pressed;
-#define BP_SAMPLES 16
-uint8_t button_is_pressed() {
- // debounce a little
- uint8_t highcount = 0;
- // measure for 16/64ths of a ms
- for(uint8_t i=0; i (BP_SAMPLES/2));
- //button_was_pressed = result;
- return result;
-}
-
-//void button_change_interrupt() {
-ISR(PCINT0_vect) {
-
- //DEBUG_FLASH;
-
- uint8_t pushed;
-
- // add event to current sequence
- if (button_is_pressed()) {
- pushed = push_event(A_PRESS);
- } else {
- pushed = push_event(A_RELEASE);
- }
-
- // check if sequence matches any defined sequences
- // if so, send event to current state callback
- if (pushed) emit_current_event(0);
-}
-
-// clock tick -- this runs every 16ms (62.5 fps)
-ISR(WDT_vect) {
- //if (ticks_since_last_event < 0xff) ticks_since_last_event ++;
- // increment, but loop from max back to half
- ticks_since_last_event = (ticks_since_last_event + 1) \
- | (ticks_since_last_event & 0x8000);
-
- // callback on each timer tick
- emit(EV_tick, ticks_since_last_event);
-
- // if time since last event exceeds timeout,
- // append timeout to current event sequence, then
- // send event to current state callback
-
- // preload recent events
- uint8_t le_num = last_event_num();
- uint8_t last_event = 0;
- uint8_t prev_event = 0;
- if (le_num >= 1) last_event = current_event[le_num-1];
- if (le_num >= 2) prev_event = current_event[le_num-2];
-
- // user held button long enough to count as a long click?
- if (last_event == A_PRESS) {
- if (ticks_since_last_event >= HOLD_TIMEOUT) {
- push_event(A_HOLD);
- emit_current_event(0);
- }
- }
-
- // user is still holding button, so tick
- else if (last_event == A_HOLD) {
- emit_current_event(ticks_since_last_event);
- }
-
- // detect completed button presses with expired timeout
- else if (last_event == A_RELEASE) {
- // no timeout required when releasing a long-press
- // TODO? move this logic to PCINT() and simplify things here?
- if (prev_event == A_HOLD) {
- //emit_current_event(0); // should have been emitted by PCINT
- empty_event_sequence();
- }
- // end and clear event after release timeout
- else if (ticks_since_last_event >= RELEASE_TIMEOUT) {
- push_event(A_RELEASE_TIMEOUT);
- emit_current_event(0);
- empty_event_sequence();
- }
- }
-
- #if defined(USE_LVP) || defined(USE_THERMAL_REGULATION)
- // start a new ADC measurement every 4 ticks
- static uint8_t adc_trigger = 0;
- adc_trigger ++;
- if (adc_trigger > 3) {
- adc_trigger = 0;
- ADCSRA |= (1 << ADSC) | (1 << ADIE);
- }
- #endif
-}
-
-// TODO: implement? (or is it better done in main()?)
-ISR(ADC_vect) {
- static uint8_t adc_step = 0;
- #ifdef USE_LVP
- #ifdef USE_LVP_AVG
- #define NUM_VOLTAGE_VALUES 4
- static int16_t voltage_values[NUM_VOLTAGE_VALUES];
- #endif
- static uint8_t lvp_timer = 0;
- static uint8_t lvp_lowpass = 0;
- #define LVP_TIMER_START 50 // ticks between LVP warnings
- #define LVP_LOWPASS_STRENGTH 4
- #endif
-
- #ifdef USE_THERMAL_REGULATION
- #define NUM_THERMAL_VALUES 4
- #define ADC_STEPS 4
- static int16_t temperature_values[NUM_THERMAL_VALUES];
- #else
- #define ADC_STEPS 2
- #endif
-
- uint16_t measurement = ADC; // latest 10-bit ADC reading
-
- adc_step = (adc_step + 1) & (ADC_STEPS-1);
-
- #ifdef USE_LVP
- // voltage
- if (adc_step == 1) {
- #ifdef USE_LVP_AVG
- // prime on first execution
- if (voltage == 0) {
- for(uint8_t i=0; i> 2;
-
- voltage = (uint16_t)(1.1*1024*10)/total + VOLTAGE_FUDGE_FACTOR;
- }
- #else // no USE_LVP_AVG
- // calculate actual voltage: volts * 10
- // ADC = 1.1 * 1024 / volts
- // volts = 1.1 * 1024 / ADC
- voltage = (uint16_t)(1.1*1024*10)/measurement + VOLTAGE_FUDGE_FACTOR;
- #endif
- // if low, callback EV_voltage_low / EV_voltage_critical
- // (but only if it has been more than N ticks since last call)
- if (lvp_timer) {
- lvp_timer --;
- } else { // it has been long enough since the last warning
- if (voltage < VOLTAGE_LOW) {
- if (lvp_lowpass < LVP_LOWPASS_STRENGTH) {
- lvp_lowpass ++;
- } else {
- // try to send out a warning
- //uint8_t err = emit(EV_voltage_low, 0);
- //uint8_t err = emit_now(EV_voltage_low, 0);
- emit(EV_voltage_low, 0);
- //if (!err) {
- // on successful warning, reset counters
- lvp_timer = LVP_TIMER_START;
- lvp_lowpass = 0;
- //}
- }
- } else {
- // voltage not low? reset count
- lvp_lowpass = 0;
- }
- }
- }
- #endif // ifdef USE_LVP
-
- // TODO: temperature
-
- // start another measurement for next time
- #ifdef USE_THERMAL_REGULATION
- #ifdef USE_LVP
- if (adc_step < 2) ADMUX = ADMUX_VCC;
- else ADMUX = ADMUX_THERM;
- #else
- ADMUX = ADMUX_THERM;
- #endif
- #else
- #ifdef USE_LVP
- ADMUX = ADMUX_VCC;
- #endif
- #endif
-}
-
-inline void ADC_on()
-{
- // read voltage on VCC by default
- // disable digital input on VCC pin to reduce power consumption
- //DIDR0 |= (1 << ADC_DIDR); // FIXME: unsure how to handle for VCC pin
- // VCC / 1.1V reference
- ADMUX = ADMUX_VCC;
- // enable, start, prescale
- ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL;
-}
-
-inline void ADC_off() {
- ADCSRA &= ~(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);
- 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);
- // 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
- DDRB |= (1 << PWM4_PIN);
- #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
- 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)?
-
- #ifdef USE_DEBUG_BLINK
- //debug_blink(1);
- #endif
-
- // all booted -- turn interrupts back on
- PCINT_on();
- WDT_on();
- ADC_on();
- sei();
-
- // fallback for handling a few things
- push_state(default_state, 0);
-
- // 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 (emissions[0].event != NULL) {
- emit_now(emissions[0].event, emissions[0].arg);
- delete_first_emission();
- }
- }
-}
+// include executable functions too, for easier compiling
+#include "fsm-states.c"
+#include "fsm-events.c"
+#include "fsm-adc.c"
+#include "fsm-wdt.c"
+#include "fsm-pcint.c"
+#include "fsm-standby.c"
+#include "fsm-main.c"
--
cgit v1.2.3
From badf37072988156a4cee753b922306195ee45916 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Thu, 24 Aug 2017 02:09:33 -0600
Subject: Added a ramping UI example. Added ramping support in general.
---
spaghetti-monster/spaghetti-monster.h | 2 ++
1 file changed, 2 insertions(+)
(limited to 'spaghetti-monster/spaghetti-monster.h')
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
index 4eeb7de..2ba3208 100644
--- a/spaghetti-monster/spaghetti-monster.h
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -33,6 +33,7 @@
#include "fsm-wdt.h"
#include "fsm-pcint.h"
#include "fsm-standby.h"
+#include "fsm-ramping.h"
#include "fsm-main.h"
#ifdef USE_DEBUG_BLINK
@@ -64,4 +65,5 @@ void setup();
#include "fsm-wdt.c"
#include "fsm-pcint.c"
#include "fsm-standby.c"
+#include "fsm-ramping.c"
#include "fsm-main.c"
--
cgit v1.2.3
From 32eaeddee34c76dda5456ed960be6278ed68e48d Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Thu, 24 Aug 2017 16:21:45 -0600
Subject: Added loop() to API, executes constantly. Added nice_delay_ms() to
process events while waiting, and abort on state change. Converted ramping-ui
strobe to smoothly variable with party and tactical modes.
---
spaghetti-monster/spaghetti-monster.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
(limited to 'spaghetti-monster/spaghetti-monster.h')
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
index 2ba3208..7d26390 100644
--- a/spaghetti-monster/spaghetti-monster.h
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -54,9 +54,11 @@ void debug_blink(uint8_t num) {
// TODO? new delay() functions which handle queue consumption?
// TODO? new interruptible delay() functions?
+// Define these in your SpaghettiMonster recipe
// boot-time tasks
-// Define this in your SpaghettiMonster recipe
void setup();
+// single loop iteration, runs continuously
+void loop();
// include executable functions too, for easier compiling
#include "fsm-states.c"
--
cgit v1.2.3
From 5184aad41fdb501f05ff7b0d7131011657ed8275 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Thu, 24 Aug 2017 19:22:10 -0600
Subject: Started on some documentation, spaghetti-monster.txt. Added #defines
for State return values: EVENT_HANDLED, EVENT_NOT_HANDLED Improved handling
of delay includes. Managed mischief.
---
spaghetti-monster/spaghetti-monster.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
(limited to 'spaghetti-monster/spaghetti-monster.h')
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
index 7d26390..56d03a3 100644
--- a/spaghetti-monster/spaghetti-monster.h
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -36,10 +36,12 @@
#include "fsm-ramping.h"
#include "fsm-main.h"
-#ifdef USE_DEBUG_BLINK
+#if defined(USE_DELAY_MS) || defined(USE_DELAY_4MS) || defined(USE_DELAY_ZERO) || defined(USE_DEBUG_BLINK)
#define OWN_DELAY
-#define USE_DELAY_4MS
#include "tk-delay.h"
+#endif
+
+#ifdef USE_DEBUG_BLINK
#define DEBUG_FLASH PWM1_LVL = 64; delay_4ms(2); PWM1_LVL = 0;
void debug_blink(uint8_t num) {
for(; num>0; num--) {
--
cgit v1.2.3
From 39b30b41f92978a3e05a8de0a416279fb35b35b1 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Fri, 25 Aug 2017 02:14:31 -0600
Subject: Added battcheck mode to ramping-ui. It's bigger than I had hoped.
:( Added fsm-misc.*, which currently only has interruptible blink functions
in it. (for blinking out numbers and such)
---
spaghetti-monster/spaghetti-monster.h | 2 ++
1 file changed, 2 insertions(+)
(limited to 'spaghetti-monster/spaghetti-monster.h')
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
index 56d03a3..3727930 100644
--- a/spaghetti-monster/spaghetti-monster.h
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -34,6 +34,7 @@
#include "fsm-pcint.h"
#include "fsm-standby.h"
#include "fsm-ramping.h"
+#include "fsm-misc.h"
#include "fsm-main.h"
#if defined(USE_DELAY_MS) || defined(USE_DELAY_4MS) || defined(USE_DELAY_ZERO) || defined(USE_DEBUG_BLINK)
@@ -70,4 +71,5 @@ void loop();
#include "fsm-pcint.c"
#include "fsm-standby.c"
#include "fsm-ramping.c"
+#include "fsm-misc.c"
#include "fsm-main.c"
--
cgit v1.2.3
From 6d9ceae8eab62ba33011a82c8fad8e55d37fe7ba Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Sat, 26 Aug 2017 16:48:25 -0600
Subject: Added eeprom load/save API (no wear levelling yet), verified it works
in DarkHorse.
---
spaghetti-monster/spaghetti-monster.h | 6 ++++++
1 file changed, 6 insertions(+)
(limited to 'spaghetti-monster/spaghetti-monster.h')
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
index 3727930..82800b4 100644
--- a/spaghetti-monster/spaghetti-monster.h
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -34,6 +34,9 @@
#include "fsm-pcint.h"
#include "fsm-standby.h"
#include "fsm-ramping.h"
+#ifdef USE_EEPROM
+#include "fsm-eeprom.h"
+#endif
#include "fsm-misc.h"
#include "fsm-main.h"
@@ -71,5 +74,8 @@ void loop();
#include "fsm-pcint.c"
#include "fsm-standby.c"
#include "fsm-ramping.c"
+#ifdef USE_EEPROM
+#include "fsm-eeprom.c"
+#endif
#include "fsm-misc.c"
#include "fsm-main.c"
--
cgit v1.2.3
From 5aa64f52af0505ebe257eafba2e46d2e477f61af Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Sat, 9 Sep 2017 14:38:55 -0600
Subject: Made "off" mode more vigilant about staying off.
---
spaghetti-monster/spaghetti-monster.h | 3 ---
1 file changed, 3 deletions(-)
(limited to 'spaghetti-monster/spaghetti-monster.h')
diff --git a/spaghetti-monster/spaghetti-monster.h b/spaghetti-monster/spaghetti-monster.h
index 82800b4..5599bca 100644
--- a/spaghetti-monster/spaghetti-monster.h
+++ b/spaghetti-monster/spaghetti-monster.h
@@ -57,9 +57,6 @@ void debug_blink(uint8_t num) {
}
#endif
-// TODO? new delay() functions which handle queue consumption?
-// TODO? new interruptible delay() functions?
-
// Define these in your SpaghettiMonster recipe
// boot-time tasks
void setup();
--
cgit v1.2.3