From 73a5a6974a98aa73ab392272b4d69d285c85dee5 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 19 Aug 2017 17:20:46 -0600 Subject: Completely reorganized SpaghettiMonster code into smaller logical pieces: fsm-*.c and fsm-*.h. --- spaghetti-monster/fsm-main.c | 107 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 spaghetti-monster/fsm-main.c (limited to 'spaghetti-monster/fsm-main.c') diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c new file mode 100644 index 0000000..2faaeda --- /dev/null +++ b/spaghetti-monster/fsm-main.c @@ -0,0 +1,107 @@ +/* + * fsm-main.c: main() function for SpaghettiMonster. + * + * 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 . + */ + +#ifndef FSM_MAIN_C +#define FSM_MAIN_C + +#include "fsm-main.h" + +int main() { + // Don't allow interrupts while booting + cli(); + //WDT_off(); + //PCINT_off(); + + // configure PWM channels + #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); + 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(); + } + } +} + +#endif -- 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/fsm-main.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'spaghetti-monster/fsm-main.c') diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index 2faaeda..1a0c425 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -97,10 +97,9 @@ int main() { // 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(); - } + process_emissions(); + + loop(); } } -- cgit v1.2.3 From 98380adfd4c1f9a5e12d7d416cc14b909284014b Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 27 Aug 2017 22:41:37 -0600 Subject: Fixed a bug where sometimes the light wouldn't respond for a second or so after connecting power. (spurious events were detected at boot, and previously had to time out before it would respond) --- spaghetti-monster/fsm-main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spaghetti-monster/fsm-main.c') diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index 1a0c425..ae63126 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -88,6 +88,10 @@ int main() { // fallback for handling a few things push_state(default_state, 0); + // in case any spurious button presses were detected at boot + delay_ms(1); + empty_event_sequence(); + // call recipe's setup setup(); -- cgit v1.2.3 From 15d5b2cbe807029c7493691a1877a1898d100455 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Wed, 30 Aug 2017 23:07:55 -0600 Subject: Replaced FSM_*_LAYOUT with FSM_*_DRIVER because I think it makes more sense. Made momentary.c compile again. Updated fsm-main to use whichever delay function is available. --- spaghetti-monster/fsm-main.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'spaghetti-monster/fsm-main.c') diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index ae63126..9505322 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -89,7 +89,11 @@ int main() { push_state(default_state, 0); // in case any spurious button presses were detected at boot + #ifdef USE_DELAY_MS delay_ms(1); + #else + delay_4ms(1); + #endif empty_event_sequence(); // call recipe's setup -- cgit v1.2.3 From a419850e536f00549120255a627137faffded47a Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 3 Sep 2017 14:58:22 -0600 Subject: 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. --- spaghetti-monster/fsm-main.c | 89 +++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 31 deletions(-) (limited to 'spaghetti-monster/fsm-main.c') 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<= 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<= 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(); } } -- cgit v1.2.3 From 520f5cdb983045c5518325f3c3665f59ca85435e Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 24 Sep 2017 20:54:07 -0600 Subject: Added idle_mode() for slightly lower power use without turning off any regular functions. (PWM, ADC, WDT all still enabled; only useful in moon mode) Changed default ceilings in Anduril FW3A config. --- spaghetti-monster/fsm-main.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'spaghetti-monster/fsm-main.c') diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index d526455..a47a4bf 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -72,8 +72,8 @@ int main() { PORTB = (1 << SWITCH_PIN); // e-switch is the only input PCMSK = (1 << SWITCH_PIN); // pin change interrupt uses this pin - // configure sleep mode - set_sleep_mode(SLEEP_MODE_PWR_DOWN); + //// configure sleep mode + //set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Read config values and saved state @@ -133,8 +133,20 @@ int main() { standby_mode(); } + #ifdef USE_IDLE_MODE + /* + // enter idle mode if requested + // (works better if deferred like this) + if (go_to_idle) { + go_to_idle = 0; + idle_mode(); + } + */ + #endif + // give the recipe some time slices loop(); + } } -- cgit v1.2.3 From 08082855cbc7aa0a07f9ddfe6daa86e6c96d5b57 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 24 Sep 2017 20:56:52 -0600 Subject: Removed unused code from first idle_mode(); experiment. --- spaghetti-monster/fsm-main.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'spaghetti-monster/fsm-main.c') diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index a47a4bf..bc41cd6 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -39,8 +39,6 @@ ISR(TIMER1_COMPA_vect) { int main() { // Don't allow interrupts while booting cli(); - //WDT_off(); - //PCINT_off(); // configure PWM channels #if PWM_CHANNELS >= 1 @@ -72,13 +70,6 @@ int main() { PORTB = (1 << SWITCH_PIN); // e-switch is the only input PCMSK = (1 << SWITCH_PIN); // pin change interrupt uses this pin - //// configure sleep mode - //set_sleep_mode(SLEEP_MODE_PWR_DOWN); - - // Read config values and saved state - - // TODO: handle long press vs short press (or even medium press)? - #ifdef USE_DEBUG_BLINK //debug_blink(1); #endif @@ -133,17 +124,6 @@ int main() { standby_mode(); } - #ifdef USE_IDLE_MODE - /* - // enter idle mode if requested - // (works better if deferred like this) - if (go_to_idle) { - go_to_idle = 0; - idle_mode(); - } - */ - #endif - // give the recipe some time slices loop(); -- cgit v1.2.3 From 9bde4b7bd0588b1d74f9b89f89419e8f11e3f25f Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sun, 24 Sep 2017 22:45:59 -0600 Subject: Cut moon power from ~4mA to ~2.5mA by running clock at half speed on very low modes. Adjusted default FET+1 ramp to compensate for speed bump. Added define(s) for whether to blink at ramp floor/ceiling/channel edges. Lowered default moon level to 1, since slower speed makes it brighter and more stable. --- spaghetti-monster/fsm-main.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'spaghetti-monster/fsm-main.c') diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index bc41cd6..5efcd4c 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -40,6 +40,12 @@ int main() { // Don't allow interrupts while booting cli(); + #ifdef HALFSPEED + // run at half speed + CLKPR = 1<= 1 DDRB |= (1 << PWM1_PIN); -- cgit v1.2.3 From 8d967e13f18cee2bc13faa502cfac0946ae2a0d9 Mon Sep 17 00:00:00 2001 From: Selene ToyKeeper Date: Sat, 21 Oct 2017 06:46:07 -0600 Subject: Delay un-setting go_to_standby until the last moment, in case set_level() wants to use it. --- spaghetti-monster/fsm-main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'spaghetti-monster/fsm-main.c') diff --git a/spaghetti-monster/fsm-main.c b/spaghetti-monster/fsm-main.c index 5efcd4c..8f21846 100644 --- a/spaghetti-monster/fsm-main.c +++ b/spaghetti-monster/fsm-main.c @@ -110,7 +110,6 @@ int main() { // 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 @@ -127,6 +126,7 @@ int main() { PWM4_LVL = 255; // inverted :( #endif #endif + go_to_standby = 0; standby_mode(); } -- cgit v1.2.3