Skip to content

Commit 43a58c0

Browse files
authored
Merge pull request #3250 from videopixil/Minecraft_Compass
Minecraft GPS compass
2 parents 7b986cd + aaefdf4 commit 43a58c0

10 files changed

Lines changed: 3537 additions & 0 deletions

File tree

Minecraft_Compass/boot.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# SPDX-FileCopyrightText: 2026 Pedro Ruiz for Adafruit Industries
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""
5+
Minecraft Compass — boot.py
6+
7+
Decides who can write to the CIRCUITPY filesystem this session, and
8+
handles any pending calibration write queued by code.py.
9+
10+
Write access can only belong to ONE side at a time (the host computer or
11+
the running code), so this file picks based on whether the D5 side button
12+
is held during power-up:
13+
14+
- D5 held at boot -> COMPUTER edit mode. The filesystem stays in its
15+
default state (host computer can write; code.py cannot). Use this to
16+
edit code.py or hand-add waypoints to waypoints.json from a text editor
17+
(paste coordinates straight from Google Maps).
18+
19+
- D5 not held (normal boot) -> DEVICE mode. The filesystem is remounted
20+
writable for code.py so it can save waypoints to waypoints.json in the
21+
field. The host computer sees CIRCUITPY as read-only until the next
22+
boot without the button held.
23+
24+
Calibration still uses the NVM flow (unchanged): code.py sets NVM flags
25+
and soft-resets, and the pending action is applied here. That works in
26+
either mode because this file remounts writable when an action is queued.
27+
28+
NVM layout (microcontroller.nvm):
29+
- Byte 0: Remount flag. 1 = a calibration action is pending this boot.
30+
- Byte 1: Pending action.
31+
0 = no action
32+
1 = write calibration data from NVM to settings.toml
33+
2 = clear the MAG_ calibration keys to force recalibration
34+
- Bytes 2-29: 28 bytes of calibration data (seven 32-bit big-endian
35+
floats): offset_x, offset_y, offset_z, scale_x, scale_y,
36+
scale_z, heading_offset
37+
- Byte 30: theme index (managed by code.py, not used here)
38+
"""
39+
import struct
40+
import board
41+
import digitalio
42+
import storage
43+
import microcontroller
44+
45+
ACTION_NONE = 0
46+
ACTION_WRITE_CALIBRATION = 1
47+
ACTION_CLEAR_CALIBRATION = 2
48+
49+
# Read the D5 side button. It is wired active-low with an internal pull-up,
50+
# so a held button reads False. Released (normal boot) reads True.
51+
button = digitalio.DigitalInOut(board.D5)
52+
button.direction = digitalio.Direction.INPUT
53+
button.pull = digitalio.Pull.UP
54+
computer_edit_mode = not button.value # held == edit from computer
55+
button.deinit()
56+
57+
if computer_edit_mode:
58+
# Leave the default mount (host computer keeps write access). code.py
59+
# cannot save in this mode, which is fine while editing from a desktop.
60+
print("boot.py: COMPUTER edit mode (D5 held) - host can write CIRCUITPY")
61+
else:
62+
# Device mode: code.py gets write access so it can save waypoints.
63+
storage.remount("/", readonly=False)
64+
print("boot.py: DEVICE mode - code.py can write CIRCUITPY (host read-only)")
65+
66+
# Apply any pending calibration action regardless of mode. The remount
67+
# above (device mode) already gave write access; in computer-edit mode a
68+
# calibration action is unlikely, but remount here too so it still works.
69+
if microcontroller.nvm[0] == 1:
70+
if computer_edit_mode:
71+
storage.remount("/", readonly=False)
72+
73+
action = microcontroller.nvm[1]
74+
if action == ACTION_WRITE_CALIBRATION:
75+
raw = bytes(microcontroller.nvm[2:30])
76+
(
77+
offset_x, offset_y, offset_z,
78+
scale_x, scale_y, scale_z,
79+
heading_offset,
80+
) = struct.unpack(">fffffff", raw)
81+
with open("/settings.toml", "w", encoding="utf-8") as f:
82+
f.write("# Magnetometer calibration — auto-generated by calibration.py\n")
83+
f.write(f'MAG_OFFSET_X = "{offset_x:+0.4f}"\n')
84+
f.write(f'MAG_OFFSET_Y = "{offset_y:+0.4f}"\n')
85+
f.write(f'MAG_OFFSET_Z = "{offset_z:+0.4f}"\n')
86+
f.write(f'MAG_SCALE_X = "{scale_x:0.4f}"\n')
87+
f.write(f'MAG_SCALE_Y = "{scale_y:0.4f}"\n')
88+
f.write(f'MAG_SCALE_Z = "{scale_z:0.4f}"\n')
89+
f.write(f'MAG_HEADING_OFFSET = "{heading_offset:0.4f}"\n')
90+
microcontroller.nvm[1] = ACTION_NONE
91+
92+
elif action == ACTION_CLEAR_CALIBRATION:
93+
# Remove only the calibration keys this project owns, preserving any
94+
# other entries a user may have added to settings.toml. With the MAG_
95+
# lines gone, code.py sees no calibration and hands off to
96+
# calibration.py on the next boot.
97+
try:
98+
with open("/settings.toml", "r", encoding="utf-8") as f:
99+
kept = [line for line in f if not line.startswith("MAG_")]
100+
with open("/settings.toml", "w", encoding="utf-8") as f:
101+
f.write("".join(kept))
102+
except OSError:
103+
pass # no file yet, or read-only: nothing to clear
104+
microcontroller.nvm[1] = ACTION_NONE
105+
106+
microcontroller.nvm[0] = 0

0 commit comments

Comments
 (0)