summaryrefslogtreecommitdiff
path: root/badger2040w.py
diff options
context:
space:
mode:
Diffstat (limited to 'badger2040w.py')
-rw-r--r--badger2040w.py181
1 files changed, 181 insertions, 0 deletions
diff --git a/badger2040w.py b/badger2040w.py
new file mode 100644
index 0000000..1b6f169
--- /dev/null
+++ b/badger2040w.py
@@ -0,0 +1,181 @@
+import machine
+import micropython
+from picographics import PicoGraphics, DISPLAY_INKY_PACK
+import network
+from network_manager import NetworkManager
+import WIFI_CONFIG
+import uasyncio
+import time
+import gc
+import wakeup
+
+
+BUTTON_DOWN = 11
+BUTTON_A = 12
+BUTTON_B = 13
+BUTTON_C = 14
+BUTTON_UP = 15
+BUTTON_USER = None # User button not available on W
+
+BUTTON_MASK = 0b11111 << 11
+
+SYSTEM_VERY_SLOW = 0
+SYSTEM_SLOW = 1
+SYSTEM_NORMAL = 2
+SYSTEM_FAST = 3
+SYSTEM_TURBO = 4
+
+UPDATE_NORMAL = 0
+UPDATE_MEDIUM = 1
+UPDATE_FAST = 2
+UPDATE_TURBO = 3
+
+LED = 22
+ENABLE_3V3 = 10
+BUSY = 26
+
+WIDTH = 296
+HEIGHT = 128
+
+SYSTEM_FREQS = [
+ 4000000,
+ 12000000,
+ 48000000,
+ 133000000,
+ 250000000
+]
+
+BUTTONS = {
+ BUTTON_DOWN: machine.Pin(BUTTON_DOWN, machine.Pin.IN, machine.Pin.PULL_DOWN),
+ BUTTON_A: machine.Pin(BUTTON_A, machine.Pin.IN, machine.Pin.PULL_DOWN),
+ BUTTON_B: machine.Pin(BUTTON_B, machine.Pin.IN, machine.Pin.PULL_DOWN),
+ BUTTON_C: machine.Pin(BUTTON_C, machine.Pin.IN, machine.Pin.PULL_DOWN),
+ BUTTON_UP: machine.Pin(BUTTON_UP, machine.Pin.IN, machine.Pin.PULL_DOWN),
+}
+
+WAKEUP_MASK = 0
+
+
+def woken_by_button():
+ return wakeup.get_gpio_state() & BUTTON_MASK > 0
+
+
+def pressed_to_wake(button):
+ return wakeup.get_gpio_state() & (1 << button) > 0
+
+
+def reset_pressed_to_wake():
+ wakeup.reset_gpio_state()
+
+
+def pressed_to_wake_get_once(button):
+ global WAKEUP_MASK
+ result = (wakeup.get_gpio_state() & ~WAKEUP_MASK & (1 << button)) > 0
+ WAKEUP_MASK |= (1 << button)
+ return result
+
+
+def system_speed(speed):
+ try:
+ machine.freq(SYSTEM_FREQS[speed])
+ except IndexError:
+ pass
+
+
+class Badger2040W():
+ def __init__(self):
+ self.display = PicoGraphics(DISPLAY_INKY_PACK)
+ self._led = machine.PWM(machine.Pin(LED))
+ self._led.freq(1000)
+ self._led.duty_u16(0)
+ self._update_speed = 0
+
+ def __getattr__(self, item):
+ # Glue to redirect calls to PicoGraphics
+ return getattr(self.display, item)
+
+ def update(self):
+ t_start = time.ticks_ms()
+ self.display.update()
+ t_elapsed = time.ticks_ms() - t_start
+
+ delay_ms = [4700, 2600, 900, 250][self._update_speed]
+
+ if t_elapsed < delay_ms:
+ time.sleep((delay_ms - t_elapsed) / 1000)
+
+ def set_update_speed(self, speed):
+ self.display.set_update_speed(speed)
+ self._update_speed = speed
+
+ def led(self, brightness):
+ brightness = max(0, min(255, brightness))
+ self._led.duty_u16(int(brightness * 256))
+
+ def invert(self, invert):
+ raise RuntimeError("Display invert not supported in PicoGraphics.")
+
+ def thickness(self, thickness):
+ raise RuntimeError("Thickness not supported in PicoGraphics.")
+
+ def halt(self):
+ time.sleep(0.05)
+ enable = machine.Pin(ENABLE_3V3, machine.Pin.OUT)
+ enable.off()
+ while not self.pressed_any():
+ pass
+
+ def pressed(self, button):
+ return BUTTONS[button].value() == 1 or pressed_to_wake_get_once(button)
+
+ def pressed_any(self):
+ for button in BUTTONS.values():
+ if button.value():
+ return True
+ return False
+
+ @micropython.native
+ def icon(self, data, index, data_w, icon_size, x, y):
+ s_x = (index * icon_size) % data_w
+ s_y = int((index * icon_size) / data_w)
+
+ for o_y in range(icon_size):
+ for o_x in range(icon_size):
+ o = ((o_y + s_y) * data_w) + (o_x + s_x)
+ bm = 0b10000000 >> (o & 0b111)
+ if data[o >> 3] & bm:
+ self.display.pixel(x + o_x, y + o_y)
+
+ def image(self, data, w, h, x, y):
+ for oy in range(h):
+ row = data[oy]
+ for ox in range(w):
+ if row & 0b1 == 0:
+ self.display.pixel(x + ox, y + oy)
+ row >>= 1
+
+ def status_handler(self, mode, status, ip):
+ print(mode, status, ip)
+ self.display.set_pen(15)
+ self.display.clear()
+ self.display.set_pen(0)
+ if status:
+ self.display.text("Connected!", 10, 10, 300, 0.5)
+ self.display.text(ip, 10, 30, 300, 0.5)
+ else:
+ self.display.text("Connecting...", 10, 10, 300, 0.5)
+ self.update()
+
+ def isconnected(self):
+ return network.WLAN(network.STA_IF).isconnected()
+
+ def ip_address(self):
+ return network.WLAN(network.STA_IF).ifconfig()[0]
+
+ def connect(self):
+ if WIFI_CONFIG.COUNTRY == "":
+ raise RuntimeError("You must populate WIFI_CONFIG.py for networking.")
+ self.display.set_update_speed(2)
+ network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=self.status_handler)
+ uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK))
+ gc.collect() \ No newline at end of file