更新 mini支持讯飞中英文识别大模型,sant增加image对图像处理

This commit is contained in:
dahanzimin
2025-10-27 10:32:44 +08:00
parent f9d3427b20
commit d98b9fb0ed
4 changed files with 465 additions and 425 deletions

View File

@@ -45,7 +45,6 @@ class ASR_WebSocket(Ws_Param):
"domain": "iat", "domain": "iat",
"language": "zh_cn", "language": "zh_cn",
"accent": "mandarin", "accent": "mandarin",
"vinfo": 1,
"vad_eos": 1000, "vad_eos": 1000,
"nbest": 1, "nbest": 1,
"wbest": 1, "wbest": 1,
@@ -56,7 +55,10 @@ class ASR_WebSocket(Ws_Param):
self.ws.settimeout(1000) self.ws.settimeout(1000)
def _frame(self, status, buf): def _frame(self, status, buf):
return {"status": status, "format": "audio/L16;rate=8000", "audio": str(b64encode(buf), 'utf-8'), "encoding": "raw"} if status == 0:
return {"common": {"app_id": self.APPID}, "business": self.business, "data": {"status": status, "format": "audio/L16;rate=8000", "audio": str(b64encode(buf), 'utf-8'), "encoding": "raw"}}
else:
return {"data": {"status": status, "format": "audio/L16;rate=8000", "audio": str(b64encode(buf), 'utf-8'), "encoding": "raw"}}
def on_message(self, message): def on_message(self, message):
result = "" result = ""
@@ -98,17 +100,16 @@ class ASR_WebSocket(Ws_Param):
if pace: print('=',end ="") if pace: print('=',end ="")
# 第一帧处理 # 第一帧处理
if _state == 0: if _state == 0:
d = {"common": {"app_id": self.APPID}, "business": self.business, "data": self._frame(_state, buf)} d = self._frame(_state, buf)
_state = 1 _state = 1
# 中间帧处理 # 中间帧处理
else: else:
d = {"data": self._frame(_state, buf)} d = self._frame(_state, buf)
self.ws.send(json.dumps(d)) self.ws.send(json.dumps(d))
#print("------",len(buf), time.ticks_diff(time.ticks_ms(), _star))
if time.ticks_diff(time.ticks_ms(), _star) > timeout: if time.ticks_diff(time.ticks_ms(), _star) > timeout:
raise OSError("Timeout pcm read error") raise OSError("Timeout pcm read error")
# 最后一帧处理 # 最后一帧处理
d = {"data": self._frame(2, b'\x00')} d = self._frame(2, b'\x00')
self.ws.send(json.dumps(d)) self.ws.send(json.dumps(d))
onboard_bot.pcm_en(False) #PCM关闭 onboard_bot.pcm_en(False) #PCM关闭
if pace: print(']') if pace: print(']')
@@ -122,6 +123,45 @@ class ASR_WebSocket(Ws_Param):
else: else:
print("Run error: %s" % (e)) print("Run error: %s" % (e))
#中英识别大模型
class IAT_WebSocket(ASR_WebSocket):
def __init__(self, APPID, APIKey, APISecret, url='ws://iat.xf-yun.com/v1', accent="mandarin", res_id=None):
super().__init__(APPID, APIKey, APISecret, url)
self.res_id = res_id
self.business = {
"domain": "slm",
"language": "zh_cn",
"accent": accent,
"result": {
"encoding": "utf8",
"compress": "raw",
"format": "plain"
}
}
def _frame(self, status, buf):
if status == 0:
return {"header": {"status": status, "app_id": self.APPID, "res_id": self.res_id}, "parameter": {"iat": self.business}, "payload": {"audio": { "audio": str(b64encode(buf), 'utf-8'), "sample_rate": 8000, "encoding": "raw"}}}
else:
return {"header": {"status": status, "app_id": self.APPID, "res_id": self.res_id}, "payload": {"audio": { "audio": str(b64encode(buf), 'utf-8'), "sample_rate": 8000, "encoding": "raw"}}}
def on_message(self, message):
result = ""
msg = json.loads(message)
code = msg['header']["code"]
if code != 0:
raise AttributeError("%s Code:%s" % (msg['header']["message"], code))
else:
if "payload" in msg:
text = msg["payload"]["result"]["text"]
data = json.loads(b64decode(text).decode())['ws']
for i in data:
for w in i["cw"]:
result += w["w"]
if msg["header"]["status"]== 2:
return result, False
return result, True
#大模型 #大模型
class LLM_WebSocket(Ws_Param): class LLM_WebSocket(Ws_Param):
Model_url = { Model_url = {

View File

@@ -1,47 +1,73 @@
""" """
Camera Camera
MicroPython library for the Camera(Inherit C module) MicroPython library for the Camera(Inherit C module)
======================================================= =======================================================
@dahanzimin From the Mixly Team @dahanzimin From the Mixly Team
""" """
import time
import time from _camera import *
import base64 from base64 import b64encode
import jpeg from machine import SoftI2C, Pin
from _camera import * from jpeg import Encoder, Decoder
from jpeg import Encoder
from machine import SoftI2C, Pin class IMG:
from mixgo_sant import onboard_bot def __init__(self, image, width, height):
self.image = image
self.width = width
class Camera(Camera): self.height = height
def __init__(self, frame_size=FrameSize.R240X240, pixel_format=PixelFormat.RGB565, hmirror=False, vflip=False, **kwargs): self.format = "RGB565"
onboard_bot.cam_en(1, 150)
super().__init__(frame_size=frame_size, pixel_format=pixel_format, **kwargs) class Camera(Camera):
self.set_hmirror(not hmirror) def __init__(self, frame_size=FrameSize.R240X240, pixel_format=PixelFormat.RGB565, hmirror=False, vflip=False, **kwargs):
time.sleep_ms(50) from mixgo_sant import onboard_bot
self.set_vflip(not vflip) onboard_bot.cam_reset(1, 0)
time.sleep_ms(50) onboard_bot.cam_en(1, 150)
SoftI2C(scl=Pin(47), sda=Pin(48), freq=400000) # 恢复I2C super().__init__(frame_size=frame_size, pixel_format=pixel_format, **kwargs)
self.set_hmirror(not hmirror)
def deinit(self): time.sleep_ms(50)
super().deinit() self.set_vflip(not vflip)
onboard_bot.cam_en(0, 100) time.sleep_ms(50)
SoftI2C(scl=Pin(47), sda=Pin(48), freq=400000) # 恢复I2C
def snapshot(self, path=None, formats=0, quality=90, rotation=0):
if formats == 0 and path is None: def deinit(self):
return self.capture() super().deinit()
else: onboard_bot.cam_reset(0, 0)
_encoder = Encoder(pixel_format="RGB565_BE", quality=quality, rotation=rotation, width=self.get_pixel_width(), height=self.get_pixel_height()) onboard_bot.cam_en(0, 100)
_jpeg = _encoder.encode(self.capture())
del _encoder def snapshot(self, path=None, quality=90, rotation=0):
if path is None: if path is None:
if formats == 1: return self.capture()
return _jpeg else:
else: Image.save(self.capture(), path, quality, rotation)
return b'data:image/jpg;base64,' + base64.b64encode(_jpeg)
else: def capture(self):
with open(path, 'wb') as f: return IMG(super().capture(), self.get_pixel_width(), self.get_pixel_height())
f.write(_jpeg)
return True class Image:
def save(self, img, path="mixly.jpg", quality=90, rotation=0, **kwargs):
_encoder = Encoder(pixel_format="RGB565_BE", quality=quality, rotation=rotation, width=img.width, height=img.height, **kwargs)
_jpeg = _encoder.encode(img.image)
del _encoder
if isinstance(path, str):
with open(path, 'wb') as f:
f.write(_jpeg)
else:
return _jpeg
def open(self, path="mixly.jpg", rotation=0, **kwargs):
with open(path, "rb") as f:
_jpeg = f.read()
_decoder = Decoder(pixel_format="RGB565_BE", rotation=rotation, **kwargs)
_info = _decoder.get_img_info(_jpeg)
_image = IMG(_decoder.decode(_jpeg), _info[0], _info[1])
del _decoder
return _image
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))
#图像处理
Image = Image()

View File

@@ -1,259 +1,245 @@
""" """
mixgo_sant Onboard resources(v1.9) mixgo_sant Onboard resources(v2.0)
Micropython library for the mixgo_sant Onboard resources Micropython library for the mixgo_sant Onboard resources
======================================================= =======================================================
@dahanzimin From the Mixly Team
@dahanzimin From the Mixly Team """
""" import gc
from music import MIDI import time
from ws2812x import NeoPixel import math
from machine import * from machine import *
import time from music import MIDI
import gc from ws2812x import NeoPixel
import st7789_cf
import math '''RTC'''
rtc_clock = RTC()
'''RTC'''
rtc_clock = RTC() '''I2C-onboard'''
# inboard_i2c = I2C(0)
'''I2C-onboard''' inboard_i2c = SoftI2C(scl=Pin(47), sda=Pin(48), freq=400000)
# inboard_i2c = I2C(0) onboard_i2c = SoftI2C(scl=Pin(47), sda=Pin(38), freq=400000)
inboard_i2c = SoftI2C(scl=Pin(47), sda=Pin(48), freq=400000)
onboard_i2c = SoftI2C(scl=Pin(47), sda=Pin(38), freq=400000) '''SPI-onboard'''
onboard_spi = SPI(1, baudrate=80000000, polarity=1, phase=1)
'''SPI-onboard'''
onboard_spi = SPI(1, baudrate=80000000, polarity=1, phase=1) '''BOT035-Sensor'''
try:
'''BOT035-Sensor''' import sant_bot
try: onboard_bot = sant_bot.BOT035(inboard_i2c)
import sant_bot except Exception as e:
onboard_bot = sant_bot.BOT035(inboard_i2c) print("Warning: Failed to communicate with BOT035 (Coprocessor) or", e)
except Exception as e:
print("Warning: Failed to communicate with BOT035 (Coprocessor) or", e) '''TFT/240*240'''
import st7789_cf
'''TFT/240*240''' onboard_tft = st7789_cf.ST7789(onboard_spi, 240, 240, dc_pin=45, reset=onboard_bot.tft_reset, backlight=onboard_bot.tft_brightness, font_address=0xF00000)
onboard_tft = st7789_cf.ST7789(onboard_spi, 240, 240, dc_pin=45, reset=onboard_bot.tft_reset, backlight=onboard_bot.tft_brightness, font_address=0xF00000)
'''ACC-Sensor'''
'''ACC-Sensor''' try:
try: import sc7a20
import sc7a20 onboard_acc = sc7a20.SC7A20(inboard_i2c)
onboard_acc = sc7a20.SC7A20(inboard_i2c) except Exception as e:
except Exception as e: print("Warning: Failed to communicate with SC7A20H (ACC) or", e)
print("Warning: Failed to communicate with SC7A20H (ACC) or", e)
'''ALS_PS-Sensor *2'''
'''ALS_PS-Sensor *2''' try:
try: import ltr553als
import ltr553als onboard_als_l = ltr553als.LTR_553ALS(onboard_i2c)
onboard_als_l = ltr553als.LTR_553ALS(onboard_i2c) except Exception as e:
except Exception as e: print("Warning: Failed to communicate with TR_553ALS-L (ALS&PS) or", e)
print("Warning: Failed to communicate with TR_553ALS-L (ALS&PS) or", e)
try:
try: # import ltr553als
# import ltr553als onboard_als_r = ltr553als.LTR_553ALS(inboard_i2c)
onboard_als_r = ltr553als.LTR_553ALS(inboard_i2c) except Exception as e:
except Exception as e: print("Warning: Failed to communicate with TR_553ALS-R (ALS&PS) or", e)
print("Warning: Failed to communicate with TR_553ALS-R (ALS&PS) or", e)
'''THS-Sensor'''
'''THS-Sensor''' try:
try: import shtc3
import shtc3 onboard_ths = shtc3.SHTC3(inboard_i2c)
onboard_ths = shtc3.SHTC3(inboard_i2c) except Exception as e:
except Exception as e: print("Warning: Failed to communicate with GXHTC3 (THS) or", e)
print("Warning: Failed to communicate with GXHTC3 (THS) or", e)
'''MGS-Sensor'''
'''MGS-Sensor''' try:
try: import mmc5603
import mmc5603 onboard_mgs = mmc5603.MMC5603(inboard_i2c)
onboard_mgs = mmc5603.MMC5603(inboard_i2c) except Exception as e:
except Exception as e: print("Warning: Failed to communicate with MMC5603 (MGS) or", e)
print("Warning: Failed to communicate with MMC5603 (MGS) or", e)
'''ASR-Sensor'''
'''ASR-Sensor''' try:
try: from ci1302x import CI1302
from ci1302x import CI1302 onboard_asr = CI1302(inboard_i2c, onboard_bot.asr_en)
onboard_asr = CI1302(inboard_i2c, onboard_bot.asr_en) except Exception as e:
except Exception as e: print("Warning: Failed to communicate with CI130X (ASR) or", e)
print("Warning: Failed to communicate with CI130X (ASR) or", e)
'''2RGB_WS2812'''
'''2RGB_WS2812''' onboard_rgb = NeoPixel(onboard_bot.rgb_sync, 4)
onboard_rgb = NeoPixel(onboard_bot.rgb_sync, 4)
'''1Buzzer-Music'''
'''1Buzzer-Music''' onboard_music = MIDI(46, pa_ctrl=onboard_bot.spk_en)
onboard_music = MIDI(46, pa_ctrl=onboard_bot.spk_en)
'''5KEY_Sensor'''
'''5KEY_Sensor''' class KEYSensor:
def __init__(self, pin, range):
self.pin = pin
class KEYSensor: self.adc = ADC(Pin(pin))
def __init__(self, pin, range): self.adc.atten(ADC.ATTN_0DB)
self.pin = pin self.range = range
self.adc = ADC(Pin(pin)) self.flag = True
self.adc.atten(ADC.ATTN_0DB)
self.range = range def _value(self):
self.flag = True values = []
for _ in range(25):
def _value(self): values.append(self.adc.read())
values = [] time.sleep_us(5)
for _ in range(25): return (self.range-200) < min(values) < (self.range+200)
values.append(self.adc.read())
time.sleep_us(5) def get_presses(self, delay=1):
return (self.range-200) < min(values) < (self.range+200) last_time, presses = time.time(), 0
while time.time() < last_time + delay:
def get_presses(self, delay=1): time.sleep_ms(50)
last_time, presses = time.time(), 0 if self.was_pressed():
while time.time() < last_time + delay: presses += 1
time.sleep_ms(50) return presses
if self.was_pressed():
presses += 1 def is_pressed(self):
return presses return self._value()
def is_pressed(self): def was_pressed(self):
return self._value() if (self._value() != self.flag):
self.flag = self._value()
def was_pressed(self): if self.flag:
if (self._value() != self.flag): return True
self.flag = self._value() else:
if self.flag: return False
return True
else: def irq(self, handler, trigger):
return False Pin(self.pin, Pin.IN).irq(handler=handler, trigger=trigger)
def irq(self, handler, trigger): '''1KEY_Button'''
Pin(self.pin, Pin.IN).irq(handler=handler, trigger=trigger) class Button(KEYSensor):
def __init__(self, pin):
self.pin = pin
'''1KEY_Button''' self.key = Pin(pin, Pin.IN)
self.flag = True
class Button(KEYSensor): def _value(self):
def __init__(self, pin): return not self.key.value()
self.pin = pin
self.key = Pin(pin, Pin.IN) B1key = Button(0)
self.flag = True B2key = KEYSensor(17, 0)
A1key = KEYSensor(17, 1600)
def _value(self): A2key = KEYSensor(17, 1100)
return not self.key.value() A3key = KEYSensor(17, 550)
A4key = KEYSensor(17, 2100)
B1key = Button(0) '''2-LED'''
B2key = KEYSensor(17, 0) class LED:
A1key = KEYSensor(17, 1600) def __init__(self, func):
A2key = KEYSensor(17, 1100) self._func = func
A3key = KEYSensor(17, 550)
A4key = KEYSensor(17, 2100) def setbrightness(self, index, val):
self._func(index, val)
'''2-LED'''
def getbrightness(self, index):
return self._func(index)
class LED:
def __init__(self, func): def setonoff(self, index, val):
self._func = func if val == -1:
self.setbrightness(index, 100) if self.getbrightness(
def setbrightness(self, index, val): index) < 50 else self.setbrightness(index, 0)
self._func(index, val) elif val == 1:
self.setbrightness(index, 100)
def getbrightness(self, index): elif val == 0:
return self._func(index) self.setbrightness(index, 0)
def setonoff(self, index, val): def getonoff(self, index):
if val == -1: return True if self.getbrightness(index) > 50 else False
self.setbrightness(index, 100) if self.getbrightness(
index) < 50 else self.setbrightness(index, 0) onboard_led = LED(onboard_bot.led_pwm)
elif val == 1:
self.setbrightness(index, 100) class Voice_Energy:
elif val == 0: def read(self, samples=10):
self.setbrightness(index, 0) values = []
for _ in range(samples):
def getonoff(self, index): values.append(int.from_bytes(onboard_asr._rreg(
return True if self.getbrightness(index) > 50 else False 0x08, 3)[:2], 'little')) # 在语音识别里获取
return sorted(values)[samples // 2]
onboard_led = LED(onboard_bot.led_pwm) onboard_sound = Voice_Energy()
class Clock:
class Voice_Energy: def __init__(self, x, y, radius, color, oled=onboard_tft): # 定义时钟中心点和半径
def read(self, samples=10): self.display = oled
values = [] self.xc = x
for _ in range(samples): self.yc = y
values.append(int.from_bytes(onboard_asr._rreg( self.r = radius
0x08, 3)[:2], 'little')) # 在语音识别里获取 self.color = color
return sorted(values)[samples // 2] self.hour = 0
self.min = 0
self.sec = 0
onboard_sound = Voice_Energy()
def set_time(self, h, m, s): # 设定时间
self.hour = h
class Clock: self.min = m
def __init__(self, x, y, radius, color, oled=onboard_tft): # 定义时钟中心点和半径 self.sec = s
self.display = oled
self.xc = x def set_rtctime(self): # 设定时间
self.yc = y t = rtc_clock.datetime()
self.r = radius self.hour = t[4]
self.color = color self.min = t[5]
self.hour = 0 self.sec = t[6]
self.min = 0
self.sec = 0 def drawDial(self, color): # 画钟表刻度
r_tic1 = self.r - 1
def set_time(self, h, m, s): # 设定时间 r_tic2 = self.r - 2
self.hour = h self.display.ellipse(self.xc, self.yc, self.r, self.r, color)
self.min = m self.display.ellipse(self.xc, self.yc, 2, 2, color, True)
self.sec = s
for h in range(12):
def set_rtctime(self): # 设定时间 at = math.pi * 2.0 * h / 12.0
t = rtc_clock.datetime() x1 = round(self.xc + r_tic1 * math.sin(at))
self.hour = t[4] x2 = round(self.xc + r_tic2 * math.sin(at))
self.min = t[5] y1 = round(self.yc - r_tic1 * math.cos(at))
self.sec = t[6] y2 = round(self.yc - r_tic2 * math.cos(at))
self.display.line(x1, y1, x2, y2, color)
def drawDial(self, color): # 画钟表刻度
r_tic1 = self.r - 1 def drawHour(self, color): # 画时针
r_tic2 = self.r - 2 r_hour = int(self.r / 10.0 * 5)
self.display.ellipse(self.xc, self.yc, self.r, self.r, color) ah = math.pi * 2.0 * ((self.hour % 12) + self.min / 60.0) / 12.0
self.display.ellipse(self.xc, self.yc, 2, 2, color, True) xh = int(self.xc + r_hour * math.sin(ah))
yh = int(self.yc - r_hour * math.cos(ah))
for h in range(12): self.display.line(self.xc, self.yc, xh, yh, color)
at = math.pi * 2.0 * h / 12.0
x1 = round(self.xc + r_tic1 * math.sin(at)) def drawMin(self, color): # 画分针
x2 = round(self.xc + r_tic2 * math.sin(at)) r_min = int(self.r / 10.0 * 7)
y1 = round(self.yc - r_tic1 * math.cos(at)) am = math.pi * 2.0 * self.min / 60.0
y2 = round(self.yc - r_tic2 * math.cos(at)) xm = round(self.xc + r_min * math.sin(am))
self.display.line(x1, y1, x2, y2, color) ym = round(self.yc - r_min * math.cos(am))
self.display.line(self.xc, self.yc, xm, ym, color)
def drawHour(self, color): # 画时针
r_hour = int(self.r / 10.0 * 5) def drawSec(self, color): # 画秒针
ah = math.pi * 2.0 * ((self.hour % 12) + self.min / 60.0) / 12.0 r_sec = int(self.r / 10.0 * 9)
xh = int(self.xc + r_hour * math.sin(ah)) asec = math.pi * 2.0 * self.sec / 60.0
yh = int(self.yc - r_hour * math.cos(ah)) xs = round(self.xc + r_sec * math.sin(asec))
self.display.line(self.xc, self.yc, xh, yh, color) ys = round(self.yc - r_sec * math.cos(asec))
self.display.line(self.xc, self.yc, xs, ys, color)
def drawMin(self, color): # 画分针
r_min = int(self.r / 10.0 * 7) def draw_clock(self, bg_color=0): # 画完整钟表
am = math.pi * 2.0 * self.min / 60.0 self.drawDial(self.color)
xm = round(self.xc + r_min * math.sin(am)) self.drawHour(self.color)
ym = round(self.yc - r_min * math.cos(am)) self.drawMin(self.color)
self.display.line(self.xc, self.yc, xm, ym, color) self.drawSec(self.color)
self.display.show()
def drawSec(self, color): # 画秒针 self.drawHour(bg_color)
r_sec = int(self.r / 10.0 * 9) self.drawMin(bg_color)
asec = math.pi * 2.0 * self.sec / 60.0 self.drawSec(bg_color)
xs = round(self.xc + r_sec * math.sin(asec))
ys = round(self.yc - r_sec * math.cos(asec)) def clear(self, color=0): # 清除
self.display.line(self.xc, self.yc, xs, ys, color) self.display.ellipse(self.xc, self.yc, self.r, self.r, color, True)
def draw_clock(self, bg_color=0): # 画完整钟表 '''Reclaim memory'''
self.drawDial(self.color) gc.collect()
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

@@ -1,113 +1,101 @@
""" """
ST7789/FrameBuffer ST7789/FrameBuffer
MicroPython library for the ST7789(TFT-SPI) MicroPython library for the ST7789(TFT-SPI)
======================================================= =======================================================
@dahanzimin From the Mixly Team @dahanzimin From the Mixly Team
""" """
import time import time
import uframebuf import uframebuf
from machine import Pin from machine import Pin
from jpeg import Decoder from camera import Image, IMG
from micropython import const from micropython import const
_CMD_SWRESET = const(0x01) _CMD_SWRESET = const(0x01)
_CMD_SLPIN = const(0x10) _CMD_SLPOUT = const(0x11)
_CMD_SLPOUT = const(0x11) _CMD_INVON = const(0x21)
_CMD_PTLON = const(0x12) _CMD_DISPON = const(0x29)
_CMD_NORON = const(0x13) _CMD_CASET = const(0x2A)
_CMD_INVOFF = const(0x20) _CMD_RASET = const(0x2B)
_CMD_INVON = const(0x21) _CMD_RAMWR = const(0x2C)
_CMD_DISPOFF = const(0x28) _CMD_COLMOD = const(0x3A)
_CMD_DISPON = const(0x29) _CMD_MADCTL = const(0x36)
_CMD_CASET = const(0x2A)
_CMD_RASET = const(0x2B) class ST7789(uframebuf.FrameBuffer_Uincode):
_CMD_RAMWR = const(0x2C) def __init__(self, spi, width, height, dc_pin=None, backlight=None, reset=None, font_address=0x700000):
_CMD_RAMRD = const(0x2E) self.spi = spi
_CMD_PTLAR = const(0x30) self.dc = Pin(dc_pin, Pin.OUT, value=1)
_CMD_VSCRDEF = const(0x33) self._buffer = bytearray(width * height * 2)
_CMD_COLMOD = const(0x3A) super().__init__(self._buffer, width, height, uframebuf.RGB565)
_CMD_MADCTL = const(0x36) reset(1, 100)
self.font(font_address)
class ST7789(uframebuf.FrameBuffer_Uincode): self._init()
def __init__(self, spi, width, height, dc_pin=None, backlight=None, reset=None, font_address=0x700000): # self.show()
self.spi = spi self._oneclight = True
self.dc = Pin(dc_pin, Pin.OUT, value=1) self._backlight = backlight
self._buffer = bytearray(width * height * 2)
super().__init__(self._buffer, width, height, uframebuf.RGB565) def display(self, data=None, rotation=0, sync=True):
reset(1, 100) if type(data) is str:
self.font(font_address) data = Image.open(data, rotation)
self._init() self._buffer[:] = data.image # 后期做图像尺寸匹配处理
# self.show() if sync: self.show()
self._oneclight = True
self._backlight = backlight def screenshot(self):
return IMG(memoryview(self._buffer), self.width, self.height)
def display(self, data=None, rotation=0, sync=True):
if type(data) is str: def _write(self, cmd, dat=None):
with open(data, "rb") as f: self.dc.off()
_jpeg = f.read() self.spi.write(bytearray([cmd]))
_decoder = Decoder(pixel_format="RGB565_BE", rotation=rotation) if dat is not None:
self._buffer[:] = _decoder.decode(_jpeg) self.dc.on()
del _decoder self.spi.write(dat)
else:
self._buffer[:] = data # 后期做图像大小处理 def _init(self):
if sync: """Display initialization configuration"""
self.show() for cmd, data, delay in [
return self._buffer # (_CMD_SWRESET, None, 20000),
(_CMD_SLPOUT, None, 120000),
def _write(self, cmd, dat=None): (_CMD_MADCTL, b'\x00', 50),
self.dc.off() (_CMD_COLMOD, b'\x05', 50),
self.spi.write(bytearray([cmd])) (0xB2, b'\x0c\x0c\x00\x33\x33', 10),
if dat is not None: (0xB7, b'\x35', 10),
self.dc.on() (0xBB, b'\x19', 10),
self.spi.write(dat) (0xC0, b'\x2C', 10),
(0xC2, b'\x01', 10),
def _init(self): (0xC3, b'\x12', 10),
"""Display initialization configuration""" (0xC4, b'\x20', 10),
for cmd, data, delay in [ (0xC6, b'\x0F', 10),
# (_CMD_SWRESET, None, 20000), (0xD0, b'\xA4\xA1', 10),
(_CMD_SLPOUT, None, 120000), (0xE0, b'\xD0\x04\x0D\x11\x13\x2B\x3F\x54\x4C\x18\x0D\x0B\x1F\x23', 10),
(_CMD_MADCTL, b'\x00', 50), (0xE1, b'\xD0\x04\x0C\x11\x13\x2C\x3F\x44\x51\x2F\x1F\x1F\x20\x23', 10),
(_CMD_COLMOD, b'\x05', 50), (_CMD_INVON, None, 10),
(0xB2, b'\x0c\x0c\x00\x33\x33', 10), (_CMD_DISPON, None, 10),
(0xB7, b'\x35', 10), ]:
(0xBB, b'\x19', 10), self._write(cmd, data)
(0xC0, b'\x2C', 10), if delay:
(0xC2, b'\x01', 10), time.sleep_us(delay)
(0xC3, b'\x12', 10),
(0xC4, b'\x20', 10), def get_brightness(self):
(0xC6, b'\x0F', 10), return self._backlight() / 100
(0xD0, b'\xA4\xA1', 10),
(0xE0, b'\xD0\x04\x0D\x11\x13\x2B\x3F\x54\x4C\x18\x0D\x0B\x1F\x23', 10), def set_brightness(self, brightness):
(0xE1, b'\xD0\x04\x0C\x11\x13\x2C\x3F\x44\x51\x2F\x1F\x1F\x20\x23', 10), if not 0.0 <= brightness <= 1.0:
(_CMD_INVON, None, 10), raise ValueError(
(_CMD_DISPON, None, 10), "Brightness must be a decimal number in the range: 0.0~1.0")
]: self._backlight(int(brightness * 100))
self._write(cmd, data)
if delay: def color(self, red, green=None, blue=None):
time.sleep_us(delay) """ Convert red, green and blue values (0-255) into a 16-bit 565 encoding."""
if green is None or blue is None:
def get_brightness(self): return red
return self._backlight() / 100 else:
return (red & 0xf8) << 8 | (green & 0xfc) << 3 | blue >> 3
def set_brightness(self, brightness):
if not 0.0 <= brightness <= 1.0: def show(self):
raise ValueError( """Refresh the display and show the changes."""
"Brightness must be a decimal number in the range: 0.0~1.0") if self._oneclight:
self._backlight(int(brightness * 100)) self.set_brightness(0.6)
self._oneclight = False
def color(self, red, green=None, blue=None): self._write(_CMD_CASET, b'\x00\x00\x00\xef')
""" Convert red, green and blue values (0-255) into a 16-bit 565 encoding.""" self._write(_CMD_RASET, b'\x00\x00\x00\xef')
if green is None or blue is None: self._write(_CMD_RAMWR, self._buffer)
return red
else:
return (red & 0xf8) << 8 | (green & 0xfc) << 3 | blue >> 3
def show(self):
"""Refresh the display and show the changes."""
if self._oneclight:
self.set_brightness(0.6)
self._oneclight = False
self._write(_CMD_CASET, b'\x00\x00\x00\xef')
self._write(_CMD_RASET, b'\x00\x00\x00\xef')
self._write(_CMD_RAMWR, self._buffer)