diff --git a/boards/OPENMV_AE3/manifest.py b/boards/OPENMV_AE3/manifest.py index 9069b62c3..025133bbd 100644 --- a/boards/OPENMV_AE3/manifest.py +++ b/boards/OPENMV_AE3/manifest.py @@ -7,6 +7,7 @@ require("lsm6dsox") #freeze ("$(OMV_LIB_DIR)/", "bno055.py") #freeze ("$(OMV_LIB_DIR)/", "ssd1306.py") freeze ("$(OMV_LIB_DIR)/", "ssd1351.py") +freeze ("$(OMV_LIB_DIR)/", "pca9674a.py") #freeze ("$(OMV_LIB_DIR)/", "tb6612.py") freeze ("$(OMV_LIB_DIR)/", "vl53l1x.py") freeze ("$(OMV_LIB_DIR)/", "machine.py") diff --git a/scripts/examples/50-OpenMV-Boards/52-Alif-Boards/51-OLED-Shield/oled_display_joystick.py b/scripts/examples/50-OpenMV-Boards/52-Alif-Boards/51-OLED-Shield/oled_display_joystick.py new file mode 100644 index 000000000..e64ed6eef --- /dev/null +++ b/scripts/examples/50-OpenMV-Boards/52-Alif-Boards/51-OLED-Shield/oled_display_joystick.py @@ -0,0 +1,61 @@ +# This work is licensed under the MIT license. +# Copyright (c) 2013-2025 OpenMV LLC. All rights reserved. +# https://github.com/openmv/openmv/blob/master/LICENSE +# +# OLED Display with Joystick Example +# +# Note: To run this example you will need a OLED Breakout Board for your OpenMV AE3 +# +# The OLED Breakout Board allows you to view your OpenMV AE3's frame buffer on the go. + +import sensor +import time +import display +from pca9674a import PCA9674A +from machine import I2C + + +sensor.reset() +sensor.set_pixformat(sensor.RGB565) +sensor.set_framesize(sensor.VGA) +sensor.set_windowing((400, 400)) + +lcd = display.SPIDisplay(width=128, height=128, controller=display.SSD1351()) +clock = time.clock() + + +def read_expander(pin): + global exp, state + state = exp.read() ^ 0xFF + + +x_scale_def = 128 / 400 +y_scale_def = 128 / 400 +state = 0 +cursor_x = 0 +cursor_y = 0 +exp = PCA9674A(I2C(1), irq_pin="P9", callback=read_expander) + + +def update_cursor(): + global cursor_x, cursor_y + if state & 0x01: # Right + cursor_x += 2 + if state & 0x02: # Up + cursor_y -= 2 + if state & 0x04: # Left + cursor_x -= 2 + if state & 0x08: # Down + cursor_y += 2 + if state & 0x10: # Center + cursor_x = 0 + cursor_y = 0 + + +while True: + clock.tick() + update_cursor() + lcd.write(sensor.snapshot(), x=cursor_x, y=cursor_y, + x_scale=x_scale_def, y_scale=y_scale_def) + + print(clock.fps()) diff --git a/scripts/libraries/pca9674a.py b/scripts/libraries/pca9674a.py new file mode 100644 index 000000000..4e3565128 --- /dev/null +++ b/scripts/libraries/pca9674a.py @@ -0,0 +1,50 @@ +# This file is part of the OpenMV project. +# +# Copyright (c) 2013-2025 OpenMV LLC. All rights reserved. +# +# This work is licensed under the MIT license, see the file LICENSE for details. +# +# PCA9674A I2C expander driver. + +from time import sleep_ms +from machine import Pin +from micropython import const + +_DEFAULT_ADDR = const(63) + + +class PCA9674A: + + def __init__(self, bus, irq_pin, address=_DEFAULT_ADDR, callback=None): + self.bus = bus + self.address = address + self.callback = callback + self.irq_pin = None + self.irq_pin_label = irq_pin + self.state = bytearray(1) + self.reset() + + def write(self, value): + self.state[0] = value + self.bus.writeto(self.address, self.state) + + def read(self): + self.bus.readfrom_into(self.address, self.state) + return self.state[0] + + def reset(self): + if self.irq_pin is not None: + self.irq_pin.irq(handler=None) + + sleep_ms(10) + self.bus.writeto(self.address, bytes([0xff])) + sleep_ms(10) + self.bus.readfrom(self.address, 1) + sleep_ms(10) + + self.irq_pin = Pin(self.irq_pin_label, Pin.IN, Pin.PULL_UP) + + if self.callback is not None: + self.irq_pin.irq( + handler=self.callback, trigger=Pin.IRQ_FALLING, hard=False + )