From 837932c257d72bbeb9b4911486f1bbf30c983cb3 Mon Sep 17 00:00:00 2001 From: Neale Pickett Date: Sun, 31 Dec 2023 10:11:55 -0700 Subject: [PATCH] Attempt to automate build --- .gitignore | 1 + Makefile | 55 +++++++++++++++++-- holiday-lights.ino | 131 ++++++++++++--------------------------------- install.sh | 15 ++++++ 4 files changed, 100 insertions(+), 102 deletions(-) create mode 100644 .gitignore create mode 100755 install.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..567609b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/Makefile b/Makefile index b90fe5d..aae740a 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,52 @@ -#FQBN = adafruit:samd:adafruit_trinket_m0 -FQBN = adafruit:avr:protrinket5 +PACKAGE = holiday-lights -install: holiday-lights.ino - arduino --upload --board $(FQBN) $@ +FQBN_QTPY = adafruit:samd:adafruit_qtpy_m0 +FQBN_XIAO = Seeeduino:samd:seeed_XIAO_m0 +UF2_MOUNT = /mnt/chromeos/removable/Arduino +ARDUINO_DIR = /app/Arduino +BUILDER = flatpak run --command ${ARDUINO_DIR}/arduino-builder cc.arduino.arduinoide + +default: build/$(PACKAGE).qtpy.uf2 build/$(PACKAGE).xiao.uf2 +install: build/$(PACKAGE).xiao.uf2 + ./install.sh $< $(UF2_MOUNT) + +clean: + rm -rf build/* + +# uf2conv.py is covered by an MIT license. +build/uf2conv.py: build/uf2families.json + mkdir -p build + curl -L https://raw.githubusercontent.com/microsoft/uf2/master/utils/$(@F) > $@ + chmod +x $@ +build/uf2families.json: + mkdir -p build + curl -L https://raw.githubusercontent.com/microsoft/uf2/master/utils/$(@F) > $@ + +%.xiao.uf2: %.xiao.bin build/uf2conv.py + build/uf2conv.py -b 0x2000 -c -o $@ $< + +%.qtpy.uf2: %.qtpy.bin build/uf2conv.py + build/uf2conv.py -b 0x2000 -c -o $@ $< + +build/%.qtpy.bin: FQBN = $(FQBN_QTPY) +build/%.xiao.bin: FQBN = $(FQBN_XIAO) +build/$(PACKAGE).%.bin: $(PACKAGE).ino *.cpp *.h + mkdir -p build/$* + arduino-builder \ + -build-cache ~/.cache/arduino \ + -build-path build/$* \ + -core-api-version 10813 \ + -fqbn $(FQBN) \ + -hardware ~/.arduino15/packages \ + -tools $(ARDUINO_DIR)/tools-builder \ + -tools ~/.arduino15/packages \ + -hardware $(ARDUINO_DIR)/hardware \ + -hardware ~/.arduino15/packages \ + -built-in-libraries $(ARDUINO_DIR)/libraries \ + -libraries ~/Arduino/libraries \ + -compile \ + $< + mv build/$*/$( #include "Debounce.h" #include "durations.h" #include "morse.h" #include "pulse.h" -// Do you want it to run forever, or cycle every 24 hours? -#ifdef TINY -#define FOREVER true -#else -#define FOREVER false -#endif - -// Which pin your LED strip is connected to -#if defined(TINY) -#define NEOPIXEL_PIN 3 -#elif defined(ADAFRUIT_TRINKET_M0) -#define NEOPIXEL_PIN 2 -#else -#define NEOPIXEL_PIN 6 -#endif +// Which pins your LED strips are connected to +#define NUM_OUTPUTS 2 +#define OUTPUT_PIN1 7 +#define OUTPUT_PIN2 8 // Which pin has the momentary switch to toggle full white. #define BUTTON_PIN 4 -// How many LEDs you have. It's okay if this is too big. +// How many LEDs you have per output. It's okay if this is too big. #define LEDS_PER_GROUP 10 -#ifdef TINY -#define NUM_GROUPS 7 -#else -#define NUM_GROUPS 20 -#endif +#define NUM_GROUPS 10 #define NUM_LEDS (LEDS_PER_GROUP * NUM_GROUPS) // How many milliseconds between activity in one group @@ -52,33 +33,22 @@ // How long a dit lasts #define DIT_DURATION_MS 150 -// Color for all-white mode -#define WHITE 0x886655 - -// The Neopixel library masks interrupts while writing. -// This means you lose time. -// How much time do you lose? -// I'm guessing 10 minutes a day. - -#define SNOSSLOSS_DAY (DURATION_DAY - (10 * DURATION_MINUTE)) -#define ON_FOR (6 * DURATION_HOUR) - #define ARK "\x03\x04" const char *message = ( - "seasons greetings" ARK "happy holiday" ARK "merry xmas" ARK "happy new year" ARK "CQ CQ OF9X" ARK - ); -CRGB leds[NUM_LEDS]; +CRGB leds[NUM_OUTPUTS][NUM_LEDS]; Debounce button(BUTTON_PIN, false, true); void setup() { - FastLED.addLeds(leds, NUM_LEDS); + FastLED.addLeds(leds[0], NUM_LEDS); + FastLED.addLeds(leds[1], NUM_LEDS); + FastLED.setTemperature(Tungsten40W); FastLED.setBrightness(52); pinMode(LED_BUILTIN, OUTPUT); } @@ -100,94 +70,59 @@ uint8_t RandomHue() { } } -Pulse mainPulse = Pulse(DELAY_MS); bool strandUpdate(unsigned long now, bool white) { - if (!mainPulse.Ticked(now)) { + static Pulse pulse = Pulse(DELAY_MS); + if (!pulse.Ticked(now)) { return false; } - for (int group = 0; group < NUM_GROUPS; ++group) { - int pos = (group * LEDS_PER_GROUP) + random(LEDS_PER_GROUP); - if (random(100) < GROUP_UPDATE_PROBABILITY) { - uint8_t hue = 0; - uint8_t saturation = 255; - uint8_t value = 255; - if (random(100) < ACTIVITY) { - if (white) { - saturation = 0; - } else { + for (int output = 0; output < NUM_OUTPUTS; output += 1) { + for (int group = 0; group < NUM_GROUPS; group += 1) { + int pos = (group * LEDS_PER_GROUP) + random(LEDS_PER_GROUP); + if (random(100) < GROUP_UPDATE_PROBABILITY) { + uint8_t hue = 0; + uint8_t saturation = white?0:255; + uint8_t value = 255; + if (random(100) < ACTIVITY) { hue = RandomHue(); + } else { + value = 0; } - } else { - value = 0; + leds[output][pos] = CHSV(hue, saturation, value); + group = (group + 1) % NUM_GROUPS; } - leds[pos] = CHSV(hue, saturation, value); - group = (group + 1) % NUM_GROUPS; } } return true; } -bool black(unsigned long now) { - if (!mainPulse.Ticked(now)) { - return false; - } - - FastLED.clear(); - - return true; -} - bool morseUpdate(unsigned long now) { static MorseEncoder enc; static Pulse pulse = Pulse(DIT_DURATION_MS); - bool ret = false; - - if (pulse.Ticked(now)) { - if (!enc.Tick()) { - enc.SetText(message); - } - ret = true; + if (!pulse.Ticked(now)) { + return false; } - leds[MORSE_PIXEL] = enc.Transmitting ? MORSE_COLOR : CRGB::Black; - return ret; -} - -bool timeUpdate(unsigned long now, unsigned long timeLeft) { - unsigned int hoursLeft = timeLeft / DURATION_HOUR; - unsigned int minutesLeft = (timeLeft / DURATION_MINUTE) % 60; - - int i; - for (i = 0; i < hoursLeft; ++i) { - leds[i] = CHSV(0, 255, 32); + if (!enc.Tick()) { + enc.SetText(message); } - if ((timeLeft / DELAY_MS) % minutesLeft == 0) { - leds[i]= CHSV(0, 255, 32); - } else { - leds[i] = CRGB::Black; - } - return false; + leds[0][MORSE_PIXEL] = enc.Transmitting ? MORSE_COLOR : CRGB::Black; + + return true; } void loop() { bool white = false; bool update = false; unsigned long now = millis(); // Everybody uses the same time so we don't do spurious updates 5ms apart - unsigned long timeOfDay = now % DURATION_DAY; button.read(); white = (button.count() % 2 == 1); - if (FOREVER || white || (timeOfDay < ON_FOR)) { - update |= strandUpdate(now, white); - update |= morseUpdate(now); - } else { - update |= black(now); - update |= timeUpdate(now, DURATION_DAY - timeOfDay); - } + update |= strandUpdate(now, white); + //update |= morseUpdate(now); if (update) { FastLED.show(); diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..3ca4683 --- /dev/null +++ b/install.sh @@ -0,0 +1,15 @@ +#! /bin/sh + +src=$1 +dst=$2 + +info=$dst/INFO_UF2.txt +echo -n "Waiting for $info to appear..." +while ! [ -f $info ]; do + echo -n "." + sleep 1 +done +echo "👍" + +cp $src $dst +echo "Installed!"