Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Port failsafe watching code to raw avr-gcc
More interrupty now
- Loading branch information
Showing
2 changed files
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
CC=avr-gcc | ||
OBJCOPY=avr-objcopy | ||
MICRONUCLEUS=/Users/dsal/Library/Arduino15/packages/digistump/tools/micronucleus/2.0a4/micronucleus | ||
CFLAGS=-Wall -Os -DF_CPU=16000000L -mmcu=attiny85 | ||
LDFLAGS=-mmcu=attiny85 | ||
|
||
failsafe.hex: failsafe.elf | ||
avr-objcopy -j .text -j .data -O ihex failsafe.elf failsafe.hex | ||
avr-size --format=avr --mcu=attiny85 failsafe.elf | ||
|
||
failsafe.elf: failsafe.o | ||
${CC} $(LDFLAGS) -o failsafe.elf failsafe.o | ||
|
||
clean: | ||
rm failsafe.{elf,hex,o} | ||
|
||
install: failsafe.hex | ||
$(MICRONUCLEUS) --run failsafe.hex |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
#include <avr/io.h> | ||
#include <avr/interrupt.h> | ||
#include <avr/wdt.h> | ||
#include <util/delay.h> | ||
#include <stdbool.h> | ||
|
||
#define PPM_PIN PB0 | ||
#define OUT_PIN PB1 | ||
#define BUTTON_PIN PB2 | ||
#define SHUTDOWN_PIN PB3 | ||
|
||
// a bit under a second | ||
#define BUTTON_OVERFLOWS 30 | ||
|
||
volatile bool disabling = false; | ||
volatile bool failed = false; | ||
volatile uint8_t prevb = 0xFF; | ||
volatile int overflows = 0; | ||
volatile bool watching_button = false; | ||
|
||
|
||
void isr_svc_button() { | ||
if (watching_button) { | ||
watching_button = false; | ||
TIMSK &= ~_BV(TOIE0); // disable timer overflow | ||
} else { | ||
watching_button = true; | ||
TIMSK |= _BV(TOIE0); // enable overflow interupt | ||
TCNT0 = 0; | ||
overflows = 0; | ||
} | ||
} | ||
|
||
ISR(PCINT0_vect) { | ||
wdt_reset(); | ||
|
||
uint8_t vals = PINB ^ prevb; | ||
if (vals & _BV(PPM_PIN)) { | ||
failed = false; | ||
} | ||
|
||
if (vals & _BV(BUTTON_PIN)) { | ||
isr_svc_button(); | ||
} | ||
} | ||
|
||
ISR(WDT_vect) { | ||
wdt_reset(); | ||
failed = true; | ||
} | ||
|
||
ISR(TIM0_OVF_vect) { | ||
if (++overflows >= BUTTON_OVERFLOWS) { | ||
disabling = true; | ||
TIMSK &= ~_BV(TOIE0); | ||
watching_button = false; | ||
} | ||
} | ||
|
||
void writeOut(bool failed) { | ||
if (failed) { | ||
DDRB |= _BV(OUT_PIN); | ||
} else { | ||
DDRB &= ~_BV(OUT_PIN); | ||
} | ||
} | ||
|
||
void disable() { | ||
// Maybe like, a beep or something? | ||
PORTB |= _BV(OUT_PIN); | ||
_delay_ms(250); | ||
PORTB &= ~_BV(OUT_PIN); | ||
|
||
DDRB |= _BV(SHUTDOWN_PIN); | ||
DDRB &= ~_BV(OUT_PIN); | ||
cli(); | ||
// No more watchdog | ||
_WD_CONTROL_REG = 0; | ||
// Stop watching inputs | ||
PCMSK &= ~(_BV(PCINT0) | _BV(PCINT2)); | ||
sei(); | ||
} | ||
|
||
int main() { | ||
DDRB = _BV(OUT_PIN) | _BV(SHUTDOWN_PIN); | ||
PORTB |= _BV(BUTTON_PIN); | ||
|
||
cli(); | ||
GIMSK |= _BV(PCIE); | ||
PCMSK |= _BV(PCINT0); | ||
|
||
// I use the timer later. Set up 1024 prescaler. | ||
TCCR0B |= _BV(CS02) | _BV(CS00); // 1024 prescaler | ||
|
||
// The watchdog timer is used for detecting failsafe state. | ||
wdt_reset(); | ||
_WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE); | ||
// Enable WDT Interrupt, and Set Timeout to ~1 seconds, | ||
_WD_CONTROL_REG = _BV(WDIE) | _BV(WDP2) | _BV(WDP1); | ||
sei(); | ||
|
||
for (;;) { | ||
// just process interrupts | ||
asm("sleep"); | ||
if (disabling) { | ||
disable(); | ||
disabling = false; | ||
} | ||
} | ||
} |