Merge pull request #313 from MichaelBell/battery-improvements
Badger2040 Micropython battery improvements
This commit is contained in:
commit
522c83dc19
|
@ -323,6 +323,8 @@ namespace pimoroni {
|
|||
void UC8151::setup(uint8_t speed) {
|
||||
reset();
|
||||
|
||||
_update_speed = speed;
|
||||
|
||||
if(speed == 0) {
|
||||
command(PSR, {
|
||||
RES_128x296 | LUT_OTP | FORMAT_BW | SHIFT_RIGHT | BOOSTER_ON | RESET_NONE
|
||||
|
@ -468,6 +470,25 @@ namespace pimoroni {
|
|||
setup(speed);
|
||||
}
|
||||
|
||||
uint8_t UC8151::update_speed() {
|
||||
return _update_speed;
|
||||
}
|
||||
|
||||
uint32_t UC8151::update_time() {
|
||||
switch(_update_speed) {
|
||||
case 0:
|
||||
return 5500;
|
||||
case 1:
|
||||
return 2600;
|
||||
case 2:
|
||||
return 1000;
|
||||
case 3:
|
||||
return 300;
|
||||
default:
|
||||
return 5500;
|
||||
}
|
||||
}
|
||||
|
||||
void UC8151::partial_update(int x, int y, int w, int h, bool blocking) {
|
||||
// y is given in columns ("banks"), which are groups of 8 horiontal pixels
|
||||
// x is given in pixels
|
||||
|
|
|
@ -146,6 +146,8 @@ namespace pimoroni {
|
|||
|
||||
bool inverted = false;
|
||||
|
||||
uint8_t _update_speed = 0;
|
||||
|
||||
public:
|
||||
UC8151(uint16_t width, uint16_t height) :
|
||||
width(width), height(height), frame_buffer(new uint8_t[width * height / 8]) {
|
||||
|
@ -199,6 +201,8 @@ namespace pimoroni {
|
|||
|
||||
void invert(bool invert);
|
||||
void update_speed(uint8_t speed);
|
||||
uint8_t update_speed();
|
||||
uint32_t update_time();
|
||||
void update(bool blocking = true);
|
||||
void partial_update(int x, int y, int w, int h, bool blocking = true);
|
||||
void off();
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace pimoroni {
|
|||
|
||||
gpio_set_function(USER, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(USER, GPIO_IN);
|
||||
gpio_set_pulls(USER, false, true);
|
||||
gpio_set_pulls(USER, true, false);
|
||||
|
||||
gpio_set_function(VBUS_DETECT, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(VBUS_DETECT, GPIO_IN);
|
||||
|
@ -195,8 +195,9 @@ namespace pimoroni {
|
|||
}
|
||||
|
||||
void Badger2040::update_button_states() {
|
||||
uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E);
|
||||
uint32_t mask = (1UL << A) | (1UL << B) | (1UL << C) | (1UL << D) | (1UL << E) | (1UL << USER);
|
||||
_button_states = gpio_get_all() & mask;
|
||||
_button_states ^= (1UL << USER); // USER button state is inverted
|
||||
}
|
||||
|
||||
uint32_t Badger2040::button_states() {
|
||||
|
@ -219,6 +220,10 @@ namespace pimoroni {
|
|||
uc8151.update_speed(speed);
|
||||
}
|
||||
|
||||
uint32_t Badger2040::update_time() {
|
||||
return uc8151.update_time();
|
||||
}
|
||||
|
||||
void Badger2040::partial_update(int x, int y, int w, int h, bool blocking) {
|
||||
uc8151.partial_update(x, y, w, h, blocking);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace pimoroni {
|
|||
void update(bool blocking=false);
|
||||
void partial_update(int x, int y, int w, int h, bool blocking=false);
|
||||
void update_speed(uint8_t speed);
|
||||
uint32_t update_time();
|
||||
void halt();
|
||||
void sleep();
|
||||
bool is_busy();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import badger2040
|
||||
import machine
|
||||
import time
|
||||
import badger2040
|
||||
import badger_os
|
||||
|
||||
# Global Constants
|
||||
WIDTH = badger2040.WIDTH
|
||||
|
@ -20,10 +20,6 @@ LEFT_PADDING = 5
|
|||
NAME_PADDING = 20
|
||||
DETAIL_SPACING = 10
|
||||
|
||||
OVERLAY_BORDER = 40
|
||||
OVERLAY_SPACING = 20
|
||||
OVERLAY_TEXT_SIZE = 0.6
|
||||
|
||||
DEFAULT_TEXT = """mustelid inc
|
||||
H. Badger
|
||||
RP2040
|
||||
|
@ -63,42 +59,6 @@ def truncatestring(text, text_size, width):
|
|||
# Drawing functions
|
||||
# ------------------------------
|
||||
|
||||
# Draw an overlay box with a given message within it
|
||||
def draw_overlay(message, width, height, line_spacing, text_size):
|
||||
|
||||
# Draw a light grey background
|
||||
display.pen(12)
|
||||
display.rectangle((WIDTH - width) // 2, (HEIGHT - height) // 2, width, height)
|
||||
|
||||
# Take the provided message and split it up into
|
||||
# lines that fit within the specified width
|
||||
words = message.split(" ")
|
||||
lines = []
|
||||
line = ""
|
||||
appended_line = ""
|
||||
for word in words:
|
||||
if len(word) > 0:
|
||||
appended_line += " "
|
||||
appended_line += word
|
||||
if display.measure_text(appended_line, text_size) >= width:
|
||||
lines.append(line)
|
||||
appended_line = word
|
||||
else:
|
||||
line = appended_line
|
||||
if len(line) != 0:
|
||||
lines.append(line)
|
||||
|
||||
display.pen(0)
|
||||
display.thickness(2)
|
||||
|
||||
# Display each line of text from the message, centre-aligned
|
||||
num_lines = len(lines)
|
||||
for i in range(num_lines):
|
||||
length = display.measure_text(lines[i], text_size)
|
||||
current_line = (i * line_spacing) - ((num_lines - 1) * line_spacing) // 2
|
||||
display.text(lines[i], (WIDTH - length) // 2, (HEIGHT // 2) + current_line, text_size)
|
||||
|
||||
|
||||
# Draw the badge, including user text
|
||||
def draw_badge():
|
||||
display.pen(0)
|
||||
|
@ -170,21 +130,19 @@ def draw_badge():
|
|||
# Program setup
|
||||
# ------------------------------
|
||||
|
||||
# Global variables
|
||||
show_overlay = False
|
||||
|
||||
# Create a new Badger and set it to update NORMAL
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
display.update_speed(badger2040.UPDATE_NORMAL)
|
||||
|
||||
# Open the badge file
|
||||
try:
|
||||
badge = open("badge.txt", "r")
|
||||
except OSError:
|
||||
badge = open("badge.txt", "w")
|
||||
badge.write(DEFAULT_TEXT)
|
||||
badge.flush()
|
||||
badge.seek(0)
|
||||
with open("badge.txt", "w") as f:
|
||||
f.write(DEFAULT_TEXT)
|
||||
f.flush()
|
||||
badge = open("badge.txt", "r")
|
||||
|
||||
# Read in the next 6 lines
|
||||
company = badge.readline() # "mustelid inc"
|
||||
|
@ -205,63 +163,21 @@ detail2_title = truncatestring(detail2_title, DETAILS_TEXT_SIZE, TEXT_WIDTH)
|
|||
detail2_text = truncatestring(detail2_text, DETAILS_TEXT_SIZE,
|
||||
TEXT_WIDTH - DETAIL_SPACING - display.measure_text(detail2_title, DETAILS_TEXT_SIZE))
|
||||
|
||||
# Set up the buttons
|
||||
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
|
||||
|
||||
# Button handling function
|
||||
def button(pin):
|
||||
global show_overlay
|
||||
|
||||
if pin == button_a:
|
||||
show_overlay = True
|
||||
return
|
||||
|
||||
if pin == button_b:
|
||||
show_overlay = True
|
||||
return
|
||||
|
||||
if pin == button_c:
|
||||
show_overlay = True
|
||||
return
|
||||
|
||||
if pin == button_up:
|
||||
show_overlay = True
|
||||
return
|
||||
|
||||
if pin == button_down:
|
||||
show_overlay = True
|
||||
return
|
||||
|
||||
|
||||
# Register the button handling function with the buttons
|
||||
button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
button_b.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
button_c.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
button_up.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
button_down.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
|
||||
|
||||
# ------------------------------
|
||||
# Main program loop
|
||||
# Main program
|
||||
# ------------------------------
|
||||
|
||||
draw_badge()
|
||||
display.update()
|
||||
|
||||
while True:
|
||||
if show_overlay:
|
||||
draw_overlay("To change the text, connect Badger2040 to a PC, load up Thonny, and modify badge.txt",
|
||||
WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, OVERLAY_TEXT_SIZE)
|
||||
display.update()
|
||||
if display.pressed(badger2040.BUTTON_A) or display.pressed(badger2040.BUTTON_B) or display.pressed(badger2040.BUTTON_C) or display.pressed(badger2040.BUTTON_UP) or display.pressed(badger2040.BUTTON_DOWN):
|
||||
badger_os.warning(display, "To change the text, connect Badger2040 to a PC, load up Thonny, and modify badge.txt")
|
||||
time.sleep(4)
|
||||
|
||||
draw_badge()
|
||||
display.update()
|
||||
show_overlay = False
|
||||
|
||||
time.sleep(0.1)
|
||||
display.update()
|
||||
|
||||
# If on battery, halt the Badger to save power, it will wake up if any of the front buttons are pressed
|
||||
display.halt()
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
"""Keep track of app state in persistent flash storage."""
|
||||
|
||||
import os
|
||||
import gc
|
||||
import time
|
||||
import json
|
||||
import machine
|
||||
import badger2040
|
||||
|
||||
|
||||
def get_battery_level():
|
||||
# Battery measurement
|
||||
vbat_adc = machine.ADC(badger2040.PIN_BATTERY)
|
||||
vref_adc = machine.ADC(badger2040.PIN_1V2_REF)
|
||||
vref_en = machine.Pin(badger2040.PIN_VREF_POWER)
|
||||
vref_en.init(machine.Pin.OUT)
|
||||
vref_en.value(0)
|
||||
|
||||
# Enable the onboard voltage reference
|
||||
vref_en.value(1)
|
||||
|
||||
# Calculate the logic supply voltage, as will be lower that the usual 3.3V when running off low batteries
|
||||
vdd = 1.24 * (65535 / vref_adc.read_u16())
|
||||
vbat = (
|
||||
(vbat_adc.read_u16() / 65535) * 3 * vdd
|
||||
) # 3 in this is a gain, not rounding of 3.3V
|
||||
|
||||
# Disable the onboard voltage reference
|
||||
vref_en.value(0)
|
||||
|
||||
# Convert the voltage to a level to display onscreen
|
||||
return vbat
|
||||
|
||||
|
||||
def get_disk_usage():
|
||||
# f_bfree and f_bavail should be the same?
|
||||
# f_files, f_ffree, f_favail and f_flag are unsupported.
|
||||
f_bsize, f_frsize, f_blocks, f_bfree, _, _, _, _, _, f_namemax = os.statvfs("/")
|
||||
|
||||
f_total_size = f_frsize * f_blocks
|
||||
f_total_free = f_bsize * f_bfree
|
||||
f_total_used = f_total_size - f_total_free
|
||||
|
||||
f_used = 100 / f_total_size * f_total_used
|
||||
f_free = 100 / f_total_size * f_total_free
|
||||
|
||||
return f_total_size, f_used, f_free
|
||||
|
||||
|
||||
def state_running():
|
||||
state = {"running": "launcher"}
|
||||
state_load("launcher", state)
|
||||
return state["running"]
|
||||
|
||||
|
||||
def state_clear_running():
|
||||
running = state_running()
|
||||
state_modify("launcher", {"running": "launcher"})
|
||||
return running != "launcher"
|
||||
|
||||
|
||||
def state_set_running(app):
|
||||
state_modify("launcher", {"running": app})
|
||||
|
||||
|
||||
def state_launch():
|
||||
app = state_running()
|
||||
if app is not None and app != "launcher":
|
||||
launch("_" + app)
|
||||
|
||||
|
||||
def state_delete(app):
|
||||
try:
|
||||
os.remove("/state/{}.json".format(app))
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
|
||||
def state_save(app, data):
|
||||
try:
|
||||
with open("/state/{}.json".format(app), "w") as f:
|
||||
f.write(json.dumps(data))
|
||||
f.flush()
|
||||
except OSError:
|
||||
import os
|
||||
try:
|
||||
os.stat("/state")
|
||||
except OSError:
|
||||
os.mkdir("/state")
|
||||
state_save(app, data)
|
||||
|
||||
|
||||
def state_modify(app, data):
|
||||
state = {}
|
||||
state_load(app, state)
|
||||
state.update(data)
|
||||
state_save(app, state)
|
||||
|
||||
|
||||
def state_load(app, defaults):
|
||||
try:
|
||||
data = json.loads(open("/state/{}.json".format(app), "r").read())
|
||||
if type(data) is dict:
|
||||
defaults.update(data)
|
||||
return True
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
|
||||
state_save(app, defaults)
|
||||
return False
|
||||
|
||||
|
||||
def launch(file):
|
||||
state_set_running(file[1:])
|
||||
|
||||
gc.collect()
|
||||
|
||||
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
|
||||
def quit_to_launcher(pin):
|
||||
if button_a.value() and button_c.value():
|
||||
machine.reset()
|
||||
|
||||
button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=quit_to_launcher)
|
||||
button_c.irq(trigger=machine.Pin.IRQ_RISING, handler=quit_to_launcher)
|
||||
|
||||
try:
|
||||
try:
|
||||
__import__(file[1:]) # Try to import _[file] (drop underscore prefix)
|
||||
except ImportError:
|
||||
__import__(file) # Failover to importing [_file]
|
||||
|
||||
except ImportError:
|
||||
# If the app doesn't exist, notify the user
|
||||
warning(None, "Could not launch: " + file[1:])
|
||||
time.sleep(4.0)
|
||||
except Exception as e:
|
||||
# If the app throws an error, catch it and display!
|
||||
print(e)
|
||||
warning(None, str(e))
|
||||
time.sleep(4.0)
|
||||
|
||||
# If the app exits or errors, do not relaunch!
|
||||
state_clear_running()
|
||||
machine.reset() # Exit back to launcher
|
||||
|
||||
|
||||
# Draw an overlay box with a given message within it
|
||||
def warning(display, message, width=badger2040.WIDTH - 40, height=badger2040.HEIGHT - 40, line_spacing=20, text_size=0.6):
|
||||
if display is None:
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
|
||||
# Draw a light grey background
|
||||
display.pen(12)
|
||||
display.rectangle((badger2040.WIDTH - width) // 2, (badger2040.HEIGHT - height) // 2, width, height)
|
||||
|
||||
# Take the provided message and split it up into
|
||||
# lines that fit within the specified width
|
||||
words = message.split(" ")
|
||||
|
||||
lines = []
|
||||
current_line = ""
|
||||
for word in words:
|
||||
if display.measure_text(current_line + word + " ", text_size) < width:
|
||||
current_line += word + " "
|
||||
else:
|
||||
lines.append(current_line.strip())
|
||||
current_line = word + " "
|
||||
lines.append(current_line.strip())
|
||||
|
||||
display.pen(0)
|
||||
display.thickness(2)
|
||||
|
||||
# Display each line of text from the message, centre-aligned
|
||||
num_lines = len(lines)
|
||||
for i in range(num_lines):
|
||||
length = display.measure_text(lines[i], text_size)
|
||||
current_line = (i * line_spacing) - ((num_lines - 1) * line_spacing) // 2
|
||||
display.text(lines[i], (badger2040.WIDTH - length) // 2, (badger2040.HEIGHT // 2) + current_line, text_size)
|
||||
|
||||
display.update()
|
|
@ -4,9 +4,10 @@ import badger2040
|
|||
|
||||
|
||||
rtc = machine.RTC()
|
||||
screen = badger2040.Badger2040()
|
||||
screen.update_speed(badger2040.UPDATE_TURBO)
|
||||
screen.font("gothic")
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
display.update_speed(badger2040.UPDATE_TURBO)
|
||||
display.font("gothic")
|
||||
|
||||
cursors = ["year", "month", "day", "hour", "minute"]
|
||||
set_clock = False
|
||||
|
@ -32,10 +33,13 @@ def days_in_month(month, year):
|
|||
def button(pin):
|
||||
global last, set_clock, cursor, year, month, day, hour, minute
|
||||
|
||||
time.sleep(0.05)
|
||||
time.sleep(0.01)
|
||||
if not pin.value():
|
||||
return
|
||||
|
||||
if button_a.value() and button_c.value():
|
||||
machine.reset()
|
||||
|
||||
adjust = 0
|
||||
changed = False
|
||||
|
||||
|
@ -94,42 +98,42 @@ def draw_clock():
|
|||
hms = "{:02}:{:02}:{:02}".format(hour, minute, second)
|
||||
ymd = "{:04}/{:02}/{:02}".format(year, month, day)
|
||||
|
||||
hms_width = screen.measure_text(hms, 1.8)
|
||||
hms_width = display.measure_text(hms, 1.8)
|
||||
hms_offset = int((badger2040.WIDTH / 2) - (hms_width / 2))
|
||||
h_width = screen.measure_text(hms[0:2], 1.8)
|
||||
mi_width = screen.measure_text(hms[3:5], 1.8)
|
||||
mi_offset = screen.measure_text(hms[0:3], 1.8)
|
||||
h_width = display.measure_text(hms[0:2], 1.8)
|
||||
mi_width = display.measure_text(hms[3:5], 1.8)
|
||||
mi_offset = display.measure_text(hms[0:3], 1.8)
|
||||
|
||||
ymd_width = screen.measure_text(ymd, 1.0)
|
||||
ymd_width = display.measure_text(ymd, 1.0)
|
||||
ymd_offset = int((badger2040.WIDTH / 2) - (ymd_width / 2))
|
||||
y_width = screen.measure_text(ymd[0:4], 1.0)
|
||||
m_width = screen.measure_text(ymd[5:7], 1.0)
|
||||
m_offset = screen.measure_text(ymd[0:5], 1.0)
|
||||
d_width = screen.measure_text(ymd[8:10], 1.0)
|
||||
d_offset = screen.measure_text(ymd[0:8], 1.0)
|
||||
y_width = display.measure_text(ymd[0:4], 1.0)
|
||||
m_width = display.measure_text(ymd[5:7], 1.0)
|
||||
m_offset = display.measure_text(ymd[0:5], 1.0)
|
||||
d_width = display.measure_text(ymd[8:10], 1.0)
|
||||
d_offset = display.measure_text(ymd[0:8], 1.0)
|
||||
|
||||
screen.pen(15)
|
||||
screen.clear()
|
||||
screen.pen(0)
|
||||
screen.thickness(5)
|
||||
screen.text(hms, hms_offset, 40, 1.8)
|
||||
screen.thickness(3)
|
||||
screen.text(ymd, ymd_offset, 100, 1.0)
|
||||
display.pen(15)
|
||||
display.clear()
|
||||
display.pen(0)
|
||||
display.thickness(5)
|
||||
display.text(hms, hms_offset, 40, 1.8)
|
||||
display.thickness(3)
|
||||
display.text(ymd, ymd_offset, 100, 1.0)
|
||||
|
||||
if set_clock:
|
||||
if cursors[cursor] == "year":
|
||||
screen.line(ymd_offset, 120, ymd_offset + y_width, 120)
|
||||
display.line(ymd_offset, 120, ymd_offset + y_width, 120)
|
||||
if cursors[cursor] == "month":
|
||||
screen.line(ymd_offset + m_offset, 120, ymd_offset + m_offset + m_width, 120)
|
||||
display.line(ymd_offset + m_offset, 120, ymd_offset + m_offset + m_width, 120)
|
||||
if cursors[cursor] == "day":
|
||||
screen.line(ymd_offset + d_offset, 120, ymd_offset + d_offset + d_width, 120)
|
||||
display.line(ymd_offset + d_offset, 120, ymd_offset + d_offset + d_width, 120)
|
||||
|
||||
if cursors[cursor] == "hour":
|
||||
screen.line(hms_offset, 70, hms_offset + h_width, 70)
|
||||
display.line(hms_offset, 70, hms_offset + h_width, 70)
|
||||
if cursors[cursor] == "minute":
|
||||
screen.line(hms_offset + mi_offset, 70, hms_offset + mi_offset + mi_width, 70)
|
||||
display.line(hms_offset + mi_offset, 70, hms_offset + mi_offset + mi_width, 70)
|
||||
|
||||
screen.update()
|
||||
display.update()
|
||||
|
||||
|
||||
year, month, day, wd, hour, minute, second, _ = rtc.datetime()
|
||||
|
@ -145,4 +149,4 @@ while True:
|
|||
if second != last_second:
|
||||
draw_clock()
|
||||
last_second = second
|
||||
time.sleep(0.1)
|
||||
time.sleep(0.01)
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import badger2040
|
||||
import machine
|
||||
import time
|
||||
import gc
|
||||
|
||||
import badger_os
|
||||
|
||||
# **** Put the name of your text file here *****
|
||||
text_file = "book.txt" # File must be on the MicroPython device
|
||||
|
@ -15,7 +14,10 @@ except OSError:
|
|||
# If the specified file doesn't exist,
|
||||
# pre-populate with Wind In The Willows
|
||||
import witw
|
||||
open(text_file, "wb").write(witw.data())
|
||||
with open(text_file, "wb") as f:
|
||||
f.write(witw.data())
|
||||
f.flush()
|
||||
time.sleep(0.1)
|
||||
del witw
|
||||
except ImportError:
|
||||
pass
|
||||
|
@ -33,9 +35,6 @@ ARROW_HEIGHT = 14
|
|||
ARROW_PADDING = 2
|
||||
|
||||
TEXT_PADDING = 4
|
||||
|
||||
TEXT_SIZE = 0.5
|
||||
TEXT_SPACING = int(34 * TEXT_SIZE)
|
||||
TEXT_WIDTH = WIDTH - TEXT_PADDING - TEXT_PADDING - ARROW_WIDTH
|
||||
|
||||
FONTS = ["sans", "gothic", "cursive", "serif"]
|
||||
|
@ -71,7 +70,7 @@ def draw_frame():
|
|||
display.rectangle(WIDTH - ARROW_WIDTH, 0, ARROW_WIDTH, HEIGHT)
|
||||
display.pen(0)
|
||||
display.thickness(ARROW_THICKNESS)
|
||||
if current_page > 1:
|
||||
if state["current_page"] > 0:
|
||||
draw_up(WIDTH - ARROW_WIDTH, (HEIGHT // 4) - (ARROW_HEIGHT // 2),
|
||||
ARROW_WIDTH, ARROW_HEIGHT, ARROW_THICKNESS, ARROW_PADDING)
|
||||
draw_down(WIDTH - ARROW_WIDTH, ((HEIGHT * 3) // 4) - (ARROW_HEIGHT // 2),
|
||||
|
@ -83,53 +82,23 @@ def draw_frame():
|
|||
# ------------------------------
|
||||
|
||||
# Global variables
|
||||
next_page = True
|
||||
prev_page = False
|
||||
change_font_size = False
|
||||
change_font = False
|
||||
last_offset = 0
|
||||
current_page = 0
|
||||
state = {
|
||||
"last_offset": 0,
|
||||
"current_page": 0,
|
||||
"font_idx": 0,
|
||||
"text_size": 0.5,
|
||||
"offsets": []
|
||||
}
|
||||
badger_os.state_load("ebook", state)
|
||||
|
||||
text_spacing = int(34 * state["text_size"])
|
||||
|
||||
|
||||
# Create a new Badger and set it to update FAST
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
display.update_speed(badger2040.UPDATE_FAST)
|
||||
|
||||
# Set up the buttons
|
||||
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
|
||||
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
|
||||
# Set up the activity LED
|
||||
led = machine.Pin(badger2040.PIN_LED, machine.Pin.OUT)
|
||||
|
||||
offsets = []
|
||||
|
||||
|
||||
# Button handling function
|
||||
def button(pin):
|
||||
global next_page, prev_page, change_font_size, change_font
|
||||
|
||||
if pin == button_down:
|
||||
next_page = True
|
||||
|
||||
if pin == button_up:
|
||||
prev_page = True
|
||||
|
||||
if pin == button_a:
|
||||
change_font_size = True
|
||||
|
||||
if pin == button_b:
|
||||
change_font = True
|
||||
|
||||
|
||||
# Register the button handling function with the buttons
|
||||
button_down.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
button_up.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
button_a.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
button_b.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
|
||||
|
||||
# ------------------------------
|
||||
# Render page
|
||||
|
@ -141,7 +110,7 @@ def render_page():
|
|||
pos = ebook.tell()
|
||||
next_pos = pos
|
||||
add_newline = False
|
||||
display.font(FONTS[0])
|
||||
display.font(FONTS[state["font_idx"]])
|
||||
|
||||
while True:
|
||||
# Read a full line and split it into words
|
||||
|
@ -180,7 +149,7 @@ def render_page():
|
|||
if len(line) > 0 and len(next_word) > 0:
|
||||
appended_line += " "
|
||||
appended_line += next_word
|
||||
appended_length = display.measure_text(appended_line, TEXT_SIZE)
|
||||
appended_length = display.measure_text(appended_line, state["text_size"])
|
||||
|
||||
# Would this appended line be longer than the text display area, or was a blank line spotted?
|
||||
if appended_length >= TEXT_WIDTH or add_newline:
|
||||
|
@ -189,14 +158,14 @@ def render_page():
|
|||
print(line)
|
||||
display.pen(0)
|
||||
display.thickness(FONT_THICKNESSES[0])
|
||||
display.text(line, TEXT_PADDING, (row * TEXT_SPACING) + (TEXT_SPACING // 2) + TEXT_PADDING, TEXT_SIZE)
|
||||
display.text(line, TEXT_PADDING, (row * text_spacing) + (text_spacing // 2) + TEXT_PADDING, state["text_size"])
|
||||
|
||||
# Clear the line and move on to the next row
|
||||
line = ""
|
||||
row += 1
|
||||
|
||||
# Have we reached the end of the page?
|
||||
if (row * TEXT_SPACING) + TEXT_SPACING >= HEIGHT:
|
||||
if (row * text_spacing) + text_spacing >= HEIGHT:
|
||||
print("+++++")
|
||||
display.update()
|
||||
|
||||
|
@ -212,7 +181,7 @@ def render_page():
|
|||
if add_newline:
|
||||
print("")
|
||||
row += 1
|
||||
if (row * TEXT_SPACING) + TEXT_SPACING >= HEIGHT:
|
||||
if (row * text_spacing) + text_spacing >= HEIGHT:
|
||||
print("+++++")
|
||||
display.update()
|
||||
return
|
||||
|
@ -227,50 +196,68 @@ def render_page():
|
|||
# Main program loop
|
||||
# ------------------------------
|
||||
|
||||
launch = True
|
||||
changed = False
|
||||
|
||||
# Open the book file
|
||||
ebook = open(text_file, "r")
|
||||
if len(state["offsets"]) > state["current_page"]:
|
||||
ebook.seek(state["offsets"][state["current_page"]])
|
||||
else:
|
||||
state["current_page"] = 0
|
||||
state["offsets"] = []
|
||||
|
||||
while True:
|
||||
# Was the next page button pressed?
|
||||
if next_page:
|
||||
current_page += 1
|
||||
if display.pressed(badger2040.BUTTON_DOWN):
|
||||
state["current_page"] += 1
|
||||
|
||||
# Is the next page one we've not displayed before?
|
||||
if current_page > len(offsets):
|
||||
offsets.append(ebook.tell()) # Add its start position to the offsets list
|
||||
draw_frame()
|
||||
render_page()
|
||||
next_page = False # Clear the next page button flag
|
||||
changed = True
|
||||
|
||||
# Was the previous page button pressed?
|
||||
if prev_page:
|
||||
if current_page > 1:
|
||||
current_page -= 1
|
||||
ebook.seek(offsets[current_page - 1]) # Retrieve the start position of the last page
|
||||
draw_frame()
|
||||
render_page()
|
||||
prev_page = False # Clear the prev page button flag
|
||||
if display.pressed(badger2040.BUTTON_UP):
|
||||
if state["current_page"] > 0:
|
||||
state["current_page"] -= 1
|
||||
if state["current_page"] == 0:
|
||||
ebook.seek(0)
|
||||
else:
|
||||
ebook.seek(state["offsets"][state["current_page"] - 1]) # Retrieve the start position of the last page
|
||||
changed = True
|
||||
|
||||
if change_font_size:
|
||||
TEXT_SIZE += 0.1
|
||||
if TEXT_SIZE > 0.8:
|
||||
TEXT_SIZE = 0.5
|
||||
TEXT_SPACING = int(34 * TEXT_SIZE)
|
||||
offsets = [0]
|
||||
if display.pressed(badger2040.BUTTON_A):
|
||||
state["text_size"] += 0.1
|
||||
if state["text_size"] > 0.8:
|
||||
state["text_size"] = 0.5
|
||||
text_spacing = int(34 * state["text_size"])
|
||||
state["offsets"] = []
|
||||
ebook.seek(0)
|
||||
current_page = 1
|
||||
state["current_page"] = 0
|
||||
changed = True
|
||||
|
||||
if display.pressed(badger2040.BUTTON_B):
|
||||
state["font_idx"] += 1
|
||||
if (state["font_idx"] >= len(FONTS)):
|
||||
state["font_idx"] = 0
|
||||
state["offsets"] = []
|
||||
ebook.seek(0)
|
||||
state["current_page"] = 0
|
||||
changed = True
|
||||
|
||||
if launch and not changed:
|
||||
if state["current_page"] > 0 and len(state["offsets"]) > state["current_page"] - 1:
|
||||
ebook.seek(state["offsets"][state["current_page"] - 1])
|
||||
changed = True
|
||||
launch = False
|
||||
|
||||
if changed:
|
||||
draw_frame()
|
||||
render_page()
|
||||
change_font_size = False
|
||||
|
||||
if change_font:
|
||||
FONTS.append(FONTS.pop(0))
|
||||
FONT_THICKNESSES.append(FONT_THICKNESSES.pop(0))
|
||||
offsets = [0]
|
||||
ebook.seek(0)
|
||||
current_page = 1
|
||||
draw_frame()
|
||||
render_page()
|
||||
change_font = False
|
||||
# Is the next page one we've not displayed before?
|
||||
if state["current_page"] >= len(state["offsets"]):
|
||||
state["offsets"].append(ebook.tell()) # Add its start position to the state["offsets"] list
|
||||
badger_os.state_save("ebook", state)
|
||||
|
||||
time.sleep(0.1)
|
||||
changed = False
|
||||
|
||||
display.halt()
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import badger2040
|
||||
import machine
|
||||
import time
|
||||
import badger_os
|
||||
|
||||
# Global Constants
|
||||
FONT_NAMES = ("sans", "gothic", "cursive", "serif", "serif_italic")
|
||||
|
@ -65,13 +64,13 @@ def draw_fonts():
|
|||
for i in range(len(FONT_NAMES)):
|
||||
name = FONT_NAMES[i]
|
||||
display.pen(0)
|
||||
if i == selected_font:
|
||||
if i == state["selected_font"]:
|
||||
display.rectangle(0, i * MENU_SPACING, MENU_WIDTH, MENU_SPACING)
|
||||
display.pen(15)
|
||||
|
||||
display.text(name, MENU_PADDING, (i * MENU_SPACING) + (MENU_SPACING // 2), MENU_TEXT_SIZE)
|
||||
|
||||
display.font(FONT_NAMES[selected_font])
|
||||
display.font(FONT_NAMES[state["selected_font"]])
|
||||
display.thickness(2)
|
||||
|
||||
display.pen(0)
|
||||
|
@ -91,51 +90,36 @@ def draw_fonts():
|
|||
# ------------------------------
|
||||
|
||||
# Global variables
|
||||
selected_font = 0
|
||||
pressed = False
|
||||
state = {"selected_font": 0}
|
||||
badger_os.state_load("fonts", state)
|
||||
|
||||
# Create a new Badger and set it to update FAST
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
display.update_speed(badger2040.UPDATE_FAST)
|
||||
|
||||
# Set up the buttons
|
||||
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
|
||||
|
||||
# Button handling function
|
||||
def button(pin):
|
||||
global pressed
|
||||
global selected_font
|
||||
|
||||
if not pressed:
|
||||
if pin == button_up:
|
||||
selected_font -= 1
|
||||
if selected_font < 0:
|
||||
selected_font = len(FONT_NAMES) - 1
|
||||
pressed = True
|
||||
return
|
||||
if pin == button_down:
|
||||
selected_font += 1
|
||||
if selected_font >= len(FONT_NAMES):
|
||||
selected_font = 0
|
||||
pressed = True
|
||||
return
|
||||
|
||||
|
||||
# Register the button handling function with the buttons
|
||||
button_up.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
button_down.irq(trigger=machine.Pin.IRQ_RISING, handler=button)
|
||||
|
||||
changed = not badger2040.woken_by_button()
|
||||
|
||||
# ------------------------------
|
||||
# Main program loop
|
||||
# ------------------------------
|
||||
|
||||
while True:
|
||||
draw_frame()
|
||||
draw_fonts()
|
||||
if display.pressed(badger2040.BUTTON_UP):
|
||||
state["selected_font"] -= 1
|
||||
if state["selected_font"] < 0:
|
||||
state["selected_font"] = len(FONT_NAMES) - 1
|
||||
changed = True
|
||||
if display.pressed(badger2040.BUTTON_DOWN):
|
||||
state["selected_font"] += 1
|
||||
if state["selected_font"] >= len(FONT_NAMES):
|
||||
state["selected_font"] = 0
|
||||
changed = True
|
||||
|
||||
pressed = False
|
||||
while not pressed:
|
||||
time.sleep(0.1)
|
||||
if changed:
|
||||
draw_frame()
|
||||
draw_fonts()
|
||||
badger_os.state_save("fonts", state)
|
||||
changed = False
|
||||
|
||||
display.halt()
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import badger2040
|
||||
import time
|
||||
from badger2040 import WIDTH
|
||||
|
||||
TEXT_SIZE = 0.45
|
||||
LINE_HEIGHT = 16
|
||||
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
|
||||
display.pen(0)
|
||||
display.rectangle(0, 0, WIDTH, 16)
|
||||
display.thickness(1)
|
||||
|
@ -27,7 +28,7 @@ y += LINE_HEIGHT
|
|||
y += LINE_HEIGHT
|
||||
|
||||
display.thickness(2)
|
||||
display.text("Holding USER button:", 0, y, TEXT_SIZE)
|
||||
display.text("Hold USER after:", 0, y, TEXT_SIZE)
|
||||
display.thickness(1)
|
||||
y += LINE_HEIGHT
|
||||
display.text("Up / Down - Change font size", 0, y, TEXT_SIZE)
|
||||
|
@ -36,5 +37,4 @@ display.text("a - Toggle invert", 0, y, TEXT_SIZE)
|
|||
y += LINE_HEIGHT
|
||||
|
||||
display.update()
|
||||
while True:
|
||||
time.sleep(1)
|
||||
display.halt()
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import os
|
||||
import sys
|
||||
import time
|
||||
import machine
|
||||
import badger2040
|
||||
from badger2040 import WIDTH, HEIGHT
|
||||
from badger2040 import HEIGHT
|
||||
import badger_os
|
||||
|
||||
|
||||
REAMDE = """
|
||||
|
@ -22,13 +22,14 @@ OVERLAY_TEXT_SIZE = 0.5
|
|||
|
||||
TOTAL_IMAGES = 0
|
||||
|
||||
|
||||
# Turn the act LED on as soon as possible
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
|
||||
# Try to preload BadgerPunk image
|
||||
try:
|
||||
os.mkdir("images")
|
||||
except OSError:
|
||||
pass
|
||||
|
||||
try:
|
||||
import badgerpunk
|
||||
with open("images/badgerpunk.bin", "wb") as f:
|
||||
f.write(badgerpunk.data())
|
||||
|
@ -40,6 +41,7 @@ try:
|
|||
except (OSError, ImportError):
|
||||
pass
|
||||
|
||||
# Load images
|
||||
try:
|
||||
IMAGES = [f for f in os.listdir("/images") if f.endswith(".bin")]
|
||||
TOTAL_IMAGES = len(IMAGES)
|
||||
|
@ -47,50 +49,12 @@ except OSError:
|
|||
pass
|
||||
|
||||
|
||||
display = badger2040.Badger2040()
|
||||
|
||||
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
|
||||
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
|
||||
image = bytearray(int(296 * 128 / 8))
|
||||
current_image = 0
|
||||
show_info = True
|
||||
|
||||
|
||||
# Draw an overlay box with a given message within it
|
||||
def draw_overlay(message, width, height, line_spacing, text_size):
|
||||
|
||||
# Draw a light grey background
|
||||
display.pen(12)
|
||||
display.rectangle((WIDTH - width) // 2, (HEIGHT - height) // 2, width, height)
|
||||
|
||||
# Take the provided message and split it up into
|
||||
# lines that fit within the specified width
|
||||
words = message.split(" ")
|
||||
|
||||
lines = []
|
||||
current_line = ""
|
||||
for word in words:
|
||||
if display.measure_text(current_line + word + " ", text_size) < width:
|
||||
current_line += word + " "
|
||||
else:
|
||||
lines.append(current_line.strip())
|
||||
current_line = word + " "
|
||||
lines.append(current_line.strip())
|
||||
|
||||
display.pen(0)
|
||||
display.thickness(2)
|
||||
|
||||
# Display each line of text from the message, centre-aligned
|
||||
num_lines = len(lines)
|
||||
for i in range(num_lines):
|
||||
length = display.measure_text(lines[i], text_size)
|
||||
current_line = (i * line_spacing) - ((num_lines - 1) * line_spacing) // 2
|
||||
display.text(lines[i], (WIDTH - length) // 2, (HEIGHT // 2) + current_line, text_size)
|
||||
state = {
|
||||
"current_image": 0,
|
||||
"show_info": True
|
||||
}
|
||||
|
||||
|
||||
def show_image(n):
|
||||
|
@ -99,7 +63,7 @@ def show_image(n):
|
|||
open("images/{}".format(file), "r").readinto(image)
|
||||
display.image(image)
|
||||
|
||||
if show_info:
|
||||
if state["show_info"]:
|
||||
name_length = display.measure_text(name, 0.5)
|
||||
display.pen(0)
|
||||
display.rectangle(0, HEIGHT - 21, name_length + 11, 21)
|
||||
|
@ -113,7 +77,7 @@ def show_image(n):
|
|||
y = int((128 / 2) - (TOTAL_IMAGES * 10 / 2) + (i * 10))
|
||||
display.pen(0)
|
||||
display.rectangle(x, y, 8, 8)
|
||||
if current_image != i:
|
||||
if state["current_image"] != i:
|
||||
display.pen(15)
|
||||
display.rectangle(x + 1, y + 1, 6, 6)
|
||||
|
||||
|
@ -123,32 +87,41 @@ def show_image(n):
|
|||
if TOTAL_IMAGES == 0:
|
||||
display.pen(15)
|
||||
display.clear()
|
||||
draw_overlay("To run this demo, create an /images directory on your device and upload some 1bit 296x128 pixel images.", WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, OVERLAY_TEXT_SIZE)
|
||||
display.update()
|
||||
badger_os.warning(display, "To run this demo, create an /images directory on your device and upload some 1bit 296x128 pixel images.")
|
||||
time.sleep(4.0)
|
||||
sys.exit()
|
||||
|
||||
|
||||
show_image(current_image)
|
||||
badger_os.state_load("image", state)
|
||||
|
||||
changed = not badger2040.woken_by_button()
|
||||
|
||||
|
||||
while True:
|
||||
if button_up.value():
|
||||
if current_image > 0:
|
||||
current_image -= 1
|
||||
show_image(current_image)
|
||||
if button_down.value():
|
||||
if current_image < TOTAL_IMAGES - 1:
|
||||
current_image += 1
|
||||
show_image(current_image)
|
||||
if button_a.value():
|
||||
show_info = not show_info
|
||||
show_image(current_image)
|
||||
if button_b.value() or button_c.value():
|
||||
if display.pressed(badger2040.BUTTON_UP):
|
||||
if state["current_image"] > 0:
|
||||
state["current_image"] -= 1
|
||||
changed = True
|
||||
if display.pressed(badger2040.BUTTON_DOWN):
|
||||
if state["current_image"] < TOTAL_IMAGES - 1:
|
||||
state["current_image"] += 1
|
||||
changed = True
|
||||
if display.pressed(badger2040.BUTTON_A):
|
||||
state["show_info"] = not state["show_info"]
|
||||
changed = True
|
||||
if display.pressed(badger2040.BUTTON_B) or display.pressed(badger2040.BUTTON_C):
|
||||
display.pen(15)
|
||||
display.clear()
|
||||
draw_overlay("To add images connect Badger2040 to a PC, load up Thonny, and see readme.txt in images/", WIDTH - OVERLAY_BORDER, HEIGHT - OVERLAY_BORDER, OVERLAY_SPACING, 0.5)
|
||||
badger_os.warning(display, "To add images connect Badger2040 to a PC, load up Thonny, and see readme.txt in images/")
|
||||
display.update()
|
||||
print(state["current_image"])
|
||||
time.sleep(4)
|
||||
show_image(current_image)
|
||||
changed = True
|
||||
|
||||
time.sleep(0.01)
|
||||
if changed:
|
||||
badger_os.state_save("image", state)
|
||||
show_image(state["current_image"])
|
||||
changed = False
|
||||
|
||||
# Halt the Badger to save power, it will wake up if any of the front buttons are pressed
|
||||
display.halt()
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
import badger2040
|
||||
import time
|
||||
from badger2040 import WIDTH
|
||||
|
||||
TEXT_SIZE = 0.45
|
||||
LINE_HEIGHT = 16
|
||||
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
|
||||
display.pen(0)
|
||||
display.rectangle(0, 0, WIDTH, 16)
|
||||
display.thickness(1)
|
||||
|
@ -33,6 +34,4 @@ y += LINE_HEIGHT
|
|||
display.text("https://pimoroni.com/badger2040", 0, y, TEXT_SIZE)
|
||||
|
||||
display.update()
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
display.halt()
|
||||
|
|
|
@ -1,20 +1,44 @@
|
|||
import gc
|
||||
import os
|
||||
import time
|
||||
import math
|
||||
import machine
|
||||
import badger2040
|
||||
from badger2040 import WIDTH
|
||||
import launchericons
|
||||
import badger_os
|
||||
|
||||
# Reduce clock speed to 48MHz, that's fast enough!
|
||||
machine.freq(48000000)
|
||||
|
||||
changed = False
|
||||
exited_to_launcher = False
|
||||
woken_by_button = badger2040.woken_by_button() # Must be done before we clear_pressed_to_wake
|
||||
|
||||
if badger2040.pressed_to_wake(badger2040.BUTTON_A) and badger2040.pressed_to_wake(badger2040.BUTTON_C):
|
||||
# Pressing A and C together at start quits app
|
||||
exited_to_launcher = badger_os.state_clear_running()
|
||||
badger2040.clear_pressed_to_wake()
|
||||
else:
|
||||
# Otherwise restore previously running app
|
||||
badger_os.state_launch()
|
||||
|
||||
# for e.g. 2xAAA batteries, try max 3.4 min 3.0
|
||||
MAX_BATTERY_VOLTAGE = 4.0
|
||||
MIN_BATTERY_VOLTAGE = 3.2
|
||||
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
|
||||
page = 0
|
||||
font_size = 1
|
||||
inverted = False
|
||||
state = {
|
||||
"page": 0,
|
||||
"font_size": 1,
|
||||
"inverted": False,
|
||||
"running": "launcher"
|
||||
}
|
||||
|
||||
badger_os.state_load("launcher", state)
|
||||
|
||||
display.invert(state["inverted"])
|
||||
|
||||
icons = bytearray(launchericons.data())
|
||||
icons_width = 576
|
||||
|
@ -38,46 +62,11 @@ centers = (41, 147, 253)
|
|||
|
||||
MAX_PAGE = math.ceil(len(examples) / 3)
|
||||
|
||||
button_a = machine.Pin(badger2040.BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_b = machine.Pin(badger2040.BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_c = machine.Pin(badger2040.BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_up = machine.Pin(badger2040.BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
button_down = machine.Pin(badger2040.BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN)
|
||||
# Inverted. For reasons.
|
||||
button_user = machine.Pin(badger2040.BUTTON_USER, machine.Pin.IN, machine.Pin.PULL_UP)
|
||||
|
||||
# Battery measurement
|
||||
vbat_adc = machine.ADC(badger2040.PIN_BATTERY)
|
||||
vref_adc = machine.ADC(badger2040.PIN_1V2_REF)
|
||||
vref_en = machine.Pin(badger2040.PIN_VREF_POWER)
|
||||
vref_en.init(machine.Pin.OUT)
|
||||
vref_en.value(0)
|
||||
|
||||
|
||||
display = badger2040.Badger2040()
|
||||
|
||||
|
||||
def map_value(input, in_min, in_max, out_min, out_max):
|
||||
return (((input - in_min) * (out_max - out_min)) / (in_max - in_min)) + out_min
|
||||
|
||||
|
||||
def get_battery_level():
|
||||
# Enable the onboard voltage reference
|
||||
vref_en.value(1)
|
||||
|
||||
# Calculate the logic supply voltage, as will be lower that the usual 3.3V when running off low batteries
|
||||
vdd = 1.24 * (65535 / vref_adc.read_u16())
|
||||
vbat = (
|
||||
(vbat_adc.read_u16() / 65535) * 3 * vdd
|
||||
) # 3 in this is a gain, not rounding of 3.3V
|
||||
|
||||
# Disable the onboard voltage reference
|
||||
vref_en.value(0)
|
||||
|
||||
# Convert the voltage to a level to display onscreen
|
||||
return int(map_value(vbat, MIN_BATTERY_VOLTAGE, MAX_BATTERY_VOLTAGE, 0, 4))
|
||||
|
||||
|
||||
def draw_battery(level, x, y):
|
||||
# Outline
|
||||
display.thickness(1)
|
||||
|
@ -103,17 +92,7 @@ def draw_battery(level, x, y):
|
|||
|
||||
|
||||
def draw_disk_usage(x):
|
||||
# f_bfree and f_bavail should be the same?
|
||||
# f_files, f_ffree, f_favail and f_flag are unsupported.
|
||||
f_bsize, f_frsize, f_blocks, f_bfree, _, _, _, _, _, f_namemax = os.statvfs(
|
||||
"/")
|
||||
|
||||
f_total_size = f_frsize * f_blocks
|
||||
f_total_free = f_bsize * f_bfree
|
||||
f_total_used = f_total_size - f_total_free
|
||||
|
||||
f_used = 100 / f_total_size * f_total_used
|
||||
# f_free = 100 / f_total_size * f_total_free
|
||||
_, f_used, _ = badger_os.get_disk_usage()
|
||||
|
||||
display.image(
|
||||
bytearray(
|
||||
|
@ -148,23 +127,23 @@ def render():
|
|||
display.pen(0)
|
||||
display.thickness(2)
|
||||
|
||||
max_icons = min(3, len(examples[(page * 3):]))
|
||||
max_icons = min(3, len(examples[(state["page"] * 3):]))
|
||||
|
||||
for i in range(max_icons):
|
||||
x = centers[i]
|
||||
label, icon = examples[i + (page * 3)]
|
||||
label, icon = examples[i + (state["page"] * 3)]
|
||||
label = label[1:].replace("_", " ")
|
||||
display.pen(0)
|
||||
display.icon(icons, icon, icons_width, 64, x - 32, 24)
|
||||
w = display.measure_text(label, font_sizes[font_size])
|
||||
display.text(label, x - int(w / 2), 16 + 80, font_sizes[font_size])
|
||||
w = display.measure_text(label, font_sizes[state["font_size"]])
|
||||
display.text(label, x - int(w / 2), 16 + 80, font_sizes[state["font_size"]])
|
||||
|
||||
for i in range(MAX_PAGE):
|
||||
x = 286
|
||||
y = int((128 / 2) - (MAX_PAGE * 10 / 2) + (i * 10))
|
||||
display.pen(0)
|
||||
display.rectangle(x, y, 8, 8)
|
||||
if page != i:
|
||||
if state["page"] != i:
|
||||
display.pen(15)
|
||||
display.rectangle(x + 1, y + 1, 6, 6)
|
||||
|
||||
|
@ -172,89 +151,93 @@ def render():
|
|||
display.rectangle(0, 0, WIDTH, 16)
|
||||
display.thickness(1)
|
||||
draw_disk_usage(90)
|
||||
draw_battery(get_battery_level(), WIDTH - 22 - 3, 3)
|
||||
vbat = badger_os.get_battery_level()
|
||||
bat = int(map_value(vbat, MIN_BATTERY_VOLTAGE, MAX_BATTERY_VOLTAGE, 0, 4))
|
||||
draw_battery(bat, WIDTH - 22 - 3, 3)
|
||||
display.pen(15)
|
||||
display.text("badgerOS", 3, 8, 0.4)
|
||||
|
||||
display.update()
|
||||
|
||||
|
||||
def launch(file):
|
||||
for k in locals().keys():
|
||||
if k not in ("gc", "file", "machine"):
|
||||
del locals()[k]
|
||||
gc.collect()
|
||||
try:
|
||||
__import__(file[1:]) # Try to import _[file] (drop underscore prefix)
|
||||
except ImportError:
|
||||
__import__(file) # Failover to importing [_file]
|
||||
machine.reset() # Exit back to launcher
|
||||
def wait_for_user_to_release_buttons():
|
||||
pr = display.pressed
|
||||
while pr(badger2040.BUTTON_A) or pr(badger2040.BUTTON_B) or pr(badger2040.BUTTON_C) or pr(badger2040.BUTTON_UP) or pr(badger2040.BUTTON_DOWN):
|
||||
time.sleep(0.01)
|
||||
|
||||
|
||||
def launch_example(index):
|
||||
try:
|
||||
launch(examples[(page * 3) + index][0])
|
||||
return True
|
||||
except IndexError:
|
||||
return False
|
||||
wait_for_user_to_release_buttons()
|
||||
|
||||
file = examples[(state["page"] * 3) + index][0]
|
||||
|
||||
for k in locals().keys():
|
||||
if k not in ("gc", "file", "badger_os"):
|
||||
del locals()[k]
|
||||
|
||||
gc.collect()
|
||||
|
||||
badger_os.launch(file)
|
||||
|
||||
|
||||
def button(pin):
|
||||
global page, font_size, inverted
|
||||
global changed
|
||||
changed = True
|
||||
|
||||
if button_user.value(): # User button is NOT held down
|
||||
if pin == button_a:
|
||||
if not display.pressed(badger2040.BUTTON_USER): # User button is NOT held down
|
||||
if pin == badger2040.BUTTON_A:
|
||||
launch_example(0)
|
||||
if pin == button_b:
|
||||
if pin == badger2040.BUTTON_B:
|
||||
launch_example(1)
|
||||
if pin == button_c:
|
||||
if pin == badger2040.BUTTON_C:
|
||||
launch_example(2)
|
||||
if pin == button_up:
|
||||
if page > 0:
|
||||
page -= 1
|
||||
render()
|
||||
if pin == button_down:
|
||||
if page < MAX_PAGE - 1:
|
||||
page += 1
|
||||
render()
|
||||
if pin == badger2040.BUTTON_UP:
|
||||
if state["page"] > 0:
|
||||
state["page"] -= 1
|
||||
render()
|
||||
if pin == badger2040.BUTTON_DOWN:
|
||||
if state["page"] < MAX_PAGE - 1:
|
||||
state["page"] += 1
|
||||
render()
|
||||
else: # User button IS held down
|
||||
if pin == button_up:
|
||||
font_size += 1
|
||||
if font_size == len(font_sizes):
|
||||
font_size = 0
|
||||
if pin == badger2040.BUTTON_UP:
|
||||
state["font_size"] += 1
|
||||
if state["font_size"] == len(font_sizes):
|
||||
state["font_size"] = 0
|
||||
render()
|
||||
if pin == button_down:
|
||||
font_size -= 1
|
||||
if font_size < 0:
|
||||
font_size = 0
|
||||
if pin == badger2040.BUTTON_DOWN:
|
||||
state["font_size"] -= 1
|
||||
if state["font_size"] < 0:
|
||||
state["font_size"] = 0
|
||||
render()
|
||||
if pin == button_a:
|
||||
inverted = not inverted
|
||||
display.invert(inverted)
|
||||
if pin == badger2040.BUTTON_A:
|
||||
state["inverted"] = not state["inverted"]
|
||||
display.invert(state["inverted"])
|
||||
render()
|
||||
|
||||
|
||||
display.update_speed(badger2040.UPDATE_MEDIUM)
|
||||
render()
|
||||
if exited_to_launcher or not woken_by_button:
|
||||
wait_for_user_to_release_buttons()
|
||||
display.update_speed(badger2040.UPDATE_MEDIUM)
|
||||
render()
|
||||
|
||||
display.update_speed(badger2040.UPDATE_FAST)
|
||||
|
||||
|
||||
# Wait for wakeup button to be released
|
||||
while button_a.value() or button_b.value() or button_c.value() or button_up.value() or button_down.value():
|
||||
pass
|
||||
|
||||
|
||||
while True:
|
||||
if button_a.value():
|
||||
button(button_a)
|
||||
if button_b.value():
|
||||
button(button_b)
|
||||
if button_c.value():
|
||||
button(button_c)
|
||||
if display.pressed(badger2040.BUTTON_A):
|
||||
button(badger2040.BUTTON_A)
|
||||
if display.pressed(badger2040.BUTTON_B):
|
||||
button(badger2040.BUTTON_B)
|
||||
if display.pressed(badger2040.BUTTON_C):
|
||||
button(badger2040.BUTTON_C)
|
||||
|
||||
if button_up.value():
|
||||
button(button_up)
|
||||
if button_down.value():
|
||||
button(button_down)
|
||||
if display.pressed(badger2040.BUTTON_UP):
|
||||
button(badger2040.BUTTON_UP)
|
||||
if display.pressed(badger2040.BUTTON_DOWN):
|
||||
button(badger2040.BUTTON_DOWN)
|
||||
|
||||
time.sleep(0.01)
|
||||
if changed:
|
||||
badger_os.state_save("launcher", state)
|
||||
changed = False
|
||||
|
||||
display.halt()
|
||||
|
|
|
@ -143,6 +143,7 @@ items_per_page = 0
|
|||
|
||||
# Create a new Badger and set it to update FAST
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
display.update_speed(badger2040.UPDATE_FAST)
|
||||
|
||||
# Set up the buttons
|
||||
|
@ -177,6 +178,13 @@ items_per_page = ((LIST_HEIGHT // ITEM_SPACING) + 1) * list_columns
|
|||
def button(pin):
|
||||
global update, current_item, needs_save
|
||||
|
||||
time.sleep(0.05)
|
||||
if not pin.value():
|
||||
return
|
||||
|
||||
if button_a.value() and button_c.value():
|
||||
machine.reset()
|
||||
|
||||
if len(list_content) > 0 and not update:
|
||||
if pin == button_a:
|
||||
if current_item > 0:
|
||||
|
|
|
@ -52,3 +52,4 @@ copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/badge.py _badge)
|
|||
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/help.py _help)
|
||||
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/info.py _info)
|
||||
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/qrgen.py _qrgen)
|
||||
copy_module(usermod_badger2040 ${CMAKE_CURRENT_LIST_DIR}/badger_os.py badger_os)
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
import badger2040
|
||||
import qrcode
|
||||
import time
|
||||
|
||||
|
||||
# Open the qrcode file
|
||||
try:
|
||||
text = open("qrcode.txt", "r")
|
||||
except OSError:
|
||||
text = open("qrcode.txt", "w")
|
||||
text.write("""https://pimoroni.com/badger2040
|
||||
with open("qrcode.txt", "w") as text:
|
||||
text.write("""https://pimoroni.com/badger2040
|
||||
Badger 2040
|
||||
* 296x128 1-bit e-ink
|
||||
* six user buttons
|
||||
|
@ -18,8 +17,8 @@ Badger 2040
|
|||
Scan this code to learn
|
||||
more about Badger 2040.
|
||||
""")
|
||||
text.flush()
|
||||
text.seek(0)
|
||||
text.flush()
|
||||
text = open("qrcode.txt", "r")
|
||||
|
||||
|
||||
lines = text.read().strip().split("\n")
|
||||
|
@ -28,6 +27,7 @@ title_text = lines.pop(0)
|
|||
detail_text = lines
|
||||
|
||||
display = badger2040.Badger2040()
|
||||
display.led(128)
|
||||
code = qrcode.QRCode()
|
||||
|
||||
|
||||
|
@ -65,6 +65,4 @@ for line in detail_text:
|
|||
top += 10
|
||||
|
||||
display.update()
|
||||
|
||||
while True:
|
||||
time.sleep(1.0)
|
||||
display.halt()
|
||||
|
|
|
@ -16,6 +16,7 @@ MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_pen_obj, Badger2040_pen);
|
|||
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_thickness_obj, Badger2040_thickness);
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_pressed_obj, Badger2040_pressed);
|
||||
MP_DEFINE_CONST_FUN_OBJ_2(Badger2040_pressed_to_wake2_obj, Badger2040_pressed_to_wake2);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_clear_obj, Badger2040_clear);
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(Badger2040_pixel_obj, Badger2040_pixel);
|
||||
MP_DEFINE_CONST_FUN_OBJ_KW(Badger2040_line_obj, 4, Badger2040_line);
|
||||
|
@ -32,6 +33,11 @@ MP_DEFINE_CONST_FUN_OBJ_KW(Badger2040_measure_glyph_obj, 2, Badger2040_measure_g
|
|||
|
||||
MP_DEFINE_CONST_FUN_OBJ_3(Badger2040_command_obj, Badger2040_command);
|
||||
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_pressed_to_wake_obj, Badger2040_pressed_to_wake);
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(Badger2040_clear_pressed_to_wake_obj, Badger2040_clear_pressed_to_wake);
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(Badger2040_halt_obj, Badger2040_halt);
|
||||
MP_DEFINE_CONST_FUN_OBJ_0(Badger2040_woken_by_button_obj, Badger2040_woken_by_button);
|
||||
|
||||
/***** Binding of Methods *****/
|
||||
STATIC const mp_rom_map_elem_t Badger2040_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&Badger2040___del___obj) },
|
||||
|
@ -40,6 +46,8 @@ STATIC const mp_rom_map_elem_t Badger2040_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&Badger2040_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_partial_update), MP_ROM_PTR(&Badger2040_partial_update_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_halt), MP_ROM_PTR(&Badger2040_halt_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_invert), MP_ROM_PTR(&Badger2040_invert_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_led), MP_ROM_PTR(&Badger2040_led_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_font), MP_ROM_PTR(&Badger2040_font_obj) },
|
||||
|
@ -47,6 +55,7 @@ STATIC const mp_rom_map_elem_t Badger2040_locals_dict_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_thickness), MP_ROM_PTR(&Badger2040_thickness_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_pressed), MP_ROM_PTR(&Badger2040_pressed_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pressed_to_wake), MP_ROM_PTR(&Badger2040_pressed_to_wake2_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&Badger2040_clear_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&Badger2040_pixel_obj) },
|
||||
|
@ -78,10 +87,14 @@ const mp_obj_type_t Badger2040_type = {
|
|||
|
||||
/***** Globals Table *****/
|
||||
|
||||
STATIC const mp_map_elem_t badger2040_globals_table[] = {
|
||||
STATIC const mp_rom_map_elem_t badger2040_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_badger2040) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_Badger2040), (mp_obj_t)&Badger2040_type },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_pressed_to_wake), MP_ROM_PTR(&Badger2040_pressed_to_wake_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_clear_pressed_to_wake), MP_ROM_PTR(&Badger2040_clear_pressed_to_wake_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_woken_by_button), MP_ROM_PTR(&Badger2040_woken_by_button_obj) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_UPDATE_NORMAL), MP_ROM_INT(0) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_UPDATE_MEDIUM), MP_ROM_INT(1) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_UPDATE_FAST), MP_ROM_INT(2) },
|
||||
|
@ -121,4 +134,4 @@ const mp_obj_module_t badger2040_user_cmodule = {
|
|||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_badger2040_globals,
|
||||
};
|
||||
MP_REGISTER_MODULE(MP_QSTR_badger2040, badger2040_user_cmodule, MODULE_BADGER2040_ENABLED);
|
||||
MP_REGISTER_MODULE(MP_QSTR_badger2040, badger2040_user_cmodule, MODULE_BADGER2040_ENABLED);
|
||||
|
|
|
@ -1,8 +1,45 @@
|
|||
#include <cstdio>
|
||||
#include "hardware/watchdog.h"
|
||||
#include "badger2040.hpp"
|
||||
|
||||
#define MP_OBJ_TO_PTR2(o, t) ((t *)(uintptr_t)(o))
|
||||
|
||||
namespace {
|
||||
struct Badger2040_WakeUpInit {
|
||||
Badger2040_WakeUpInit()
|
||||
: state(gpio_get_all() & (0x1f << pimoroni::Badger2040::DOWN)) // Record state of front buttons
|
||||
{
|
||||
gpio_set_function(pimoroni::Badger2040::ENABLE_3V3, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(pimoroni::Badger2040::ENABLE_3V3, GPIO_OUT);
|
||||
gpio_put(pimoroni::Badger2040::ENABLE_3V3, 1);
|
||||
|
||||
gpio_set_function(pimoroni::Badger2040::LED, GPIO_FUNC_SIO);
|
||||
gpio_set_dir(pimoroni::Badger2040::LED, GPIO_OUT);
|
||||
gpio_put(pimoroni::Badger2040::LED, 1);
|
||||
}
|
||||
|
||||
bool any() const {
|
||||
return state > 0;
|
||||
}
|
||||
|
||||
bool get(uint32_t pin) const {
|
||||
return state & (0b1 << pin);
|
||||
}
|
||||
|
||||
bool get_once(uint32_t pin) {
|
||||
uint32_t mask = 0b1 << pin;
|
||||
bool value = state & mask;
|
||||
state &= ~mask;
|
||||
return value;
|
||||
}
|
||||
void clear() { state = 0; }
|
||||
|
||||
private:
|
||||
uint32_t state;
|
||||
};
|
||||
|
||||
Badger2040_WakeUpInit button_wake_state __attribute__ ((init_priority (101)));
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
#include "badger2040.h"
|
||||
|
@ -116,9 +153,12 @@ MICROPY_EVENT_POLL_HOOK
|
|||
#endif
|
||||
}
|
||||
|
||||
absolute_time_t t_end = make_timeout_time_ms(self->badger2040->update_time());
|
||||
self->badger2040->update(false);
|
||||
|
||||
while(self->badger2040->is_busy()) {
|
||||
// Ensure blocking for the minimum amount of time
|
||||
// in cases where "is_busy" is unreliable.
|
||||
while(self->badger2040->is_busy() || absolute_time_diff_us(t_end, get_absolute_time()) > 0) {
|
||||
#ifdef MICROPY_EVENT_POLL_HOOK
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
#endif
|
||||
|
@ -157,9 +197,12 @@ MICROPY_EVENT_POLL_HOOK
|
|||
#endif
|
||||
}
|
||||
|
||||
absolute_time_t t_end = make_timeout_time_ms(self->badger2040->update_time());
|
||||
self->badger2040->partial_update(x, y, w, h);
|
||||
|
||||
while(self->badger2040->is_busy()) {
|
||||
// Ensure blocking for the minimum amount of time
|
||||
// in cases where "is_busy" is unreliable.
|
||||
while(self->badger2040->is_busy() || absolute_time_diff_us(t_end, get_absolute_time()) > 0) {
|
||||
#ifdef MICROPY_EVENT_POLL_HOOK
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
#endif
|
||||
|
@ -170,7 +213,27 @@ MICROPY_EVENT_POLL_HOOK
|
|||
return mp_const_none;
|
||||
}
|
||||
|
||||
// halt
|
||||
mp_obj_t Badger2040_woken_by_button() {
|
||||
return button_wake_state.any() ? mp_const_true : mp_const_false;
|
||||
}
|
||||
|
||||
mp_obj_t Badger2040_halt(mp_obj_t self_in) {
|
||||
_Badger2040_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Badger2040_obj_t);
|
||||
|
||||
// Don't use the Badger halt so we can allow Micropython to be interrupted.
|
||||
gpio_put(pimoroni::Badger2040::ENABLE_3V3, 0);
|
||||
|
||||
self->badger2040->update_button_states();
|
||||
while (self->badger2040->button_states() == 0) {
|
||||
#ifdef MICROPY_EVENT_POLL_HOOK
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
#endif
|
||||
self->badger2040->update_button_states();
|
||||
}
|
||||
//watchdog_reboot(0, SRAM_END, 0);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
// sleep
|
||||
|
||||
mp_obj_t Badger2040_invert(mp_obj_t self_in, mp_obj_t invert) {
|
||||
|
@ -206,10 +269,25 @@ mp_obj_t Badger2040_thickness(mp_obj_t self_in, mp_obj_t thickness) {
|
|||
mp_obj_t Badger2040_pressed(mp_obj_t self_in, mp_obj_t button) {
|
||||
_Badger2040_obj_t *self = MP_OBJ_TO_PTR2(self_in, _Badger2040_obj_t);
|
||||
self->badger2040->update_button_states();
|
||||
bool wake_state = button_wake_state.get_once(mp_obj_get_int(button));
|
||||
bool state = self->badger2040->pressed(mp_obj_get_int(button));
|
||||
return (state || wake_state) ? mp_const_true : mp_const_false;
|
||||
}
|
||||
|
||||
mp_obj_t Badger2040_pressed_to_wake(mp_obj_t button) {
|
||||
bool state = button_wake_state.get(mp_obj_get_int(button));
|
||||
return state ? mp_const_true : mp_const_false;
|
||||
}
|
||||
|
||||
mp_obj_t Badger2040_pressed_to_wake2(mp_obj_t self_in, mp_obj_t button) {
|
||||
return Badger2040_pressed_to_wake(button);
|
||||
}
|
||||
|
||||
mp_obj_t Badger2040_clear_pressed_to_wake() {
|
||||
button_wake_state.clear();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
// pressed
|
||||
// pressed_to_wake
|
||||
// wait_for_press - implement in terms of MicroPython!
|
||||
|
@ -467,4 +545,4 @@ mp_obj_t Badger2040_measure_glyph(size_t n_args, const mp_obj_t *pos_args, mp_ma
|
|||
return mp_obj_new_int(self->badger2040->measure_glyph(c, scale));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ extern mp_obj_t Badger2040_update_speed(mp_obj_t self_in, mp_obj_t speed);
|
|||
extern mp_obj_t Badger2040_update(mp_obj_t self_in);
|
||||
extern mp_obj_t Badger2040_partial_update(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
|
||||
extern mp_obj_t Badger2040_halt(mp_obj_t self_in);
|
||||
|
||||
extern mp_obj_t Badger2040_invert(mp_obj_t self_in, mp_obj_t invert);
|
||||
extern mp_obj_t Badger2040_led(mp_obj_t self_in, mp_obj_t brightness);
|
||||
extern mp_obj_t Badger2040_font(mp_obj_t self_in, mp_obj_t font);
|
||||
|
@ -22,6 +24,7 @@ extern mp_obj_t Badger2040_pen(mp_obj_t self_in, mp_obj_t color);
|
|||
extern mp_obj_t Badger2040_thickness(mp_obj_t self_in, mp_obj_t thickness);
|
||||
|
||||
extern mp_obj_t Badger2040_pressed(mp_obj_t self_in, mp_obj_t button);
|
||||
extern mp_obj_t Badger2040_pressed_to_wake2(mp_obj_t self_in, mp_obj_t button);
|
||||
|
||||
extern mp_obj_t Badger2040_clear(mp_obj_t self_in);
|
||||
extern mp_obj_t Badger2040_pixel(mp_obj_t self_in, mp_obj_t x, mp_obj_t y);
|
||||
|
@ -37,4 +40,8 @@ extern mp_obj_t Badger2040_glyph(size_t n_args, const mp_obj_t *pos_args, mp_map
|
|||
extern mp_obj_t Badger2040_measure_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
extern mp_obj_t Badger2040_measure_glyph(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
|
||||
|
||||
extern mp_obj_t Badger2040_command(mp_obj_t self_in, mp_obj_t reg, mp_obj_t data);
|
||||
extern mp_obj_t Badger2040_command(mp_obj_t self_in, mp_obj_t reg, mp_obj_t data);
|
||||
|
||||
extern mp_obj_t Badger2040_pressed_to_wake(mp_obj_t button);
|
||||
extern mp_obj_t Badger2040_clear_pressed_to_wake();
|
||||
extern mp_obj_t Badger2040_woken_by_button();
|
||||
|
|
Loading…
Reference in New Issue