aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSelene ToyKeeper2017-08-18 23:31:11 -0600
committerSelene ToyKeeper2017-08-18 23:31:11 -0600
commit086aaabd39d3c6736ace56f2badac06b75567651 (patch)
treeb756e3cfa612127c409ee59203ed5177ceee1db6
parentSome early ideas for Round Table. Nothing close to compile-able yet. (diff)
downloadanduril-086aaabd39d3c6736ace56f2badac06b75567651.tar.gz
anduril-086aaabd39d3c6736ace56f2badac06b75567651.tar.bz2
anduril-086aaabd39d3c6736ace56f2badac06b75567651.zip
First RoundTable example actually works (simple momentary 1-mode UI).
Changed how tk-attiny.h detects whether a layout was defined. Changed how tk-attiny.h detects number of PWM channels for new-style layouts. Added no-underscore versions of delay functions. Lots of RoundTable refactoring and blank-filling.
-rw-r--r--RoundTable/momentary.c72
-rw-r--r--RoundTable/round-table.c489
-rw-r--r--tk-attiny.h17
-rw-r--r--tk-delay.h4
4 files changed, 423 insertions, 159 deletions
diff --git a/RoundTable/momentary.c b/RoundTable/momentary.c
index 120406e..4394f46 100644
--- a/RoundTable/momentary.c
+++ b/RoundTable/momentary.c
@@ -20,7 +20,12 @@
*/
#define RT_EMISAR_D4_LAYOUT
+#define USE_LVP
+#define USE_DEBUG_BLINK
+#define OWN_DELAY
+#define USE_DELAY_MS
#include "round-table.c"
+#include "tk-delay.h"
volatile uint8_t brightness;
@@ -34,35 +39,58 @@ void light_off() {
PWM2_LVL = 0;
}
+//State momentary_state {
uint8_t momentary_state(EventPtr event, uint16_t arg) {
- switch(event) {
- case EV_press:
- brightness = 255;
- light_on();
- // reset current event queue
- empty_event_sequence();
- return 0;
+ if (event == EV_click1_press) {
+ brightness = 255;
+ light_on();
+ // reset current event queue
+ empty_event_sequence();
+ return 0;
+ }
+
+ else if (event == EV_release) {
+ light_off();
+ // reset current event queue
+ empty_event_sequence();
+ return 0;
+ }
- case EV_release:
+ /*
+ // LVP / low-voltage protection
+ //else if ((event == EV_voltage_low) || (event == EV_voltage_critical)) {
+ else if (event == EV_voltage_low) {
+ if (brightness > 0) brightness >>= 1;
+ else {
light_off();
- // reset current event queue
- empty_event_sequence();
- return 0;
+ standby_mode();
+ }
+ return 0;
+ }
+ */
- // LVP / low-voltage protection
- case EV_voltage_low:
- case EV_voltage_critical:
- if (brightness > 0) brightness >>= 1;
- else {
- light_off();
- standby_mode();
- }
- return 0;
+ // event not handled
+ return 1;
+}
+
+// LVP / low-voltage protection
+void low_voltage() {
+ if (brightness > 0) brightness >>= 1;
+ else {
+ light_off();
+ standby_mode();
}
- return 1; // event not handled
}
void setup() {
- set_state(momentary_state);
+ //debug_blink(1);
+ /*
+ brightness = 255;
+ light_on();
+ delay_ms(10);
+ light_off();
+ */
+
+ push_state(momentary_state);
}
diff --git a/RoundTable/round-table.c b/RoundTable/round-table.c
index 6cd1b10..c6ffc08 100644
--- a/RoundTable/round-table.c
+++ b/RoundTable/round-table.c
@@ -1,23 +1,51 @@
#include "tk-attiny.h"
-//
+#include <avr/pgmspace.h>
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/wdt.h>
+#include <avr/eeprom.h>
+#include <avr/sleep.h>
+#include <util/delay_basic.h>
+
+// 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);
-// FIXME: Why does a state need a number? Why not just a function pointer?
-// (I don't think it actually needs a number...)
-typedef struct State {
- uint8_t num;
- EventCallback event_callback;
-} State;
-typedef struct State* StatePtr;
+typedef uint8_t State(EventPtr event, uint16_t arg);
+typedef State * StatePtr;
volatile StatePtr current_state;
#define EV_MAX_LEN 16
-volatile uint8_t current_event[EV_MAX_LEN];
+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
volatile int16_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
@@ -33,7 +61,7 @@ volatile int16_t temperature;
#define A_UNDERHEATING 10
// TODO: add events for low voltage conditions
#define A_VOLTAGE_LOW 11
-#define A_VOLTAGE_CRITICAL 12
+//#define A_VOLTAGE_CRITICAL 12
// TODO: maybe compare events by number instead of pointer?
// (number = index in event types array)
@@ -42,8 +70,6 @@ volatile int16_t temperature;
// (also eliminates the need to duplicate single-entry events like for voltage or timer tick)
// Event types
-typedef PROGMEM const uint8_t Event;
-typedef Event* EventPtr;
Event EV_enter_state[] = {
A_ENTER_STATE,
0 } ;
@@ -53,7 +79,20 @@ Event EV_leave_state[] = {
Event EV_tick[] = {
A_TICK,
0 } ;
-Event EV_press[] = {
+#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
@@ -61,41 +100,66 @@ Event EV_press[] = {
Event EV_release[] = {
A_RELEASE,
0 };
-Event EV_press_release[] = {
+Event EV_click1_release[] = {
A_PRESS,
A_RELEASE,
0 };
-#define EV_1click EV_press_release_timeout
-Event EV_press_release_timeout[] = {
+#define EV_1click EV_click1_complete
+Event EV_click1_complete[] = {
A_PRESS,
A_RELEASE,
A_RELEASE_TIMEOUT,
0 };
-#define EV_hold EV_press_hold
+#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_press_hold[] = {
+Event EV_click1_hold[] = {
A_PRESS,
- A_HOLD_TIMEOUT,
+ A_HOLD_START,
0 };
-Event EV_press_hold_release[] = {
+Event EV_click1_hold_release[] = {
A_PRESS,
- A_HOLD_TIMEOUT,
+ A_HOLD_START,
A_RELEASE,
0 };
-Event EV_press_release_press[] = {
+Event EV_click2_press[] = {
A_PRESS,
A_RELEASE,
A_PRESS,
0 };
-Event EV_press_release_press_release[] = {
+Event EV_click2_release[] = {
A_PRESS,
A_RELEASE,
A_PRESS,
A_RELEASE,
0 };
-#define EV_2clicks EV_press_release_press_release_timeout
-Event EV_press_release_press_release_timeout[] = {
+#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,
@@ -106,90 +170,41 @@ Event EV_press_release_press_release_timeout[] = {
// A list of event types for easy iteration
EventPtr event_sequences[] = {
- EV_press,
- EV_press_release,
- EV_press_release_timeout,
- EV_press_release_press,
- EV_press_release_press_release,
- EV_press_release_press_release_timeout,
+ 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,
// ...
};
-// TODO: move this to a separate UI-specific file
-/*
-State states[] = {
-
-};
-*/
-
-// 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 uint8_t ticks_since_last_event = 0; // TODO: 16 bits?
-
-void WDT_tick() {
- timer ++;
-
- //static uint8_t hold_ticks = 0; // TODO: 16 bits?
-
- // callback on each timer tick
- emit(EV_tick, timer);
-
- // 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(hold_ticks);
- // or
- // //release_timeout()
- // //emit(EV_press_release_timeout, 0);
- // emit_current(0);
-
- // add 4-step voltage / temperature thing?
- // with averaged values,
- // once every N ticks?
-}
-
-void button_change_interrupt() {
- // TODO: debounce a little
-
- //ticks_since_last_event = 0; // something happened
-
- // TODO: add event to current sequence
-
- // check if sequence matches any defined sequences
- // if so, send event to current state callback
- emit_current(0);
-}
-
-uint8_t emit_current(uint16_t arg) {
- uint8_t err = 1;
- for (uint8_t i=0; i<sizeof(event_sequences); i++) {
- if (events_match(event_sequences[i], current_event)) {
- err = emit(event_sequences[i], arg);
- break;
- }
- }
- return err;
-}
-
#define events_match(a,b) compare_event_sequences(a,b)
-uint8_t compare_event_sequences(uint8_t *a, uint8_t *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<EV_MAX_LEN) && (a[i] == pgm_read_byte(b+i)); i++) {
+ // end of zero-terminated sequence
+ if (a[i] == 0) return 1;
+ }
+ // if we ever fall out, that means something was different
+ // (or the sequence is too long)
+ return 0;
}
void empty_event_sequence() {
for(uint8_t i=0; i<EV_MAX_LEN; i++) current_event[i] = 0;
}
-void append_event(uint8_t ev_type) {
+void push_event(uint8_t ev_type) {
ticks_since_last_event = 0; // something happened
uint8_t i;
- for(i=0; current_event[i], i<EV_MAX_LEN; i++);
+ for(i=0; current_event[i] && (i<EV_MAX_LEN); i++);
if (i < EV_MAX_LEN) {
current_event[i] = ev_type;
} else {
@@ -199,6 +214,9 @@ void append_event(uint8_t ev_type) {
// TODO: stack for states, to allow shared utility states like "input a number"
// and such, which return to the previous state after finishing
+#define STATE_STACK_SIZE 8
+StatePtr state_stack[STATE_STACK_SIZE];
+uint8_t state_stack_len = 0;
// TODO: if callback doesn't handle current event,
// pass event to next state on stack?
// Callback return values:
@@ -206,46 +224,157 @@ void append_event(uint8_t ev_type) {
// 1: event not handled
// 255: error (not sure what this would even mean though, or what difference it would make)
// TODO: function to call stacked callbacks until one returns "handled"
+// Call stacked callbacks for the given event until one handles it.
uint8_t emit(EventPtr event, uint16_t arg) {
// TODO: implement
- for(;;) {
- uint8_t err = foo.callback(event, arg);
+ for(int8_t i=state_stack_len-1; i>=0; i--) {
+ uint8_t err = state_stack[i](event, arg);
if (! err) return 0;
}
return 1; // event not handled
}
-uint8_t push_state(State *new_state) {
- // TODO: implement
+// Search the pre-defined event list for one matching what the user just did,
+// and emit it if one was found.
+uint8_t 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;
+ }
+ }
+ return err;
}
-State * pop_state() {
- // TODO: implement
+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;
+ }
}
-uint8_t set_state(State *new_state) {
+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);
}
-uint8_t _set_state(State *new_state) {
- // call old state-exit hook (don't use stack)
- current_state.callback(EV_leave_state, 0);
- // set new state
- current_state = new_state;
- // call new state-enter hook (don't use stack)
- current_state.callback(EV_enter_state, 0);
+// 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?
+
+
+uint8_t button_is_pressed() {
+ // debounce a little
+ uint8_t measurement = 0;
+ // measure for 8/64ths of a ms
+ for(uint8_t i=0; i<8; i++) {
+ // check current value
+ measurement = (measurement << 1) | ((PINB & (1<<SWITCH_PIN)) == 0);
+ // wait a moment
+ _delay_loop_2(BOGOMIPS/64);
+ }
+ // 0 bits mean "pressed", 1 bits mean "not pressed"
+ // only return "pressed" if all bits match
+ return (measurement != 0);
+}
+
+//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) {
+ //timer ++; // Is this needed at all?
+
+ /*
+ if (ticks_since_last_event & 0b00000111 ) {
+ DEBUG_FLASH;
+ }
+ */
+
+ if (ticks_since_last_event < 0xff) ticks_since_last_event ++;
+
+ //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);
+
+ // add 4-step voltage / temperature thing?
+ // with averaged values,
+ // once every N ticks?
}
// TODO: implement? (or is it better done in main()?)
ISR(ADC_vect) {
static uint8_t adc_step = 0;
+ #ifdef USE_LVP
static uint8_t lvp_timer = 0;
#define LVP_TIMER_START 255 // TODO: calibrate this value
+ #endif
#ifdef USE_THERMAL_REGULATION
#define NUM_THERMAL_VALUES 4
@@ -259,6 +388,7 @@ ISR(ADC_vect) {
adc_step = (adc_step + 1) & (ADC_STEPS-1);
+ #ifdef USE_LVP
// TODO: voltage
// TODO: if low, callback EV_voltage_low / EV_voltage_critical
// (but only if it has been more than N ticks since last call)
@@ -270,15 +400,22 @@ ISR(ADC_vect) {
// if (!err) lvp_timer = LVP_TIMER_START;
// }
// }
+ #endif
// TODO: temperature
// start another measurement for next time
#ifdef USE_THERMAL_REGULATION
- if (adc_step < 2) ADMUX = ADMUX_VCC;
- else ADMUX = ADMUX_THERM;
+ #ifdef USE_LVP
+ if (adc_step < 2) ADMUX = ADMUX_VCC;
+ else ADMUX = ADMUX_THERM;
+ #else
+ ADMUX = ADMUX_THERM;
+ #endif
#else
- ADMUX = ADMUX_VCC;
+ #ifdef USE_LVP
+ ADMUX = ADMUX_VCC;
+ #endif
#endif
}
@@ -293,6 +430,44 @@ inline void ADC_on()
ADCSRA = (1 << ADEN) | (1 << ADSC) | ADC_PRSCL;
}
+inline void ADC_off() {
+ ADCSRA &= ~(1<<ADEN); //ADC off
+}
+
+inline void PCINT_on() {
+ // enable pin change interrupt for pin N
+ GIMSK |= (1 << PCIE);
+ // only pay attention to the e-switch pin
+ //PCMSK = (1 << SWITCH_PCINT);
+ // set bits 1:0 to 0b01 (interrupt on rising *and* falling edge) (default)
+ // MCUCR &= 0b11111101; MCUCR |= 0b00000001;
+}
+
+inline void PCINT_off() {
+ // disable all pin-change interrupts
+ GIMSK &= ~(1 << PCIE);
+}
+
+void WDT_on()
+{
+ // interrupt every 16ms
+ //cli(); // Disable interrupts
+ wdt_reset(); // Reset the WDT
+ WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
+ WDTCR = (1<<WDIE); // Enable interrupt every 16ms
+ //sei(); // Enable interrupts
+}
+
+inline void WDT_off()
+{
+ //cli(); // Disable interrupts
+ wdt_reset(); // Reset the WDT
+ MCUSR &= ~(1<<WDRF); // Clear Watchdog reset flag
+ WDTCR |= (1<<WDCE) | (1<<WDE); // Start timed sequence
+ WDTCR = 0x00; // Disable WDT
+ //sei(); // Enable interrupts
+}
+
// low-power standby mode used while off but power still connected
#define standby_mode sleep_until_eswitch_pressed
void sleep_until_eswitch_pressed()
@@ -301,7 +476,7 @@ void sleep_until_eswitch_pressed()
ADC_off();
// TODO: make sure switch isn't currently pressed
- while (switch_pressed()) {}
+ while (button_is_pressed()) {}
PCINT_on(); // wake on e-switch event
@@ -311,35 +486,71 @@ void sleep_until_eswitch_pressed()
// something happened; wake up
sleep_disable();
- PCINT_off();
+ //PCINT_off(); // we use this for more than just waking up
ADC_on();
WDT_on();
}
-// boot-time tasks
-/* Define this in your RoundTable recipe
-void setup() {
+// last-called state on stack
+// handles default actions for LVP, thermal regulation, etc
+uint8_t default_state(EventPtr event, uint16_t arg) {
+ if (0) {}
+
+ #ifdef USE_LVP
+ else if (event == EV_voltage_low) {
+ low_voltage();
+ return 0;
+ }
+ #endif
+
+ #ifdef USE_THERMAL_REGULATION
+ else if (event == EV_temperature_high) {
+ high_temperature();
+ return 0;
+ }
+
+ else if (event == EV_temperature_low) {
+ low_temperature();
+ return 0;
+ }
+ #endif
+
+ // event not handled
+ return 1;
}
-*/
-void main() {
+// boot-time tasks
+// Define this in your RoundTable recipe
+void setup();
+
+int main() {
// Don't allow interrupts while booting
cli();
- WDT_off();
- PCINT_off();
-
- // TODO: configure PWM channels
- #if PWM_CHANNELS == 1
- #elif PWM_CHANNELS == 2
- #elif PWM_CHANNELS == 3
+ //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 << 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?
- // TODO: configure e-switch
- //PORTB = (1 << SWITCH_PIN); // e-switch is the only input
- //PCMSK = (1 << SWITCH_PIN); // pin change interrupt uses this pin
+ // 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);
@@ -349,18 +560,26 @@ void main() {
// TODO: handle long press vs short press (or even medium press)?
- // TODO: call recipe's setup
- setup();
+ #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: if wait queue not empty, process and pop first item in queue
+ // TODO: update e-switch press state?
+ // TODO: if wait queue not empty, process and pop first item in queue?
// TODO: check voltage?
// TODO: check temperature?
}
diff --git a/tk-attiny.h b/tk-attiny.h
index ebd997f..22b73f9 100644
--- a/tk-attiny.h
+++ b/tk-attiny.h
@@ -55,8 +55,11 @@
#endif
+#include <avr/interrupt.h>
+
/******************** I/O pin and register layout ************************/
#ifdef FET_7135_LAYOUT
+#define LAYOUT_DEFINED
/*
* ----
* Reset -|1 8|- VCC
@@ -92,6 +95,7 @@
#endif // FET_7135_LAYOUT
#ifdef TRIPLEDOWN_LAYOUT
+#define LAYOUT_DEFINED
/*
* ----
* Reset -|1 8|- VCC
@@ -128,6 +132,7 @@
#endif // TRIPLEDOWN_LAYOUT
#ifdef FERRERO_ROCHER_LAYOUT
+#define LAYOUT_DEFINED
/*
* ----
* Reset -|1 8|- VCC
@@ -142,6 +147,7 @@
#endif // FERRERO_ROCHER_LAYOUT
#ifdef NANJG_LAYOUT
+#define LAYOUT_DEFINED
#define STAR2_PIN PB0
#define STAR3_PIN PB4
#define STAR4_PIN PB3
@@ -160,6 +166,7 @@
#ifdef RT_EMISAR_D4_LAYOUT
+#define LAYOUT_DEFINED
/*
* ----
* Reset -|1 8|- VCC
@@ -169,9 +176,12 @@
* ----
*/
+#define PWM_CHANNELS 2
+
#define AUXLED_PIN PB4 // pin 3
-#define SWITCH_PIN PB3 // pin 2, OTC
+#define SWITCH_PIN PB3 // pin 2
+#define SWITCH_PCINT PCINT3 // pin 2 pin change interrupt
#define CAP_CHANNEL 0x03 // MUX 03 corresponds with PB3 (Star 4)
#define CAP_DIDR ADC3D // Digital input disable bit corresponding with PB3
@@ -195,6 +205,7 @@
#ifdef RT_TKSABER_LAYOUT
+#define LAYOUT_DEFINED
/*
* ----
* Reset -|1 8|- VCC
@@ -204,6 +215,7 @@
* ----
*/
+#define PWM_CHANNELS 4
#define PWM1_PIN PB0 // pin 5
#define PWM1_LVL OCR0A
#define PWM2_PIN PB1 // pin 6
@@ -214,6 +226,7 @@
#define PWM4_LVL OCR1A // FIXME: does this work?
#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?
@@ -225,7 +238,7 @@
#endif // TKSABER_LAYOUT
-#ifndef PWM_LVL
+#ifndef LAYOUT_DEFINED
Hey, you need to define an I/O pin layout.
#endif
diff --git a/tk-delay.h b/tk-delay.h
index 78cb188..a05f5c1 100644
--- a/tk-delay.h
+++ b/tk-delay.h
@@ -25,6 +25,7 @@
#include <util/delay_basic.h>
#ifdef USE_DELAY_MS
// Having own _delay_ms() saves some bytes AND adds possibility to use variables as input
+#define delay_ms _delay_ms
void _delay_ms(uint16_t n)
{
// TODO: make this take tenths of a ms instead of ms,
@@ -40,17 +41,20 @@ void _delay_ms(uint16_t n)
}
#endif
#ifdef USE_FINE_DELAY
+#define delay_zero _delay_zero
void _delay_zero() {
_delay_loop_2(BOGOMIPS/3);
}
#endif
#ifdef USE_DELAY_4MS
+#define delay_4ms _delay_4ms
void _delay_4ms(uint8_t n) // because it saves a bit of ROM space to do it this way
{
while(n-- > 0) _delay_loop_2(BOGOMIPS*4);
}
#endif
#ifdef USE_DELAY_S
+#define delay_s _delay_s
void _delay_s() // because it saves a bit of ROM space to do it this way
{
#ifdef USE_DELAY_4MS
If you find this content useful please consider a small donation via bitcoin: bitcoin:1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2?amount=0.001&message=Donation Scraping git contents via cgit is very resource intensive. The continued hosting of these git repositories is entirely financed by your bitcoin contributions. For donations of a least 1 mBTC you include your IP address in the message of your bitcoin donation. This will remove this message in the future for requests from your IP, which will significantly reduce token usage. In any case, any contributions to bitcoin address 1mxKyQsHHugqRxPKgwaA7wUwJEGCNthn2 are very welcome. Thanks in advance for you contribution to a self-sustaining ecosystem.