初始化提交

This commit is contained in:
王立帮
2024-07-19 10:16:00 +08:00
parent 4c7b571f20
commit 4a2d56dcc4
7084 changed files with 741212 additions and 63 deletions

View File

@@ -0,0 +1,187 @@
# -*- coding: UTF-8 -*-
import time
from micropython import const
_ES_MODULE_ADC = const(0x01)
_ES_MODULE_DAC = const(0x02)
_ES_MODULE_ADC_DAC = const(0x03)
_ES_MODULE_LINE = const(0x04)
_BIT_LENGTH_16BITS = const(0x03)
_FMT_I2S_NORMAL = const(0x00)
_I2S_MODE_SLAVE = const(0x00)
_ADC_INPUT_LINE = const(0x01)
_DAC_OUTPUT_ALL = const(0x02)
_LCLK_DIV = const(256)
_MCLK_DIV = const(0x04)
class ES8374:
def __init__(self, i2c_bus=None, i2c_addr=0x10, gain=5, pga_en=1):
self.i2c_bus = i2c_bus
self.i2c_addr = i2c_addr
self.stop()
self.init_reg(_I2S_MODE_SLAVE, ((_BIT_LENGTH_16BITS << 4) | _FMT_I2S_NORMAL), _DAC_OUTPUT_ALL, _ADC_INPUT_LINE)
self.mic_gain(gain)
self.pga_enable(pga_en)
self.configI2SFormat(_ES_MODULE_ADC_DAC, _FMT_I2S_NORMAL)
def _readReg(self, regAddr):
return self.i2c_bus.readfrom_mem(self.i2c_addr, regAddr, 1)[0]
def _writeReg(self, regAddr, data):
self.i2c_bus.writeto_mem(self.i2c_addr, regAddr, data.to_bytes(1, 'little'))
def init_reg(self, ms_mode, fmt, out_channel, in_channel):
self._writeReg(0x00, 0x3F)# IC Rst start
self._writeReg(0x00, 0x03)# IC Rst stop
self._writeReg(0x01, 0x7F)# IC clk on # M ORG 7F
self._writeReg(0x0f, (self._readReg(0x0F) & 0x7f) | (ms_mode << 7))# CODEC IN I2S SLAVE MODE
self._writeReg(0x6F, 0xA0)# pll set:mode enable
self._writeReg(0x72, 0x41)# pll set:mode set
self._writeReg(0x09, 0x01)# pll set:reset on ,set start
self._writeReg(0x0C, 0x22)# pll set:k
self._writeReg(0x0D, 0x2E)# pll set:k
self._writeReg(0x0E, 0xC6)# pll set:k
self._writeReg(0x0A, 0x3A)# pll set:
self._writeReg(0x0B, 0x07)# pll set:n
self._writeReg(0x09, 0x41)# pll set:reset off ,set stop
self.i2sConfigClock()
self._writeReg(0x24, 0x08)# adc set
self._writeReg(0x36, 0x00)# dac set
self._writeReg(0x12, 0x30)# timming set
self._writeReg(0x13, 0x20)# timming set
self.configI2SFormat(_ES_MODULE_ADC, fmt)
self.configI2SFormat(_ES_MODULE_DAC, fmt)
self._writeReg(0x21, 0x50)# adc set: SEL LIN1 CH+PGAGAIN=0DB
self._writeReg(0x22, 0xFF)# adc set: PGA GAIN=0DB
self._writeReg(0x21, 0x14)# adc set: SEL LIN1 CH+PGAGAIN=18DB
self._writeReg(0x22, 0x55)# pga = +15db
self._writeReg(0x08, 0x21)# set class d divider = 33, to avoid the high frequency tone on laudspeaker
self._writeReg(0x00, 0x80)# IC START
time.sleep(0.05)
self._writeReg(0x25, 0x00)# ADCVOLUME on
self._writeReg(0x38, 0x00)# DACVOLUME on
self._writeReg(0x14, 0x8A)# IC START
self._writeReg(0x15, 0x40)# IC START
self._writeReg(0x1A, 0xA0)# monoout set
self._writeReg(0x1B, 0x19)# monoout set
self._writeReg(0x1C, 0x90)# spk set
self._writeReg(0x1D, 0x01)# spk set
self._writeReg(0x1F, 0x00)# spk set
self._writeReg(0x1E, 0x20)# spk on
self._writeReg(0x28, 0x70)# alc set 0x70
#self._writeReg(0x26, 0x4E)# alc set
#self._writeReg(0x27, 0x10)# alc set
#self._writeReg(0x29, 0x00)# alc set
#self._writeReg(0x2B, 0x00)# alc set
self._writeReg(0x25, 0x00)# ADCVOLUME on
self._writeReg(0x38, 0x00)# DACVOLUME on
self._writeReg(0x37, 0x30)# dac set
self._writeReg(0x6D, 0x60)# SEL:GPIO1=DMIC CLK OUT+SEL:GPIO2=PLL CLK OUT
self._writeReg(0x71, 0x05)# for automute setting
self._writeReg(0x73, 0x70)
self.configDACOutput(out_channel)# 0x3c Enable DAC and Enable Lout/Rout/1/2
self.configADCInput(in_channel)# 0x00 LINSEL & RINSEL, LIN1/RIN1 as ADC Input DSSEL,use one DS Reg11 DSR, LINPUT1-RINPUT1
self.voice_volume(95)
self._writeReg(0x37, 0x00)# dac set
'''
reg = self._readReg(0x1a) # disable lout
reg |= 0x08
self._writeReg(0x1a, reg)
reg &= 0xdf
self._writeReg(0x1a, reg)
self._writeReg(0x1D, 0x12) # mute speaker
self._writeReg(0x1E, 0x20) # disable class d
reg = self._readReg(0x15) # power up dac
reg &= 0xdf
self._writeReg(0x15, reg)
reg = self._readReg(0x1a) # disable lout
reg |= 0x20
self._writeReg(0x1a, reg)
reg &= 0xf7
self._writeReg(0x1a, reg)
self._writeReg(0x1D, 0x02) # mute speaker
self._writeReg(0x1E, 0xa0) # disable class d
self.voice_mute(0)
'''
def stop(self):
self.voice_mute(1)
self._writeReg(0x1a, self._readReg(0x1a)| 0x08)
self._writeReg(0x1a, self._readReg(0x1a)& 0xdf)
self._writeReg(0x1D, 0x12)# mute speaker
self._writeReg(0x1E, 0x20)# disable class d
self._writeReg(0x15, self._readReg(0x15)| 0x20)
self._writeReg(0x10, self._readReg(0x10)| 0xc0)
self._writeReg(0x21, self._readReg(0x21)| 0xc0)
def i2sConfigClock(self):
self._writeReg(0x0f, (self._readReg(0x0F) & 0xe0) | _MCLK_DIV)
self._writeReg(0x06, _LCLK_DIV >> 8)# ADCFsMode,singel SPEED,RATIO=256
self._writeReg(0x07, _LCLK_DIV & 0xFF)# ADCFsMode,singel SPEED,RATIO=256
def configI2SFormat(self, mode, fmt):
fmt_tmp = ((fmt & 0xf0) >> 4)
fmt_i2s = fmt & 0x0f
if (mode == _ES_MODULE_ADC or mode == _ES_MODULE_ADC_DAC):
reg = self._readReg(0x10)
reg &= 0xfc
self._writeReg(0x10, (reg|fmt_i2s))
self.setBitsPerSample(mode, 3)
if (mode == _ES_MODULE_DAC or mode == _ES_MODULE_ADC_DAC):
reg = self._readReg(0x11)
reg &= 0xfc
self._writeReg(0x11, (reg|fmt_i2s))
self.setBitsPerSample(mode, 3)
# set Bits Per Sample
def setBitsPerSample(self, mode, bit_per_smaple):
bits = bit_per_smaple & 0x0f
if (mode == _ES_MODULE_ADC or mode == _ES_MODULE_ADC_DAC):
reg = self._readReg(0x10)
reg &= 0xe3
self._writeReg(0x10, (reg| (bits << 2)))
if (mode == _ES_MODULE_DAC or mode == _ES_MODULE_ADC_DAC):
reg = self._readReg(0x11)
reg &= 0xe3
self._writeReg(0x11, (reg| (bits << 2)))
def configDACOutput(self, output):
self._writeReg(0x1d, 0x02)
reg = self._readReg(0x1c) # set spk mixer
reg |= 0x80
self._writeReg(0x1c, reg)
self._writeReg(0x1D, 0x02) # spk set
self._writeReg(0x1F, 0x00) # spk set
self._writeReg(0x1E, 0xA0) # spk on
def configADCInput(self, input):
reg = self._readReg(0x21)
reg = (reg & 0xcf) | 0x24
self._writeReg( 0x21, reg)
def mic_volume(self, volume=None):
if volume is None:
return round(100 - self._readReg(0x25) * 100 / 192)
else:
self._writeReg(0x25, (100 - volume) * 192 // 100)
def voice_volume(self, volume=None):
if volume is None:
return round(100 - self._readReg(0x38) * 100 / 192)
else:
self._writeReg(0x38, (100 - volume) * 192 // 100)
def voice_mute(self, enable=None):
if enable is None:
return True if self._readReg(0x36) & 0x40 else False
else:
self._writeReg(0x36, (self._readReg(0x36)& 0xdf) | (enable << 5))
def mic_gain(self, gain):
gain_n = max(min(gain, 15), 0)
self._writeReg(0x22, (gain_n | (gain_n<<4))) # MIC PGA -3.5db ~ 24db
def pga_enable(self, enable):
self._writeReg(0x21, (self._readReg(0x21) & 0xfb) | (enable << 2)) # MIC PGA 0db or 15db

View File

@@ -0,0 +1,329 @@
"""
mixgo_zero Zi Onboard resources
Micropython library for the mixgo_zero Zi Onboard resources
=======================================================
#Preliminary composition 20231020
#S3定时器ID(-1,0,1,2,3(led))
dahanzimin From the Mixly Team
"""
from machine import *
import time, gc, st7735, math
'''RTC'''
rtc_clock = RTC()
'''I2C-onboard'''
version = not Pin(13, Pin.IN, Pin.PULL_DOWN).value()
onboard_i2c = SoftI2C(scl=Pin(36), sda=Pin(37), freq=400000)
onboard_i2c_soft = SoftI2C(scl=Pin(36) if version else Pin(13), sda=Pin(15), freq=400000)
onboard_i2c_scan = onboard_i2c.scan()
'''SPI-onboard'''
try:
import _boot
onboard_spi = _boot.onboard_spi
onboard_spi.init(baudrate=50000000)
except:
onboard_spi = SPI(1, baudrate=50000000, polarity=0, phase=0)
'''TFT/128*160'''
onboard_tft = st7735.ST7735(onboard_spi, 160, 128, dc_pin=18, cs_pin=45, bl_pin=14, font_address=0x700000)
'''ACC-Sensor'''
try :
import mxc6655xa
onboard_acc = mxc6655xa.MXC6655XA(onboard_i2c, front=True)
except Exception as e:
print("Warning: Failed to communicate with MXC6655XA (ACC) or",e)
'''ALS_PS-Sensor *2'''
try :
import ltr553als
onboard_als_l = ltr553als.LTR_553ALS(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with TR_553ALS (ALS&PS) or",e)
try :
import ltr553als
onboard_als_r = ltr553als.LTR_553ALS(onboard_i2c_soft)
except Exception as e:
print("Warning: Failed to communicate with TR_553ALS (ALS&PS) or",e)
'''BPS-Sensor'''
if 0x76 in onboard_i2c_scan:
try :
import hp203x
onboard_bps = hp203x.HP203X(onboard_i2c_soft)
except Exception as e:
print("Warning: Failed to communicate with HP203X (BPS) or",e)
'''THS-Sensor'''
if 0x38 in onboard_i2c_scan:
try :
import ahtx0
onboard_ths = ahtx0.AHTx0(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with AHTx0 (THS) or",e)
if 0x70 in onboard_i2c_scan:
try :
import shtc3
onboard_ths = shtc3.SHTC3(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with GXHTC3 (THS) or",e)
'''RFID-Sensor'''
try :
import rc522
onboard_rfid = rc522.RC522(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with RC522 (RFID) 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)
'''2RGB_WS2812'''
from ws2812 import NeoPixel
onboard_rgb = NeoPixel(Pin(38), 4)
'''5KEY_Sensor'''
class KEYSensor:
def __init__(self, pin, range):
self.pin = pin
self.adc = ADC(Pin(pin), atten=ADC.ATTN_0DB)
self.range = range
self.flag = True
def _value(self):
values = []
for _ in range(50):
values.append(self.adc.read())
time.sleep_us(2)
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(0)
B2key = KEYSensor(17,0)
A1key = KEYSensor(17,2900)
A2key = KEYSensor(17,2300)
A3key = KEYSensor(17,1650)
A4key = KEYSensor(17,850)
'''2-TouchPad'''
class Touch_Pad:
__species = {}
__first_init = True
def __new__(cls, pin, *args, **kwargs):
if pin not in cls.__species.keys():
cls.__first_init = True
cls.__species[pin]=object.__new__(cls)
return cls.__species[pin]
def __init__(self, pin, default=30000):
if self.__first_init:
self.__first_init = False
from machine import TouchPad
self._pin = TouchPad(Pin(pin))
self.raw = self._pin.read()
if self.raw >= default * 1.5:
self.raw = default
def touch(self,value=None ):
return self._pin.read() > value if value else self._pin.read()
#Touch with function call
def touched(pin,value=60000):
return Touch_Pad(pin).touch(value)
def touch_slide(pina, pinb):
return ((Touch_Pad(pina).touch() - Touch_Pad(pina).raw) - (Touch_Pad(pinb).touch() - Touch_Pad(pinb).raw)) // 10
'''2LED-Tristate'''
class LED_T:
def __init__(self, pin, timer_id=3):
self._pin = pin
self._pwm = 0
self._index_pwm = [0,0]
Timer(timer_id, freq=2500, mode=Timer.PERIODIC, callback=self.tim_callback)
def _cutonoff(self,val):
if val == 0:
Pin(self._pin, Pin.IN)
elif val == 1:
Pin(self._pin, Pin.OUT).value(1)
elif val == -1:
Pin(self._pin, Pin.OUT).value(0)
def tim_callback(self,tim):
if self._pwm <= 25:
if self._pwm * 4 < self._index_pwm[0]:
self._cutonoff(1)
else:
self._cutonoff(0)
else:
if (self._pwm - 26) * 4 < self._index_pwm[1]:
self._cutonoff(-1)
else:
self._cutonoff(0)
self._pwm = self._pwm + 1 if self._pwm <= 51 else 0
def setbrightness(self,index,val):
if not 0 <= val <= 100:
raise ValueError("Brightness must be in the range: 0~100%")
self._index_pwm[index-1] = val
def getbrightness(self,index):
return self._index_pwm[index-1]
def setonoff(self,index,val):
if(val == -1):
if self._index_pwm[index-1] < 50:
self._index_pwm[index-1] = 100
else:
self._index_pwm[index-1] = 0
elif(val == 1):
self._index_pwm[index-1] = 100
elif(val == 0):
self._index_pwm[index-1] = 0
def getonoff(self,index):
return True if self._index_pwm[index-1] > 0 else False
'''2LED-Independent'''
class LED_I:
def __init__(self, pins=[]):
self._pins = [PWM(Pin(pin), duty_u16=0) for pin in pins]
self._brightness = [0 for _ in range(len(self._pins))]
def setbrightness(self, index, val):
if not 0 <= val <= 100:
raise ValueError("Brightness must be in the range: 0-100%")
self._brightness[index - 1] = val
self._pins[index - 1].duty_u16(val * 65535 // 100)
def getbrightness(self, index):
return self._brightness[index - 1]
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_I(pins=[42, 13]) if version else LED_T(42, timer_id=3)
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, self.color)
self.display.ellipse(self.xc, self.yc, 2, 2, self.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): #画完整钟表
self.drawDial(self.color)
self.drawHour(self.color)
self.drawMin(self.color)
self.drawSec(self.color)
self.display.show()
self.clear(0)
def clear(self,color=0): #清除
self.drawHour(color)
self.drawMin(color)
self.drawSec(color)
'''Reclaim memory'''
gc.collect()

View File

@@ -0,0 +1,89 @@
"""
mixgo_zero Zi Voice Onboard resources
Micropython library for the mixgo_zero Zi Onboard resources
=======================================================
#Preliminary composition 20230818
dahanzimin From the Mixly Team
"""
import ustruct
import time
import music_spk
import es8374
from machine import Pin, I2S
from mixgo_nova import onboard_i2c
sample_rate = 22050
ob_code = es8374.ES8374(onboard_i2c)
time.sleep(0.2)
#ps 特殊改双全工i2s支持
ob_audio = I2S(0, sck=Pin(34), ws=Pin(47), dout=Pin(48), din=Pin(33), mck=Pin(35), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=sample_rate, ibuf=20000)
spk_midi = music_spk.MIDI(ob_audio, sample_rate)
def u2s(n):
return n if n < (1 << 15) else n - (1 << 16)
def sound_level():
buf = bytearray(100)
values = []
ob_audio.readinto(buf)
for i in range(len(buf)//2):
values.append(u2s(buf[i * 2] | buf[i * 2 + 1]<<8))
return max(values) - min(values)
def play_audio(path):
file = open(path, 'rb')
header = file.read(44)
if header[8:12] != b'WAVE':
raise Error('not a WAVE file')
_rate = ustruct.unpack('<I', header[24:28])[0]
print("sample_rate", _rate)
file.seek(44)
ob_audio = I2S(0, sck=Pin(34), ws=Pin(47), dout=Pin(48), din=Pin(33), mck=Pin(35), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=_rate, ibuf=20000)
while True:
block = file.read(1024)
if not block:
break
ob_audio.write(block)
ob_audio = I2S(0, sck=Pin(34), ws=Pin(47), dout=Pin(48), din=Pin(33), mck=Pin(35), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=sample_rate, ibuf=20000)
file.close()
def record_audio(path, seconds=5):
ob_audio = I2S(0, sck=Pin(34), ws=Pin(47), dout=Pin(48), din=Pin(33), mck=Pin(35), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=sample_rate*4, ibuf=20000)
file_size = sample_rate * 16 * 1 * seconds // 8
wav_header = bytearray(44)
wav_header[0:4] = b'RIFF'
ustruct.pack_into('<I', wav_header, 4, file_size + 36)
wav_header[8:40] = b'WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00"V\x00\x00D\xac\x00\x00\x02\x00\x10\x00data'
ustruct.pack_into('<I', wav_header, 40, file_size)
buf = bytearray(512)
file = open(path, 'wb')
file.write(wav_header)
for _ in range(file_size // 512):
ob_audio.readinto(buf)
file.write(buf)
ob_audio = I2S(0, sck=Pin(34), ws=Pin(47), dout=Pin(48), din=Pin(33), mck=Pin(35), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=sample_rate, ibuf=20000)
file.close()
def play_audio_url(url):
import urequests
response = urequests.get(url, stream=True)
header = response.raw.read(44)
if header[8:12] != b'WAVE':
raise Error('not a WAVE file')
_rate = ustruct.unpack('<I', header[24:28])[0]
#print("sample_rate", _rate)
ob_audio = I2S(0, sck=Pin(34), ws=Pin(47), dout=Pin(48), din=Pin(33), mck=Pin(35), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=_rate, ibuf=20000)
while True:
block = response.raw.read(1024)
if not block:
break
ob_audio.write(block)
ob_audio = I2S(0, sck=Pin(34), ws=Pin(47), dout=Pin(48), din=Pin(33), mck=Pin(35), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=sample_rate, ibuf=20000)
response.close()

View File

@@ -0,0 +1,283 @@
"""
mixgo_zero Onboard resources
Micropython library for the mixgo_zero Onboard resources
=======================================================
#Preliminary composition 20240110
#S3定时器ID(-1,0,1,2,3)
@dahanzimin From the Mixly Team
"""
from machine import *
import time, gc, st7789_bf, math
'''RTC'''
rtc_clock = RTC()
'''I2C-onboard'''
#onboard_i2c = I2C(0)
onboard_i2c = SoftI2C(scl=Pin(47), sda=Pin(48), freq=400000)
onboard_i2c_1 = SoftI2C(scl=Pin(47), sda=Pin(21), freq=400000)
'''SPI-onboard'''
try:
import _boot
onboard_spi = _boot.onboard_spi
onboard_spi.init(baudrate=50000000)
except:
onboard_spi = SPI(1, baudrate=50000000, polarity=0, phase=0)
'''TFT/320*240'''
onboard_tft = st7789_bf.ST7789(onboard_spi, 320, 240, dc_pin=18, cs_pin=45, bl_pin=46, font_address=0xE00000)
'''ACC-Sensor'''
try :
import mxc6655xa
onboard_acc = mxc6655xa.MXC6655XA(onboard_i2c, front=True)
except Exception as e:
print("Warning: Failed to communicate with MXC6655XA (ACC) or",e)
'''ALS_PS-Sensor *2'''
try :
import ltr553als
onboard_als_l = ltr553als.LTR_553ALS(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with TR_553ALS (ALS&PS) or",e)
try :
import ltr553als
onboard_als_r = ltr553als.LTR_553ALS(onboard_i2c_1)
except Exception as e:
print("Warning: Failed to communicate with TR_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)
'''RFID-Sensor'''
try :
import rc522
onboard_rfid = rc522.RC522(onboard_i2c)
except Exception as e:
print("Warning: Failed to communicate with RC522 (RFID) 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)
'''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)
'''2RGB_WS2812'''
from ws2812 import NeoPixel
onboard_rgb = NeoPixel(Pin(0), 6, multiplex=True, leds=2)
'''5KEY_Sensor'''
class KEYSensor:
def __init__(self, pin, range):
self.pin = pin
self.adc = ADC(Pin(pin), atten=ADC.ATTN_0DB)
self.range = range
self.flag = True
def _value(self):
values = []
for _ in range(50):
values.append(self.adc.read())
time.sleep_us(2)
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(0)
B2key = KEYSensor(13,0)
A1key = KEYSensor(13,2900)
A2key = KEYSensor(13,2300)
A3key = KEYSensor(13,1650)
A4key = KEYSensor(13,850)
'''2-TouchPad'''
class Touch_Pad:
__species = {}
__first_init = True
def __new__(cls, pin, *args, **kwargs):
if pin not in cls.__species.keys():
cls.__first_init = True
cls.__species[pin]=object.__new__(cls)
return cls.__species[pin]
def __init__(self, pin, default=30000):
if self.__first_init:
self.__first_init = False
from machine import TouchPad
self._pin = TouchPad(Pin(pin))
self.raw = self._pin.read()
if self.raw >= default * 1.5:
self.raw = default
def touch(self,value=None ):
return self._pin.read() > value if value else self._pin.read()
#Touch with function call
def touched(pin,value=60000):
return Touch_Pad(pin).touch(value)
def touch_slide(pina, pinb):
return ((Touch_Pad(pina).touch() - Touch_Pad(pina).raw) - (Touch_Pad(pinb).touch() - Touch_Pad(pinb).raw)) // 10
'''2LED-WS2812'''
class LED:
def __init__(self, rgb, num=2, color=3):
self._rgb = rgb
self._col = [color] * num
self._color = ((0, 0, 0), (1, 0, 0), (0, 1, 0), (0, 0, 1), (1, 1, 0), (0, 1, 1), (1, 0, 1), (1, 1, 1))
def setbrightness(self, index, value):
self._rgb.led_set(index - 1, (value if self._color[self._col[index-1]][0] else 0,
value if self._color[self._col[index-1]][1] else 0,
value if self._color[self._col[index-1]][2] else 0))
self._rgb.write()
def getbrightness(self, index):
color = self._rgb.led_get(index - 1)
return color[0] | color[1] | color[2]
def setonoff(self, index, value):
if value == -1:
if self.getbrightness(index) < 50:
self.setbrightness(index, 100)
else:
self.setbrightness(index, 0)
elif value == 1:
self.setbrightness(index, 100)
elif value == 0:
self.setbrightness(index, 0)
def getonoff(self, index):
return True if self.getbrightness(index) > 50 else False
def setcolor(self, index, color):
self._col[index-1] = color
def getcolor(self, index):
return self._col[index-1]
onboard_led = LED(onboard_rgb)
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, self.color)
self.display.ellipse(self.xc, self.yc, 2, 2, self.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): #画完整钟表
self.drawDial(self.color)
self.drawHour(self.color)
self.drawMin(self.color)
self.drawSec(self.color)
self.display.show()
def clear(self,color=0): #清除
self.drawHour(color)
self.drawMin(color)
self.drawSec(color)
'''Reclaim memory'''
gc.collect()

View File

@@ -0,0 +1,88 @@
"""
mixgo_zero Zi Voice Onboard resources
Micropython library for the mixgo_zero Zi Onboard resources
=======================================================
#Preliminary composition 20230818
dahanzimin From the Mixly Team
"""
import ustruct
import time
import music_spk
import es8374
from machine import Pin, I2S
from mixgo_zero import onboard_i2c
sample_rate = 22050
ob_code = es8374.ES8374(onboard_i2c)
time.sleep(0.2)
#ps 特殊改双全工i2s支持
ob_audio = I2S(0, sck=Pin(39), ws=Pin(41), dout=Pin(42), din=Pin(40), mck=Pin(38), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=sample_rate, ibuf=20000)
spk_midi = music_spk.MIDI(ob_audio, sample_rate)
def u2s(n):
return n if n < (1 << 15) else n - (1 << 16)
def sound_level():
buf = bytearray(100)
values = []
ob_audio.readinto(buf)
for i in range(len(buf)//2):
values.append(u2s(buf[i * 2] | buf[i * 2 + 1]<<8))
return max(values) - min(values)
def play_audio(path):
file = open(path, 'rb')
header = file.read(44)
if header[8:12] != b'WAVE':
raise Error('not a WAVE file')
_rate = ustruct.unpack('<I', header[24:28])[0]
print("sample_rate", _rate)
file.seek(44)
ob_audio = I2S(0, sck=Pin(39), ws=Pin(41), dout=Pin(42), din=Pin(40), mck=Pin(38), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=_rate, ibuf=20000)
while True:
block = file.read(1024)
if not block:
break
ob_audio.write(block)
ob_audio = I2S(0, sck=Pin(39), ws=Pin(41), dout=Pin(42), din=Pin(40), mck=Pin(38), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=sample_rate, ibuf=20000)
file.close()
def record_audio(path, seconds=5):
ob_audio = I2S(0, sck=Pin(39), ws=Pin(41), dout=Pin(42), din=Pin(40), mck=Pin(38), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=sample_rate*4, ibuf=20000)
file_size = sample_rate * 16 * 1 * seconds // 8
wav_header = bytearray(44)
wav_header[0:4] = b'RIFF'
ustruct.pack_into('<I', wav_header, 4, file_size + 36)
wav_header[8:40] = b'WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00"V\x00\x00D\xac\x00\x00\x02\x00\x10\x00data'
ustruct.pack_into('<I', wav_header, 40, file_size)
buf = bytearray(512)
file = open(path, 'wb')
file.write(wav_header)
for _ in range(file_size // 512):
ob_audio.readinto(buf)
file.write(buf)
ob_audio = I2S(0, sck=Pin(39), ws=Pin(41), dout=Pin(42), din=Pin(40), mck=Pin(38), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=sample_rate, ibuf=20000)
file.close()
def play_audio_url(url):
import urequests
response = urequests.get(url, stream=True)
header = response.raw.read(44)
if header[8:12] != b'WAVE':
raise Error('not a WAVE file')
_rate = ustruct.unpack('<I', header[24:28])[0]
#print("sample_rate", _rate)
ob_audio = I2S(0, sck=Pin(39), ws=Pin(41), dout=Pin(42), din=Pin(40), mck=Pin(38), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=_rate, ibuf=20000)
while True:
block = response.raw.read(1024)
if not block:
break
ob_audio.write(block)
ob_audio = I2S(0, sck=Pin(39), ws=Pin(41), dout=Pin(42), din=Pin(40), mck=Pin(38), mode=I2S.RTX, bits=16, format=I2S.MONO, rate=sample_rate, ibuf=20000)
response.close()

View File

@@ -0,0 +1,151 @@
"""
Music buzzer
Micropython library for the Music buzzer
=======================================================
#Based on Author: qiren123(MIDI Music) 20220618
#Make changes to instantiation 20220622
#Increase level reversal selection 20220716
dahanzimin From the Mixly Team
"""
import time
import math
import array,struct
normal_tone = {
'A1': 55, 'B1': 62, 'C1': 33, 'D1': 37, 'E1': 41, 'F1': 44, 'G1': 49,
'A2': 110, 'B2': 123, 'C2': 65, 'D2': 73, 'E2': 82, 'F2': 87, 'G2': 98,
'A3': 220, 'B3': 247, 'C3': 131, 'D3': 147, 'E3': 165, 'F3': 175, 'G3': 196,
'A4': 440, 'B4': 494, 'C4': 262, 'D4': 294, 'E4': 330, 'F4': 349, 'G4': 392,
'A5': 880, 'B5': 988, 'C5': 523, 'D5': 587, 'E5': 659, 'F5': 698, 'G5': 784,
'A6': 1760, 'B6': 1976, 'C6': 1047, 'D6': 1175, 'E6': 1319, 'F6': 1397, 'G6': 1568,
'A7': 3520, 'B7': 3951, 'C7': 2093, 'D7': 2349, 'E7': 2637, 'F7': 2794, 'G7': 3135,
'A8': 7040, 'B8': 7902, 'C8': 4186, 'D8': 4699, 'E8': 5274, 'F8': 5588, 'G8': 6271,
'A9': 14080, 'B9': 15804 }
Letter = 'ABCDEFG#R'
class MIDI():
def __init__(self, i2s_bus, rate=22050):
self.reset()
self._rate = rate
self.i2s_bus = i2s_bus
def _tone(self, frequency, run_ms=1000):
# create a buffer containing the pure tone samples
samples_per_cycle = self._rate // frequency
sample_size_in_bytes = 16 // 8
samples = bytearray(samples_per_cycle * sample_size_in_bytes)
_range = 32768
for i in range(samples_per_cycle):
sample = _range + int((_range - 1) * math.sin(2 * math.pi * i / samples_per_cycle))
struct.pack_into("<h", samples, i * sample_size_in_bytes, sample)
star = time.ticks_ms()
while time.ticks_diff(time.ticks_ms(), star) <= run_ms:
self.i2s_bus.write(samples)
def set_tempo(self, ticks=4, bpm=120):
self.ticks = ticks
self.bpm = bpm
self.beat = 60000 / self.bpm / self.ticks
def set_octave(self, octave=4):
self.octave = octave
def set_duration(self, duration=4):
self.duration = duration
def get_tempo(self):
return (self.ticks, self.bpm)
def get_octave(self):
return self.octave
def get_duration(self):
return self.duration
def reset(self):
self.set_duration()
self.set_octave()
self.set_tempo()
def parse(self, tone, dict):
time = self.beat * self.duration
pos = tone.find(':')
if pos != -1:
time = self.beat * int(tone[(pos + 1):])
tone = tone[:pos]
freq, tone_size = 1, len(tone)
if 'R' in tone:
freq = 20000
elif tone_size == 1:
freq = dict[tone[0] + str(self.octave)]
elif tone_size == 2:
freq = dict[tone]
self.set_octave(tone[1:])
return int(freq), int(time)
def midi(self, tone):
pos = tone.find('#')
if pos != -1:
return self.parse(tone.replace('#', ''), normal_tone)
pos = tone.find('B')
if pos != -1 and pos != 0:
return self.parse(tone.replace('B', ''), normal_tone)
return self.parse(tone, normal_tone)
def set_default(self, tone):
pos = tone.find(':')
if pos != -1:
self.set_duration(int(tone[(pos + 1):]))
tone = tone[:pos]
def play(self, tune, duration=None):
if duration is None:
self.set_default(tune[0])
else:
self.set_duration(duration)
for tone in tune:
tone = tone.upper()
if tone[0] not in Letter:
continue
midi = self.midi(tone)
self._tone(midi[0], midi[1])
self._tone(20000, 1)
time.sleep_ms(10)
def pitch(self, freq):
pass
def pitch_time(self, freq, delay):
self._tone(freq, delay)
time.sleep_ms(10)
def stop(self):
pass
DADADADUM=['r4:2','g','g','g','eb:8','r:2','f','f','f','d:8']
ENTERTAINER=['d4:1','d#','e','c5:2','e4:1','c5:2','e4:1','c5:3','c:1','d','d#','e','c','d','e:2','b4:1','d5:2','c:4']
PRELUDE=['c4:1','e','g','c5','e','g4','c5','e','c4','e','g','c5','e','g4','c5','e','c4','d','g','d5','f','g4','d5','f','c4','d','g','d5','f','g4','d5','f','b3','d4','g','d5','f','g4','d5','f','b3','d4','g','d5','f','g4','d5','f','c4','e','g','c5','e','g4','c5','e','c4','e','g','c5','e','g4','c5','e']
ODE=['e4','e','f','g','g','f','e','d','c','c','d','e','e:6','d:2','d:8','e:4','e','f','g','g','f','e','d','c','c','d','e','d:6','c:2','c:8']
NYAN=['f#5:1','g#','c#:1','d#:2','b4:1','d5:1','c#','b4:2','b','c#5','d','d:1','c#','b4:1','c#5:1','d#','f#','g#','d#','f#','c#','d','b4','c#5','b4','d#5:2','f#','g#:1','d#','f#','c#','d#','b4','d5','d#','d','c#','b4','c#5','d:2','b4:1','c#5','d#','f#','c#','d','c#','b4','c#5:2','b4','c#5','b4','f#:1','g#','b:2','f#:1','g#','b','c#5','d#','b4','e5','d#','e','f#','b4:2','b','f#:1','g#','b','f#','e5','d#','c#','b4','f#','d#','e','f#','b:2','f#:1','g#','b:2','f#:1','g#','b','b','c#5','d#','b4','f#','g#','f#','b:2','b:1','a#','b','f#','g#','b','e5','d#','e','f#','b4:2','c#5']
RINGTONE=['c4:1','d','e:2','g','d:1','e','f:2','a','e:1','f','g:2','b','c5:4']
FUNK=['c2:2','c','d#','c:1','f:2','c:1','f:2','f#','g','c','c','g','c:1','f#:2','c:1','f#:2','f','d#']
BLUES=['c2:2','e','g','a','a#','a','g','e','c2:2','e','g','a','a#','a','g','e','f','a','c3','d','d#','d','c','a2','c2:2','e','g','a','a#','a','g','e','g','b','d3','f','f2','a','c3','d#','c2:2','e','g','e','g','f','e','d']
BIRTHDAY=['c4:4','c:1','d:4','c:4','f','e:8','c:3','c:1','d:4','c:4','g','f:8','c:3','c:1','c5:4','a4','f','e','d','a#:3','a#:1','a:4','f','g','f:8']
WEDDING=['c4:4','f:3','f:1','f:8','c:4','g:3','e:1','f:8','c:4','f:3','a:1','c5:4','a4:3','f:1','f:4','e:3','f:1','g:8']
FUNERAL=['c3:4','c:3','c:1','c:4','d#:3','d:1','d:3','c:1','c:3','b2:1','c3:4']
PUNCHLINE=['c4:3','g3:1','f#','g','g#:3','g','r','b','c4']
PYTHON=['d5:1','b4','r','b','b','a#','b','g5','r','d','d','r','b4','c5','r','c','c','r','d','e:5','c:1','a4','r','a','a','g#','a','f#5','r','e','e','r','c','b4','r','b','b','r','c5','d:5','d:1','b4','r','b','b','a#','b','b5','r','g','g','r','d','c#','r','a','a','r','a','a:5','g:1','f#:2','a:1','a','g#','a','e:2','a:1','a','g#','a','d','r','c#','d','r','c#','d:2','r:3']
BADDY=['c3:3','r','d:2','d#','r','c','r','f#:8']
CHASE=['a4:1','b','c5','b4','a:2','r','a:1','b','c5','b4','a:2','r','a:2','e5','d#','e','f','e','d#','e','b4:1','c5','d','c','b4:2','r','b:1','c5','d','c','b4:2','r','b:2','e5','d#','e','f','e','d#','e']
BA_DING=['b5:1','e6:3']
WAWAWAWAA=['e3:3','r:1','d#:3','r:1','d:4','r:1','c#:8']
JUMP_UP=['c5:1','d','e','f','g']
JUMP_DOWN=['g5:1','f','e','d','c']
POWER_UP=['g4:1','c5','e4','g5:2','e5:1','g5:3']
POWER_DOWN=['g5:1','d#','c','g4:2','b:1','c5:3']

View File

@@ -0,0 +1,111 @@
"""
NOVA_G1
Micropython library for the NOVA_G1(PWM*6, IO*2, ADC*1)
=======================================================
#Preliminary composition 20240222
@dahanzimin From the Mixly Team
"""
from micropython import const
from mixgo_nova import onboard_i2c
_NOVA_G1_ADDRESS = const(0x25)
_NOVA_G1_ID = const(0x00)
_NOVA_G1_ADC = const(0x01)
_NOVA_G1_IO = const(0x03)
_NOVA_G1_PWM = const(0x04)
class NOVA_G1:
def __init__(self, i2c_bus, addr=_NOVA_G1_ADDRESS):
self._i2c=i2c_bus
self._addr = addr
if self._rreg(_NOVA_G1_ID)!= 0x25:
raise AttributeError("Cannot find a NOVA_G1")
self.reset()
def _wreg(self, reg, val):
'''Write memory address'''
try:
self._i2c.writeto_mem(self._addr, reg, val.to_bytes(1, 'little'))
except:
return 0
def _rreg(self, reg, nbytes=1):
'''Read memory address'''
try:
self._i2c.writeto(self._addr, reg.to_bytes(1, 'little'))
return self._i2c.readfrom(self._addr, nbytes)[0] if nbytes<=1 else self._i2c.readfrom(self._addr, nbytes)[0:nbytes]
except:
return 0
def reset(self):
"""Reset all registers to default state"""
for reg in range(_NOVA_G1_PWM,_NOVA_G1_PWM + 6):
self._wreg(reg,0x00)
def varistor(self, ratio=100/1023):
'''Read battery power'''
_adc= self._rreg(_NOVA_G1_ADC) << 2 | self._rreg(_NOVA_G1_ADC+1) >> 6
return round(_adc * ratio)
def pwm(self, index, duty=None):
"""Motor*2*2 & USB*2 PWM duty cycle data register"""
if duty is None:
return self._rreg(_NOVA_G1_PWM + index)
else:
duty = min(255, max(0, duty))
self._wreg(_NOVA_G1_PWM + index, duty)
def motor(self, index, action, speed=0):
if not 0 <= index <= 1:
raise ValueError("Motor port must be a number in the range: 0~1")
speed = min(100, max(speed, -100))
if action=="N":
self.pwm(index * 2, 0)
self.pwm(index * 2 + 1, 0)
elif action=="P":
self.pwm(index * 2, 255)
self.pwm(index * 2 + 1, 255)
elif action=="CW":
if speed >= 0:
self.pwm(index * 2, 0)
self.pwm(index * 2 + 1, speed * 255 // 100)
else:
self.pwm(index * 2, 0)
self.pwm(index * 2 + 1, - speed * 255 // 100)
elif action=="CCW":
if speed >= 0:
self.pwm(index * 2, speed * 255 // 100)
self.pwm(index * 2 + 1, 0)
else:
self.pwm(index * 2, - speed * 255 // 100)
self.pwm(index * 2 + 1, 0)
elif action=="NC":
return round(self.pwm(index * 2) * 100 / 255), round(self.pwm(index * 2 + 1) * 100 / 255)
else:
raise ValueError('Invalid input, valid are "N","P","CW","CCW"')
def usb_pwm(self, index, duty=None):
if not 0 <= index <= 1:
raise ValueError("USB-2.0 port must be a number in the range: 0~1")
if duty is None:
return round((self.pwm(index + 4) * 100 / 255))
else:
self.pwm(index + 4, duty * 255 // 100)
def spk_en(self, onoff=True):
if onoff:
self._wreg(_NOVA_G1_IO, (self._rreg(_NOVA_G1_IO)) | 0x02)
else:
self._wreg(_NOVA_G1_IO, (self._rreg(_NOVA_G1_IO)) & 0xFD)
def ldo_en(self, onoff=True):
if onoff:
self._wreg(_NOVA_G1_IO, (self._rreg(_NOVA_G1_IO)) | 0x01)
else:
self._wreg(_NOVA_G1_IO, (self._rreg(_NOVA_G1_IO)) & 0xFE)
#Constructor
ext_g1 = NOVA_G1(onboard_i2c)

View File

@@ -0,0 +1,231 @@
"""
MicroPython driver for SD cards using SPI bus.
"""
import time
from machine import Pin
from micropython import const
_CMD_TIMEOUT = const(100)
_R1_IDLE_STATE = const(1 << 0)
_R1_ILLEGAL_COMMAND = const(1 << 2)
_TOKEN_CMD25 = const(0xFC)
_TOKEN_STOP_TRAN = const(0xFD)
_TOKEN_DATA = const(0xFE)
class SDCard:
def __init__(self, spi, cs_pin, baudrate=50000000):
self.spi = spi
self.cs = Pin(cs_pin, Pin.OUT, value=1)
self.cmdbuf = bytearray(6)
self.dummybuf = bytearray(512)
self.tokenbuf = bytearray(1)
for i in range(512):
self.dummybuf[i] = 0xFF
self.dummybuf_memoryview = memoryview(self.dummybuf)
# initialise the card
self.init_card(baudrate)
def init_spi(self, baudrate):
self.spi.init(baudrate=baudrate, phase=0, polarity=0)
def init_card(self, baudrate):
# init SPI bus; use low data rate for initialisation
self.init_spi(100000)
# clock card at least 100 cycles with cs high
for i in range(16):
self.spi.write(b"\xff")
# CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
for _ in range(5):
if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
break
else:
raise OSError("no SD card")
# CMD8: determine card version
r = self.cmd(8, 0x01AA, 0x87, 4)
if r == _R1_IDLE_STATE:
self.init_card_v2()
elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
self.init_card_v1()
else:
raise OSError("couldn't determine SD card version")
# CMD9: response R2 (R1 byte + 16-byte block read)
if self.cmd(9, 0, 0, 0, False) != 0:
raise OSError("no response from SD card")
csd = bytearray(16)
self.readinto(csd)
if csd[0] & 0xC0 == 0x40: # CSD version 2.0
self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024
elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB)
c_size = (csd[6] & 0b11) << 10 | csd[7] << 2 | csd[8] >> 6
c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7
read_bl_len = csd[5] & 0b1111
capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len)
self.sectors = capacity // 512
else:
raise OSError("SD card CSD format not supported")
# CMD16: set block length to 512 bytes
if self.cmd(16, 512, 0) != 0:
raise OSError("can't set 512 block size")
# set to high data rate now that it's initialised
self.init_spi(baudrate)
def init_card_v1(self):
for i in range(_CMD_TIMEOUT):
time.sleep_ms(50)
self.cmd(55, 0, 0)
if self.cmd(41, 0, 0) == 0:
# SDSC card, uses byte addressing in read/write/erase commands
self.cdv = 512
# print("[SDCard] v1 card")
return
raise OSError("timeout waiting for v1 card")
def init_card_v2(self):
for i in range(_CMD_TIMEOUT):
time.sleep_ms(50)
self.cmd(58, 0, 0, 4)
self.cmd(55, 0, 0)
if self.cmd(41, 0x40000000, 0) == 0:
self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte
ocr = self.tokenbuf[0] # get first byte of response, which is OCR
if not ocr & 0x40:
# SDSC card, uses byte addressing in read/write/erase commands
self.cdv = 512
else:
# SDHC/SDXC card, uses block addressing in read/write/erase commands
self.cdv = 1
# print("[SDCard] v2 card")
return
raise OSError("timeout waiting for v2 card")
def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
self.cs(0)
# create and send the command
buf = self.cmdbuf
buf[0] = 0x40 | cmd
buf[1] = arg >> 24
buf[2] = arg >> 16
buf[3] = arg >> 8
buf[4] = arg
buf[5] = crc
self.spi.write(buf)
if skip1:
self.spi.readinto(self.tokenbuf, 0xFF)
# wait for the response (response[7] == 0)
for i in range(_CMD_TIMEOUT):
self.spi.readinto(self.tokenbuf, 0xFF)
response = self.tokenbuf[0]
if not (response & 0x80):
if final < 0:
self.spi.readinto(self.tokenbuf, 0xFF)
final = -1 - final
for j in range(final):
self.spi.write(b"\xff")
if release:
self.cs(1)
self.spi.write(b"\xff")
return response
self.cs(1)
self.spi.write(b"\xff")
return -1
def readinto(self, buf):
self.cs(0)
for i in range(_CMD_TIMEOUT):
self.spi.readinto(self.tokenbuf, 0xFF)
if self.tokenbuf[0] == _TOKEN_DATA:
break
time.sleep_ms(1)
else:
self.cs(1)
raise OSError("timeout waiting for response")
mv = self.dummybuf_memoryview
if len(buf) != len(mv):
mv = mv[: len(buf)]
self.spi.write_readinto(mv, buf)
self.spi.write(b"\xff")
self.spi.write(b"\xff")
self.cs(1)
self.spi.write(b"\xff")
def write(self, token, buf):
self.cs(0)
self.spi.read(1, token)
self.spi.write(buf)
self.spi.write(b"\xff")
self.spi.write(b"\xff")
if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05:
self.cs(1)
self.spi.write(b"\xff")
return
while self.spi.read(1, 0xFF)[0] == 0:
pass
self.cs(1)
self.spi.write(b"\xff")
def write_token(self, token):
self.cs(0)
self.spi.read(1, token)
self.spi.write(b"\xff")
while self.spi.read(1, 0xFF)[0] == 0x00:
pass
self.cs(1)
self.spi.write(b"\xff")
def readblocks(self, block_num, buf):
# workaround for shared bus, required for (at least) some Kingston
self.spi.write(b"\xff")
nblocks = len(buf) // 512
assert nblocks and not len(buf) % 512, "Buffer length is invalid"
if nblocks == 1:
# CMD17: set read address for single block
if self.cmd(17, block_num * self.cdv, 0, release=False) != 0:
# release the card
self.cs(1)
raise OSError(5) # EIO
# receive the data and release card
self.readinto(buf)
else:
# CMD18: set read address for multiple blocks
if self.cmd(18, block_num * self.cdv, 0, release=False) != 0:
self.cs(1)
raise OSError(5) # EIO
offset = 0
mv = memoryview(buf)
while nblocks:
self.readinto(mv[offset : offset + 512])
offset += 512
nblocks -= 1
if self.cmd(12, 0, 0xFF, skip1=True):
raise OSError(5) # EIO
def writeblocks(self, block_num, buf):
# workaround for shared bus, required for (at least) some Kingston
self.spi.write(b"\xff")
nblocks, err = divmod(len(buf), 512)
assert nblocks and not err, "Buffer length is invalid"
if nblocks == 1:
# CMD24: set write address for single block
if self.cmd(24, block_num * self.cdv, 0) != 0:
raise OSError(5) # EIO
self.write(_TOKEN_DATA, buf)
else:
# CMD25: set write address for first block
if self.cmd(25, block_num * self.cdv, 0) != 0:
raise OSError(5) # EIO
offset = 0
mv = memoryview(buf)
while nblocks:
self.write(_TOKEN_CMD25, mv[offset : offset + 512])
offset += 512
nblocks -= 1
self.write_token(_TOKEN_STOP_TRAN)
def ioctl(self, op, arg):
if op == 4: # get number of blocks
return self.sectors
if op == 5: # get block size in bytes
return 512

View File

@@ -0,0 +1,107 @@
"""
ST7789/FrameBuffer
MicroPython library for the ST7789(TFT-SPI)
=======================================================
#Preliminary composition 20240110
@dahanzimin From the Mixly Team
"""
import time, uframebuf
from machine import Pin, PWM
from micropython import const
_CMD_SWRESET = const(0x01)
_CMD_SLPIN = const(0x10)
_CMD_SLPOUT = const(0x11)
_CMD_PTLON = const(0x12)
_CMD_NORON = const(0x13)
_CMD_INVOFF = const(0x20)
_CMD_INVON = const(0x21)
_CMD_DISPOFF = const(0x28)
_CMD_DISPON = const(0x29)
_CMD_CASET = const(0x2A)
_CMD_RASET = const(0x2B)
_CMD_RAMWR = const(0x2C)
_CMD_RAMRD = const(0x2E)
_CMD_PTLAR = const(0x30)
_CMD_VSCRDEF = const(0x33)
_CMD_COLMOD = const(0x3A)
_CMD_MADCTL = const(0x36)
class ST7789(uframebuf.FrameBuffer_Uincode):
def __init__(self, spi, width, height, dc_pin=None, cs_pin=None, bl_pin=None, font_address=0x700000):
if height != 240 or width not in [320, 240, 135]:
raise ValueError("Unsupported display. 320x240, 240x240 and 135x240 are supported.")
self.spi = spi
self.dc = Pin(dc_pin, Pin.OUT, value=1)
self.cs = Pin(cs_pin, Pin.OUT, value=1)
self._buffer = bytearray(width * height * 2)
super().__init__(self._buffer, width, height, uframebuf.RGB565)
self.font(font_address)
self._init()
self.show()
time.sleep_ms(100)
self._brightness = 0.6
self.bl_led = PWM(Pin(bl_pin), duty_u16=int(self._brightness * 60000)) if bl_pin else None
def _write(self, cmd, dat = None):
self.cs.off()
self.dc.off()
self.spi.write(bytearray([cmd]))
self.cs.on()
if dat is not None:
self.cs.off()
self.dc.on()
self.spi.write(dat)
self.cs.on()
def _init(self):
"""Display initialization configuration"""
for cmd, data, delay in [
(_CMD_SWRESET, None, 150),
(_CMD_SLPOUT, None, None),
(_CMD_COLMOD, b'\x55', 50),
(_CMD_MADCTL, b'\x60', 50),
(_CMD_INVOFF, None, 10),
(_CMD_NORON, None, 10),
(_CMD_DISPON, None, 200),
]:
self._write(cmd, data)
if delay:
time.sleep_us(delay)
def _write(self, command=None, data=None):
"""SPI write to the device: commands and data."""
if command is not None:
self.cs.off()
self.dc.off()
self.spi.write(bytes([command]))
self.cs.on()
if data is not None:
self.cs.off()
self.dc.on()
self.spi.write(data)
self.cs.on()
def get_brightness(self):
return self._brightness
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._brightness = brightness
self.bl_led.duty_u16(int(brightness*60000))
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(_CMD_CASET, b'\x00\x00\x01\x3f')
self._write(_CMD_RASET, b'\x00\x00\x00\xef')
self._write(_CMD_RAMWR, self._buffer)