From 746b53cc9d36049d171ed15a151f380ffa778867 Mon Sep 17 00:00:00 2001 From: dahanzimin <353767514@qq.com> Date: Fri, 9 Jan 2026 16:55:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=94=AF=E6=8C=81mixgo=5Fsow?= =?UTF-8?q?l/ESP32C5=E7=9A=84=E6=9D=BF=E8=BD=BD=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../micropython/origin/build/lib/image.py | 87 ++++++ .../origin/build/lib/mixgo_sowl.py | 263 ++++++++++++++++++ .../origin/build/lib/sowl_bot.py | 121 ++++++++ .../origin/build/lib/st7735_cf.py | 100 +++++++ .../origin/build/lib/ws2812x.py | 66 +++++ 5 files changed, 637 insertions(+) create mode 100644 boards/default_src/micropython/origin/build/lib/image.py create mode 100644 boards/default_src/micropython_esp32c5/origin/build/lib/mixgo_sowl.py create mode 100644 boards/default_src/micropython_esp32c5/origin/build/lib/sowl_bot.py create mode 100644 boards/default_src/micropython_esp32c5/origin/build/lib/st7735_cf.py create mode 100644 boards/default_src/micropython_esp32c5/origin/build/lib/ws2812x.py diff --git a/boards/default_src/micropython/origin/build/lib/image.py b/boards/default_src/micropython/origin/build/lib/image.py new file mode 100644 index 00000000..87dd2431 --- /dev/null +++ b/boards/default_src/micropython/origin/build/lib/image.py @@ -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() diff --git a/boards/default_src/micropython_esp32c5/origin/build/lib/mixgo_sowl.py b/boards/default_src/micropython_esp32c5/origin/build/lib/mixgo_sowl.py new file mode 100644 index 00000000..e338422d --- /dev/null +++ b/boards/default_src/micropython_esp32c5/origin/build/lib/mixgo_sowl.py @@ -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() diff --git a/boards/default_src/micropython_esp32c5/origin/build/lib/sowl_bot.py b/boards/default_src/micropython_esp32c5/origin/build/lib/sowl_bot.py new file mode 100644 index 00000000..de75f437 --- /dev/null +++ b/boards/default_src/micropython_esp32c5/origin/build/lib/sowl_bot.py @@ -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)) diff --git a/boards/default_src/micropython_esp32c5/origin/build/lib/st7735_cf.py b/boards/default_src/micropython_esp32c5/origin/build/lib/st7735_cf.py new file mode 100644 index 00000000..574b9dc9 --- /dev/null +++ b/boards/default_src/micropython_esp32c5/origin/build/lib/st7735_cf.py @@ -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) diff --git a/boards/default_src/micropython_esp32c5/origin/build/lib/ws2812x.py b/boards/default_src/micropython_esp32c5/origin/build/lib/ws2812x.py new file mode 100644 index 00000000..a2e3c253 --- /dev/null +++ b/boards/default_src/micropython_esp32c5/origin/build/lib/ws2812x.py @@ -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)