Merge branch 'master' of https://gitee.com/bnu_mixly/mixly3
This commit is contained in:
@@ -3,14 +3,9 @@ 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
|
||||
@dahanzimin From the Mixly Team
|
||||
"""
|
||||
|
||||
import _thread, gc
|
||||
from time import sleep_ms
|
||||
from machine import Pin, PWM
|
||||
|
||||
@@ -30,13 +25,15 @@ Letter = 'ABCDEFG#R'
|
||||
class MIDI():
|
||||
def __init__(self, pin, volume=100, invert=0, pa_ctrl=None):
|
||||
self.reset()
|
||||
self._invert=invert
|
||||
self._invert = invert
|
||||
self._pin = pin
|
||||
self._volume = volume
|
||||
self._play = False
|
||||
self._over = True
|
||||
self._pwm = None
|
||||
self._pa_ctrl = pa_ctrl
|
||||
|
||||
def set_volume(self,volume):
|
||||
def set_volume(self, volume):
|
||||
if not 0 <= volume <= 100:
|
||||
raise ValueError("Volume value is in the range: 0-100")
|
||||
self._volume=volume
|
||||
@@ -97,45 +94,60 @@ class MIDI():
|
||||
self.set_duration(int(tone[(pos + 1):]))
|
||||
tone = tone[:pos]
|
||||
|
||||
def play(self, tune, duration=None):
|
||||
if self._pa_ctrl: self._pa_ctrl(1)
|
||||
def play(self, tune, duration=None, pa_delay=100):
|
||||
if self._pa_ctrl: self._pa_ctrl(1, pa_delay)
|
||||
self._pwm = PWM(Pin(self._pin), duty=1023 if self._invert else 0)
|
||||
self._play = True
|
||||
self._over = False
|
||||
if duration is None:
|
||||
self.set_default(tune[0])
|
||||
else:
|
||||
self.set_duration(duration)
|
||||
for tone in tune:
|
||||
tone = tone.upper()
|
||||
if not self._play:
|
||||
break
|
||||
if tone[0] not in Letter:
|
||||
continue
|
||||
midi = self.midi(tone)
|
||||
self._pwm.duty(1023-self._volume) if self._invert else self._pwm.duty(self._volume)
|
||||
self._pwm.freq(midi[0])
|
||||
if self._play: self._pwm.duty((1023-self._volume) if self._invert else self._volume)
|
||||
if self._play: self._pwm.freq(midi[0])
|
||||
sleep_ms(midi[1])
|
||||
self._pwm.freq(400000)
|
||||
if self._play: self._pwm.freq(400000)
|
||||
sleep_ms(1)
|
||||
if self._pa_ctrl: self._pa_ctrl(0)
|
||||
if self._pa_ctrl: self._pa_ctrl(0, 0)
|
||||
self._pwm.deinit()
|
||||
sleep_ms(10)
|
||||
self._over = True
|
||||
|
||||
def pitch(self, freq):
|
||||
if self._pa_ctrl: self._pa_ctrl(1)
|
||||
self._pwm = PWM(Pin(self._pin))
|
||||
self._pwm.duty(1023-self._volume) if self._invert else self._pwm.duty(self._volume)
|
||||
self._pwm.freq(int(freq))
|
||||
def play_thread(self, tune, duration=None, pa_delay=100):
|
||||
self._play = False
|
||||
while not self._over:
|
||||
sleep_ms(10)
|
||||
if not self._play:
|
||||
gc.collect()
|
||||
_thread.start_new_thread(self.play, (tune, duration, pa_delay))
|
||||
sleep_ms(100)
|
||||
|
||||
def pitch_time(self, freq, delay):
|
||||
if self._pa_ctrl: self._pa_ctrl(1)
|
||||
def pitch(self, freq, pa_delay=100):
|
||||
if self._pa_ctrl: self._pa_ctrl(1, pa_delay)
|
||||
self._pwm = PWM(Pin(self._pin))
|
||||
self._pwm.duty(1023-self._volume) if self._invert else self._pwm.duty(self._volume)
|
||||
self._pwm.freq(int(freq))
|
||||
self._pwm.duty((1023-self._volume) if self._invert else self._volume)
|
||||
self._pwm.freq(int(freq))
|
||||
|
||||
def pitch_time(self, freq, delay, pa_delay=100):
|
||||
if self._pa_ctrl: self._pa_ctrl(1, pa_delay)
|
||||
self._pwm = PWM(Pin(self._pin))
|
||||
self._pwm.duty((1023-self._volume) if self._invert else self._volume)
|
||||
self._pwm.freq(int(freq))
|
||||
sleep_ms(delay)
|
||||
if self._pa_ctrl: self._pa_ctrl(0)
|
||||
if self._pa_ctrl: self._pa_ctrl(0, 0)
|
||||
self._pwm.deinit()
|
||||
sleep_ms(10)
|
||||
|
||||
|
||||
def stop(self):
|
||||
if self._pa_ctrl: self._pa_ctrl(0)
|
||||
self._play = False
|
||||
if self._pa_ctrl: self._pa_ctrl(0, 0)
|
||||
if self._pwm: self._pwm.deinit()
|
||||
sleep_ms(10)
|
||||
|
||||
|
||||
@@ -553,15 +553,17 @@ class FrameBuffer_Uincode(FrameBuffer_Base):
|
||||
self.show()
|
||||
time.sleep_ms(speed)
|
||||
|
||||
def qrcode(self, data, x=0, y=0, size=None, bold=0, type=None, correct=0, color=0xffff, bg_color=0x0, sync=True):
|
||||
def qrcode(self, data, x=None, y=None, size=None, bold=0, type=None, correct=0, color=0xffff, bg_color=0x0, sync=True):
|
||||
if self._miniqr is None:
|
||||
from adafruit_miniqr import QRCode
|
||||
self._miniqr = QRCode
|
||||
_qr = self._miniqr(qr_type=type, error_correct=correct)
|
||||
_qr.add_data(data)
|
||||
_qr.add_data(str(data))
|
||||
_qr.make()
|
||||
if sync: self.fill(bg_color, sync=False)
|
||||
size = min(self.height // _qr.matrix.height, self.width // _qr.matrix.width) if size is None else size
|
||||
x = (self.width - _qr.matrix.width * size) // 2 if x is None else x
|
||||
y = (self.height - _qr.matrix.height * size) // 2 if y is None else y
|
||||
for j in range(_qr.matrix.height):
|
||||
for i in range(_qr.matrix.width):
|
||||
if _qr.matrix[i, j]:
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,15 +1,12 @@
|
||||
"""
|
||||
MixGo CC -Onboard resources
|
||||
MixGo CC Onboard resources
|
||||
|
||||
MicroPython library for the MixGo CC -Onboard resources
|
||||
MicroPython library for the MixGo CC Onboard resources
|
||||
=======================================================
|
||||
|
||||
#Preliminary composition 20221010
|
||||
|
||||
dahanzimin From the Mixly Team
|
||||
@dahanzimin From the Mixly Team
|
||||
"""
|
||||
import time, gc
|
||||
from machine import Pin, SoftI2C, ADC, PWM, RTC
|
||||
from machine import *
|
||||
|
||||
'''i2c-onboard'''
|
||||
onboard_i2c=SoftI2C(scl = Pin(7), sda = Pin(6), freq = 400000)
|
||||
@@ -95,7 +92,7 @@ onboard_rgb = NeoPixel(Pin(8), 4, ORDER=(0, 1, 2, 3))
|
||||
|
||||
'''1Buzzer-Music'''
|
||||
from music import MIDI
|
||||
onboard_music =MIDI(10)
|
||||
onboard_music = MIDI(10)
|
||||
|
||||
'''MIC_Sensor'''
|
||||
class MICSensor:
|
||||
@@ -105,10 +102,10 @@ class MICSensor:
|
||||
def read(self):
|
||||
maxloudness = 0
|
||||
for i in range(5):
|
||||
loudness = self.sample()
|
||||
loudness = self.sample()
|
||||
if loudness > maxloudness:
|
||||
maxloudness = loudness
|
||||
return maxloudness
|
||||
return maxloudness
|
||||
|
||||
def sample(self):
|
||||
values = []
|
||||
@@ -119,21 +116,24 @@ class MICSensor:
|
||||
|
||||
onboard_sound = MICSensor(pin=4 if version else 3)
|
||||
|
||||
'''4,5KEY_Sensor'''
|
||||
'''5KEY_Sensor'''
|
||||
class KEYSensor:
|
||||
def __init__(self, pin, range):
|
||||
self.adc = ADC(Pin(pin), atten=ADC.ATTN_11DB)
|
||||
self.pin = pin
|
||||
self.adc = ADC(Pin(pin), atten=ADC.ATTN_11DB)
|
||||
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 - 300) < min(sorted(values)[25:]) < (self.range + 300)
|
||||
|
||||
for _ in range(25):
|
||||
try:
|
||||
values.append(self.adc.read())
|
||||
except: #IDF>5.2.2存在ADC2问题
|
||||
pass
|
||||
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:
|
||||
@@ -148,7 +148,7 @@ class KEYSensor:
|
||||
def was_pressed(self):
|
||||
if(self._value() != self.flag):
|
||||
self.flag = self._value()
|
||||
if self.flag :
|
||||
if self.flag:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -156,34 +156,15 @@ class KEYSensor:
|
||||
def irq(self, handler, trigger):
|
||||
Pin(self.pin, Pin.IN).irq(handler = handler, trigger = trigger)
|
||||
|
||||
'''2,1KEY_Button'''
|
||||
class Button:
|
||||
'''1KEY_Button'''
|
||||
class Button(KEYSensor):
|
||||
def __init__(self, pin):
|
||||
self.pin = Pin(pin, Pin.IN)
|
||||
self.pin = pin
|
||||
self.key = Pin(pin, Pin.IN)
|
||||
self.flag = True
|
||||
|
||||
def get_presses(self, delay = 1):
|
||||
last_time,presses = time.time(), 0
|
||||
while time.time() < last_time + delay:
|
||||
time.sleep(0.05)
|
||||
if self.was_pressed():
|
||||
presses += 1
|
||||
return presses
|
||||
|
||||
def is_pressed(self):
|
||||
return not self.pin.value()
|
||||
|
||||
def was_pressed(self, flag = 0):
|
||||
if(self.pin.value() != self.flag):
|
||||
self.flag = self.pin.value()
|
||||
time.sleep(0.02)
|
||||
if self.flag:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def irq(self, handler, trigger):
|
||||
self.pin.irq(handler = handler, trigger = trigger)
|
||||
def _value(self):
|
||||
return not self.key.value()
|
||||
|
||||
if version==0:
|
||||
B1key = Button(9)
|
||||
@@ -191,7 +172,7 @@ if version==0:
|
||||
A1key = KEYSensor(2,20)
|
||||
A2key = KEYSensor(2,1170)
|
||||
A3key = KEYSensor(2,2400)
|
||||
A4key = KEYSensor(2,3610)
|
||||
A4key = KEYSensor(2,3610)
|
||||
|
||||
else:
|
||||
B1key = Button(9)
|
||||
@@ -201,7 +182,7 @@ else:
|
||||
A3key = KEYSensor(5,2500)
|
||||
A4key = KEYSensor(5,3500)
|
||||
|
||||
'''2-LED''' #Modify indexing method
|
||||
'''2-LED''' #Modify indexing method
|
||||
class LED:
|
||||
def __init__(self, pins=[]):
|
||||
self._pins = pins
|
||||
@@ -231,11 +212,11 @@ class LED:
|
||||
print("Warning: Old version, without this function")
|
||||
else:
|
||||
if val == -1:
|
||||
self.setbrightness(index, 100) if self.getbrightness(index) < 50 else self.setbrightness(index, 0)
|
||||
self.setbrightness(index, 100) if self.getbrightness(index) < 50 else self.setbrightness(index, 0)
|
||||
elif val == 1:
|
||||
self.setbrightness(index, 100)
|
||||
self.setbrightness(index, 100)
|
||||
elif val == 0:
|
||||
self.setbrightness(index, 0)
|
||||
self.setbrightness(index, 0)
|
||||
|
||||
def getonoff(self, index):
|
||||
if len(self._pins) == 0:
|
||||
|
||||
@@ -1,16 +1,12 @@
|
||||
"""
|
||||
MixGo ME -Onboard resources
|
||||
MixGo ME Onboard resources
|
||||
|
||||
MicroPython library for the MixGo ME -Onboard resources
|
||||
MicroPython library for the MixGo ME Onboard resources
|
||||
=======================================================
|
||||
|
||||
#Preliminary composition 20221010
|
||||
|
||||
dahanzimin From the Mixly Team
|
||||
@dahanzimin From the Mixly Team
|
||||
"""
|
||||
|
||||
import time, gc
|
||||
from machine import Pin, SoftI2C, ADC, PWM, RTC
|
||||
from machine import *
|
||||
|
||||
'''i2c-onboard'''
|
||||
onboard_i2c=SoftI2C(scl = Pin(7), sda = Pin(6), freq = 400000)
|
||||
@@ -52,7 +48,7 @@ onboard_rgb = NeoPixel(Pin(9), 2, ORDER=(0, 1, 2, 3), multiplex=1)
|
||||
|
||||
'''1Buzzer-Music'''
|
||||
from music import MIDI
|
||||
onboard_music =MIDI(10)
|
||||
onboard_music = MIDI(10)
|
||||
|
||||
'''MIC_Sensor'''
|
||||
class MICSensor:
|
||||
@@ -62,7 +58,7 @@ class MICSensor:
|
||||
def read(self):
|
||||
maxloudness = 0
|
||||
for i in range(5):
|
||||
loudness = self.sample()
|
||||
loudness = self.sample()
|
||||
if loudness > maxloudness:
|
||||
maxloudness = loudness
|
||||
return maxloudness
|
||||
@@ -78,18 +74,22 @@ onboard_sound = MICSensor()
|
||||
|
||||
'''5KEY_Sensor'''
|
||||
class KEYSensor:
|
||||
def __init__(self,range):
|
||||
self.adc=ADC(Pin(5), atten=ADC.ATTN_11DB)
|
||||
self.range=range
|
||||
def __init__(self, pin, range):
|
||||
self.pin = pin
|
||||
self.adc = ADC(Pin(pin), atten=ADC.ATTN_11DB)
|
||||
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 - 300) < min(sorted(values)[25:]) < (self.range + 300)
|
||||
|
||||
for _ in range(25):
|
||||
try:
|
||||
values.append(self.adc.read())
|
||||
except: #IDF>5.2.2存在ADC2问题
|
||||
pass
|
||||
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:
|
||||
@@ -97,57 +97,37 @@ class KEYSensor:
|
||||
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 :
|
||||
if self.flag:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def irq(self, handler, trigger):
|
||||
Pin(5, Pin.IN).irq(handler = handler, trigger = trigger)
|
||||
|
||||
B2key = KEYSensor(20)
|
||||
A1key = KEYSensor(800)
|
||||
A2key = KEYSensor(1600)
|
||||
A3key = KEYSensor(2500)
|
||||
A4key = KEYSensor(3500)
|
||||
Pin(self.pin, Pin.IN).irq(handler = handler, trigger = trigger)
|
||||
|
||||
'''1KEY_Button'''
|
||||
class Button:
|
||||
class Button(KEYSensor):
|
||||
def __init__(self, pin):
|
||||
self.pin = Pin(pin, Pin.IN)
|
||||
self.pin = pin
|
||||
self.key = Pin(pin, Pin.IN)
|
||||
self.flag = True
|
||||
|
||||
def get_presses(self, delay = 1):
|
||||
last_time,presses = time.time(), 0
|
||||
while time.time() < last_time + delay:
|
||||
time.sleep(0.05)
|
||||
if self.was_pressed():
|
||||
presses += 1
|
||||
return presses
|
||||
|
||||
def is_pressed(self):
|
||||
return not self.pin.value()
|
||||
def _value(self):
|
||||
return not self.key.value()
|
||||
|
||||
def was_pressed(self, flag = 0):
|
||||
if(self.pin.value() != self.flag):
|
||||
self.flag = self.pin.value()
|
||||
time.sleep(0.02)
|
||||
if self.flag:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def irq(self, handler, trigger):
|
||||
self.pin.irq(handler = handler, trigger = trigger)
|
||||
|
||||
B1key = Button(9)
|
||||
B2key = KEYSensor(5,20)
|
||||
A1key = KEYSensor(5,800)
|
||||
A2key = KEYSensor(5,1600)
|
||||
A3key = KEYSensor(5,2500)
|
||||
A4key = KEYSensor(5,3500)
|
||||
|
||||
'''2LED-Multiplex RGB'''
|
||||
class LED:
|
||||
|
||||
@@ -3,13 +3,10 @@ MixGo CAR -Onboard resources
|
||||
|
||||
MicroPython library for the MixGo CAR (ESP32C3)
|
||||
=======================================================
|
||||
|
||||
#Preliminary composition 20220804
|
||||
|
||||
dahanzimin From the Mixly Team
|
||||
@dahanzimin From the Mixly Team
|
||||
"""
|
||||
import time,gc,ms32006
|
||||
from machine import Pin,SoftI2C,ADC,RTC
|
||||
from machine import *
|
||||
|
||||
'''RTC'''
|
||||
rtc_clock=RTC()
|
||||
@@ -17,7 +14,7 @@ rtc_clock=RTC()
|
||||
'''i2c-onboard'''
|
||||
onboard_i2c=SoftI2C(scl = Pin(7), sda = Pin(6), freq = 400000)
|
||||
|
||||
'''4RGB_WS2812''' #color_chase(),rainbow_cycle()方法移至类里
|
||||
'''4RGB_WS2812'''
|
||||
from ws2812 import NeoPixel
|
||||
onboard_rgb = NeoPixel(Pin(8), 4, ORDER=(0, 1, 2, 3))
|
||||
|
||||
|
||||
@@ -118,16 +118,16 @@
|
||||
"type": "command",
|
||||
"portSelect": "all",
|
||||
"micropython:esp32c3:mixgo_cc": {
|
||||
"command": "\"{esptool}\" --chip esp32c3 --port {com} --baud {baudrate} write_flash -e 0x0 \"{indexPath}/build/Mixgo_CC_lib-v1.23.0.bin\" 0X3A0000 \"{indexPath}/../micropython/build/HZK12.bin\""
|
||||
"command": "\"{esptool}\" --chip esp32c3 --port {com} --baud {baudrate} write_flash -e 0x0 \"{indexPath}/build/Mixgo_CC_lib-v1.25.0.bin\" 0X3A0000 \"{indexPath}/../micropython/build/HZK12.bin\""
|
||||
},
|
||||
"micropython:esp32c3:mixgo_me": {
|
||||
"command": "\"{esptool}\" --chip esp32c3 --port {com} --baud {baudrate} write_flash -e 0x0 \"{indexPath}/build/Mixgo_ME_lib-v1.23.0.bin\" 0X3A0000 \"{indexPath}/../micropython/build/HZK12.bin\""
|
||||
"command": "\"{esptool}\" --chip esp32c3 --port {com} --baud {baudrate} write_flash -e 0x0 \"{indexPath}/build/Mixgo_ME_lib-v1.25.0.bin\" 0X3A0000 \"{indexPath}/../micropython/build/HZK12.bin\""
|
||||
},
|
||||
"micropython:esp32c3:mixgocar_c3": {
|
||||
"command": "\"{esptool}\" --chip esp32c3 --port {com} --baud {baudrate} write_flash -e 0x0 \"{indexPath}/build/Mixgo_Car_lib-v1.23.0.bin\" 0X3A0000 \"{indexPath}/../micropython/build/HZK12.bin\""
|
||||
"command": "\"{esptool}\" --chip esp32c3 --port {com} --baud {baudrate} write_flash -e 0x0 \"{indexPath}/build/Mixgo_Car_lib-v1.25.0.bin\" 0X3A0000 \"{indexPath}/../micropython/build/HZK12.bin\""
|
||||
},
|
||||
"micropython:esp32c3:generic": {
|
||||
"command": "\"{esptool}\" --chip esp32c3 --port {com} --baud {baudrate} write_flash -e 0x0 \"{indexPath}/build/Generic_C3_UART_lib-v1.23.0.bin\" 0X3A0000 \"{indexPath}/../micropython/build/HZK12.bin\""
|
||||
"command": "\"{esptool}\" --chip esp32c3 --port {com} --baud {baudrate} write_flash -e 0x0 \"{indexPath}/build/Generic_C3_UART_lib-v1.25.0.bin\" 0X3A0000 \"{indexPath}/../micropython/build/HZK12.bin\""
|
||||
}
|
||||
},
|
||||
"upload": {
|
||||
@@ -182,7 +182,7 @@
|
||||
"binFile": [
|
||||
{
|
||||
"offset": "0x0000",
|
||||
"path": "./build/Mixgo_CC_lib-v1.23.0.bin"
|
||||
"path": "./build/Mixgo_CC_lib-v1.25.0.bin"
|
||||
}, {
|
||||
"offset": "0x3A0000",
|
||||
"path": "../micropython/build/HZK12.bin"
|
||||
@@ -193,7 +193,7 @@
|
||||
"binFile": [
|
||||
{
|
||||
"offset": "0x0000",
|
||||
"path": "./build/Mixgo_ME_lib-v1.23.0.bin"
|
||||
"path": "./build/Mixgo_ME_lib-v1.25.0.bin"
|
||||
}, {
|
||||
"offset": "0x3A0000",
|
||||
"path": "../micropython/build/HZK12.bin"
|
||||
@@ -204,7 +204,7 @@
|
||||
"binFile": [
|
||||
{
|
||||
"offset": "0x0000",
|
||||
"path": "./build/Mixgo_Car_lib-v1.23.0.bin"
|
||||
"path": "./build/Mixgo_Car_lib-v1.25.0.bin"
|
||||
}, {
|
||||
"offset": "0x3A0000",
|
||||
"path": "../micropython/build/HZK12.bin"
|
||||
@@ -215,7 +215,7 @@
|
||||
"binFile": [
|
||||
{
|
||||
"offset": "0x0000",
|
||||
"path": "./build/Generic_C3_UART_lib-v1.23.0.bin"
|
||||
"path": "./build/Generic_C3_UART_lib-v1.25.0.bin"
|
||||
}, {
|
||||
"offset": "0x3A0000",
|
||||
"path": "../micropython/build/HZK12.bin"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,110 +0,0 @@
|
||||
"""
|
||||
AI-Camera (Inherit C module)
|
||||
|
||||
MicroPython library for the AI-Camera(Inherit C module)
|
||||
=======================================================
|
||||
@dahanzimin From the Mixly Team
|
||||
"""
|
||||
|
||||
import esp_ai
|
||||
from micropython import const
|
||||
|
||||
CODE_DETECTION = const(0)
|
||||
COLOR_DETECTION = const(1)
|
||||
MOTION_DEECTION = const(2)
|
||||
CAT_FACE_DETECTION = const(3)
|
||||
FACE_DETECTION = const(4)
|
||||
FACE_RECOGNITION = const(5)
|
||||
|
||||
class AI:
|
||||
def __init__(self, function):
|
||||
self._func = function
|
||||
self._ai = None
|
||||
self._once = True
|
||||
|
||||
def _init(self, *args):
|
||||
if self._func == CODE_DETECTION:
|
||||
self._ai = esp_ai.code_recognition()
|
||||
elif self._func == COLOR_DETECTION:
|
||||
self._ai = esp_ai.color_detection(color=args[0])
|
||||
elif self._func == MOTION_DEECTION:
|
||||
self._ai = esp_ai.motion_recognition(threshold=args[0])
|
||||
elif self._func == CAT_FACE_DETECTION:
|
||||
self._ai = esp_ai.cat_detection()
|
||||
elif self._func == FACE_DETECTION:
|
||||
self._ai = esp_ai.face_detection()
|
||||
elif self._func == FACE_RECOGNITION:
|
||||
self._ai = esp_ai.face_recognition()
|
||||
else:
|
||||
raise AttributeError('AI model is not supported')
|
||||
self._ai.start() #启动检测,可以通过LCD观察结果
|
||||
self._once = False
|
||||
|
||||
def _result(self, res, _t, _s=0, _n=0): #_s:第几个, _n:细分第几个
|
||||
if not res: return None
|
||||
if _t == 'len':
|
||||
return res[0]
|
||||
elif _t == 'pos':
|
||||
if len(res) >= (5 + _s * 4):
|
||||
return res[(1 + _s * 4):(5 + _s * 4)]
|
||||
elif _t == 'keypoint':
|
||||
if len(res) >= (7 + _s * 14 + _n * 2):
|
||||
return res[(5 + _s * 14 + _n * 2):(7 + _s * 14 + _n * 2)]
|
||||
|
||||
def code_recognition(self):
|
||||
if self._func == CODE_DETECTION:
|
||||
if self._once: self._init()
|
||||
return self._ai.read()
|
||||
else:
|
||||
raise AttributeError('This model can only run QR code detection')
|
||||
|
||||
def color_detection(self, color=0, event='pos', num=0):
|
||||
if self._func == COLOR_DETECTION:
|
||||
if self._once: self._init(color)
|
||||
return self._result(self._ai.read(), event, num)
|
||||
else:
|
||||
raise AttributeError('This model can only run color detection')
|
||||
|
||||
def motion_recognition(self, threshold=50):
|
||||
if self._func == MOTION_DEECTION:
|
||||
if self._once: self._init(threshold)
|
||||
return bool(self._ai.read() >= threshold)
|
||||
else:
|
||||
raise AttributeError('This model can only run motion recognition')
|
||||
|
||||
def cat_detection(self, event='pos', num=0):
|
||||
if self._func == CAT_FACE_DETECTION:
|
||||
if self._once: self._init()
|
||||
return self._result(self._ai.read(), event, num)
|
||||
else:
|
||||
raise AttributeError('This model can only run cat face detection')
|
||||
|
||||
def face_detection(self, event='pos', num=0, point=0):
|
||||
if self._func == FACE_DETECTION:
|
||||
if self._once: self._init()
|
||||
return self._result(self._ai.read(), event, num, point)
|
||||
else:
|
||||
raise AttributeError('This model can only run face detection')
|
||||
|
||||
def face_recognition(self, event='pos', num=0, point=0):
|
||||
if self._func == FACE_RECOGNITION:
|
||||
if self._once: self._init()
|
||||
return self._result(self._ai.recognize(), event, num, point)
|
||||
else:
|
||||
raise AttributeError('This model can only run face recognition')
|
||||
|
||||
def face_enroll(self):
|
||||
if self._func == FACE_RECOGNITION:
|
||||
return self._ai.enroll()
|
||||
else:
|
||||
raise AttributeError('This model can only run face recognition')
|
||||
|
||||
def face_delete(self, _id):
|
||||
if self._func == FACE_RECOGNITION:
|
||||
self._ai.delete(_id)
|
||||
else:
|
||||
raise AttributeError('This model can only run face recognition')
|
||||
|
||||
def stop(self):
|
||||
if self._ai is not None:
|
||||
self._ai.stop()
|
||||
@@ -1,69 +1,45 @@
|
||||
"""
|
||||
Camera GC032A/FrameBuffer(Inherit C module)
|
||||
Camera
|
||||
|
||||
MicroPython library for the GC032A(Inherit C module)
|
||||
MicroPython library for the Camera(Inherit C module)
|
||||
=======================================================
|
||||
@dahanzimin From the Mixly Team
|
||||
"""
|
||||
|
||||
import time
|
||||
import base64
|
||||
from sensor import *
|
||||
import base64, jpeg
|
||||
from _camera import *
|
||||
from jpeg import Encoder
|
||||
from machine import SoftI2C, Pin
|
||||
from mixgo_sant import onboard_bot
|
||||
from esp_usb import CAM
|
||||
|
||||
class GC032A(Camera):
|
||||
def __init__(self, framesize=LCD, hmirror=None, frame=1):
|
||||
onboard_bot.cam_en(1, 500)
|
||||
super().__init__(frame)
|
||||
super().set_framesize(framesize)
|
||||
time.sleep_ms(100)
|
||||
if hmirror is not None:
|
||||
super().set_hmirror(hmirror)
|
||||
time.sleep_ms(100)
|
||||
SoftI2C(scl=Pin(47), sda=Pin(48), freq=400000)
|
||||
SoftI2C(scl=Pin(47), sda=Pin(38), freq=400000)
|
||||
class Camera(Camera):
|
||||
def __init__(self, frame_size=FrameSize.R240X240, pixel_format=PixelFormat.RGB565, hmirror=False, vflip=False, **kwargs):
|
||||
onboard_bot.cam_en(1, 150)
|
||||
super().__init__(frame_size=frame_size, pixel_format=pixel_format, **kwargs)
|
||||
self.set_hmirror(not hmirror)
|
||||
time.sleep_ms(50)
|
||||
self.set_vflip(not vflip)
|
||||
time.sleep_ms(50)
|
||||
SoftI2C(scl=Pin(47), sda=Pin(48), freq=400000) #恢复I2C
|
||||
|
||||
def deinit(self):
|
||||
super().deinit()
|
||||
onboard_bot.cam_en(0, 100)
|
||||
|
||||
def display(self, show=True):
|
||||
if show:
|
||||
super().display()
|
||||
def snapshot(self, path=None, formats=0, quality=90, rotation=0):
|
||||
if formats == 0 and path is None:
|
||||
return self.capture()
|
||||
else:
|
||||
super().display_stop()
|
||||
|
||||
def snapshot(self, path=None, formats=0, quality=50):
|
||||
if path is None:
|
||||
_data = super().snapshot(formats=formats, quality=quality)
|
||||
if formats >= 2:
|
||||
return b'data:image/jpg;base64,' + base64.b64encode(_data)
|
||||
_encoder = Encoder(pixel_format="RGB565_BE", quality=quality, rotation=rotation, width=self.get_pixel_width(), height=self.get_pixel_height())
|
||||
_jpeg = _encoder.encode(self.capture())
|
||||
del _encoder
|
||||
if path is None:
|
||||
if formats == 1:
|
||||
return _jpeg
|
||||
else:
|
||||
return b'data:image/jpg;base64,' + base64.b64encode(_jpeg)
|
||||
else:
|
||||
return _data
|
||||
else:
|
||||
return super().snapshot(path, quality=50)
|
||||
|
||||
class UVC(CAM):
|
||||
def __init__(self, framesize=QVGA):
|
||||
super().__init__(framesize)
|
||||
|
||||
def deinit(self):
|
||||
super().deinit()
|
||||
|
||||
def display(self, show=True):
|
||||
if show:
|
||||
super().display()
|
||||
else:
|
||||
super().display_stop()
|
||||
|
||||
def snapshot(self, path=None, formats=0, quality=50):
|
||||
if path is None:
|
||||
_data = super().snapshot(formats=formats, quality=quality)
|
||||
if formats >= 2:
|
||||
return b'data:image/jpg;base64,' + base64.b64encode(_data)
|
||||
else:
|
||||
return _data
|
||||
else:
|
||||
return super().snapshot(path, quality=50)
|
||||
with open(path, 'wb') as f:
|
||||
f.write(_jpeg)
|
||||
return True
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
"""
|
||||
ESP-DL
|
||||
|
||||
MicroPython library for the ESP-DL(Inherit C module)
|
||||
=======================================================
|
||||
@dahanzimin From the Mixly Team
|
||||
"""
|
||||
from espdl import *
|
||||
|
||||
def analyze(results, keys=None, num=0):
|
||||
if keys is None:
|
||||
return results is not None
|
||||
if results:
|
||||
if keys == "len":
|
||||
return len(results)
|
||||
else:
|
||||
return results[num][keys]
|
||||
@@ -17,6 +17,9 @@ rtc_clock = RTC()
|
||||
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)
|
||||
|
||||
'''BOT035-Sensor'''
|
||||
try :
|
||||
import sant_bot
|
||||
@@ -25,7 +28,7 @@ except Exception as e:
|
||||
print("Warning: Failed to communicate with BOT035 (Coprocessor) or",e)
|
||||
|
||||
'''TFT/240*240'''
|
||||
onboard_tft = st7789_cf.ST7789(reset=onboard_bot.tft_reset, backlight=onboard_bot.tft_brightness, font_address=0xE00000)
|
||||
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'''
|
||||
try :
|
||||
@@ -73,7 +76,7 @@ from ws2812x import NeoPixel
|
||||
onboard_rgb = NeoPixel(onboard_bot.rgb_sync, 4)
|
||||
|
||||
'''1Buzzer-Music'''
|
||||
from musicx import MIDI
|
||||
from music import MIDI
|
||||
onboard_music = MIDI(46, pa_ctrl=onboard_bot.spk_en)
|
||||
|
||||
'''5KEY_Sensor'''
|
||||
|
||||
@@ -1,283 +0,0 @@
|
||||
"""
|
||||
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()
|
||||
@@ -1,88 +0,0 @@
|
||||
"""
|
||||
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()
|
||||
@@ -1,159 +0,0 @@
|
||||
"""
|
||||
Music buzzer
|
||||
|
||||
Micropython library for the Music buzzer
|
||||
=======================================================
|
||||
|
||||
#Based on Author: qiren123(MIDI Music)
|
||||
@dahanzimin From the Mixly Team
|
||||
"""
|
||||
|
||||
from time import sleep_ms
|
||||
from machine import Pin, PWM
|
||||
|
||||
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, pin, volume=100, invert=0, pa_ctrl=None):
|
||||
self.reset()
|
||||
self._invert=invert
|
||||
self._pin = pin
|
||||
self._volume = volume
|
||||
self._pwm = None
|
||||
self._pa_ctrl = pa_ctrl
|
||||
|
||||
def set_volume(self,volume):
|
||||
if not 0 <= volume <= 100:
|
||||
raise ValueError("Volume value is in the range: 0-100")
|
||||
self._volume=volume
|
||||
|
||||
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 = 40000
|
||||
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, pa_delay=100):
|
||||
if self._pa_ctrl: self._pa_ctrl(1, pa_delay)
|
||||
self._pwm = PWM(Pin(self._pin), duty=1023 if self._invert else 0)
|
||||
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._pwm.duty(1023-self._volume) if self._invert else self._pwm.duty(self._volume)
|
||||
self._pwm.freq(midi[0])
|
||||
sleep_ms(midi[1])
|
||||
self._pwm.freq(40000)
|
||||
sleep_ms(1)
|
||||
if self._pa_ctrl: self._pa_ctrl(0, 0)
|
||||
self._pwm.deinit()
|
||||
sleep_ms(10)
|
||||
|
||||
def pitch(self, freq, pa_delay=100):
|
||||
if self._pa_ctrl: self._pa_ctrl(1, pa_delay)
|
||||
self._pwm = PWM(Pin(self._pin))
|
||||
self._pwm.duty(1023-self._volume) if self._invert else self._pwm.duty(self._volume)
|
||||
self._pwm.freq(int(freq))
|
||||
|
||||
def pitch_time(self, freq, delay, pa_delay=100):
|
||||
if self._pa_ctrl: self._pa_ctrl(1, pa_delay)
|
||||
self._pwm = PWM(Pin(self._pin))
|
||||
self._pwm.duty(1023-self._volume) if self._invert else self._pwm.duty(self._volume)
|
||||
self._pwm.freq(int(freq))
|
||||
sleep_ms(delay)
|
||||
if self._pa_ctrl: self._pa_ctrl(0, 0)
|
||||
self._pwm.deinit()
|
||||
sleep_ms(10)
|
||||
|
||||
def stop(self):
|
||||
if self._pa_ctrl: self._pa_ctrl(0, 0)
|
||||
if self._pwm: self._pwm.deinit()
|
||||
sleep_ms(10)
|
||||
|
||||
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']
|
||||
@@ -43,7 +43,7 @@ class BOT035:
|
||||
time.sleep_ms(delay)
|
||||
|
||||
def reset(self):
|
||||
self._i2c.writeto_mem(_BOT035_ADDRESS, _BOT035_PWM, b' Ndddd\x00\x00\x00\x8c\xb0')
|
||||
self._i2c.writeto_mem(_BOT035_ADDRESS, _BOT035_PWM, b' Ndddd\x00\x00\x00\x8c\x20')
|
||||
|
||||
def key_adc(self):
|
||||
return self._rreg(_BOT035_ADC, 2)
|
||||
|
||||
@@ -1,231 +0,0 @@
|
||||
"""
|
||||
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
|
||||
@@ -1,29 +1,89 @@
|
||||
"""
|
||||
ST7789/FrameBuffer(Inherit C module)
|
||||
ST7789/FrameBuffer
|
||||
|
||||
MicroPython library for the ST7789(Inherit C module)
|
||||
MicroPython library for the ST7789(TFT-SPI)
|
||||
=======================================================
|
||||
@dahanzimin From the Mixly Team
|
||||
"""
|
||||
import time, uframebuf
|
||||
from tftlcd import LCD15
|
||||
from machine import Pin
|
||||
from jpeg import Decoder
|
||||
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, width=240, height=240, reset=None, backlight=None, direction=1, font_address=0x700000):
|
||||
self.display = LCD15(portrait=direction)
|
||||
self.display.deinit()
|
||||
if reset is not None:
|
||||
reset(0, 50)
|
||||
reset(1, 100)
|
||||
self.display = LCD15(portrait=direction)
|
||||
self._width = width
|
||||
self._height = height
|
||||
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)
|
||||
reset(1, 100)
|
||||
self.font(font_address)
|
||||
self.show()
|
||||
self._init()
|
||||
# self.show()
|
||||
self._oneclight = True
|
||||
self._backlight = backlight
|
||||
if backlight: self.set_brightness(0.5)
|
||||
|
||||
def display(self, data=None, rotation=0, sync=True):
|
||||
if type(data) is str:
|
||||
with open(data, "rb") as f:
|
||||
_jpeg = f.read()
|
||||
_decoder = Decoder(pixel_format="RGB565_BE", rotation=rotation)
|
||||
self._buffer[:] = _decoder.decode(_jpeg)
|
||||
del _decoder
|
||||
else:
|
||||
self._buffer[:] = data #后期做图像大小处理
|
||||
if sync: self.show()
|
||||
return self._buffer
|
||||
|
||||
def _write(self, cmd, dat=None):
|
||||
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 [
|
||||
##(_CMD_SWRESET, None, 20000),
|
||||
(_CMD_SLPOUT, None, 120000),
|
||||
(_CMD_MADCTL, b'\x00', 50),
|
||||
(_CMD_COLMOD, b'\x05', 50),
|
||||
(0xB2, b'\x0c\x0c\x00\x33\x33', 10),
|
||||
(0xB7, b'\x35', 10),
|
||||
(0xBB, b'\x19', 10),
|
||||
(0xC0, b'\x2C', 10),
|
||||
(0xC2, b'\x01', 10),
|
||||
(0xC3, b'\x12', 10),
|
||||
(0xC4, b'\x20', 10),
|
||||
(0xC6, b'\x0F', 10),
|
||||
(0xD0, b'\xA4\xA1', 10),
|
||||
(0xE0, b'\xD0\x04\x0D\x11\x13\x2B\x3F\x54\x4C\x18\x0D\x0B\x1F\x23', 10),
|
||||
(0xE1, b'\xD0\x04\x0C\x11\x13\x2C\x3F\x44\x51\x2F\x1F\x1F\x20\x23', 10),
|
||||
(_CMD_INVON, None, 10),
|
||||
(_CMD_DISPON, None, 10),
|
||||
]:
|
||||
self._write(cmd, data)
|
||||
if delay:
|
||||
time.sleep_us(delay)
|
||||
|
||||
def get_brightness(self):
|
||||
return self._backlight() / 100
|
||||
@@ -40,9 +100,11 @@ class ST7789(uframebuf.FrameBuffer_Uincode):
|
||||
else:
|
||||
return (red & 0xf8) << 8 | (green & 0xfc) << 3 | blue >> 3
|
||||
|
||||
def picture(self, x, y, path):
|
||||
self.display.Picture(x, y, path)
|
||||
|
||||
def show(self):
|
||||
"""Refresh the display and show the changes."""
|
||||
self.display.write_buf(self._buffer, 0, 0, self._width, self._height)
|
||||
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)
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -218,6 +218,7 @@ class Serial {
|
||||
|
||||
async close() {
|
||||
this.#isOpened_ = false;
|
||||
this.#baud_ = 0;
|
||||
}
|
||||
|
||||
async toggle() {
|
||||
|
||||
@@ -116,7 +116,8 @@ class USBMini extends Serial {
|
||||
#defaultConfiguration_ = 1;
|
||||
#endpointIn_ = null;
|
||||
#endpointOut_ = null;
|
||||
#interfaceNumber_ = 0;
|
||||
#ctrlInterfaceNumber_ = -1;
|
||||
#dataInterfaceNumber_ = -1;
|
||||
#dataLength_ = 64;
|
||||
constructor(port) {
|
||||
super(port);
|
||||
@@ -149,7 +150,7 @@ class USBMini extends Serial {
|
||||
recipient: 'interface',
|
||||
request: 0x01,
|
||||
value: 0x100,
|
||||
index: this.#interfaceNumber_
|
||||
index: this.#dataInterfaceNumber_
|
||||
}, 64);
|
||||
}
|
||||
return result?.data;
|
||||
@@ -164,7 +165,7 @@ class USBMini extends Serial {
|
||||
recipient: 'interface',
|
||||
request: 0x09,
|
||||
value: 0x200,
|
||||
index: this.#interfaceNumber_
|
||||
index: this.#dataInterfaceNumber_
|
||||
}, data);
|
||||
}
|
||||
}
|
||||
@@ -203,7 +204,7 @@ class USBMini extends Serial {
|
||||
if (!selectedInterface) {
|
||||
selectedInterface = interfaces[0];
|
||||
}
|
||||
this.#interfaceNumber_ = selectedInterface.interfaceNumber;
|
||||
this.#dataInterfaceNumber_ = selectedInterface.interfaceNumber;
|
||||
const { endpoints } = selectedInterface.alternates[0];
|
||||
for (const endpoint of endpoints) {
|
||||
if (endpoint.direction === 'in') {
|
||||
@@ -212,9 +213,15 @@ class USBMini extends Serial {
|
||||
this.#endpointOut_ = endpoint.endpointNumber;
|
||||
}
|
||||
}
|
||||
await this.#device_.claimInterface(this.#interfaceNumber_);
|
||||
await this.setBaudRate(baud);
|
||||
try {
|
||||
await this.#device_.claimInterface(0);
|
||||
this.#ctrlInterfaceNumber_ = 0;
|
||||
} catch (_) {
|
||||
this.#ctrlInterfaceNumber_ = -1;
|
||||
}
|
||||
await this.#device_.claimInterface(this.#dataInterfaceNumber_);
|
||||
super.open(baud);
|
||||
await this.setBaudRate(baud);
|
||||
this.onOpen();
|
||||
this.#addEventsListener_();
|
||||
}
|
||||
@@ -237,6 +244,30 @@ class USBMini extends Serial {
|
||||
if (!this.isOpened() || this.getRawBaudRate() === baud) {
|
||||
return;
|
||||
}
|
||||
if (this.#ctrlInterfaceNumber_ !== -1) {
|
||||
const dwDTERate = new Uint8Array([
|
||||
baud & 0xFF,
|
||||
(baud >> 8) & 0xFF,
|
||||
(baud >> 16) & 0xFF,
|
||||
(baud >> 24) & 0xFF
|
||||
]);
|
||||
const bCharFormat = 0x00;
|
||||
const bParityType = 0x00;
|
||||
const bDataBits = 0x08;
|
||||
const lineCoding = new Uint8Array([
|
||||
...dwDTERate,
|
||||
bCharFormat,
|
||||
bParityType,
|
||||
bDataBits
|
||||
]);
|
||||
await this.#device_.controlTransferOut({
|
||||
requestType: 'class',
|
||||
recipient: 'interface',
|
||||
request: 0x20,
|
||||
value: 0x0000,
|
||||
index: this.#ctrlInterfaceNumber_
|
||||
}, lineCoding);
|
||||
}
|
||||
await super.setBaudRate(baud);
|
||||
}
|
||||
|
||||
@@ -264,6 +295,15 @@ class USBMini extends Serial {
|
||||
|| (this.getDTR() === dtr && this.getRTS() === rts)) {
|
||||
return;
|
||||
}
|
||||
if (this.#ctrlInterfaceNumber_ !== -1) {
|
||||
await this.#device_.controlTransferOut({
|
||||
requestType: 'class',
|
||||
recipient: 'interface',
|
||||
request: 0x22,
|
||||
value: dtr | (rts << 1),
|
||||
index: this.#ctrlInterfaceNumber_
|
||||
});
|
||||
}
|
||||
await super.setDTRAndRTS(dtr, rts);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user