aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-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