You've already forked MicroPythonOS
mirror of
https://github.com/m5stack/MicroPythonOS.git
synced 2026-05-20 11:51:27 -07:00
Merge branch 'main' of https://github.com/MicroPythonOS/MicroPythonOS
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
import struct
|
||||
|
||||
from micropython import const
|
||||
from machine import I2C, UART
|
||||
|
||||
from .device import Device
|
||||
|
||||
# registers
|
||||
_COMM_REG_KEY_REPORT = const(0x03)
|
||||
_COMM_REG_CONFIG = const(0x0B)
|
||||
_COMM_REG_BACKLIGHT = const(0x0C)
|
||||
_COMM2024_REG_RGB_LED = const(0x0E)
|
||||
_COMM2024_REG_RED_LED = const(0x11)
|
||||
|
||||
_COMM2024_I2CADDR_DEFAULT = const(0x38)
|
||||
_COMM2026_I2CADDR_DEFAULT = const(0x39)
|
||||
|
||||
|
||||
class Communicator2026(Device):
|
||||
"""Fri3d Badge 2026 expander MCU."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
i2c_bus: I2C,
|
||||
uart_bus: UART = None,
|
||||
address: int = _COMM2026_I2CADDR_DEFAULT,
|
||||
):
|
||||
"""Read from a 2026 communicator"""
|
||||
Device.__init__(self, i2c_bus, address)
|
||||
self.use_uart = False
|
||||
self.write_idx = 0
|
||||
self.data_ready = False
|
||||
if uart_bus:
|
||||
self.use_uart = True
|
||||
self.uart = uart_bus.init(115200, bits=8, parity=None, stop=1)
|
||||
self._rx_buf = bytearray(8)
|
||||
self._rx_mv = memoryview(self._rx_buf)
|
||||
self.uart.irq(handler=self.uart_handler, trigger=UART.IRQ_RX)
|
||||
|
||||
def uart_handler(self, uart):
|
||||
"""Interrupt handler for incoming UART data"""
|
||||
while uart.any() and not self.data_ready:
|
||||
# Calculate how much space is left
|
||||
space_left = 8 - self.write_idx
|
||||
|
||||
# Read directly into the slice of the memoryview
|
||||
# readinto returns the number of bytes actually read
|
||||
num_read = uart.readinto(self._rx_mv[self.write_idx :], space_left)
|
||||
|
||||
if num_read:
|
||||
self.write_idx += num_read
|
||||
|
||||
if self.write_idx >= 8:
|
||||
self.data_ready = True
|
||||
|
||||
@property
|
||||
def key_report(self) -> tuple[int, int, int, int, int, int, int, int, int]:
|
||||
"""return the key report read using I2C or UART"""
|
||||
ret = None
|
||||
if self.use_uart and self.data_ready:
|
||||
# Process the data (raw_buffer now contains the 8 bytes)
|
||||
ret = tuple(self._rx_buf)
|
||||
self.write_idx = 0
|
||||
self.data_ready = False
|
||||
else:
|
||||
ret = self._read("BBBBBBBB", _COMM_REG_KEY_REPORT, 8)
|
||||
return ret
|
||||
|
||||
@property
|
||||
def configuration(self) -> int:
|
||||
"""get the configuration byte"""
|
||||
return self._read("B", _COMM_REG_CONFIG, 1)[0]
|
||||
|
||||
@configuration.setter
|
||||
def configuration(self, value: int):
|
||||
"""Set the configuration byte"""
|
||||
self._write(_COMM_REG_CONFIG, struct.pack("B", value))
|
||||
|
||||
@property
|
||||
def backlight(self) -> int:
|
||||
"""Get the backlight value (0-100)"""
|
||||
return self._read("<H", _COMM_REG_BACKLIGHT, 2)[0]
|
||||
|
||||
@backlight.setter
|
||||
def backlight(self, value: int):
|
||||
"""Set the backlight value (0-100)"""
|
||||
if value >= 0 and value <= 100:
|
||||
self.i2c.writeto_mem(
|
||||
self.address, _COMM_REG_BACKLIGHT, struct.pack("<H", value), addrsize=8
|
||||
)
|
||||
|
||||
|
||||
class Communicator2024(Communicator2026):
|
||||
def __init__(
|
||||
self,
|
||||
i2c_bus: I2C,
|
||||
uart_bus: UART = None,
|
||||
address: int = _COMM2024_I2CADDR_DEFAULT,
|
||||
):
|
||||
"""Read from a 2024 communicator"""
|
||||
Communicator2026.__init__(self, i2c_bus, uart_bus, address)
|
||||
|
||||
@property
|
||||
def rgb_led(self) -> tuple[int, int, int]:
|
||||
"""Get the LANA module RGB LED"""
|
||||
return self._read("BBB", _COMM2024_REG_RGB_LED, 3)
|
||||
|
||||
@rgb_led.setter
|
||||
def rgb_led(self, value: tuple[int, int, int]):
|
||||
"""Set the LANA module RGB LED"""
|
||||
self._write(_COMM2024_REG_RGB_LED, struct.pack("BBB", *value))
|
||||
|
||||
@property
|
||||
def red_led(self) -> int:
|
||||
"""Get the CAPS LED"""
|
||||
return self._read("B", _COMM2024_REG_RED_LED, 1)[0]
|
||||
|
||||
@red_led.setter
|
||||
def red_led(self, value: int):
|
||||
"""Set the CAPS LED"""
|
||||
if value >= 0 and value <= 0xFF:
|
||||
self._write(_COMM2024_REG_RED_LED, struct.pack("B", value))
|
||||
@@ -0,0 +1,26 @@
|
||||
import struct
|
||||
|
||||
from micropython import const
|
||||
from machine import I2C
|
||||
|
||||
# common registers
|
||||
_REG_VERSION = const(0x00)
|
||||
|
||||
|
||||
class Device:
|
||||
"""Fri3d I2C device."""
|
||||
|
||||
def __init__(self, i2c_bus: I2C, address: int):
|
||||
"""Read from a sensor on the given I2C bus, at the given address."""
|
||||
self.i2c = i2c_bus
|
||||
self.address = address
|
||||
|
||||
def _read(self, format, reg, amount):
|
||||
return struct.unpack(format, self.i2c.readfrom_mem(self.address, reg, amount))
|
||||
|
||||
def _write(self, reg, value):
|
||||
self.i2c.writeto_mem(self.address, reg, value, addrsize=8)
|
||||
|
||||
@property
|
||||
def version(self) -> tuple[int, int, int]:
|
||||
return self._read("BBB", _REG_VERSION, 3)
|
||||
@@ -0,0 +1,89 @@
|
||||
import struct
|
||||
|
||||
from micropython import const
|
||||
from machine import I2C, Pin
|
||||
|
||||
from .device import Device
|
||||
|
||||
# registers
|
||||
_EXPANDER_REG_INPUTS = const(0x04)
|
||||
_EXPANDER_REG_ANALOG = const(0x06)
|
||||
_EXPANDER_REG_LCD_BRIGHTNESS = const(0x12)
|
||||
_EXPANDER_REG_DEBUG_LED = const(0x14)
|
||||
_EXPANDER_REG_CONFIG = const(0x16)
|
||||
|
||||
_EXPANDER_I2CADDR_DEFAULT = const(0x50)
|
||||
|
||||
|
||||
class Expander(Device):
|
||||
"""Fri3d Badge 2026 expander MCU."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
i2c_bus: I2C,
|
||||
address: int = _EXPANDER_I2CADDR_DEFAULT,
|
||||
int_pin: Pin = None,
|
||||
):
|
||||
"""Read from a sensor on the given I2C bus, at the given address."""
|
||||
Device.__init__(self, i2c_bus, address)
|
||||
self.use_interrupt = False
|
||||
if int_pin:
|
||||
self.use_interrupt = True
|
||||
self._rx_buf = bytearray(2)
|
||||
self._rx_mv = memoryview(self._rx_buf)
|
||||
self.int_pin = int_pin
|
||||
self.i2c.readfrom_mem_into(self.address, _EXPANDER_REG_INPUTS, self._rx_mv)
|
||||
self.int_pin.irq(trigger=Pin.IRQ_RISING, handler=self.int_callback)
|
||||
|
||||
def int_callback(self, p):
|
||||
self.i2c.readfrom_mem_into(self.address, _EXPANDER_REG_INPUTS, self._rx_mv)
|
||||
|
||||
@property
|
||||
def analog(self) -> tuple[int, int, int, int, int, int]:
|
||||
"""Read the analog inputs: ain1, ain0, battery_monitor, usb_monitor, joystick_y, joystick_x"""
|
||||
return self._read("<HHHHHH", _EXPANDER_REG_ANALOG, 12)
|
||||
|
||||
@property
|
||||
def digital(
|
||||
self,
|
||||
) -> tuple[bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool, bool]:
|
||||
"""Read the digital inputs: usb_plugged, joy_right, joy_left, joy_down, joy_up, button_menu, button_b, button_a, button_y, button_x, charger_standby, charger_charging"""
|
||||
if self.use_interrupt:
|
||||
inputs = struct.unpack("<H", self._rx_buf)[0]
|
||||
else:
|
||||
inputs = self._read("<H", _EXPANDER_REG_INPUTS, 2)[0]
|
||||
return tuple([bool(int(digit)) for digit in "{:016b}".format(inputs)[4:]])
|
||||
|
||||
@property
|
||||
def lcd_brightness(self) -> int:
|
||||
"""Read the LCD brightness state (0-100)"""
|
||||
return self._read("<H", _EXPANDER_REG_LCD_BRIGHTNESS, 2)[0]
|
||||
|
||||
@lcd_brightness.setter
|
||||
def lcd_brightness(self, value: int):
|
||||
"""Set the LCD brightness (0-100)"""
|
||||
if value >= 0 and value <= 100:
|
||||
self._write(_EXPANDER_REG_LCD_BRIGHTNESS, struct.pack("<H", value))
|
||||
|
||||
@property
|
||||
def debug_led(self) -> int:
|
||||
"""Read the Debug LED state (0-100)"""
|
||||
return self._read("<H", _EXPANDER_REG_DEBUG_LED, 2)[0]
|
||||
|
||||
@debug_led.setter
|
||||
def debug_led(self, value: int):
|
||||
"""Set the Debug LED (0-100)"""
|
||||
if value >= 0 and value <= 100:
|
||||
self._write(_EXPANDER_REG_DEBUG_LED, struct.pack("<H", value))
|
||||
|
||||
@property
|
||||
def config(self) -> tuple[bool, bool, bool]:
|
||||
"""Read the configuration bits: reboot, lcd_reset, aux_power"""
|
||||
config = self._read("B", _EXPANDER_REG_CONFIG, 1)[0]
|
||||
return tuple([bool(int(digit)) for digit in "{:08b}".format(config)[5:]])
|
||||
|
||||
@config.setter
|
||||
def config(self, value: int):
|
||||
"""set the configuration byte"""
|
||||
if value >= 0 and value <= 0xFF:
|
||||
self._write(_EXPANDER_REG_CONFIG, struct.pack("B", value))
|
||||
Reference in New Issue
Block a user