From e96562e36df96ca755d527e479e597ae4e4e09e1 Mon Sep 17 00:00:00 2001
From: Selene ToyKeeper
Date: Fri, 18 Aug 2017 18:12:17 -0600
Subject: Some early ideas for Round Table. Nothing close to compile-able yet.
---
RoundTable/momentary.c | 68 +++++++++
RoundTable/round-table.c | 367 +++++++++++++++++++++++++++++++++++++++++++++++
RoundTable/rt-ramping.h | 26 ++++
3 files changed, 461 insertions(+)
create mode 100644 RoundTable/momentary.c
create mode 100644 RoundTable/round-table.c
create mode 100644 RoundTable/rt-ramping.h
(limited to 'RoundTable')
diff --git a/RoundTable/momentary.c b/RoundTable/momentary.c
new file mode 100644
index 0000000..120406e
--- /dev/null
+++ b/RoundTable/momentary.c
@@ -0,0 +1,68 @@
+/*
+ * Momentary: Very simple example UI for RoundTable.
+ * Is intended to be the simplest possible RT e-switch UI.
+ * The light is in while the button is held; off otherwise.
+ *
+ * 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 .
+ */
+
+#define RT_EMISAR_D4_LAYOUT
+#include "round-table.c"
+
+volatile uint8_t brightness;
+
+void light_on() {
+ PWM1_LVL = brightness;
+ PWM2_LVL = 0;
+}
+
+void light_off() {
+ PWM1_LVL = 0;
+ PWM2_LVL = 0;
+}
+
+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;
+
+ case EV_release:
+ light_off();
+ // reset current event queue
+ empty_event_sequence();
+ 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;
+ }
+ return 1; // event not handled
+}
+
+void setup() {
+ set_state(momentary_state);
+}
diff --git a/RoundTable/round-table.c b/RoundTable/round-table.c
new file mode 100644
index 0000000..6cd1b10
--- /dev/null
+++ b/RoundTable/round-table.c
@@ -0,0 +1,367 @@
+#include "tk-attiny.h"
+
+//
+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;
+
+volatile StatePtr current_state;
+#define EV_MAX_LEN 16
+volatile uint8_t current_event[EV_MAX_LEN];
+
+volatile int16_t voltage;
+#ifdef USE_THERMAL_REGULATION
+volatile int16_t temperature;
+#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
+
+// 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
+typedef PROGMEM const uint8_t Event;
+typedef Event* EventPtr;
+Event EV_enter_state[] = {
+ A_ENTER_STATE,
+ 0 } ;
+Event EV_leave_state[] = {
+ A_LEAVE_STATE,
+ 0 } ;
+Event EV_tick[] = {
+ A_TICK,
+ 0 } ;
+Event EV_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_press_release[] = {
+ A_PRESS,
+ A_RELEASE,
+ 0 };
+#define EV_1click EV_press_release_timeout
+Event EV_press_release_timeout[] = {
+ A_PRESS,
+ A_RELEASE,
+ A_RELEASE_TIMEOUT,
+ 0 };
+#define EV_hold EV_press_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[] = {
+ A_PRESS,
+ A_HOLD_TIMEOUT,
+ 0 };
+Event EV_press_hold_release[] = {
+ A_PRESS,
+ A_HOLD_TIMEOUT,
+ A_RELEASE,
+ 0 };
+Event EV_press_release_press[] = {
+ A_PRESS,
+ A_RELEASE,
+ A_PRESS,
+ 0 };
+Event EV_press_release_press_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[] = {
+ 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_press,
+ EV_press_release,
+ EV_press_release_timeout,
+ EV_press_release_press,
+ EV_press_release_press_release,
+ EV_press_release_press_release_timeout,
+ // ...
+};
+
+// 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.
+ */
+
+// TODO: ramp tables
+// TODO: RAMP_SIZE / MAX_LVL
+// TODO: actual_lvl
+// TODO: target_lvl
+// TODO: set_lvl
+// TODO: set_lvl_smooth
--
cgit v1.2.3