Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • flow3r/flow3r-firmware
  • Vespasian/flow3r-firmware
  • alxndr42/flow3r-firmware
  • pl/flow3r-firmware
  • Kari/flow3r-firmware
  • raimue/flow3r-firmware
  • grandchild/flow3r-firmware
  • mu5tach3/flow3r-firmware
  • Nervengift/flow3r-firmware
  • arachnist/flow3r-firmware
  • TheNewCivilian/flow3r-firmware
  • alibi/flow3r-firmware
  • manuel_v/flow3r-firmware
  • xeniter/flow3r-firmware
  • maxbachmann/flow3r-firmware
  • yGifoom/flow3r-firmware
  • istobic/flow3r-firmware
  • EiNSTeiN_/flow3r-firmware
  • gnudalf/flow3r-firmware
  • 999eagle/flow3r-firmware
  • toerb/flow3r-firmware
  • pandark/flow3r-firmware
  • teal/flow3r-firmware
  • x42/flow3r-firmware
  • alufers/flow3r-firmware
  • dos/flow3r-firmware
  • yrlf/flow3r-firmware
  • LuKaRo/flow3r-firmware
  • ThomasElRubio/flow3r-firmware
  • ai/flow3r-firmware
  • T_X/flow3r-firmware
  • highTower/flow3r-firmware
  • beanieboi/flow3r-firmware
  • Woazboat/flow3r-firmware
  • gooniesbro/flow3r-firmware
  • marvino/flow3r-firmware
  • kressnerd/flow3r-firmware
  • quazgar/flow3r-firmware
  • aoid/flow3r-firmware
  • jkj/flow3r-firmware
  • naomi/flow3r-firmware
41 results
Show changes
Commits on Source (19)
Showing
with 217 additions and 38 deletions
......@@ -9,7 +9,7 @@ variables:
default:
# built via:
# docker load < $(nix-build nix/docker-image.nix)
image: registry.k0.hswaw.net/q3k/flow3r-build:v4ljgs5czzm6j79m7r30vw6xz6990kkv
image: registry.k0.hswaw.net/q3k/flow3r-build:ymrsh8w1z9l89qvvksw52k7sl54lx73q
clang-tidy:
stage: check
......@@ -72,3 +72,29 @@ pages:
artifacts:
paths: ['public']
expire_in: 1d
dist-branch:
stage: deploy
variables:
# Force a full clone to make version machinery work.
GIT_STRATEGY: clone
only:
- /^release\/[0-9]+\.[0-9]+\.[0-9]+$/
- branches
script:
- bash tools/dist.sh
artifacts:
paths: ['dist']
dist-tag:
stage: deploy
variables:
# Force a full clone to make version machinery work.
GIT_STRATEGY: clone
only:
- /^v\/[0-9]+\.[0-9]+\.[0-9]+.*$/
- tags
script:
- bash tools/dist.sh
artifacts:
paths: ['dist']
......@@ -210,7 +210,7 @@ esp_err_t flow3r_bsp_imu_init(flow3r_bsp_imu_t *imu) {
rslt = bmp5_init(&imu->bmp);
bmp5_error_codes_print_result("bmp5_init", rslt);
if (rslt != BMP5_OK) return ESP_FAIL;
if (rslt != BMP5_OK && rslt != BMP5_E_POWER_UP) return ESP_FAIL;
rslt = set_bmp_config(&imu->osr_odr_press_cfg, &imu->bmp);
if (rslt != BMP5_OK) return ESP_FAIL;
......
......@@ -56,6 +56,7 @@
#define MICROPY_USE_INTERNAL_PRINTF (0) // ESP32 SDK requires its own printf
#define MICROPY_SCHEDULER_DEPTH (8)
#define MICROPY_VFS (1)
#define MICROPY_READLINE_HISTORY_SIZE (32)
// control over Python builtins
#define MICROPY_PY_STR_BYTES_CMP_WARN (1)
......
......@@ -10,6 +10,7 @@ and the release process.
import subprocess
import sys
import os
class Tag:
......@@ -50,7 +51,7 @@ def tags_for_commit(release, commit):
return res
def get_version():
def get_git_based_version():
commit = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode().strip()
branches = (
subprocess.check_output(
......@@ -118,7 +119,15 @@ if len(sys.argv) > 1:
if sys.argv[1] == "-c":
fmt = "C"
v = get_version()
v = None
if os.environ.get('CI') is not None:
tag = os.environ.get('CI_COMMIT_TAG')
if tag is not None:
# If we're building a tag, just use that as a version.
v = tag
if v is None:
v = get_git_based_version()
if fmt == "C":
print('const char *st3m_version = "' + v + '";')
else:
......
......@@ -31,6 +31,8 @@ pkgs.dockerTools.buildImage {
gcc gnused findutils gnugrep
git wget gnumake
cmake ninja pkgconfig
gnutar curl bzip2
cacert
];
pathsToLink = [ "/bin" ];
};
......@@ -47,6 +49,7 @@ pkgs.dockerTools.buildImage {
"IDF_PATH=${pkgs.esp-idf}"
"IDF_COMPONENT_MANAGER=0"
"TMPDIR=/tmp"
"NIX_SSL_CERT_FILE=${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"
];
};
}
......@@ -26,19 +26,17 @@ class HarmonicApp(Application):
self.color_intensity = 0.0
self.chord_index = 0
self.chord: List[int] = []
self.synths = [blm.new(bl00mbox.patches.tinysynth_fm) for i in range(5)]
self.synths = [blm.new(bl00mbox.patches.tinysynth) for i in range(5)]
self.cp_prev = captouch.read()
for i, synth in enumerate(self.synths):
synth.signals.decay = 500
synth.signals.waveform = -32767
synth.signals.waveform = 0
synth.signals.attack = 50
synth.signals.volume = 0.3 * 32767
synth.signals.sustain = 0.9 * 32767
synth.signals.release = 800
synth.signals.fm_waveform = -32767
synth.signals.output = blm.mixer
# synth.fm = 1.5
self._set_chord(3)
self.prev_captouch = [0] * 10
......
......@@ -2,16 +2,15 @@ import bl00mbox
blm = bl00mbox.Channel("Melodic Demo")
import captouch
import leds
from st3m.goose import List, Optional
from st3m.input import InputState
from st3m.input import InputState, InputController
from st3m.ui.view import ViewManager
from ctx import Context
octave = 0
synths: List[bl00mbox.patches.tinysynth_fm] = []
synths: List[bl00mbox.patches.tinysynth] = []
scale = [0, 2, 4, 5, 7, 9, 11]
......@@ -44,13 +43,17 @@ def adjust_playing_field_to_octave() -> None:
change_playing_field_color(0, 55, 0)
def run(ins: InputState) -> None:
def run(input: InputController) -> None:
global scale
global octave
global synths
any_down = False
for i in range(10):
petal = ins.captouch.petals[i]
petal = input.captouch.petals[i].whole
if petal.down:
any_down = True
if petal.pressed:
any_down = True
if i == 6:
octave = -1
adjust_playing_field_to_octave()
......@@ -69,11 +72,14 @@ def run(ins: InputState) -> None:
synths[0].signals.pitch.tone = note
synths[0].signals.trigger.start()
if not any_down:
synths[0].signals.trigger.stop()
def init() -> None:
global synths
for i in range(1):
synth = blm.new(bl00mbox.patches.tinysynth_fm)
synth = blm.new(bl00mbox.patches.tinysynth)
synth.signals.output = blm.mixer
synths += [synth]
for synth in synths:
......@@ -105,4 +111,4 @@ class MelodicApp(Application):
def think(self, ins: InputState, delta_ms: int) -> None:
super().think(ins, delta_ms)
run(ins)
run(self.input)
......@@ -39,15 +39,15 @@ class Browser(ActionView):
self._scan_path()
def _on_action(self, index: int) -> None:
if index == 1:
if index == 4:
if self.current_pos > 0:
self.current_pos -= 1
self._update_position()
if index == 2:
self._up()
if index == 3:
self._up()
if index == 2:
self._select()
elif index == 4:
elif index == 1:
if self.current_pos < len(self.dir_entries) - 1:
self.current_pos += 1
self._update_position()
......@@ -144,10 +144,10 @@ class Browser(ActionView):
def _update_actions(self) -> None:
self.actions = [
Action(icon="\ue3e3", label="Menu", enabled=False),
Action(icon="\ue5cb", label="Prev", enabled=self.prev_enabled),
Action(icon="\ue5c4", label="Back", enabled=self.up_enabled),
Action(icon="\ue876", label="Select"),
Action(icon="\ue409", label="Next", enabled=self.next_enabled),
Action(icon="\ue876", label="Select"),
Action(icon="\ue5c4", label="Back", enabled=self.up_enabled),
Action(icon="\ue5cb", label="Prev", enabled=self.prev_enabled),
]
def _update_position(self) -> None:
......
......@@ -47,7 +47,7 @@ class ActionView(BaseView):
self.input = InputController()
for i in range(0, 5):
petal_angle = 2.0 * pi / 5.0
petal_angle = 2.0 * -pi / 5.0
self.action_x[i] = int(cos(-petal_angle * float(i) - pi / 2.0) * 100.0)
self.action_y[i] = int(sin(-petal_angle * float(i) - pi / 2.0) * 100.0)
......
......@@ -42,10 +42,10 @@ class Reader(ActionView):
self.actions = [
None,
Action(icon="\ue8d4", label="Scroll X"),
Action(icon="\ue5c4", label="Back"),
Action(icon="\ue8b6", label="Zoom"),
Action(icon="\ue8d5", label="Scroll Y"),
Action(icon="\ue8b6", label="Zoom"),
Action(icon="\ue5c4", label="Back"),
Action(icon="\ue8d4", label="Scroll X"),
]
# TODO: Buffered reading?
......@@ -62,14 +62,14 @@ class Reader(ActionView):
if self.is_loading:
return
if self.input.captouch.petals[4].whole.pressed:
if self.input.captouch.petals[6].whole.pressed:
self._back()
elif self.input.captouch.petals[6].whole.pressed:
elif self.input.captouch.petals[4].whole.pressed:
self.zoom_enabled = not self.zoom_enabled
# TODO: Use "joystick-style" input for scrolling
self.scroll_x.update(self.input.captouch.petals[2].gesture, delta_ms)
self.scroll_y.update(self.input.captouch.petals[8].gesture, delta_ms)
self.scroll_x.update(self.input.captouch.petals[8].gesture, delta_ms)
self.scroll_y.update(self.input.captouch.petals[2].gesture, delta_ms)
x = self.scroll_x.position[0] * 0.2
y = self.scroll_y.position[0] * 0.2
self.viewport_offset = (x - 80, y - 80)
......
......@@ -189,8 +189,6 @@ class ShoegazeApp(Application):
ctx.rgb(0, 0.6, 0)
ctx.text("fuzz off")
ctx.restore()
def think(self, ins: InputState, delta_ms: int) -> None:
super().think(ins, delta_ms)
......
......@@ -56,11 +56,11 @@ def _make_bundle_menu(bundles: List[BundleMetadata], kind: str) -> SimpleMenu:
return SimpleMenu(entries)
def _make_compositor(reactor: Reactor, r: Responder) -> overlays.Compositor:
def _make_compositor(reactor: Reactor, vm: ViewManager) -> overlays.Compositor:
"""
Set up top-level compositor (for combining viewmanager with overlays).
"""
compositor = overlays.Compositor(r)
compositor = overlays.Compositor(vm)
volume = overlays.OverlayVolume()
compositor.add_overlay(volume)
......@@ -75,6 +75,7 @@ def _make_compositor(reactor: Reactor, r: Responder) -> overlays.Compositor:
# Configure debug overlay fragments.
debug = overlays.OverlayDebug()
debug.add_fragment(overlays.DebugReactorStats(reactor))
debug.add_fragment(overlays.DebugBattery())
compositor.add_overlay(debug)
debug_touch = overlays.OverlayCaptouch()
......@@ -135,7 +136,6 @@ def run_main() -> None:
MenuItemAction("Disk Mode (SD)", machine.disk_mode_sd),
MenuItemLaunchPersistentView("About", About),
MenuItemAction("Yeet Local Changes", _yeet_local_changes),
MenuItemAction("Reboot", lambda: machine.reset()),
MenuItemAction("Reboot", machine.reset),
],
)
......
......@@ -9,6 +9,8 @@ etc.
from st3m import Responder, InputState, Reactor
from st3m.goose import Dict, Enum, List, ABCBase, abstractmethod, Optional
from st3m.utils import tau
from st3m.ui.view import ViewManager
from st3m.input import power
from ctx import Context
import math
......@@ -43,11 +45,11 @@ class Overlay(Responder):
class Compositor(Responder):
"""
A Compositor blends together some main Responder (usually a ViewManager)
alongside with active Overlays. Overlays can be enabled/disabled by kind.
A Compositor blends together some ViewManager alongside with active
Overlays. Overlays can be enabled/disabled by kind.
"""
def __init__(self, main: Responder):
def __init__(self, main: ViewManager):
self.main = main
self.overlays: Dict[OverlayKind, List[Responder]] = {}
self.enabled: Dict[OverlayKind, bool] = {
......@@ -61,6 +63,8 @@ class Compositor(Responder):
for kind in _all_kinds:
if not self.enabled.get(kind, False):
continue
if kind == OverlayKind.Indicators and not self.main.wants_icons():
continue
for overlay in self.overlays.get(kind, []):
res.append(overlay)
return res
......@@ -119,6 +123,17 @@ class DebugReactorStats(DebugFragment):
return " ".join(res)
class DebugBattery(DebugFragment):
"""
DebugFragment which provides the OverlayDebug with information about the
battery voltage.
"""
def text(self) -> str:
v = power.battery_voltage
return f"bat: {v:.2f}V"
class OverlayDebug(Overlay):
"""
Overlay which renders a text bar at the bottom of the screen with random
......
......@@ -211,3 +211,6 @@ class MenuController(BaseView):
Automatically called on canonical user input.
"""
self._items[self._scroll_controller.target_position()].press(self.vm)
def show_icons(self) -> bool:
return True
......@@ -25,6 +25,13 @@ class View(Responder):
"""
pass
def show_icons(self) -> bool:
"""
View should return True if it accepts having system icons drawn on top
if it.
"""
return False
class BaseView(View):
"""
......@@ -229,3 +236,12 @@ class ViewManager(Responder):
return
r = self._history.pop()
self.replace(r, override_vt)
def wants_icons(self) -> bool:
"""
Returns true if the current active view wants icon to be drawn on top of it.
"""
if self._incoming is not None:
return self._incoming.show_icons()
else:
return True
#!/usr/bin/env bash
# Builds an official distribution tarball for the firmware.
#
# Contains main firmware, recovery firmware and recovery bootloader.
set -e -x
if [ ! -f sdkconfig.defaults ] || [ ! -f recovery/sdkconfig.defaults ]; then
echo >/dev/stderr "Run this script for the root of the repository (ie. tools/dist.sh)."
exit 1
fi
# Always fetch full history on Gitlab when not building a tag, otherwise we get bogus results.
if [ ! -z "${CI}" && -z "${CI_COMMIT_TAG}" ]; then
git fetch --unshallow origin "$CI_COMMIT_REF_NAME"
git checkout "$CI_COMMIT_REF_NAME"
fi
version="$(python3 components/st3m/host-tools/version.py)"
rm -rf sdkconfig build
rm -rf recovery/sdkconfig recovery/build
idf.py build
( cd recovery ; idf.py build )
tmpdir="$(mktemp -d -t flow3r-dist-XXXX)"
function cleanup {
rm -rf "$tmpdir"
}
trap cleanup EXIT
name="flow3r-${version}"
distdir="${tmpdir}/${name}"
mkdir -p "${distdir}"
cp recovery/build/flow3r-recovery.bin "${distdir}/recovery.bin"
cp recovery/build/partition_table/partition-table.bin "${distdir}/partition-table.bin"
cp recovery/build/bootloader/bootloader.bin "${distdir}/bootloader.bin"
cp build/flow3r.bin "${distdir}/flow3r.bin"
cat > "${distdir}/README.txt" <<EOF
This is release ${version} of the flow3r firmware.
There are three ways to install this firmware to your badge:
// Option 1: Update via webflash
If you have a web browser which supports WebSerial, you can connect your badge
to your computer then navigate to:
https://flash.flow3r.garden/?v=${version}
// Option 2: Update via the badge
Put your badge into SD Card Disk Mode: either by selecting 'Disk Mode (SD)'
from the badge's System menu, or by rebooting into Recovery Mode (by holding
down the right trigger) and selecting 'Disk Mode (SD)' from there.
Now, with the badge connected to a computer, you should see a USB Mass Storage
('pendrive') appear. Copy flow3r.bin from this archive there.
Then, stop disk mode, and from either the System menu or Recovery Mode, select
'Flash Firmware Image', then flow3r.bin.
// Option 3: Update using esptool.py
You can also fully flash the badge, meaning you can update it even if its
firmware is totally bricked. To do that, start the badge in bootrom mode (this
is different from recovery mode!) by holding down the left trigger while
powering it up.
Then, run esptool.py with the following arguments:
esptool.py -p /dev/ttyACM0 -b 460800 \\
--before default_reset --after no_reset --chip esp32s3 \\
write_flash --flash_mode dio --flash_size 16MB --flash_freq 80m \\
0x0 bootloader.bin \\
0x8000 partition-table.bin \\
0x10000 recovery.bin \\
0x90000 flow3r.bin \\
-e
EOF
mkdir -p dist
tar="dist/${name}.tar.bz2"
tar -cjf "${tar}" -C "${tmpdir}" "${name}"
function upload() {
from=$1
to=$2
if [ ! -z "$CI_JOB_TOKEN" ]; then
curl --header "JOB-TOKEN: $CI_JOB_TOKEN" \
--upload-file "${from}" \
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/packages/generic/flow3r-firmware/${version}/${to}"
else
echo Would upload $from to $to
fi
}
upload "${tar}" "${name}.tar.bz2"
upload "${distdir}/recovery.bin" "recovery.bin"
upload "${distdir}/partition-table.bin" "partition-table.bin"
upload "${distdir}/bootloader.bin" "bootloader.bin"
upload "${distdir}/flow3r.bin" "flow3r.bin"