From 5a4bf238055478d8ec53b5ff59f1f150cfc6a01e Mon Sep 17 00:00:00 2001 From: Starfall Date: Tue, 4 Mar 2025 12:34:48 -0600 Subject: Initial commit --- blade.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ blade.h | 11 +++++++++ input.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ input.h | 13 +++++++++++ saber.ino | 29 +++++++++++++++++++++++ 5 files changed, 207 insertions(+) create mode 100644 blade.cpp create mode 100644 blade.h create mode 100644 input.cpp create mode 100644 input.h create mode 100644 saber.ino diff --git a/blade.cpp b/blade.cpp new file mode 100644 index 0000000..381c1dc --- /dev/null +++ b/blade.cpp @@ -0,0 +1,80 @@ +#include "blade.h" + +#define LED_PIN 6 +#define LED_COUNT 32 + +CRGB blade[LED_COUNT]; +CHSV blade_color = CHSV(144, 255, 216); + +#define BLADE_OFF 0 +#define BLADE_ON 1 +#define BLADE_IGNITE 2 +#define BLADE_RETRACT 3 +uint8_t state = BLADE_OFF; + +#define IGNITE_MS 200 +#define RETRACT_MS 400 +uint32_t anim_start; + +void setup_blade() { + FastLED.addLeds(blade, LED_COUNT); +} + +void draw_blade() { + int num_lit = LED_COUNT; + + switch(state) { + case BLADE_OFF: + return; + + case BLADE_ON: + if(blade[0] == blade_color) return; + break; + + case BLADE_IGNITE: + num_lit = (millis() - anim_start) * LED_COUNT / IGNITE_MS; + if(num_lit >= LED_COUNT) { + state = BLADE_ON; + num_lit = LED_COUNT; + } + break; + + case BLADE_RETRACT: + num_lit = LED_COUNT - (millis() - anim_start) * LED_COUNT / RETRACT_MS; + if(num_lit <= 0) { + state = BLADE_OFF; + num_lit = 0; + } + break; + } + + for(int i = 0; i < num_lit; i++) { + blade[i] = CHSV(blade_color.h - i, blade_color.s - i - i, blade_color.v); + } + for(int i = num_lit; i < LED_COUNT; i++) { + blade[i] = CRGB::Black; + } + FastLED.show(); +} + +// good blade colors +// skywalker blue (136, 255, 216) +// blue-white (144, 128, 216) + +void change_hue(uint8_t d) { + blade_color.h += d; +} + +void change_sat(uint8_t d) { + blade_color.s += d; +} + +void toggle_blade() { + if(state == BLADE_OFF) { + state = BLADE_IGNITE; + anim_start = millis(); + } else { + state = BLADE_RETRACT; + anim_start = millis(); + } +} \ No newline at end of file diff --git a/blade.h b/blade.h new file mode 100644 index 0000000..0e7e34a --- /dev/null +++ b/blade.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +void setup_blade(); +void draw_blade(); + +void toggle_blade(); +void change_hue(uint8_t); +void change_sat(uint8_t); diff --git a/input.cpp b/input.cpp new file mode 100644 index 0000000..ec95b1e --- /dev/null +++ b/input.cpp @@ -0,0 +1,74 @@ +#include "input.h" + +#define CLK_PIN 2 +#define DT_PIN 3 +#define SW_PIN 4 + +Encoder encoder(CLK_PIN, DT_PIN); +void setup_input() { + pinMode(SW_PIN, INPUT_PULLUP); +} + +#define KNOB_DIR -1 +uint32_t read_knob() { + uint32_t rotate = KNOB_DIR * encoder.read() / 4; + if(rotate != 0) { + encoder.write(0); + } + return rotate; +} + +// button physical state +#define PRESSED 0 +#define RELEASED 1 +uint8_t pstate = RELEASED; +#define DEBOUNCE_CYCLES 3 +uint8_t debounce; + +uint8_t debounced_read() { + byte read = digitalRead(SW_PIN); + if (read != pstate && ++debounce >= DEBOUNCE_CYCLES) { + pstate = read; + debounce = 0; + } + return pstate; +} + +// button logical state +#define DOWN 0 +#define UP 1 +#define LONGPRESS 2 +uint8_t lstate = UP; + +#define LONGPRESS_MS 500 +uint32_t pressed_at; + +uint8_t read_button() { + uint8_t read = debounced_read(); + + switch(lstate) { + case UP: + if(read == PRESSED) { + lstate = DOWN; + pressed_at = millis(); + } + break; + + case DOWN: + if(millis() - pressed_at >= LONGPRESS_MS) { + lstate = LONGPRESS; + return EVENT_HOLD; + } + if(read == RELEASED) { + lstate = UP; + return EVENT_CLICK; + } + break; + + case LONGPRESS: + if(read == RELEASED) lstate = UP; + break; + } + + return EVENT_NONE; +} diff --git a/input.h b/input.h new file mode 100644 index 0000000..a772835 --- /dev/null +++ b/input.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include + +void setup_input(); + +uint32_t read_knob(); + +#define EVENT_NONE 0 +#define EVENT_CLICK 1 +#define EVENT_HOLD 2 +uint8_t read_button(); diff --git a/saber.ino b/saber.ino new file mode 100644 index 0000000..3ee7ca4 --- /dev/null +++ b/saber.ino @@ -0,0 +1,29 @@ +#include "input.h" +#include "blade.h" + +// TODO for simple storage #include + +void setup() { + Serial.begin(9600); + Serial.println("Hello, world!"); + + setup_input(); + setup_blade(); +} + +void loop() { + uint32_t knob = read_knob(); + if(knob != 0) { + change_hue(16 * knob); + } + + byte button = read_button(); + if(button == EVENT_CLICK) { + toggle_blade(); + } + if(button == EVENT_HOLD) { + Serial.println("long press"); + } + + draw_blade(); +} -- cgit