更新支持mixgo_sowl/ESP32C5的板载库

This commit is contained in:
dahanzimin
2026-01-09 16:55:37 +08:00
parent c9f37bbadf
commit 746b53cc9d
5 changed files with 637 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
"""
Iamge
MicroPython library for the Iamge(jpeg C module)
=======================================================
@dahanzimin From the Mixly Team
"""
import gc
import urequests
from base64 import b64encode
from jpeg import Encoder, Decoder
class IMG:
def __init__(self, image, width, height):
self.image = image
self.width = width
self.height = height
self.format = "RGB565"
class Image:
def save(self, img, path="mixly.jpg", **kwargs):
'''quality(1-100), rotation (0, 90, 180, 270)'''
_encoder = Encoder(pixel_format="RGB565_BE", width=img.width, height=img.height, **kwargs)
_jpeg = _encoder.encode(img.image)
del _encoder
gc.collect()
if isinstance(path, str):
with open(path, 'wb') as f:
f.write(_jpeg)
else:
return _jpeg
def open(self, path="mixly.jpg", scale_width=None, scale_height=None, tft_width=240, tft_height=240, **kwargs):
'''rotation (0, 90, 180, 270), clipper_width, clipper_height'''
with open(path, "rb") as f:
_jpeg = f.read()
return self._jpg_decoder(_jpeg, scale_width, scale_height, tft_width, tft_height, **kwargs)
def convert(self, img, formats=0, **kwargs):
if formats == 0:
return self.save(img, None, **kwargs)
elif formats == 1:
return b'data:image/jpg;base64,' + b64encode(self.save(img, None, **kwargs))
def download(self, url, path=None, scale_width=None, scale_height=None, tft_width=240, tft_height=240, block=1024, **kwargs):
'''rotation (0, 90, 180, 270), clipper_width, clipper_height'''
response = urequests.get(url, stream=True)
if path is None:
_image = self._jpg_decoder(response.raw.read(), scale_width, scale_height, tft_width, tft_height, **kwargs)
response.close()
return _image
else:
with open(path, 'wb') as f:
while True:
_data = response.raw.read(block)
if not _data:
break
else:
f.write(_data)
response.close()
def _jpg_decoder(self, jpg, scale_width, scale_height, tft_width, tft_height, **kwargs):
'''Automatically zoom based on the screen'''
if scale_width is None or scale_height is None:
_width = tft_width
_height = tft_height
for i in range(min(len(jpg), 1024)):
if jpg[i] == 0xFF and (jpg[i + 1] & 0xF0) == 0xC0:
if jpg[i + 1] not in [0xC4, 0xC8, 0xCC]:
_width = jpg[i + 7] << 8 | jpg[i + 8]
_height = jpg[i + 5] << 8| jpg[i + 6]
break
if _width > tft_width or _height > tft_height:
_scale = max(_width / tft_width, _height / tft_height) * 8
_decoder = Decoder(pixel_format="RGB565_BE", scale_width=round(_width / _scale) * 8, scale_height=round(_height / _scale) * 8, **kwargs)
else:
_decoder = Decoder(pixel_format="RGB565_BE", **kwargs)
else:
_decoder = Decoder(pixel_format="RGB565_BE", scale_width=scale_width // 8 * 8, scale_height=scale_height // 8 * 8, **kwargs)
_info = _decoder.get_img_info(jpg)
_image = IMG(_decoder.decode(jpg), _info[0], _info[1])
del _decoder, jpg
gc.collect()
return _image
#图像处理
Image = Image()

View File

@@ -0,0 +1,263 @@
"""
mixgo_sowl Onboard resources(v1.3)
Micropython library for the mixgo_sant Onboard resources
=======================================================
@dahanzimin From the Mixly Team
"""
import gc
import time
import math
from machine import *
from music import MIDI
from ws2812x import NeoPixel
'''RTC'''
rtc_clock = RTC()
'''I2C-onboard'''
# onboard_i2c = I2C(0)
onboard_i2c = SoftI2C(scl=Pin(27), sda=Pin(26), freq=400000)
'''SPI-onboard'''
onboard_spi = SPI(1, baudrate=80000000, polarity=0, phase=0)
'''BOT035-Sensor'''
try:
import sowl_bot
onboard_bot = sowl_bot.BOT035(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with BOT035 (Coprocessor) or", e)
'''TFT/128*128'''
import st7735_cf
onboard_tft = st7735_cf.ST7735(onboard_spi, 128, 128, dc_pin=23, reset=onboard_bot.tft_reset, backlight=onboard_bot.tft_brightness, font_address=0x700000)
'''BPS-Sensor'''
try:
import spl06_001
onboard_bps = spl06_001.SPL06(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with SPL06-001 (BPS) or", e)
'''ACC-Sensor'''
try:
import sc7a20
onboard_acc = sc7a20.SC7A20(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with SC7A20H (ACC) or", e)
'''ALS_PS-Sensor'''
try:
import ltr553als
onboard_als = ltr553als.LTR_553ALS(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with LTR_553ALS (ALS&PS) or", e)
'''THS-Sensor'''
try:
import shtc3
onboard_ths = shtc3.SHTC3(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with GXHTC3 (THS) or", e)
'''MGS-Sensor'''
try:
import mmc5603
onboard_mgs = mmc5603.MMC5603(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with MMC5603 (MGS) or", e)
'''RFID_Sensor'''
try :
import rc522
onboard_rfid = rc522.RC522(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with SI522 (RFID) or",e)
'''ASR-Sensor'''
try:
from ci130x import CI130X
onboard_asr = CI130X(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with CI1316XP (ASR) or", e)
'''2RGB_WS2812'''
onboard_rgb = NeoPixel(onboard_bot.rgb_sync, 3)
'''1Buzzer-Music'''
onboard_music = MIDI(0, pa_ctrl=onboard_asr.pa_ctrl)
'''5KEY_Sensor'''
class KEYSensor:
def __init__(self, pin, range):
self.pin = pin
self.adc = ADC(Pin(pin))
self.adc.atten(ADC.ATTN_0DB)
self.range = range
self.flag = True
def _value(self):
values = []
for _ in range(25):
values.append(self.adc.read())
time.sleep_us(5)
return (self.range-200) < min(values) < (self.range+200)
def get_presses(self, delay=1):
last_time, presses = time.time(), 0
while time.time() < last_time + delay:
time.sleep_ms(50)
if self.was_pressed():
presses += 1
return presses
def is_pressed(self):
return self._value()
def was_pressed(self):
if (self._value() != self.flag):
self.flag = self._value()
if self.flag:
return True
else:
return False
def irq(self, handler, trigger):
Pin(self.pin, Pin.IN).irq(handler=handler, trigger=trigger)
'''1KEY_Button'''
class Button(KEYSensor):
def __init__(self, pin):
self.pin = pin
self.key = Pin(pin, Pin.IN)
self.flag = True
def _value(self):
return not self.key.value()
B1key = Button(28)
B2key = KEYSensor(5, 0)
A1key = KEYSensor(5, 800)
A2key = KEYSensor(5, 2050)
A3key = KEYSensor(5, 2600)
A4key = KEYSensor(5, 1450)
'''2-LED'''
class LED:
def __init__(self, func):
self._func = func
def setbrightness(self, index, val):
self._func(index, val)
def getbrightness(self, index):
return self._func(index)
def setonoff(self, index, val):
if val == -1:
self.setbrightness(index, 100) if self.getbrightness(index) < 50 else self.setbrightness(index, 0)
elif val == 1:
self.setbrightness(index, 100)
elif val == 0:
self.setbrightness(index, 0)
def getonoff(self, index):
return True if self.getbrightness(index) > 50 else False
onboard_led = LED(onboard_bot.led_pwm)
'''MIC_Sensor'''
class MICSensor:
def __init__(self,pin):
self.adc=ADC(Pin(pin), atten=ADC.ATTN_11DB)
def read(self):
maxloudness = 0
for i in range(5):
loudness = self.sample()
if loudness > maxloudness:
maxloudness = loudness
return maxloudness
def sample(self):
values = []
for i in range(50):
val = self.adc.read_u16()
values.append(val)
return max(values) - min(values)
onboard_sound = MICSensor(6)
class Clock:
def __init__(self, x, y, radius, color, oled=onboard_tft): # 定义时钟中心点和半径
self.display = oled
self.xc = x
self.yc = y
self.r = radius
self.color = color
self.hour = 0
self.min = 0
self.sec = 0
def set_time(self, h, m, s): # 设定时间
self.hour = h
self.min = m
self.sec = s
def set_rtctime(self): # 设定时间
t = rtc_clock.datetime()
self.hour = t[4]
self.min = t[5]
self.sec = t[6]
def drawDial(self, color): # 画钟表刻度
r_tic1 = self.r - 1
r_tic2 = self.r - 2
self.display.ellipse(self.xc, self.yc, self.r, self.r, color)
self.display.ellipse(self.xc, self.yc, 2, 2, color, True)
for h in range(12):
at = math.pi * 2.0 * h / 12.0
x1 = round(self.xc + r_tic1 * math.sin(at))
x2 = round(self.xc + r_tic2 * math.sin(at))
y1 = round(self.yc - r_tic1 * math.cos(at))
y2 = round(self.yc - r_tic2 * math.cos(at))
self.display.line(x1, y1, x2, y2, color)
def drawHour(self, color): # 画时针
r_hour = int(self.r / 10.0 * 5)
ah = math.pi * 2.0 * ((self.hour % 12) + self.min / 60.0) / 12.0
xh = int(self.xc + r_hour * math.sin(ah))
yh = int(self.yc - r_hour * math.cos(ah))
self.display.line(self.xc, self.yc, xh, yh, color)
def drawMin(self, color): # 画分针
r_min = int(self.r / 10.0 * 7)
am = math.pi * 2.0 * self.min / 60.0
xm = round(self.xc + r_min * math.sin(am))
ym = round(self.yc - r_min * math.cos(am))
self.display.line(self.xc, self.yc, xm, ym, color)
def drawSec(self, color): # 画秒针
r_sec = int(self.r / 10.0 * 9)
asec = math.pi * 2.0 * self.sec / 60.0
xs = round(self.xc + r_sec * math.sin(asec))
ys = round(self.yc - r_sec * math.cos(asec))
self.display.line(self.xc, self.yc, xs, ys, color)
def draw_clock(self, bg_color=0): # 画完整钟表
self.drawDial(self.color)
self.drawHour(self.color)
self.drawMin(self.color)
self.drawSec(self.color)
self.display.show()
self.drawHour(bg_color)
self.drawMin(bg_color)
self.drawSec(bg_color)
def clear(self, color=0): # 清除
self.display.ellipse(self.xc, self.yc, self.r, self.r, color, True)
'''Reclaim memory'''
gc.collect()

View File

@@ -0,0 +1,121 @@
"""
SOWL_WCH
Micropython library for the SOWL_WCH(--V1.0--)
=======================================================
@dahanzimin From the Mixly Team
"""
import time
from micropython import const
_BOT035_ADDRESS = const(0x13)
_BOT5_TOUCH = const(0x01)
_BOT035_PHZ = const(0x05)
_BOT035_PWM = const(0x09)
_BOT035_LED = const(0x0D)
_BOT035_STA = const(0x10)
_BOT035_RGB = const(0x11)
_BOT035_KB = const(0x1A)
_BOT035_MS = const(0xAE)
_BOT035_STR = const(0x22)
class BOT035:
def __init__(self, i2c_bus):
self._i2c = i2c_bus
self._touchs = [self.touch(0), self.touch(1)]
self.reset()
def _wreg(self, reg, val, digit=1):
'''Write memory address'''
self._i2c.writeto_mem(_BOT035_ADDRESS, reg, val.to_bytes(digit, 'little'))
def _rreg(self, reg, nbytes=1):
'''Read memory address'''
self._i2c.writeto(_BOT035_ADDRESS, reg.to_bytes(1, 'little'))
return int.from_bytes(self._i2c.readfrom(_BOT035_ADDRESS, nbytes), 'little')
def _bits(self, offset, mask, value=None, delay=100, reg=_BOT035_STA):
if value is None:
return (self._rreg(reg) & mask) >> offset
else:
self._wreg(reg, (self._rreg(reg) & (~ mask & 0xFF)) | (value << offset))
time.sleep_ms(delay)
def reset(self):
self._i2c.writeto_mem(_BOT035_ADDRESS, _BOT035_PHZ, b' N Nddddd\x00\x00\x0c')
def touch(self, index, value=None):
index = max(min(index, 1), 0)
touch = 4095 - self._rreg(_BOT5_TOUCH + index * 2, 2)
return touch > value if value else touch
def touched(self, index, value=600):
return self.touch(index, value)
def touch_slide(self):
values = []
for i in range(20):
values.append((self.touch(1) - self._touchs[1]) - (self.touch(0) - self._touchs[0]))
return round(sorted(values)[10] / 10)
def usben(self, index=1, duty=None, freq=None):
if index not in (1, 2, 4, 5):
raise ValueError("USB port must be a number in (1, 2, 4, 5)")
if duty is not None:
self._wreg(_BOT035_PWM + index - (1 if index < 3 else 2), int(max(min(duty, 100), 0)))
if freq is not None:
self._wreg(_BOT035_PHZ + (0 if index < 3 else 2) , max(min(freq, 65535), 10), 2)
if freq is None and duty is None:
return self._rreg(_BOT035_PWM + index - (1 if index < 3 else 2)), self._rreg(_BOT035_PHZ + (0 if index < 3 else 2), 2)
def tft_brightness(self, brightness=None):
"""PMOS inverting level driver"""
if brightness is None:
return 100 - self._rreg(_BOT035_LED)
else:
self._wreg(_BOT035_LED, max(min(100 - brightness, 100), 0))
def led_pwm(self, index=1, duty=None):
index = max(min(index, 2), 1)
if duty is None:
return self._rreg(_BOT035_LED + index)
else:
self._wreg(_BOT035_LED + index, max(min(duty, 100), 0))
def tft_reset(self, value=None, delay=50):
return self._bits(7, 0x80, value, delay)
def mcu_reset(self, value=None, delay=10):
return self._bits(2, 0x04, value, delay)
def rgb_sync(self, buffer, n=9):
self._i2c.writeto_mem(_BOT035_ADDRESS, _BOT035_RGB, buffer if len(buffer) < n else buffer[:n])
def hid_keyboard(self, special=0, general=0, release=True):
self._buf = bytearray(4)
self._buf[0] = special
if type(general) in (tuple, list):
for i in range(len(general)):
if i > 2: break
self._buf[i + 1] = general[i]
else:
self._buf[1] = general
self._i2c.writeto_mem(_BOT035_ADDRESS, _BOT035_KB, self._buf)
if release:
time.sleep_ms(10)
self._i2c.writeto_mem(_BOT035_ADDRESS, _BOT035_KB, bytes(4))
def hid_keyboard_str(self, string, delay=0):
for char in str(string):
self._wreg(_BOT035_STR, ord(char) & 0xFF)
time.sleep_ms(20 + delay)
def hid_keyboard_state(self):
state = self._rreg(_BOT035_STA)
return bool(state & 0x10), bool(state & 0x20), bool(state & 0x40)
def hid_mouse(self, keys=0, move=(0, 0), wheel=0, release=True):
self._i2c.writeto_mem(_BOT035_ADDRESS, _BOT035_MS, bytes([keys & 0x0F, move[0] & 0xFF, move[1] & 0xFF, wheel & 0xFF]))
if release:
time.sleep_ms(10)
self._i2c.writeto_mem(_BOT035_ADDRESS, _BOT035_MS, bytes(4))

View File

@@ -0,0 +1,100 @@
"""
ST7735/FrameBuffer
MicroPython library for the ST7735(TFT-SPI)
=======================================================
@dahanzimin From the Mixly Team
"""
import time
import uframebuf
from machine import Pin
from image import Image, IMG
class ST7735(uframebuf.FrameBuffer_Uincode):
def __init__(self, spi, width, height, dc_pin=None, backlight=None, reset=None, font_address=0x700000):
self.spi = spi
self.dc = Pin(dc_pin, Pin.OUT, value=1)
self._buffer = bytearray(width * height * 2)
super().__init__(self._buffer, width, height, uframebuf.RGB565)
if reset: reset(1, 100)
self.font(font_address)
self._init()
self._oneclight = True
self._backlight = backlight
def _write(self, cmd, dat=None):
"""Write command or data"""
self.dc.off()
self.spi.write(bytearray([cmd]))
if dat is not None:
self.dc.on()
self.spi.write(dat)
def _init(self):
"""Display initialization configuration"""
for cmd, data, delay in [
(0x11, None, 120000),
(0xB1, b'\x01\x2C\x2D', 10),
(0xB2, b'\x01\x2C\x2D', 10),
(0xB3, b'\x01\x2C\x2D', 10),
(0xB4, b'\x07', 10),
(0xC0, b'\xA2\x02\x84', 10),
(0xC1, b'\xC5', 10),
(0xC2, b'\x0A\x00', 10),
(0xC3, b'\x8A\x2A', 10),
(0xC4, b'\x8A\xEE', 10),
(0xC5, b'\x0E', 10),
(0x36, b'\xC8', 10),
(0xE0, b'\x02\x1C\x07\x12\x37\x32\x29\x2D\x29\x25\x2B\x39\x00\x01\x03\x10', 10),
(0xE1, b'\x03\x1D\x07\x06\x2E\x2C\x29\x2D\x2E\x2E\x37\x3F\x00\x00\x02\x10', 10),
(0x3A, b'\x05', 10),
(0x29, None, 10),
(0x2A, b'\x00\x02\x00\x81', 10),
(0x2B, b'\x00\x03\x00\x82', 10)
]:
self._write(cmd, data)
if delay:
time.sleep_us(delay)
def display(self, data=None, x=None, y=None, scale_width=None, scale_height=None, rotation=0, sync=True):
'''data is a string, display the path image; otherwise, display the image of data'''
if type(data) is str:
data = Image.open(data, scale_width, scale_height, self.width, self.height, rotation=rotation)
if sync: self.fill(0x0, sync=False)
self.blit_rgb565(data.image, data.width, data.height, x, y)
if sync: self.show()
def screenshot(self, data=None, x=0, y=0, w=None, h=None, **kwargs):
'''data is a string, save the path image; otherwise, return the image of data'''
if (w is None and h is None):
_img = IMG(memoryview(self._buffer), self.width, self.height)
else:
_img = IMG(memoryview(self.crop_rgb565(x,y,w,h)), w, h)
if type(data) is str:
Image.save(_img, data, **kwargs)
return _img
def get_brightness(self):
return self._backlight() / 100
def set_brightness(self, brightness):
if not 0.0 <= brightness <= 1.0:
raise ValueError(
"Brightness must be a decimal number in the range: 0.0~1.0")
self._backlight(int(brightness * 100))
def color(self, red, green=None, blue=None):
""" Convert red, green and blue values (0-255) into a 16-bit 565 encoding."""
if green is None or blue is None:
return red
else:
return (red & 0xf8) << 8 | (green & 0xfc) << 3 | blue >> 3
def show(self):
"""Refresh the display and show the changes."""
self._write(0x2C, self._buffer)
if self._oneclight:
self._oneclight = False
for i in range(60): #slow down display
self.set_brightness(i / 100)
time.sleep_ms(5)

View File

@@ -0,0 +1,66 @@
"""
WS2812 RGB(x035)
Micropython library for the WS2812 NeoPixel-RGB(method inheritance)
=======================================================
@dahanzimin From the Mixly Team
"""
from time import sleep
class NeoPixel:
def __init__(self, func, n, bpp=3, ORDER=(0, 1, 2, 3)):
self.func = func
self.bpp = bpp
self.rgbs = n
self.ORDER = ORDER
self.rgb_buf = bytearray(self.rgbs * bpp)
self.write()
def __len__(self):
return self.rgbs
def __setitem__(self, n, v):
for i in range(self.bpp):
self.rgb_buf[n * self.bpp + self.ORDER[i]] = v[i]
def __getitem__(self, n):
return tuple(self.rgb_buf[n * self.bpp + self.ORDER[i]] for i in range(self.bpp))
def fill(self, v):
for i in range(self.bpp):
j = self.ORDER[i]
while j < self.rgbs * self.bpp:
self.rgb_buf[j] = v[i]
j += self.bpp
def write(self):
self.func(self.rgb_buf)
def color_chase(self, R, G, B, wait):
for i in range(self.rgbs):
self.__setitem__(i, (R, G, B))
self.write()
sleep(wait/1000)
def rainbow_cycle(self, wait, clear=True):
for j in range(255):
for i in range(self.rgbs):
rc_index = (i * 256 // self.rgbs) + j
self.__setitem__(i, self.wheel(rc_index & 255))
self.write()
sleep(wait / 1000 / 256)
if clear:
self.fill((0, 0, 0))
self.write()
def wheel(self, pos):
if pos < 0 or pos > 255:
return (0, 0, 0)
elif pos < 85:
return (pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return (255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return (0, pos * 3, 255 - pos * 3)