From efb2b80b25d0caecb4d2e9ad77e373b8557746fa Mon Sep 17 00:00:00 2001 From: true Date: Fri, 3 Nov 2023 09:47:33 -0700 Subject: [PATCH] Initial commit of original SC7 code --- A.py | 34 ++++ B.py | 63 +++++++ C.py | 34 ++++ D.py | 34 ++++ adc_reader.py | 146 ++++++++++++++++ aiorepl.py | 186 ++++++++++++++++++++ codec.py | 64 +++++++ colors.py | 24 +++ dds.py | 109 ++++++++++++ dma_defs.py | 171 ++++++++++++++++++ examples.py | 106 ++++++++++++ generate_wavetables.py | 70 ++++++++ joystick.py | 42 +++++ keyboardcb.py | 121 +++++++++++++ keyboardio.py | 223 ++++++++++++++++++++++++ keyleds.py | 61 +++++++ lissajous.py | 147 ++++++++++++++++ main.py | 16 ++ menu.py | 282 ++++++++++++++++++++++++++++++ menudemo.py | 79 +++++++++ minimal_example.py | 20 +++ phosphor_gradient_14.py | 10 ++ pin_defs.py | 40 +++++ pio_code.py | 124 +++++++++++++ pio_defs.py | 39 +++++ pixel_pusher.py | 249 ++++++++++++++++++++++++++ pl_earth.jpg | Bin 0 -> 31246 bytes pl_jupiter.jpg | Bin 0 -> 18617 bytes pl_mars.jpg | Bin 0 -> 24023 bytes pl_mercury.jpg | Bin 0 -> 21553 bytes pl_moon.jpg | Bin 0 -> 25072 bytes pl_neptune.jpg | Bin 0 -> 11984 bytes pl_saturn.jpg | Bin 0 -> 10831 bytes pl_uranus.jpg | Bin 0 -> 9284 bytes pl_venus.jpg | Bin 0 -> 24232 bytes random_walk.py | 24 +++ romans.py | 208 ++++++++++++++++++++++ screen.py | 74 ++++++++ screennorm.py | 125 ++++++++++++++ screentest.py | 60 +++++++ sketch.py | 169 ++++++++++++++++++ slideshow.py | 60 +++++++ splash_7.jpg | Bin 0 -> 14635 bytes splash_wrencher.jpg | Bin 0 -> 16365 bytes splash_x.jpg | Bin 0 -> 12630 bytes static_buffer_example.py | 25 +++ supercon_menu.py | 102 +++++++++++ timer.py | 277 +++++++++++++++++++++++++++++ vectoros.py | 364 +++++++++++++++++++++++++++++++++++++++ vectorscope.py | 112 ++++++++++++ vga1_16x32.py | 104 +++++++++++ vos_debug.py | 17 ++ vos_launch.py | 40 +++++ vos_state.py | 18 ++ waveform.py | 132 ++++++++++++++ 55 files changed, 4405 insertions(+) create mode 100644 A.py create mode 100644 B.py create mode 100644 C.py create mode 100644 D.py create mode 100644 adc_reader.py create mode 100644 aiorepl.py create mode 100644 codec.py create mode 100644 colors.py create mode 100644 dds.py create mode 100644 dma_defs.py create mode 100644 examples.py create mode 100644 generate_wavetables.py create mode 100644 joystick.py create mode 100644 keyboardcb.py create mode 100644 keyboardio.py create mode 100644 keyleds.py create mode 100644 lissajous.py create mode 100644 main.py create mode 100644 menu.py create mode 100644 menudemo.py create mode 100644 minimal_example.py create mode 100644 phosphor_gradient_14.py create mode 100644 pin_defs.py create mode 100644 pio_code.py create mode 100644 pio_defs.py create mode 100644 pixel_pusher.py create mode 100644 pl_earth.jpg create mode 100644 pl_jupiter.jpg create mode 100644 pl_mars.jpg create mode 100644 pl_mercury.jpg create mode 100644 pl_moon.jpg create mode 100644 pl_neptune.jpg create mode 100644 pl_saturn.jpg create mode 100644 pl_uranus.jpg create mode 100644 pl_venus.jpg create mode 100644 random_walk.py create mode 100644 romans.py create mode 100644 screen.py create mode 100644 screennorm.py create mode 100644 screentest.py create mode 100644 sketch.py create mode 100644 slideshow.py create mode 100644 splash_7.jpg create mode 100644 splash_wrencher.jpg create mode 100644 splash_x.jpg create mode 100644 static_buffer_example.py create mode 100644 supercon_menu.py create mode 100644 timer.py create mode 100644 vectoros.py create mode 100644 vectorscope.py create mode 100644 vga1_16x32.py create mode 100644 vos_debug.py create mode 100644 vos_launch.py create mode 100644 vos_state.py create mode 100644 waveform.py diff --git a/A.py b/A.py new file mode 100644 index 0000000..556f6f8 --- /dev/null +++ b/A.py @@ -0,0 +1,34 @@ + +from vectorscope import Vectorscope +import vectoros +import keyboardcb +import keyleds +import asyncio + +import random_walk + +_abort=False + +async def random_walker(v): + ## Minimal example + global _abort + r = random_walk.RW(v) + x,y = 0,0 + while _abort==False: + x,y = r.random_walk(x,y) + ## this is important -- it yields to the key scanner + await asyncio.sleep_ms(10) + +## Below here is boilerplate. +def do_abort(key): + global _abort + _abort=True + +from vos_state import vos_state + +async def slot_main(v): + global _abort + # watch the keys -- you can define your own callbacks here + mykeys = keyboardcb.KeyboardCB( {keyleds.KEY_MENU: do_abort} ) + await random_walker(v) + print("OK done") diff --git a/B.py b/B.py new file mode 100644 index 0000000..66ee7af --- /dev/null +++ b/B.py @@ -0,0 +1,63 @@ + +import math +import time + +from vectorscope import Vectorscope + +import vectoros +import keyboardcb +import keyleds +import asyncio + + +_abort=False +_xscale=1 +_yscale=1 + +async def kminimal_example(v): + ## Minimal example with keys + global _abort, _xscale, _yscale + while _abort==False: + for i in range(360): + scale=1 + if _abort: + print("Get out!") + break + v.wave.constantX(int(math.cos(i * math.pi / 180 * 5*_xscale) * 10000)) + v.wave.constantY(int(math.sin(i * math.pi / 180 * 5*_yscale)* 10000)) + await asyncio.sleep_ms(10) + + +def do_abort(key): + global _abort + _abort=True + +def do_xscale(key): + global _xscale + _xscale+=1 + if _xscale>6: + _xscale=1 + + +def do_yscale(key): + global _yscale + _yscale+=1 + if _yscale>6: + _yscale=1 + + + +from vos_state import vos_state + +async def slot_main(v): + global _abort,_continue +# So... Press D (or whatever is configured) and note the message below. Press Range to start the demo +# The demo will run until you press Menu. LEVEL/RANGE will change frequency of X and Y in steps +# Note that if you don't yield occasionaly, you don't get key scanning + + # watch the keys + mykeys=keyboardcb.KeyboardCB({ keyleds.KEY_LEVEL: do_xscale, keyleds.KEY_RANGE: do_yscale, keyleds.KEY_MENU: do_abort}) + + + await kminimal_example(v) + print("OK done") diff --git a/C.py b/C.py new file mode 100644 index 0000000..556f6f8 --- /dev/null +++ b/C.py @@ -0,0 +1,34 @@ + +from vectorscope import Vectorscope +import vectoros +import keyboardcb +import keyleds +import asyncio + +import random_walk + +_abort=False + +async def random_walker(v): + ## Minimal example + global _abort + r = random_walk.RW(v) + x,y = 0,0 + while _abort==False: + x,y = r.random_walk(x,y) + ## this is important -- it yields to the key scanner + await asyncio.sleep_ms(10) + +## Below here is boilerplate. +def do_abort(key): + global _abort + _abort=True + +from vos_state import vos_state + +async def slot_main(v): + global _abort + # watch the keys -- you can define your own callbacks here + mykeys = keyboardcb.KeyboardCB( {keyleds.KEY_MENU: do_abort} ) + await random_walker(v) + print("OK done") diff --git a/D.py b/D.py new file mode 100644 index 0000000..556f6f8 --- /dev/null +++ b/D.py @@ -0,0 +1,34 @@ + +from vectorscope import Vectorscope +import vectoros +import keyboardcb +import keyleds +import asyncio + +import random_walk + +_abort=False + +async def random_walker(v): + ## Minimal example + global _abort + r = random_walk.RW(v) + x,y = 0,0 + while _abort==False: + x,y = r.random_walk(x,y) + ## this is important -- it yields to the key scanner + await asyncio.sleep_ms(10) + +## Below here is boilerplate. +def do_abort(key): + global _abort + _abort=True + +from vos_state import vos_state + +async def slot_main(v): + global _abort + # watch the keys -- you can define your own callbacks here + mykeys = keyboardcb.KeyboardCB( {keyleds.KEY_MENU: do_abort} ) + await random_walker(v) + print("OK done") diff --git a/adc_reader.py b/adc_reader.py new file mode 100644 index 0000000..55b8b39 --- /dev/null +++ b/adc_reader.py @@ -0,0 +1,146 @@ +from uctypes import addressof +import array +import rp2 +import time +import machine +import dma_defs +import pio_defs + +# read_debug = machine.Pin(26, machine.Pin.OUT) + +num_frames = const(16) +num_samples_per_frame = const(1024) +bytes_per_sample = const(4) +audio_data_length = const(num_frames * num_samples_per_frame * bytes_per_sample) + +class ADC_Reader(): + + def __init__(self): + + self.num_samples_per_frame = num_samples_per_frame + ## Setup storage for frames of samples + self.audio_data = bytearray(audio_data_length) + ## and the individual frames start here + self.frame_starts = array.array("L", [addressof(self.audio_data) + i*num_samples_per_frame*bytes_per_sample for i in range(num_frames)]) + self.current_frame = 0 + ## finish up init + self.align_frame_lookup_address() + self.config_dmas() + + def init(self): + self.__init__() + + def deinit(self): + """unwind all of the above""" + self.audio_read_control.ctrl = 0 + time.sleep_ms(10) ## (@_@) replace with asyncio when necessary + self.audio_read_transfer.ctrl = 0 + self.audio_read_control.close() + time.sleep_ms(10) ## (@_@) replace with asyncio when necessary + self.audio_read_transfer.close() + + def pause(self): + self.audio_read_transfer.ctrl &= ~(1) ## mask enable bit + time.sleep_ms(10) + self.audio_read_control.ctrl &= ~(1) ## mask enable bit + + def resume(self): + self.audio_read_control.ctrl |= 1 ## set enable bit + time.sleep_ms(10) + self.audio_read_transfer.ctrl |= 1 ## set enable bit + self.audio_read_transfer.config(trigger=True) + + @micropython.viper + def audio_read_frame_interrupt(self, calling_dma): + """fires off once per frame, in parallel with audio_read_control""" + # read_debug.high() + self.current_frame = (int(self.current_frame)+1) & 0x0F + ## setup frames/colors and trigger pixel pusher here + ## want it to go through one cycle -- 15 frames at 15 colors. + + # read_debug.low() + + def config_dmas(self): + self.audio_read_transfer = rp2.DMA() + #print("self.audio_read_transfer") + #print(self.audio_read_transfer) + self.audio_read_control = rp2.DMA() + #print("self.audio_read_control") + #print(self.audio_read_control) + self.audio_read_transfer.ctrl = self.audio_read_transfer.pack_ctrl(default = 0, + size = dma_defs.SIZE_4BYTES, + enable = 1, + treq_sel = dma_defs.DREQ_PIO0_RX0, + inc_write = 1, + chain_to = self.audio_read_control.channel_id + ) + self.audio_read_transfer.config(count = num_samples_per_frame, + read = pio_defs.PIO0_BASE + pio_defs.RXF0_OFFSET) + self.audio_read_transfer.irq(handler = self.audio_read_frame_interrupt) + # manual trigger + # self.audio_read_transfer.config(write = audio_data, trigger=True) + + self.audio_read_control.ctrl = self.audio_read_control.pack_ctrl(default = 0, + size = dma_defs.SIZE_4BYTES, + enable = 1, + treq_sel = dma_defs.TREQ_PERMANENT, + IRQ_quiet = 1, + chain_to = self.audio_read_transfer.channel_id, + inc_read = 1, + ring_size = 6) ## 16 addresses * 4 bytes + ## feed write addresses of each frame start when done with a frame + self.audio_read_control.config(write = addressof(self.audio_read_transfer.registers[1:]), + read = self.frame_lookup_address, + count = 1, + trigger = True) + + + def align_frame_lookup_address(self): + ## Need to align this for DMA to enable ring looping over frame starts. + ## each address is 4 bytes, need 16 of them: 2+4 = 6 bits clear -- align to nearest 0b11000000 = C0 + ## with 64 bytes to be stored, need 128 to guarantee clear (2x num_frames * 4 bytes) + ## Make an aligned lookup table for DMA porpoises + self.frame_lookup = bytearray(num_frames * 4 * 2) + self.frame_lookup_address = addressof(self.frame_lookup) + + ## spool forward to nearest /64 block : frame_lookup_address is now ready to use + while self.frame_lookup_address != self.frame_lookup_address & (0xFFFFFFC0): + self.frame_lookup_address = self.frame_lookup_address + 1 + + ## copy frame starts over into lookup LSB first + ## could probably do this with struct.pack()? + tempaddress = self.frame_lookup_address + for f in self.frame_starts: + machine.mem8[tempaddress] = f & 0xFF + machine.mem8[tempaddress+1] = (f & 0xFF00) >> 8 + machine.mem8[tempaddress+2] = (f & 0xFF0000) >> 16 + machine.mem8[tempaddress+3] = (f & 0xFF000000) >> 24 + tempaddress = tempaddress + 4 + + + #################################### + ## Residual useful debugging stuff + #################################### + + def debug_print_frames(self,n): + for j in range(16): + print(f'############## {j} ################') + for i in range(n): + dma_defs.print_friendly(machine.mem32[self.frame_starts[j]+4*i]) + + def dma_frame_diagnostics(self): + current_write_addr = self.audio_read_transfer.write + current_frame_pointer = self.audio_read_control.read + current_frame = (current_frame_pointer - self.frame_lookup_address) // 4 + current_frame_start_addr = machine.mem32[current_frame_pointer] + print("Address of frame start pointer") + print(hex(current_frame_pointer)) + print("Address of frame start") + print(hex(current_frame_start_addr)) + print(f"Frame number: {current_frame}") + print("Address of current datapoint") + print(hex(current_write_addr)) + + + + diff --git a/aiorepl.py b/aiorepl.py new file mode 100644 index 0000000..e75fc8b --- /dev/null +++ b/aiorepl.py @@ -0,0 +1,186 @@ +# MIT license; Copyright (c) 2022 Jim Mussared + +import micropython +from micropython import const +import re +import sys +import time +import asyncio + +# Import statement (needs to be global, and does not return). +_RE_IMPORT = re.compile("^import ([^ ]+)( as ([^ ]+))?") +_RE_FROM_IMPORT = re.compile("^from [^ ]+ import ([^ ]+)( as ([^ ]+))?") +# Global variable assignment. +_RE_GLOBAL = re.compile("^([a-zA-Z0-9_]+) ?=[^=]") +# General assignment expression or import statement (does not return a value). +_RE_ASSIGN = re.compile("[^=]=[^=]") + +# Command hist (One reserved slot for the current command). +_HISTORY_LIMIT = const(5 + 1) + + +async def execute(code, g, s): + if not code.strip(): + return + + try: + if "await " in code: + # Execute the code snippet in an async context. + if m := _RE_IMPORT.match(code) or _RE_FROM_IMPORT.match(code): + code = "global {}\n {}".format(m.group(3) or m.group(1), code) + elif m := _RE_GLOBAL.match(code): + code = "global {}\n {}".format(m.group(1), code) + elif not _RE_ASSIGN.search(code): + code = "return {}".format(code) + + code = """ +import uasyncio as asyncio +async def __code(): + {} + +__exec_task = asyncio.create_task(__code()) +""".format( + code + ) + + async def kbd_intr_task(exec_task, s): + while True: + if ord(await s.read(1)) == 0x03: + exec_task.cancel() + return + + l = {"__exec_task": None} + exec(code, g, l) + exec_task = l["__exec_task"] + + # Concurrently wait for either Ctrl-C from the stream or task + # completion. + intr_task = asyncio.create_task(kbd_intr_task(exec_task, s)) + + try: + try: + return await exec_task + except asyncio.CancelledError: + pass + finally: + intr_task.cancel() + try: + await intr_task + except asyncio.CancelledError: + pass + else: + # Excute code snippet directly. + try: + try: + micropython.kbd_intr(3) + try: + return eval(code, g) + except SyntaxError: + # Maybe an assignment, try with exec. + return exec(code, g) + except KeyboardInterrupt: + pass + finally: + micropython.kbd_intr(-1) + + except Exception as err: + print("{}: {}".format(type(err).__name__, err)) + + +# REPL task. Invoke this with an optional mutable globals dict. +async def task(g=None, prompt="--> "): + print("Starting asyncio REPL...") + if g is None: + g = __import__("__main__").__dict__ + try: + micropython.kbd_intr(-1) + s = asyncio.StreamReader(sys.stdin) + # clear = True + hist = [None] * _HISTORY_LIMIT + hist_i = 0 # Index of most recent entry. + hist_n = 0 # Number of history entries. + c = 0 # ord of most recent character. + t = 0 # timestamp of most recent character. + while True: + hist_b = 0 # How far back in the history are we currently. + sys.stdout.write(prompt) + cmd = "" + while True: + b = await s.read(1) + pc = c # save previous character + c = ord(b) + pt = t # save previous time + t = time.ticks_ms() + if c < 0x20 or c > 0x7E: + if c == 0x0A: + # LF + # If the previous character was also LF, and was less + # than 20 ms ago, this was likely due to CRLF->LFLF + # conversion, so ignore this linefeed. + if pc == 0x0A and time.ticks_diff(t, pt) < 20: + continue + sys.stdout.write("\n") + if cmd: + # Push current command. + hist[hist_i] = cmd + # Increase history length if possible, and rotate ring forward. + hist_n = min(_HISTORY_LIMIT - 1, hist_n + 1) + hist_i = (hist_i + 1) % _HISTORY_LIMIT + + result = await execute(cmd, g, s) + if result is not None: + sys.stdout.write(repr(result)) + sys.stdout.write("\n") + break + elif c == 0x08 or c == 0x7F: + # Backspace. + if cmd: + cmd = cmd[:-1] + sys.stdout.write("\x08 \x08") + elif c == 0x02: + # Ctrl-B + continue + elif c == 0x03: + # Ctrl-C + if pc == 0x03 and time.ticks_diff(t, pt) < 120: #was 20 + # Two very quick Ctrl-C (faster than a human + # typing) likely means mpremote trying to + # escape. + asyncio.new_event_loop() + return + sys.stdout.write("\n") + break + elif c == 0x04: + # Ctrl-D + sys.stdout.write("\n") + # Shutdown asyncio. + asyncio.new_event_loop() + return + elif c == 0x1B: + # Start of escape sequence. + key = await s.read(2) + if key in ("[A", "[B"): + # Stash the current command. + hist[(hist_i - hist_b) % _HISTORY_LIMIT] = cmd + # Clear current command. + b = "\x08" * len(cmd) + sys.stdout.write(b) + sys.stdout.write(" " * len(cmd)) + sys.stdout.write(b) + # Go backwards or forwards in the history. + if key == "[A": + hist_b = min(hist_n, hist_b + 1) + else: + hist_b = max(0, hist_b - 1) + # Update current command. + cmd = hist[(hist_i - hist_b) % _HISTORY_LIMIT] + sys.stdout.write(cmd) + else: + # sys.stdout.write("\\x") + # sys.stdout.write(hex(c)) + pass + else: + sys.stdout.write(b) + cmd += b + finally: + micropython.kbd_intr(3) diff --git a/codec.py b/codec.py new file mode 100644 index 0000000..884a72e --- /dev/null +++ b/codec.py @@ -0,0 +1,64 @@ +from machine import Pin, SPI, PWM, I2C, I2S, PWM, freq +import time +import rp2 +import machine +import pin_defs +import pio_defs +import pio_code + +## I2C bus address +ak4619_addr = const(0x10) +READ_FIFO = pio_defs.PIO0_BASE + pio_defs.RXF0_OFFSET ## 0, 0 +WRITE_FIFO = pio_defs.PIO0_BASE + pio_defs.TXF1_OFFSET ## 0, 1 + +class Codec(): + def __init__(self): + # RPi I2S doesn't have master clock -- we make one with PWM + # 125000000 / 16 = 7.8125 MHz master clock + # 250_000_000 / 16 = 7.8125 MHz master clock + self.MASTER_CLOCK_HZ = freq() // 32 + # fs sample clock = MCLK / 256 = 30517.578 Hz + self.mclk = Pin(pin_defs.mclk, Pin.OUT) + self.mclk_pwm = PWM(self.mclk, freq=self.MASTER_CLOCK_HZ, duty_u16=32768) + + self.bit_clock = Pin(pin_defs.bit_clock, Pin.OUT, value=0) ## fs / 32 + self.lr_clock = Pin(pin_defs.lr_clock, Pin.OUT, value=0) ## fs + self.sd_in = Pin(pin_defs.sd_in, Pin.IN) ## In 3/4 (Y=L, X=R) + self.sd_out = Pin(pin_defs.sd_out, Pin.OUT, value=0) ## Out 1/2 (Y=L, X=R) + self.pdn = Pin(pin_defs.pdn, Pin.OUT, value=0) ## Power down on low + + self.i2s_read_sm = rp2.StateMachine(0, pio_code.i2s_read_pio, freq=self.MASTER_CLOCK_HZ // 2, sideset_base=self.bit_clock, in_base=self.sd_in) + self.i2s_write_sm = rp2.StateMachine(1, pio_code.i2s_write_pio, freq=self.MASTER_CLOCK_HZ // 2, out_base=self.sd_out) + self.start() + + def deinit(self): + self.i2s_read_sm.active(0) + self.i2s_write_sm.active(0) + self.mclk_pwm.deinit() + self.pdn.value(0) + + ## Manually resync the PIO state machines so they run in cycle + def start(self): + self.mclk_pwm = PWM(self.mclk, freq=self.MASTER_CLOCK_HZ, duty_u16=32768) + machine.mem32[pio_defs.PIO0_BASE] = (0b1111 << pio_defs.CLKDIV_RESTART_BIT) ## reset all clock dividers + machine.mem32[pio_defs.PIO0_BASE] = (0b1111 << pio_defs.SM_ENABLE_BIT) ## enable all simultaneously to sync up + self.config_i2c() + + def config_i2c(self): + self.i2c = I2C(0, scl=Pin(pin_defs.i2c_scl), sda=Pin(pin_defs.i2c_sda), freq=400_000) + ## Initialize AK4619 registers + ## PDN starts 0, when goes high, enters config mode after 10 ms -- datasheet + self.pdn.value(1) + time.sleep_ms(10) + ## Config for 16-bit samples & 16-bit slots + self.i2c.writeto(ak4619_addr, bytes([0x01, 0x3A])) # MSB Justified, 16 bit slot and read data on falling bit-clock + self.i2c.writeto(ak4619_addr, bytes([0x02, 0x0A])) # 16 bit data on in and out + ## Config single-ended input on 3 & 4 + self.i2c.writeto(ak4619_addr, bytes([0x0B, 0x05])) + ## slow ADC filters -- need to look into this later? + self.i2c.writeto(ak4619_addr, bytes([0x0A, 0x22])) + self.i2c.writeto(ak4619_addr, bytes([0x0D, 0x06])) + self.i2c.writeto(ak4619_addr, bytes([0x00, 0x37])) ## Power on, release reset bit + + + diff --git a/colors.py b/colors.py new file mode 100644 index 0000000..a226fd3 --- /dev/null +++ b/colors.py @@ -0,0 +1,24 @@ +from gc9a01 import color565 +import gc9a01 as lcd +import phosphor_gradient_14 + +PHOSPHOR = phosphor_gradient_14.phosphor_gradient + +PHOSPHOR_BRIGHT=PHOSPHOR[15] +PHOSPHOR_DARK=PHOSPHOR[12] +PHOSPHOR_BG=PHOSPHOR[0] + +BLACK=lcd.BLACK +WHITE=lcd.WHITE +RED=lcd.RED +GREEN=lcd.GREEN +BLUE=lcd.BLUE +CYAN=lcd.CYAN +MAGENTA=lcd.MAGENTA +YELLOW=lcd.YELLOW + +GRAY=color565(0x80,0x80,0x80) + +def rgb(r,g,b): + return color565(r,g,b) + diff --git a/dds.py b/dds.py new file mode 100644 index 0000000..acb4cfb --- /dev/null +++ b/dds.py @@ -0,0 +1,109 @@ +import array +import generate_wavetables + +NUM_SAMPLES = const(256) +ACCUMULATOR_BITS = const(16) + +X_CHANNEL = const(0) +Y_CHANNEL = const(1) + +WAVEFORM_SINE = const(0) +WAVEFORM_SQUARE = const(1) +WAVEFORM_SAWTOOTH = const(2) +WAVEFORM_TRIANGLE = const(3) + + +class DDS(): + + def __init__(self, vectorscope): + """ pass it an instance of the Vectorscope module from main, it needs to write to the DMA audio registers""" + self.wave = vectorscope.wave + + self.waveform = ["sine", "sine"] + self.increment = [51000, 25000] + self.amplitude = [1, 1] ## set this infrequently? -- it's an expensive calculation + self.phase = [0, 0] + self.phase_increment = [0, 0] + self.index = [0, 0] + self.accumulator = [0, 0] + self.samplesX = [0]*NUM_SAMPLES + self.samplesY = [0]*NUM_SAMPLES + self.samples = [self.samplesX, self.samplesY] + + self.base_waveforms = {} + self.base_waveforms["sine"] = generate_wavetables.sine() + self.base_waveforms["square"] = generate_wavetables.square() + self.base_waveforms["sawtooth"] = generate_wavetables.sawtooth() + self.base_waveforms["triangle"] = generate_wavetables.triangle() + + ## init + self.waves = [[0]*256, [0]*256] + self.recalculate_waveforms() ## have to do this every time you change parameters. + + def recalculate_waveforms(self): ## select 0=X, 1=Y + for i in [0,1]: + self.waves[i] = [int(self.amplitude[i]*x) for x in self.base_waveforms[self.waveform[i]]] + + def initial_wait_for_buffer_sync(self): + self.wave.outBuffer_ready = False ## mark seen + while not self.wave.outBuffer_ready: + pass ## (@_@) should be async wait + + @micropython.viper + def do_dds(self): + for i in [0,1]: ## X , Y + self.phase[i] = int(self.phase[i]) + int(self.phase_increment[i]) + for s in range(NUM_SAMPLES): + self.index[i] = int(self.phase[i]) + (int(self.accumulator[i]) >> ACCUMULATOR_BITS) & 0xFF ## roll over sample bits + self.accumulator[i] = (int(self.accumulator[i]) + int(self.increment[i])) & 0xFFFFFF ## sample bits + accumulator bits + self.samples[i][s] = self.waves[i][self.index[i]] + + def populate_buffer(self): + while not self.wave.outBuffer_ready: + pass ## (@_@) should be async wait + self.wave.packX(self.samplesX) + self.wave.packY(self.samplesY) + self.wave.outBuffer_ready = False + + +if __name__ == "__main__": + import vectorscope + import machine + userbutton = machine.Pin(19, machine.Pin.IN) + + v = vectorscope.Vectorscope() + d = DDS(v) + d.amplitude=[0.5, 0.5] + d.recalculate_waveforms() + ## but you can also write them yourself directly: 16-bit signed, 256 values + d.waves[0] = [0]*256 + ## but it gets overwritten if you recalculate_waveforms() + d.recalculate_waveforms() + + + def go(n=200): + for i in range(n): + d.do_dds() + d.populate_buffer() + d.waves[0] = d.base_waveforms["square"] + d.recalculate_waveforms() + + + for i in range(n): + d.do_dds() + d.populate_buffer() + + go() + + + + + + + + + + + + + diff --git a/dma_defs.py b/dma_defs.py new file mode 100644 index 0000000..7ef9b6e --- /dev/null +++ b/dma_defs.py @@ -0,0 +1,171 @@ +import machine +from uctypes import BF_POS, BF_LEN, UINT32, BFUINT32, struct, addressof + +## configure DMA +BASE = const(0x50000000) +CHAN_WIDTH = const(0x40) +CHAN_COUNT = const(12) + +def dma_num_tempy(x): + return BASE + CHAN_WIDTH * x +## ex: dma_num(7) + +def hexmem(x): + return hex(machine.mem32[x]) + +def hexaddr(x): + return hex(addressof(x)) + +def print_friendly(u32): + a = (u32 & 0xFF000000) >> 24 + b = (u32 & 0x00FF0000) >> 16 + c = (u32 & 0x0000FF00) >> 8 + d = (u32 & 0x000000FF) + print(f'{a:#010b} {b:#010b} {c:#010b} {d:#010b}') + +def dma_scan(): + used = [] + for i in range(12): + ctrl_reg_contents = machine.mem32[dma_num_tempy(i)+0x10] + if ctrl_reg_contents != 0: + used.append(i) + print(f"{i:02}: {ctrl_reg_contents:#034b}") + print(f"Used DMAs: {used}") + +def dma_debug(dma): + base=addressof(dma.registers) + print(f"READ: {dma.registers[0]:x} WRITE: {dma.registers[1]:x} COUNT next: {machine.mem32[base+0x804]} current: {machine.mem32[base+0x08]}") + print(dma.unpack_ctrl(dma.ctrl)) + print("\n") + + +## Control fields, packed into a nice structure +## cribbed from rp2040_pio_dma.py +## Thanks to https://github.com/benevpi/MicroPython_PIO_Music_DMA/blob/main/rp2040_pio_dma.py +DMA_CTRL_FIELDS = { + "AHB_ERROR": 31<0: + self.cursor=self.cursor-1 + else: + if self.dispmenu>0: + self.dispmenu=self.dispmenu-1 + await self.menu_update() + + if key==keyleds.JOY_DN: + if self.cursor=0: + await asyncio.sleep(0) + + if self.clear_after: + screen.clear() + + if (self._extjoy): + self.joy.detach() + + + + + diff --git a/menudemo.py b/menudemo.py new file mode 100644 index 0000000..2605b26 --- /dev/null +++ b/menudemo.py @@ -0,0 +1,79 @@ +import joystick +from menu import * # bad habit but makes our menu definition nice +from vos_state import vos_state +import blinker +import vectoros +import colors +import gc + +# run the sketch demo +def runsketch(arg): + vos_state.show_menu=False # get the menu of the way + vectoros.launch_task('sketch') + return EXIT + +def gfxdemo(arg): + vos_state.show_menu=False # get the menu of the way + vectoros.launch_task('screen') # launch + return EXIT + +def testdemo(arg): + import tester2 + vectoros.vectoros_shutdown() + tester2.main() # this never returns but it does reboot + + +# the main vector scope demo +def run_demo(arg): + vos_state.show_menu=False + vectoros.launch_task('demo') + # we never come back + return EXIT + +def reboot(arg): + if arg==False: + vectoros.reset() + else: + vectoros.soft_reset() + +# handle slots +def abcd(key): + if vos_state.show_menu: + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,f"Menu key {key}") + kdict={ keyleds.KEY_A: 'A', keyleds.KEY_B: 'B', keyleds.KEY_C: 'C', keyleds.KEY_D: 'D'} + await vectoros.launch_vecslot("slot"+kdict[key]) + + +# I really didn't want this to be async but it seems like do_menu must have an await +# and run rarely returns when you have a lot going on +async def vos_main(): +# you do NOT have to use with here +# but if you don't you have to worry about the menu controller's joystick instance going out of scope yourself +# or just make everything global -- the menu is smart enough to not listen to events when it is not active +# note: m_back and m_exit were imported from menu + while True: # since this is the main menu, we don't really every quit + print("creating slotkey") + slotkey=keyboardcb.KeyboardCB(abcd,keyleds.KEY_ABCD) + with Menu(clear_after=True,fg_color=colors.PHOSPHOR_DARK,bg_color=colors.PHOSPHOR_BG, + cursor_bg=colors.PHOSPHOR_BG, cursor_fg=colors.PHOSPHOR_BRIGHT) as amenu: + # submenu=[["Test", testdemo, 0],["Previous",m_back,None],["Abort",m_exit,None],["Reset CPU",reboot,False]] + mainmenu=[["Demo",run_demo,None],["Sketch", runsketch, 0],["GFX",gfxdemo,0 ] ] + # ["Test Menu",SUBMENU,submenu]] +# comment next line for default font + amenu.set_font("*") # set default vector font + #amenu.set_callback(menu_custom) + await amenu.do_menu(mainmenu) +# screen.text(40,80,"menu done") + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,f"Menu waiting {vos_state.show_menu}") + while vos_state.show_menu==False: # wait until we have to be seen again + await asyncio.sleep_ms(0) + + +def main(): + asyncio.run(vos_main()) + # this never runs + +if __name__=="__main__": + import vectoros + vectoros.run() + diff --git a/minimal_example.py b/minimal_example.py new file mode 100644 index 0000000..19b0c0a --- /dev/null +++ b/minimal_example.py @@ -0,0 +1,20 @@ + +import math +import time + +from vectorscope import Vectorscope +from random_walk import RW + + + +def minimal_example(v): + ## Minimal example + for i in range(200): + v.wave.constantX(int(math.cos(i * math.pi / 180 * 5) * 10000)) + v.wave.constantY(int(math.sin(i * math.pi / 180 * 5)* 10000)) + time.sleep_ms(10) + +async def slot_main(v): + minimal_example(v) + + \ No newline at end of file diff --git a/phosphor_gradient_14.py b/phosphor_gradient_14.py new file mode 100644 index 0000000..b5b95a3 --- /dev/null +++ b/phosphor_gradient_14.py @@ -0,0 +1,10 @@ +import gc9a01 +import struct +## https://colordesigner.io/gradient-generator + +_gradient_rgb = [ (10, 15, 10),(10, 15, 10), (15, 22, 15), (19, 31, 20), (24, 47, 26), (28, 64, 32), (31, 82, 39), + (34, 100, 45), (37, 118, 51), (38, 138, 57), (40, 157, 63), (41, 177, 68), + (41, 198, 74), (41, 219, 80), (41, 240, 85), (150, 255, 200) ] + +phosphor_gradient = [gc9a01.color565(r,g,b) for r,g,b in _gradient_rgb] + diff --git a/pin_defs.py b/pin_defs.py new file mode 100644 index 0000000..7c92ad1 --- /dev/null +++ b/pin_defs.py @@ -0,0 +1,40 @@ +## Hardware GPIO # pin defines + +## Screen pins +sck = const(2) +data = const(3) +reset = const(4) +dc = const(5) + +## there are a number of libs that require pins that we don't provide +## pass them the on-board LED. It's unlikely to hurt. +throwaway = const(25) +debug = const(27) + +user_button = const(19) +audio_shutdown = const(22) + +## Codec pins +## clocks +mclk = const(7) +bit_clock = const(8) +lr_clock = const(9) +## data +sd_in = const(13) ## In 3/4 (Y=L, X=R) +sd_out = const(10) ## Out 1/2 (Y=L, X=R) +## config +pdn = const(6) +i2c_scl = const(21) +i2c_sda = const(20) + + + + +## some globally useful pin inits +# debug_pin = machine.Pin(debug, machine.Pin.OUT, value=0) +# audio_shutdown_pin = machine.Pin(audio_shutdown, machine.Pin.OUT, value=1) +# user_button = machine.Pin(user_button, machine.Pin.IN) + + +#sd_in=Pin(13, Pin.IN) ## In 3/4 (Y=L, X=R) +#sd_out=Pin(10, Pin.OUT, value=0) ## Out 1/2 (Y=L, X=R) diff --git a/pio_code.py b/pio_code.py new file mode 100644 index 0000000..c70d927 --- /dev/null +++ b/pio_code.py @@ -0,0 +1,124 @@ +import rp2 + +###################################################### +## Define I2S PIO machines +## 16-bit slots, data +## read on falling edge of bit clock +###################################################### + +@rp2.asm_pio(sideset_init=[rp2.PIO.OUT_LOW]*2, fifo_join=rp2.PIO.JOIN_RX) +## bitclock and LR clock on the sidesets, respectively +def i2s_read_pio(): + nop()[3] ## delay to sync up with write PIO -- empirically determined + wrap_target() + + set(y,14) .side(0b00)[1] ## send 32 bits per LR read + label("L") + in_(pins, 1) .side(0b01)[1] ## Left, bits + jmp(y_dec, "L") .side(0b00)[1] + in_(pins, 1) .side(0b11)[1] + + set(y,14) .side(0b10)[1] + label("R") + in_(pins,1) .side(0b11)[1] ## right, bits + jmp(y_dec, "R") .side(0b10)[1] + in_(pins,1) .side(0b01) + + push(noblock) ## noblock keeps PIOs in sync + wrap() + +## 10 + +@rp2.asm_pio(out_init=rp2.PIO.OUT_LOW, fifo_join=rp2.PIO.JOIN_TX) +## runs lockstep with read pio, spits out data when it's got it, zeros otherwise +def i2s_write_pio(): + wrap_target() + + pull(noblock) ## noblock keeps PIOs in sync + set(y,14) ## send 16 bits per LR clock + label("L") + out(pins,1) [1] ## Left, bits + jmp(y_dec, "L") [1] + out(pins,1) [1] + + set(y,14) [1] + label("R") + out(pins,1) [1] + jmp(y_dec, "R") [1] + out(pins,1) [1] + wrap() + +## 19 + +@rp2.asm_pio(in_shiftdir=1, out_shiftdir=1) +def bit_flipper_pio(): + ## takes in two 16-bit as signed/unsigned integers + ## converts them by flipping MSBit of each 16-bitter + ## tailored for reading X/Y channel from DAC and fitting + ## the result on the (unsigned 8bit) screen + pull() + set(y,1) + label("twice") + + in_(osr, 15) ## copy 15 LSB unchanged to output + out(null, 15) ## discard 15 bits from OSR to keep pace + + mov(osr, invert(osr)) ## inverted what's left + in_(osr, 1) ## copy out one inverted bit + out(null, 1) ## drop that bit from OSR + mov(osr, invert(osr)) ## reinvert for the next word + + jmp(y_dec, "twice") + push() + +## 29 + + + +######################################################## +## Pixel Pusher: Handle Screen Command +## Takes commands and data +## sends it to the screen pretty fast +## Format: +# 0 2A 0 X +# 0 2B 0 Y +# 0 2C C1 C2 +## Screen expects 2A 0 X 0 X 2B 0 Y 0 Y 2C C1 C2 +## with the commands framed by the DC line going low +## This PIO ignores the first byte, +## transmits the second, framed by DC, +## then doubles the second pair +## This means it actually transmits C1 C2 C1 C2, but +## the screen doesn't seem to care (hack, hack!) +######################################################## + +@rp2.asm_pio(out_init=rp2.PIO.OUT_LOW, set_init=rp2.PIO.OUT_HIGH, + sideset_init=rp2.PIO.OUT_LOW, autopull=True, autopush=True) +def handle_screen_command(): + pull(block).side(0) + out(null, 8).side(0) ## drop initial zeros + + set(pins, 0).side(0) ## DC set low, CMD mode + + set(y,7).side(0) ## send 8 command bits + label("send_cmd") + out(pins, 1).side(0) + jmp(y_dec, "send_cmd").side(1) + + set(pins, 1).side(0) ## DC set high, data mode + + mov(x, osr).side(0) ## copy next bytes over, b/c going to send them twice + mov(osr, x).side(0) ## copy next bytes over, b/c going to send them twice + set(y,15).side(0) ## send 0, X + label("one_time") + out(pins, 1).side(0) + jmp(y_dec, "one_time").side(1) + + mov(osr,x).side(0) ## copy bytes back + + set(y,15).side(0) ## re-send 0, X + label("one_more_time") + out(pins, 1).side(0) + jmp(y_dec, "one_more_time").side(1) + +# 16 diff --git a/pio_defs.py b/pio_defs.py new file mode 100644 index 0000000..0dbf290 --- /dev/null +++ b/pio_defs.py @@ -0,0 +1,39 @@ + + +PIO0_BASE = const(0x50200000) +PIO1_BASE = const(0x50300000) + +CLKDIV_RESTART_BIT = const(8) +SM_ENABLE_BIT = const(0) + +FSTAT_OFFSET = const(0x004) +FDEBUG_OFFSET = const(0x008) + +TXF0_OFFSET = const(0x010) +TXF1_OFFSET = const(0x014) +TXF2_OFFSET = const(0x018) +TXF3_OFFSET = const(0x01C) + +RXF0_OFFSET = const(0x020) +RXF1_OFFSET = const(0x024) +RXF2_OFFSET = const(0x028) +RXF3_OFFSET = const(0x02C) + +## Direct write-only access to instruction memory. +INSTR_MEM0 = const(0x048) +INSTR_MEM1 = const(0x04C) +# etc. +INSTR_MEM31 = const(0x0C4) + +SM0_CLKDIV = const(0x0C8) +SM1_CLKDIV = const(0x0E0) +SM2_CLKDIV = const(0x0F8) +SM3_CLKDIV = const(0x110) +## Frequency = clock freq / (CLKDIV_INT + CLKDIV_FRAC / 256) + + + + + + + diff --git a/pixel_pusher.py b/pixel_pusher.py new file mode 100644 index 0000000..658bfe8 --- /dev/null +++ b/pixel_pusher.py @@ -0,0 +1,249 @@ +## pixel pusher! +import rp2 +import array +import machine +import pin_defs +import dma_defs +import pio_code +import pio_defs +import micropython +from phosphor_gradient_14 import phosphor_gradient +from uctypes import addressof + +## allows interrupts to throw errors +import micropython +micropython.alloc_emergency_exception_buf(100) + +NOP = const(41) # 0x29 -- display on +SET_X = const(42) # 0x2A -- column select +SET_Y = const(43) # 0x2B -- row select +SET_COLOR = const(44) # 0x2C -- send data +X_MSB_OFFSET = const(1) # data from ADC comes 16 bits X | 16 bits Y, LSB order +Y_MSB_OFFSET = const(3) + +COLOR_MASK = const(0x0F) ## 16 colors max +FRAME_MASK = const(0x0F) ## 16 colors max + +_LOOPING = const(False) +_IRQ = const(False) +# pixel_debug = machine.Pin(27, machine.Pin.OUT) + +class Pixel_Pusher(): + + @micropython.viper + def boop(self, color:int, frame:int): + """Trigger me once per adc_reader frame update""" + # pixel_debug.high() + ## set frame, color + machine.mem16[self.color_storage_address] = self.phosphors[color & COLOR_MASK] + self.stage_sample_data.registers[0] = self.frame_starts[frame & FRAME_MASK] + ## reset counter lookup + self.pixel_frame_counter.registers[0] = self.frame_counter_lookup_address + ## and go! + self.stage_sample_data.registers[7] = 1 ## transaction count trigger register + # pixel_debug.low() + + @micropython.viper + def pixel_frame_interrupt_handler(self, dma_caller): + ## even this is too much -- my guess is that the IRQs stack up during a GC or other system stupid thing + self.frame_done = True + + def resume(self): + for d in self.allDMAs: + d.ctrl = d.ctrl | 1 + self.stage_sample_data.config(trigger=True) + def pause(self): + for d in self.allDMAs: + d.ctrl = d.ctrl & ~1 ## clear enable bit + def deinit(self): + # print(self.allDMAs) + self.pixel_pusher_sm.active(0) + self.pause() + for d in self.allDMAs: + d.close() + + def __init__(self, adc_reader): + ## Consider deinitializing screen here? Or should that just always happen in code: risky! (@_@) + ## Needs adc_reader b/c it needs to know where the samples are stored + self.frame_starts = adc_reader.frame_starts + self.adc_frame = adc_reader.current_frame + self.phosphors = phosphor_gradient + self.num_samples_per_frame = adc_reader.num_samples_per_frame + self.frame_done = False + self._init_PIO() + + ## Data storage for DMA trickery + ## These three 32-bit numbers are formatted up to pass to the pixel_pusher_pio + ## It takes care of setting the command bit when relevant, and repeating the data + ## 120s are just placeholders for the X/Y coordinates + self.pixel_command_array = array.array("B", + [0, SET_X, 0, 120, + 0, SET_Y, 0, 120, + 0, SET_COLOR, 0xFF,0xFF, + 0, NOP, 0, 0]) + self.pixel_command_addr = array.array("L", [addressof(self.pixel_command_array)]) ## one element, for resetter + + self.command_x = addressof(self.pixel_command_array) + 3 ## byte position in array + self.command_y = addressof(self.pixel_command_array) + 7 + self.command_color = addressof(self.pixel_command_array) + 10 + + ## Storage for one sample from ADC + self.one_sample_storage = bytearray(4) + self.one_sample_storage_address = addressof(self.one_sample_storage) + + ## Storage for the color + self.color_storage = bytearray(2) + ## One way to set it + machine.mem16[addressof(self.color_storage)] = self.phosphors[15] + self.color_storage_address = addressof(self.color_storage) + + ## Strange array for counting purposes + ## returns a count for stage_sample_data, num_samples_per_frame-1 times + ## and then a 0, which will trigger and IRQ @ end of frame + ## and then you can reset + self.frame_counter_lookup = array.array("L", [1]*(self.num_samples_per_frame-1)) + self.frame_counter_lookup.append(0) + self.frame_counter_lookup_address = addressof(self.frame_counter_lookup) + + ## And here's the world's most convoluted DMA / PIO chain! + self.stage_sample_data = rp2.DMA() ## pulls one sample pair from memory into bit_flipper_pio + self.store_flipped_data = rp2.DMA() ## pulls bit-flipped pair and writes to sample storage + self.pixel_load_x = rp2.DMA() ## extracts X from sample storage, puts it in pixel command array + self.pixel_load_y = rp2.DMA() ## extracts Y ... + self.pixel_load_color = rp2.DMA() ## extracts color ... + self.pixel_command_to_screen = rp2.DMA() ## writes pixel command array to screen + self.pixel_command_resetter = rp2.DMA() ## resets command_to_screen after three commands + self.pixel_frame_counter = rp2.DMA() ## refreshes pixel command array address, stalls stage_sample_data at end of every frame + ## by sending a zero read address. Restart by configuring these two. + self.allDMAs = [self.stage_sample_data, self.store_flipped_data, self.pixel_load_x , self.pixel_load_y , self.pixel_load_color, self.pixel_command_to_screen, + self.pixel_command_resetter , self.pixel_frame_counter ] + + self.pixel_frame_counter_read_address = int(addressof(self.pixel_frame_counter.registers[0:])) + + ## Control defs: + ## {'inc_read': 0, 'high_pri': 0, 'ring_sel': 0, 'size': 0, + ## 'enable': 0, 'treq_sel': 0, 'sniff_en': 0, 'chain_to': 0, + ## 'inc_write': 0, 'ring_size': 0, 'bswap': 0, 'IRQ_quiet': 0} + self.stage_sample_data.ctrl = self.stage_sample_data.pack_ctrl(default = 0, + size = dma_defs.SIZE_4BYTES, + enable = 1, + treq_sel = dma_defs.DREQ_PIO0_TX2, ## pace to TX FIFO + chain_to = self.store_flipped_data.channel_id, + IRQ_quiet = 1, + inc_read = 1 + ) + self.stage_sample_data.config(count = 1, + read = self.frame_starts[0], ## initial value, set this to start of frame to begin chain + write = pio_defs.PIO0_BASE + pio_defs.TXF2_OFFSET +) + if _IRQ: + self.stage_sample_data.irq(handler=self.pixel_frame_interrupt_handler, hard=True) + ## when one-shot, don't need to interrupt itself. + + + ## The bit-flipper PIO is in the middle here. + ## It's PIO 0, 2 + + self.store_flipped_data.ctrl = self.store_flipped_data.pack_ctrl(default = 0, + size = dma_defs.SIZE_4BYTES, + enable = 1, + treq_sel = dma_defs.DREQ_PIO0_RX2, ## on PIO + chain_to = self.pixel_load_x.channel_id, + IRQ_quiet = 1 + ) + self.store_flipped_data.config(count = 1, + read = pio_defs.PIO0_BASE + pio_defs.RXF2_OFFSET, + write = self.one_sample_storage_address) +###### + + self.pixel_load_x.ctrl = self.pixel_load_x.pack_ctrl(default = 0, + size = dma_defs.SIZE_1BYTE, + enable = 1, + treq_sel = dma_defs.TREQ_PERMANENT, + chain_to = self.pixel_load_y.channel_id, + IRQ_quiet = 1 + ) + self.pixel_load_x.config(count = 1, + read = self.one_sample_storage_address + X_MSB_OFFSET, + write = self.command_x) + + self.pixel_load_y.ctrl = self.pixel_load_y.pack_ctrl(default = 0, + size = dma_defs.SIZE_1BYTE, + enable = 1, + treq_sel = dma_defs.TREQ_PERMANENT, + chain_to = self.pixel_load_color.channel_id, + IRQ_quiet = 1 + ) + self.pixel_load_y.config(count = 1, + read = self.one_sample_storage_address + Y_MSB_OFFSET, + write = self.command_y) + + self.pixel_load_color.ctrl = self.pixel_load_color.pack_ctrl(default = 0, + bswap = 1, + size = dma_defs.SIZE_2BYTES, + enable = 1, + treq_sel = dma_defs.TREQ_PERMANENT, + chain_to = self.pixel_command_to_screen.channel_id, + IRQ_quiet = 1 + ) + self.pixel_load_color.config(count = 1, + read = self.color_storage_address, + write = self.command_color) + + self.pixel_command_to_screen.ctrl = self.pixel_command_to_screen.pack_ctrl(default = 0, + bswap = 1, + inc_read = 1, + size = dma_defs.SIZE_4BYTES, + enable = 1, + treq_sel = dma_defs.DREQ_PIO1_TX0, + chain_to = self.pixel_command_resetter.channel_id, + IRQ_quiet = 1, + ring_sel = 0, # ring on read + ring_size = 4 # 2**4 = 16 bytes = 4 transfers + ) + self.pixel_command_to_screen.config(count = 3, + read = addressof(self.pixel_command_array), + write = pio_defs.PIO1_BASE + pio_defs.TXF0_OFFSET) ## PIO sm(4) + + + self.pixel_command_resetter.ctrl = self.pixel_command_resetter.pack_ctrl(default = 0, + size = dma_defs.SIZE_4BYTES, + enable = 1, + treq_sel = dma_defs.TREQ_PERMANENT, + IRQ_quiet = 1, + chain_to = self.pixel_frame_counter.channel_id + ) + self.pixel_command_resetter.config(count = 1, + write = addressof(self.pixel_command_to_screen.registers[0:]), ## set read address back to top + read = addressof(self.pixel_command_addr)) + + self.pixel_frame_counter.ctrl = self.pixel_frame_counter.pack_ctrl(default = 0, + inc_read = 1, + size = dma_defs.SIZE_4BYTES, + enable = 1, + treq_sel = dma_defs.TREQ_PERMANENT, + IRQ_quiet = 1, + chain_to = self.pixel_frame_counter.channel_id + ## ends the chain. reset the frame_counter_lookup to restart. + ) + self.pixel_frame_counter.config(count = 1, + write = addressof(self.stage_sample_data.registers[7:]), ## count trigger register + read = addressof(self.frame_counter_lookup)) + + + def _init_PIO(self): + ## same pins shared with + self.sck_pin = machine.Pin(pin_defs.sck, machine.Pin.OUT) + self.data_pin = machine.Pin(pin_defs.data, machine.Pin.OUT) + self.dc_pin = machine.Pin(pin_defs.dc, machine.Pin.OUT) + + ## PIO 1, 0 + self.pixel_pusher_sm = rp2.StateMachine(4, pio_code.handle_screen_command, freq=250_000_000, + out_base=self.data_pin, set_base=self.dc_pin, sideset_base=self.sck_pin) + self.pixel_pusher_sm.active(1) + + ## PIO 0, 2 + self.bit_flipper_sm = rp2.StateMachine(2, pio_code.bit_flipper_pio, freq=250_000_000) + self.bit_flipper_sm.restart() ## flush buffers? belt and suspenders. + self.bit_flipper_sm.active(1) + diff --git a/pl_earth.jpg b/pl_earth.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7e23ab5bcb040e5416fd2ad579601bd12d0e2470 GIT binary patch literal 31246 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�+G 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 literal 0 HcmV?d00001 diff --git a/pl_jupiter.jpg b/pl_jupiter.jpg new file mode 100644 index 0000000000000000000000000000000000000000..0f4ac7f6652cf87351e0c5d9e935eca84d13343f GIT binary patch literal 18617 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 IB>;c_*{Wq$8~^|S literal 0 HcmV?d00001 diff --git a/pl_mars.jpg b/pl_mars.jpg new file mode 100644 index 0000000000000000000000000000000000000000..718294c285d2b9016c2f590d0d76f1d034edb136 GIT binary patch literal 24023 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 szp{dszAMNJMMtA>X7~pn$$SD;l~00Mx2M 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 O@c(`h|9yD&ckW-3o3yzA literal 0 HcmV?d00001 diff --git a/pl_moon.jpg b/pl_moon.jpg new file mode 100644 index 0000000000000000000000000000000000000000..41eef81d312617a1123f2da85659943e18db1c85 GIT binary patch literal 25072 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 literal 0 HcmV?d00001 diff --git a/pl_neptune.jpg b/pl_neptune.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5646e6a4e7136b9476d36a74ee7a704d812ba033 GIT binary patch literal 11984 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 z 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 literal 0 HcmV?d00001 diff --git a/pl_uranus.jpg b/pl_uranus.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a3a47fae34e60531b95bd8c7003d8be3951367b6 GIT binary patch literal 9284 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 atcHs5;89$>izYKDdiCyqo;0#IKmH5lylX)K literal 0 HcmV?d00001 diff --git a/random_walk.py b/random_walk.py new file mode 100644 index 0000000..4744030 --- /dev/null +++ b/random_walk.py @@ -0,0 +1,24 @@ +import random +import time + +class RW(): + def __init__(self, vectorscope, scale=5000, iterations=1000, delay=10): + self.scale = scale + self.v = vectorscope + self.delay = delay + self.iterations=iterations + + def random_walk(self, x, y): + x = x + random.randint(-self.scale,self.scale) + y = y + random.randint(-self.scale,self.scale) + self.v.wave.point(x,y) + return x,y + + def go(self): + x,y = 0,0 + for i in range(self.iterations): + x,y = self.random_walk(x,y) + time.sleep_ms(self.delay) + + + diff --git a/romans.py b/romans.py new file mode 100644 index 0000000..2f5f3c4 --- /dev/null +++ b/romans.py @@ -0,0 +1,208 @@ +WIDTH = 32 +HEIGHT = 32 +FIRST = 0x20 +LAST = 0x7f + +_font =\ +b'\x00\x4a\x5a\x08\x4d\x57\x52\x46\x52\x54\x20\x52\x52\x59\x51'\ +b'\x5a\x52\x5b\x53\x5a\x52\x59\x05\x4a\x5a\x4e\x46\x4e\x4d\x20'\ +b'\x52\x56\x46\x56\x4d\x0b\x48\x5d\x53\x42\x4c\x62\x20\x52\x59'\ +b'\x42\x52\x62\x20\x52\x4c\x4f\x5a\x4f\x20\x52\x4b\x55\x59\x55'\ +b'\x1a\x48\x5c\x50\x42\x50\x5f\x20\x52\x54\x42\x54\x5f\x20\x52'\ +b'\x59\x49\x57\x47\x54\x46\x50\x46\x4d\x47\x4b\x49\x4b\x4b\x4c'\ +b'\x4d\x4d\x4e\x4f\x4f\x55\x51\x57\x52\x58\x53\x59\x55\x59\x58'\ +b'\x57\x5a\x54\x5b\x50\x5b\x4d\x5a\x4b\x58\x1f\x46\x5e\x5b\x46'\ +b'\x49\x5b\x20\x52\x4e\x46\x50\x48\x50\x4a\x4f\x4c\x4d\x4d\x4b'\ +b'\x4d\x49\x4b\x49\x49\x4a\x47\x4c\x46\x4e\x46\x50\x47\x53\x48'\ +b'\x56\x48\x59\x47\x5b\x46\x20\x52\x57\x54\x55\x55\x54\x57\x54'\ +b'\x59\x56\x5b\x58\x5b\x5a\x5a\x5b\x58\x5b\x56\x59\x54\x57\x54'\ +b'\x22\x45\x5f\x5c\x4f\x5c\x4e\x5b\x4d\x5a\x4d\x59\x4e\x58\x50'\ +b'\x56\x55\x54\x58\x52\x5a\x50\x5b\x4c\x5b\x4a\x5a\x49\x59\x48'\ +b'\x57\x48\x55\x49\x53\x4a\x52\x51\x4e\x52\x4d\x53\x4b\x53\x49'\ +b'\x52\x47\x50\x46\x4e\x47\x4d\x49\x4d\x4b\x4e\x4e\x50\x51\x55'\ +b'\x58\x57\x5a\x59\x5b\x5b\x5b\x5c\x5a\x5c\x59\x07\x4d\x57\x52'\ +b'\x48\x51\x47\x52\x46\x53\x47\x53\x49\x52\x4b\x51\x4c\x0a\x4b'\ +b'\x59\x56\x42\x54\x44\x52\x47\x50\x4b\x4f\x50\x4f\x54\x50\x59'\ +b'\x52\x5d\x54\x60\x56\x62\x0a\x4b\x59\x4e\x42\x50\x44\x52\x47'\ +b'\x54\x4b\x55\x50\x55\x54\x54\x59\x52\x5d\x50\x60\x4e\x62\x08'\ +b'\x4a\x5a\x52\x4c\x52\x58\x20\x52\x4d\x4f\x57\x55\x20\x52\x57'\ +b'\x4f\x4d\x55\x05\x45\x5f\x52\x49\x52\x5b\x20\x52\x49\x52\x5b'\ +b'\x52\x07\x4e\x56\x53\x57\x52\x58\x51\x57\x52\x56\x53\x57\x53'\ +b'\x59\x51\x5b\x02\x45\x5f\x49\x52\x5b\x52\x05\x4e\x56\x52\x56'\ +b'\x51\x57\x52\x58\x53\x57\x52\x56\x02\x47\x5d\x5b\x42\x49\x62'\ +b'\x11\x48\x5c\x51\x46\x4e\x47\x4c\x4a\x4b\x4f\x4b\x52\x4c\x57'\ +b'\x4e\x5a\x51\x5b\x53\x5b\x56\x5a\x58\x57\x59\x52\x59\x4f\x58'\ +b'\x4a\x56\x47\x53\x46\x51\x46\x04\x48\x5c\x4e\x4a\x50\x49\x53'\ +b'\x46\x53\x5b\x0e\x48\x5c\x4c\x4b\x4c\x4a\x4d\x48\x4e\x47\x50'\ +b'\x46\x54\x46\x56\x47\x57\x48\x58\x4a\x58\x4c\x57\x4e\x55\x51'\ +b'\x4b\x5b\x59\x5b\x0f\x48\x5c\x4d\x46\x58\x46\x52\x4e\x55\x4e'\ +b'\x57\x4f\x58\x50\x59\x53\x59\x55\x58\x58\x56\x5a\x53\x5b\x50'\ +b'\x5b\x4d\x5a\x4c\x59\x4b\x57\x06\x48\x5c\x55\x46\x4b\x54\x5a'\ +b'\x54\x20\x52\x55\x46\x55\x5b\x11\x48\x5c\x57\x46\x4d\x46\x4c'\ +b'\x4f\x4d\x4e\x50\x4d\x53\x4d\x56\x4e\x58\x50\x59\x53\x59\x55'\ +b'\x58\x58\x56\x5a\x53\x5b\x50\x5b\x4d\x5a\x4c\x59\x4b\x57\x17'\ +b'\x48\x5c\x58\x49\x57\x47\x54\x46\x52\x46\x4f\x47\x4d\x4a\x4c'\ +b'\x4f\x4c\x54\x4d\x58\x4f\x5a\x52\x5b\x53\x5b\x56\x5a\x58\x58'\ +b'\x59\x55\x59\x54\x58\x51\x56\x4f\x53\x4e\x52\x4e\x4f\x4f\x4d'\ +b'\x51\x4c\x54\x05\x48\x5c\x59\x46\x4f\x5b\x20\x52\x4b\x46\x59'\ +b'\x46\x1d\x48\x5c\x50\x46\x4d\x47\x4c\x49\x4c\x4b\x4d\x4d\x4f'\ +b'\x4e\x53\x4f\x56\x50\x58\x52\x59\x54\x59\x57\x58\x59\x57\x5a'\ +b'\x54\x5b\x50\x5b\x4d\x5a\x4c\x59\x4b\x57\x4b\x54\x4c\x52\x4e'\ +b'\x50\x51\x4f\x55\x4e\x57\x4d\x58\x4b\x58\x49\x57\x47\x54\x46'\ +b'\x50\x46\x17\x48\x5c\x58\x4d\x57\x50\x55\x52\x52\x53\x51\x53'\ +b'\x4e\x52\x4c\x50\x4b\x4d\x4b\x4c\x4c\x49\x4e\x47\x51\x46\x52'\ +b'\x46\x55\x47\x57\x49\x58\x4d\x58\x52\x57\x57\x55\x5a\x52\x5b'\ +b'\x50\x5b\x4d\x5a\x4c\x58\x0b\x4e\x56\x52\x4f\x51\x50\x52\x51'\ +b'\x53\x50\x52\x4f\x20\x52\x52\x56\x51\x57\x52\x58\x53\x57\x52'\ +b'\x56\x0d\x4e\x56\x52\x4f\x51\x50\x52\x51\x53\x50\x52\x4f\x20'\ +b'\x52\x53\x57\x52\x58\x51\x57\x52\x56\x53\x57\x53\x59\x51\x5b'\ +b'\x03\x46\x5e\x5a\x49\x4a\x52\x5a\x5b\x05\x45\x5f\x49\x4f\x5b'\ +b'\x4f\x20\x52\x49\x55\x5b\x55\x03\x46\x5e\x4a\x49\x5a\x52\x4a'\ +b'\x5b\x14\x49\x5b\x4c\x4b\x4c\x4a\x4d\x48\x4e\x47\x50\x46\x54'\ +b'\x46\x56\x47\x57\x48\x58\x4a\x58\x4c\x57\x4e\x56\x4f\x52\x51'\ +b'\x52\x54\x20\x52\x52\x59\x51\x5a\x52\x5b\x53\x5a\x52\x59\x37'\ +b'\x45\x60\x57\x4e\x56\x4c\x54\x4b\x51\x4b\x4f\x4c\x4e\x4d\x4d'\ +b'\x50\x4d\x53\x4e\x55\x50\x56\x53\x56\x55\x55\x56\x53\x20\x52'\ +b'\x51\x4b\x4f\x4d\x4e\x50\x4e\x53\x4f\x55\x50\x56\x20\x52\x57'\ +b'\x4b\x56\x53\x56\x55\x58\x56\x5a\x56\x5c\x54\x5d\x51\x5d\x4f'\ +b'\x5c\x4c\x5b\x4a\x59\x48\x57\x47\x54\x46\x51\x46\x4e\x47\x4c'\ +b'\x48\x4a\x4a\x49\x4c\x48\x4f\x48\x52\x49\x55\x4a\x57\x4c\x59'\ +b'\x4e\x5a\x51\x5b\x54\x5b\x57\x5a\x59\x59\x5a\x58\x20\x52\x58'\ +b'\x4b\x57\x53\x57\x55\x58\x56\x08\x49\x5b\x52\x46\x4a\x5b\x20'\ +b'\x52\x52\x46\x5a\x5b\x20\x52\x4d\x54\x57\x54\x17\x47\x5c\x4b'\ +b'\x46\x4b\x5b\x20\x52\x4b\x46\x54\x46\x57\x47\x58\x48\x59\x4a'\ +b'\x59\x4c\x58\x4e\x57\x4f\x54\x50\x20\x52\x4b\x50\x54\x50\x57'\ +b'\x51\x58\x52\x59\x54\x59\x57\x58\x59\x57\x5a\x54\x5b\x4b\x5b'\ +b'\x12\x48\x5d\x5a\x4b\x59\x49\x57\x47\x55\x46\x51\x46\x4f\x47'\ +b'\x4d\x49\x4c\x4b\x4b\x4e\x4b\x53\x4c\x56\x4d\x58\x4f\x5a\x51'\ +b'\x5b\x55\x5b\x57\x5a\x59\x58\x5a\x56\x0f\x47\x5c\x4b\x46\x4b'\ +b'\x5b\x20\x52\x4b\x46\x52\x46\x55\x47\x57\x49\x58\x4b\x59\x4e'\ +b'\x59\x53\x58\x56\x57\x58\x55\x5a\x52\x5b\x4b\x5b\x0b\x48\x5b'\ +b'\x4c\x46\x4c\x5b\x20\x52\x4c\x46\x59\x46\x20\x52\x4c\x50\x54'\ +b'\x50\x20\x52\x4c\x5b\x59\x5b\x08\x48\x5a\x4c\x46\x4c\x5b\x20'\ +b'\x52\x4c\x46\x59\x46\x20\x52\x4c\x50\x54\x50\x16\x48\x5d\x5a'\ +b'\x4b\x59\x49\x57\x47\x55\x46\x51\x46\x4f\x47\x4d\x49\x4c\x4b'\ +b'\x4b\x4e\x4b\x53\x4c\x56\x4d\x58\x4f\x5a\x51\x5b\x55\x5b\x57'\ +b'\x5a\x59\x58\x5a\x56\x5a\x53\x20\x52\x55\x53\x5a\x53\x08\x47'\ +b'\x5d\x4b\x46\x4b\x5b\x20\x52\x59\x46\x59\x5b\x20\x52\x4b\x50'\ +b'\x59\x50\x02\x4e\x56\x52\x46\x52\x5b\x0a\x4a\x5a\x56\x46\x56'\ +b'\x56\x55\x59\x54\x5a\x52\x5b\x50\x5b\x4e\x5a\x4d\x59\x4c\x56'\ +b'\x4c\x54\x08\x47\x5c\x4b\x46\x4b\x5b\x20\x52\x59\x46\x4b\x54'\ +b'\x20\x52\x50\x4f\x59\x5b\x05\x48\x59\x4c\x46\x4c\x5b\x20\x52'\ +b'\x4c\x5b\x58\x5b\x0b\x46\x5e\x4a\x46\x4a\x5b\x20\x52\x4a\x46'\ +b'\x52\x5b\x20\x52\x5a\x46\x52\x5b\x20\x52\x5a\x46\x5a\x5b\x08'\ +b'\x47\x5d\x4b\x46\x4b\x5b\x20\x52\x4b\x46\x59\x5b\x20\x52\x59'\ +b'\x46\x59\x5b\x15\x47\x5d\x50\x46\x4e\x47\x4c\x49\x4b\x4b\x4a'\ +b'\x4e\x4a\x53\x4b\x56\x4c\x58\x4e\x5a\x50\x5b\x54\x5b\x56\x5a'\ +b'\x58\x58\x59\x56\x5a\x53\x5a\x4e\x59\x4b\x58\x49\x56\x47\x54'\ +b'\x46\x50\x46\x0d\x47\x5c\x4b\x46\x4b\x5b\x20\x52\x4b\x46\x54'\ +b'\x46\x57\x47\x58\x48\x59\x4a\x59\x4d\x58\x4f\x57\x50\x54\x51'\ +b'\x4b\x51\x18\x47\x5d\x50\x46\x4e\x47\x4c\x49\x4b\x4b\x4a\x4e'\ +b'\x4a\x53\x4b\x56\x4c\x58\x4e\x5a\x50\x5b\x54\x5b\x56\x5a\x58'\ +b'\x58\x59\x56\x5a\x53\x5a\x4e\x59\x4b\x58\x49\x56\x47\x54\x46'\ +b'\x50\x46\x20\x52\x53\x57\x59\x5d\x10\x47\x5c\x4b\x46\x4b\x5b'\ +b'\x20\x52\x4b\x46\x54\x46\x57\x47\x58\x48\x59\x4a\x59\x4c\x58'\ +b'\x4e\x57\x4f\x54\x50\x4b\x50\x20\x52\x52\x50\x59\x5b\x14\x48'\ +b'\x5c\x59\x49\x57\x47\x54\x46\x50\x46\x4d\x47\x4b\x49\x4b\x4b'\ +b'\x4c\x4d\x4d\x4e\x4f\x4f\x55\x51\x57\x52\x58\x53\x59\x55\x59'\ +b'\x58\x57\x5a\x54\x5b\x50\x5b\x4d\x5a\x4b\x58\x05\x4a\x5a\x52'\ +b'\x46\x52\x5b\x20\x52\x4b\x46\x59\x46\x0a\x47\x5d\x4b\x46\x4b'\ +b'\x55\x4c\x58\x4e\x5a\x51\x5b\x53\x5b\x56\x5a\x58\x58\x59\x55'\ +b'\x59\x46\x05\x49\x5b\x4a\x46\x52\x5b\x20\x52\x5a\x46\x52\x5b'\ +b'\x0b\x46\x5e\x48\x46\x4d\x5b\x20\x52\x52\x46\x4d\x5b\x20\x52'\ +b'\x52\x46\x57\x5b\x20\x52\x5c\x46\x57\x5b\x05\x48\x5c\x4b\x46'\ +b'\x59\x5b\x20\x52\x59\x46\x4b\x5b\x06\x49\x5b\x4a\x46\x52\x50'\ +b'\x52\x5b\x20\x52\x5a\x46\x52\x50\x08\x48\x5c\x59\x46\x4b\x5b'\ +b'\x20\x52\x4b\x46\x59\x46\x20\x52\x4b\x5b\x59\x5b\x0b\x4b\x59'\ +b'\x4f\x42\x4f\x62\x20\x52\x50\x42\x50\x62\x20\x52\x4f\x42\x56'\ +b'\x42\x20\x52\x4f\x62\x56\x62\x02\x4b\x59\x4b\x46\x59\x5e\x0b'\ +b'\x4b\x59\x54\x42\x54\x62\x20\x52\x55\x42\x55\x62\x20\x52\x4e'\ +b'\x42\x55\x42\x20\x52\x4e\x62\x55\x62\x05\x4a\x5a\x52\x44\x4a'\ +b'\x52\x20\x52\x52\x44\x5a\x52\x02\x49\x5b\x49\x62\x5b\x62\x07'\ +b'\x4e\x56\x53\x4b\x51\x4d\x51\x4f\x52\x50\x53\x4f\x52\x4e\x51'\ +b'\x4f\x11\x49\x5c\x58\x4d\x58\x5b\x20\x52\x58\x50\x56\x4e\x54'\ +b'\x4d\x51\x4d\x4f\x4e\x4d\x50\x4c\x53\x4c\x55\x4d\x58\x4f\x5a'\ +b'\x51\x5b\x54\x5b\x56\x5a\x58\x58\x11\x48\x5b\x4c\x46\x4c\x5b'\ +b'\x20\x52\x4c\x50\x4e\x4e\x50\x4d\x53\x4d\x55\x4e\x57\x50\x58'\ +b'\x53\x58\x55\x57\x58\x55\x5a\x53\x5b\x50\x5b\x4e\x5a\x4c\x58'\ +b'\x0e\x49\x5b\x58\x50\x56\x4e\x54\x4d\x51\x4d\x4f\x4e\x4d\x50'\ +b'\x4c\x53\x4c\x55\x4d\x58\x4f\x5a\x51\x5b\x54\x5b\x56\x5a\x58'\ +b'\x58\x11\x49\x5c\x58\x46\x58\x5b\x20\x52\x58\x50\x56\x4e\x54'\ +b'\x4d\x51\x4d\x4f\x4e\x4d\x50\x4c\x53\x4c\x55\x4d\x58\x4f\x5a'\ +b'\x51\x5b\x54\x5b\x56\x5a\x58\x58\x11\x49\x5b\x4c\x53\x58\x53'\ +b'\x58\x51\x57\x4f\x56\x4e\x54\x4d\x51\x4d\x4f\x4e\x4d\x50\x4c'\ +b'\x53\x4c\x55\x4d\x58\x4f\x5a\x51\x5b\x54\x5b\x56\x5a\x58\x58'\ +b'\x08\x4d\x59\x57\x46\x55\x46\x53\x47\x52\x4a\x52\x5b\x20\x52'\ +b'\x4f\x4d\x56\x4d\x16\x49\x5c\x58\x4d\x58\x5d\x57\x60\x56\x61'\ +b'\x54\x62\x51\x62\x4f\x61\x20\x52\x58\x50\x56\x4e\x54\x4d\x51'\ +b'\x4d\x4f\x4e\x4d\x50\x4c\x53\x4c\x55\x4d\x58\x4f\x5a\x51\x5b'\ +b'\x54\x5b\x56\x5a\x58\x58\x0a\x49\x5c\x4d\x46\x4d\x5b\x20\x52'\ +b'\x4d\x51\x50\x4e\x52\x4d\x55\x4d\x57\x4e\x58\x51\x58\x5b\x08'\ +b'\x4e\x56\x51\x46\x52\x47\x53\x46\x52\x45\x51\x46\x20\x52\x52'\ +b'\x4d\x52\x5b\x0b\x4d\x57\x52\x46\x53\x47\x54\x46\x53\x45\x52'\ +b'\x46\x20\x52\x53\x4d\x53\x5e\x52\x61\x50\x62\x4e\x62\x08\x49'\ +b'\x5a\x4d\x46\x4d\x5b\x20\x52\x57\x4d\x4d\x57\x20\x52\x51\x53'\ +b'\x58\x5b\x02\x4e\x56\x52\x46\x52\x5b\x12\x43\x61\x47\x4d\x47'\ +b'\x5b\x20\x52\x47\x51\x4a\x4e\x4c\x4d\x4f\x4d\x51\x4e\x52\x51'\ +b'\x52\x5b\x20\x52\x52\x51\x55\x4e\x57\x4d\x5a\x4d\x5c\x4e\x5d'\ +b'\x51\x5d\x5b\x0a\x49\x5c\x4d\x4d\x4d\x5b\x20\x52\x4d\x51\x50'\ +b'\x4e\x52\x4d\x55\x4d\x57\x4e\x58\x51\x58\x5b\x11\x49\x5c\x51'\ +b'\x4d\x4f\x4e\x4d\x50\x4c\x53\x4c\x55\x4d\x58\x4f\x5a\x51\x5b'\ +b'\x54\x5b\x56\x5a\x58\x58\x59\x55\x59\x53\x58\x50\x56\x4e\x54'\ +b'\x4d\x51\x4d\x11\x48\x5b\x4c\x4d\x4c\x62\x20\x52\x4c\x50\x4e'\ +b'\x4e\x50\x4d\x53\x4d\x55\x4e\x57\x50\x58\x53\x58\x55\x57\x58'\ +b'\x55\x5a\x53\x5b\x50\x5b\x4e\x5a\x4c\x58\x11\x49\x5c\x58\x4d'\ +b'\x58\x62\x20\x52\x58\x50\x56\x4e\x54\x4d\x51\x4d\x4f\x4e\x4d'\ +b'\x50\x4c\x53\x4c\x55\x4d\x58\x4f\x5a\x51\x5b\x54\x5b\x56\x5a'\ +b'\x58\x58\x08\x4b\x58\x4f\x4d\x4f\x5b\x20\x52\x4f\x53\x50\x50'\ +b'\x52\x4e\x54\x4d\x57\x4d\x11\x4a\x5b\x58\x50\x57\x4e\x54\x4d'\ +b'\x51\x4d\x4e\x4e\x4d\x50\x4e\x52\x50\x53\x55\x54\x57\x55\x58'\ +b'\x57\x58\x58\x57\x5a\x54\x5b\x51\x5b\x4e\x5a\x4d\x58\x08\x4d'\ +b'\x59\x52\x46\x52\x57\x53\x5a\x55\x5b\x57\x5b\x20\x52\x4f\x4d'\ +b'\x56\x4d\x0a\x49\x5c\x4d\x4d\x4d\x57\x4e\x5a\x50\x5b\x53\x5b'\ +b'\x55\x5a\x58\x57\x20\x52\x58\x4d\x58\x5b\x05\x4a\x5a\x4c\x4d'\ +b'\x52\x5b\x20\x52\x58\x4d\x52\x5b\x0b\x47\x5d\x4a\x4d\x4e\x5b'\ +b'\x20\x52\x52\x4d\x4e\x5b\x20\x52\x52\x4d\x56\x5b\x20\x52\x5a'\ +b'\x4d\x56\x5b\x05\x4a\x5b\x4d\x4d\x58\x5b\x20\x52\x58\x4d\x4d'\ +b'\x5b\x09\x4a\x5a\x4c\x4d\x52\x5b\x20\x52\x58\x4d\x52\x5b\x50'\ +b'\x5f\x4e\x61\x4c\x62\x4b\x62\x08\x4a\x5b\x58\x4d\x4d\x5b\x20'\ +b'\x52\x4d\x4d\x58\x4d\x20\x52\x4d\x5b\x58\x5b\x27\x4b\x59\x54'\ +b'\x42\x52\x43\x51\x44\x50\x46\x50\x48\x51\x4a\x52\x4b\x53\x4d'\ +b'\x53\x4f\x51\x51\x20\x52\x52\x43\x51\x45\x51\x47\x52\x49\x53'\ +b'\x4a\x54\x4c\x54\x4e\x53\x50\x4f\x52\x53\x54\x54\x56\x54\x58'\ +b'\x53\x5a\x52\x5b\x51\x5d\x51\x5f\x52\x61\x20\x52\x51\x53\x53'\ +b'\x55\x53\x57\x52\x59\x51\x5a\x50\x5c\x50\x5e\x51\x60\x52\x61'\ +b'\x54\x62\x02\x4e\x56\x52\x42\x52\x62\x27\x4b\x59\x50\x42\x52'\ +b'\x43\x53\x44\x54\x46\x54\x48\x53\x4a\x52\x4b\x51\x4d\x51\x4f'\ +b'\x53\x51\x20\x52\x52\x43\x53\x45\x53\x47\x52\x49\x51\x4a\x50'\ +b'\x4c\x50\x4e\x51\x50\x55\x52\x51\x54\x50\x56\x50\x58\x51\x5a'\ +b'\x52\x5b\x53\x5d\x53\x5f\x52\x61\x20\x52\x53\x53\x51\x55\x51'\ +b'\x57\x52\x59\x53\x5a\x54\x5c\x54\x5e\x53\x60\x52\x61\x50\x62'\ +b'\x17\x46\x5e\x49\x55\x49\x53\x4a\x50\x4c\x4f\x4e\x4f\x50\x50'\ +b'\x54\x53\x56\x54\x58\x54\x5a\x53\x5b\x51\x20\x52\x49\x53\x4a'\ +b'\x51\x4c\x50\x4e\x50\x50\x51\x54\x54\x56\x55\x58\x55\x5a\x54'\ +b'\x5b\x51\x5b\x4f\x22\x4a\x5a\x4a\x46\x4a\x5b\x4b\x5b\x4b\x46'\ +b'\x4c\x46\x4c\x5b\x4d\x5b\x4d\x46\x4e\x46\x4e\x5b\x4f\x5b\x4f'\ +b'\x46\x50\x46\x50\x5b\x51\x5b\x51\x46\x52\x46\x52\x5b\x53\x5b'\ +b'\x53\x46\x54\x46\x54\x5b\x55\x5b\x55\x46\x56\x46\x56\x5b\x57'\ +b'\x5b\x57\x46\x58\x46\x58\x5b\x59\x5b\x59\x46\x5a\x46\x5a\x5b'\ +b'' + +_index =\ +b'\x00\x00\x03\x00\x16\x00\x23\x00\x3c\x00\x73\x00\xb4\x00\xfb'\ +b'\x00\x0c\x01\x23\x01\x3a\x01\x4d\x01\x5a\x01\x6b\x01\x72\x01'\ +b'\x7f\x01\x86\x01\xab\x01\xb6\x01\xd5\x01\xf6\x01\x05\x02\x2a'\ +b'\x02\x5b\x02\x68\x02\xa5\x02\xd6\x02\xef\x02\x0c\x03\x15\x03'\ +b'\x22\x03\x2b\x03\x56\x03\xc7\x03\xda\x03\x0b\x04\x32\x04\x53'\ +b'\x04\x6c\x04\x7f\x04\xae\x04\xc1\x04\xc8\x04\xdf\x04\xf2\x04'\ +b'\xff\x04\x18\x05\x2b\x05\x58\x05\x75\x05\xa8\x05\xcb\x05\xf6'\ +b'\x05\x03\x06\x1a\x06\x27\x06\x40\x06\x4d\x06\x5c\x06\x6f\x06'\ +b'\x88\x06\x8f\x06\xa8\x06\xb5\x06\xbc\x06\xcd\x06\xf2\x06\x17'\ +b'\x07\x36\x07\x5b\x07\x80\x07\x93\x07\xc2\x07\xd9\x07\xec\x07'\ +b'\x05\x08\x18\x08\x1f\x08\x46\x08\x5d\x08\x82\x08\xa7\x08\xcc'\ +b'\x08\xdf\x08\x04\x09\x17\x09\x2e\x09\x3b\x09\x54\x09\x61\x09'\ +b'\x76\x09\x89\x09\xda\x09\xe1\x09\x32\x0a\x63\x0a' + +FONT = memoryview(_font) +INDEX = memoryview(_index) + diff --git a/screen.py b/screen.py new file mode 100644 index 0000000..2b2ef8e --- /dev/null +++ b/screen.py @@ -0,0 +1,74 @@ +from machine import Pin, SPI, SoftSPI +import pin_defs +import gc9a01 +import gc +import rp2 + +class Screen(): + def __init__(self, softSPI=False): + self.softSPI = softSPI + self.sck = Pin(pin_defs.sck, Pin.OUT) + self.data = Pin(pin_defs.data, Pin.OUT) + self.dc = Pin(pin_defs.dc, Pin.OUT) + self.init() + + def deinit(self): + self.spi.deinit() + ## this does not appear to de-initialize the DMAs -- the enable bits are still set + del(self.spi) + del(self.tft) + gc.collect() + + def init(self): + if self.softSPI: + self.spi = SoftSPI(baudrate=10_000_000, sck=self.sck, mosi=self.data, miso=Pin(pin_defs.throwaway)) + else: + self.spi = SPI(0, baudrate=40_000_000, sck=self.sck, mosi=self.data) + + self.tft = gc9a01.GC9A01(self.spi, 240, 240, + reset = Pin(pin_defs.reset, Pin.OUT), + cs = Pin(pin_defs.throwaway, Pin.OUT), ## not used, grounded on board + dc = self.dc, + backlight = Pin(pin_defs.throwaway, Pin.OUT), ## not used, always on + rotation = 0) + self.tft.init() + self.tft.fill(gc9a01.color565(10,15,10)) + + +if __name__ == "__main__": + + import time + import random + + ## instantiate and init + s = Screen() + + ## For everything you can do with the GC9A01 library: + ## https://github.com/russhughes/gc9a01_mpy + + s.tft.fill(gc9a01.BLUE) + time.sleep_ms(500) + s.tft.fill(gc9a01.YELLOW) + time.sleep_ms(500) + s.tft.fill(gc9a01.BLACK) + + phosphor_bright = gc9a01.color565(120, 247, 180) + phosphor_dark = gc9a01.color565(45, 217, 80) + + ## better graphic demo should go here + for i in range(200): + x1 = random.randint(0, 240) + x2 = random.randint(0, 240) + y1 = random.randint(0, 240) + y2 = random.randint(0, 240) + + if i % 2: + s.tft.line(x1, y1, x2, y2, phosphor_bright) + else: + s.tft.line(x1, y1, x2, y2, phosphor_dark) + time.sleep_ms(20) + + + + + diff --git a/screennorm.py b/screennorm.py new file mode 100644 index 0000000..4519dab --- /dev/null +++ b/screennorm.py @@ -0,0 +1,125 @@ +import gc9a01 +from machine import Pin, SPI +import vga1_16x32 as font +import gc +import romans as deffont + +class ScreenNorm: + """ + A light wrapper around the gc9a01 screen. + + Attributes: + _spi (SPI): The SPI interface. + tft (gc9a01.GC9A01): The TFT display. + """ + + def __init__(self): + """ + The constructor for ScreenNorm class. + """ + + self._spi = SPI(0, baudrate=40000000, sck=Pin(2, Pin.OUT), mosi=Pin(3, Pin.OUT), miso=Pin(20,Pin.IN)) + self.wake() + + def get_font(self): + """ + Get the normal font + + Returns: + font object + """ + return font + + def get_vfont(self): + """ + Get the default vector font (romans) + """ + return deffont + + def wake(self): + """ + Method to wake up the display. + """ + + self.tft = gc9a01.GC9A01(self._spi, 240, 240, + reset=Pin(4, Pin.OUT), + cs=Pin(26, Pin.OUT), + dc=Pin(5, Pin.OUT), + backlight=Pin(27, Pin.OUT), + rotation=0) + + self.tft.init() + + def idle(self): + """ + Method to get the display out of the way for another screen helper. + """ + + self._spi.deinit() + self.tft=None + + def jpg(self,filename): + """ + Method to show a jpg on the display. + + Args: + filename (str): The name of the jpg file. + """ + + if self.tft!=None: + gc.collect() + self.tft.jpg(filename,0,0,1) + + def text(self,x,y,txt,fg_color=gc9a01.color565(45, 217, 80),bg_color=gc9a01.color565(10,15,10)): + """ + Method to draw text on the display. + + Args: + x (int): The x-coordinate of the top left corner of the text. + y (int): The y-coordinate of the top left corner of the text. + txt (str): The text to draw. + fg_color (int): The foreground color. Default is gc9a01.color565(243,191,16). + bg_color (int): The background color. Default is gc9a01.color565(26,26,26). + """ + + if self.tft!=None: + self.tft.text(font,txt,x,y,fg_color,bg_color) + + def text_font(self,font,x,y,txt,fg_color=gc9a01.color565(45, 217, 80),scale=1.0): + """ + Method to draw text with a font. + + Args: + font (font or None): The font to use (or use default font) + x,y (int): X and Y coordinate + txt (str): String + fg_color (int) Foreground color (note: no background color -- always transparent) + """ + if self.tft!=None: + if font==None: + font=deffont + self.tft.draw(font,txt,x,y,fg_color,scale) + + def clear(self,color=0): + """ + Method to clear the display with a color. + + Args: + color (int): The background color. Default is 0. + """ + + if self.tft!=None: + self.tft.fill_rect(0,0,240,240,color) + + def pixel(self,x,y,color): + """ + Method to set a pixel on the display. + + Args: + x (int): The x-coordinate of the pixel. + y (int): The y-coordinate of the pixel. + color (int): The color of the pixel. + """ + + if self.tft!=None: + self.tft.pixel(x,y,color) diff --git a/screentest.py b/screentest.py new file mode 100644 index 0000000..118eea8 --- /dev/null +++ b/screentest.py @@ -0,0 +1,60 @@ +import screennorm +import keyboardcb +import keyleds +import vectoros +import gc +import asyncio + +screen=screennorm.ScreenNorm() + + +exit_flag=False + +def text_overlay(): + screen.text(60,25,"SUPERCON") + screen.text(85,190,"2023") + +def back(key): + screen.jpg("bluemarble.jpg") # button A globe + text_overlay() + +def fwd(key): + screen.jpg("wrencher.jpg") # button B wrencher + text_overlay() + +def menu(key): # menu -bail out + global exit_flag + exit_flag=True + +def startlcd(key): # button D - start LCD + if screen.tft==None: + screen.wake() + back(None) + +def stoplcd(key): # button C stop LCD + if screen.tft!=None: + screen.clear() + screen.idle() + +async def vos_main(): + global exit_flag + keys=keyboardcb.KeyboardCB({keyleds.KEY_A: back, keyleds.KEY_B: fwd, keyleds.KEY_C: stoplcd, keyleds.KEY_D: startlcd, + keyleds.KEY_MENU: menu}) + back(None) + while exit_flag==False: + await asyncio.sleep_ms(500) + if vectoros.vectoros_active==False: + gc.collect() +# stop listening for keys + keys.detach() + exit_flag=False # next time + from vos_state import vos_state + vos_state.show_menu=True + +def main(): + asyncio.run(vos_main()) + + +if __name__=="__main__": + keyboardcb.KeyboardCB.run(100) + main() diff --git a/sketch.py b/sketch.py new file mode 100644 index 0000000..cd8c4fc --- /dev/null +++ b/sketch.py @@ -0,0 +1,169 @@ +import screennorm +import keyboardcb +import keyleds +import joystick +import vectoros +from vos_state import vos_state +import gc9a01 + +# little etch-a-sketch demo + +pendown = True # start off with pen down +color = gc9a01.BLACK # start off black + +# To maintain the cursor we need a bit map which is slow +# so less is more. Also pixels are tiny +# so 40 is a good compromise (40x40 drawing area) +SIZE=40 +PIXSIZE=240//SIZE # size of each "pixel" + +# start cursor in the middle +cursor_x = (SIZE+1)//2 +cursor_y = (SIZE+1)//2 + +# This will be the backing store for the screen +model=[] + +stopflag=False # stop when true + +# clear the mdoel with color c (does not draw; see cursor) +def fill_model(c): + global model + model=[[c for i in range(SIZE)] for j in range(SIZE)] + + + +# update screen and overlay cursor (or just cursor area if blit==False) +def cursor(blit=True): + global model + global cursor_x + global cursor_y + global PIXSIZE + global pendown + ccolor=gc9a01.color565(0xC0,0xFF,0x80) + if pendown: + ccolor=gc9a01.color565(0xFF,0x80,0x80) + if blit: + for x in range(SIZE): + for y in range(SIZE): + screen.tft.fill_rect(x*PIXSIZE,y*PIXSIZE,PIXSIZE,PIXSIZE,model[x][y]) + else: # only draw around the cursor + for x in range(-1,2): + for y in range(-1,2): + nx=cursor_x+x + ny=cursor_y+y + screen.tft.fill_rect(nx*PIXSIZE,ny*PIXSIZE,PIXSIZE,PIXSIZE,model[nx][ny]) + screen.tft.fill_rect(cursor_x*PIXSIZE,cursor_y*PIXSIZE,PIXSIZE,PIXSIZE,ccolor) + +# flip pen/up down on joystick button (non-repeating) +def joybtn(key): + global pendown + pendown=not pendown + cursor(False) # update cursor color + +# normal joystick commands +def joycmd(key): + global pendown, cursor_x, cursor_y + x=0 + y=0 + if key==keyleds.JOY_N: + y=-1 + elif key==keyleds.JOY_S: + y=1 + elif key==keyleds.JOY_E: + x=1 + elif key==keyleds.JOY_W: + x=-1 + elif key==keyleds.JOY_NW: + y=-1 + x=-1 + elif key==keyleds.JOY_SW: + y=1 + x=-1 + elif key==keyleds.JOY_NE: + y=-1 + x=1 + elif key==keyleds.JOY_SE: + y=1 + x=1 + if x!=0 or y!=0: + newx=cursor_x+x + if newx>=0 and newx=0 and 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�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 bbw`P26GE>pZLL4Q+xbHM|Mi4+HuS#$W<(Bg literal 0 HcmV?d00001 diff --git a/static_buffer_example.py b/static_buffer_example.py new file mode 100644 index 0000000..c0982f3 --- /dev/null +++ b/static_buffer_example.py @@ -0,0 +1,25 @@ +import math +import time + +from vectorscope import Vectorscope +from random_walk import RW + + + +def static_buffer_example(v): + ## Example of more complicated, repetitive waveform + ## v.wave has two buffers of 256 samples for putting sample-wise data into: + ## v.wave.outBufferX and outBufferY. These are packed 16 bits each, LSB first + ## To make your life easier, v.wave.packX() will put a list of 16-bit ints there for you + + ramp = range(-2**15, 2**15, 2**8) + v.wave.packX(ramp) + sine = [int(math.sin(2*x*math.pi/256)*16_000) for x in range(256)] + v.wave.packY(sine) + time.sleep(5) + ## That discontinuity and wobble is real -- + ## that's what happens when you try to push around a real DAC that's bandwidth-limited. + +async def slot_main(v): + static_buffer_example(v) + diff --git a/supercon_menu.py b/supercon_menu.py new file mode 100644 index 0000000..3e5a86a --- /dev/null +++ b/supercon_menu.py @@ -0,0 +1,102 @@ +import machine +import joystick +from menu import * # bad habit but makes our menu definition nice +from vos_state import vos_state +import vectoros +import colors +import gc +import random + + +# run the sketch demo +def runsketch(arg): + vos_state.show_menu=False # get the menu of the way + vectoros.launch_task('sketch') + return EXIT + +def planets(arg): + vos_state.show_menu=False # get the menu of the way + vectoros.launch_task('planets') # launch + return EXIT + +def menu_custom(the_menu): + if the_menu.level==1: + if machine.Pin(22).value(): + the_menu.current[2]=[" Sound Off",toggle_sound,0] + else: + the_menu.current[2]=[" Sound On",toggle_sound,1] + +def toggle_sound(arg): + ## toggle sound here + machine.Pin(22, machine.Pin.OUT).toggle() + return CONT + + +# the main vector scope demo +def run_lissajous(arg): + vos_state.show_menu=False + vectoros.launch_task('lissajous') + # we never come back, vectorscope + return EXIT + +def reboot(arg): + if arg==False: + vectoros.reset() + else: + vectoros.soft_reset() + +# handle slots +def abcd(key): + if vos_state.show_menu: + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,f"Menu key {key}") + kdict={ keyleds.KEY_A: 'A', keyleds.KEY_B: 'B', keyleds.KEY_C: 'C', keyleds.KEY_D: 'D'} + await vectoros.launch_vecslot("slot"+kdict[key]) + + +# I really didn't want this to be async but it seems like do_menu must have an await +# and run rarely returns when you have a lot going on +async def vos_main(): +# you do NOT have to use with here +# but if you don't you have to worry about the menu controller's joystick instance going out of scope yourself +# or just make everything global -- the menu is smart enough to not listen to events when it is not active +# note: m_back and m_exit were imported from menu + ## Start with sound off + machine.Pin(22, machine.Pin.OUT).toggle() + + screen=vectoros.get_screen() + splashes = ["splash_x.jpg", "splash_7.jpg", "splash_wrencher.jpg"] + screen.jpg(random.choice(splashes)) + await asyncio.sleep_ms(1000) + + + + while True: # since this is the main menu, we don't really every quit + print("creating slotkey") + slotkey=keyboardcb.KeyboardCB(abcd,keyleds.KEY_ABCD) + with Menu(clear_after=True,fg_color=colors.PHOSPHOR_DARK,bg_color=colors.PHOSPHOR_BG, + cursor_bg=colors.PHOSPHOR_BG, cursor_fg=colors.PHOSPHOR_BRIGHT) as amenu: + ## name in menu, command to run, return value? + submenu=[[" Planets", planets, 0],[" Sketch",runsketch,0],[" Back",m_exit,None]] + mainmenu=[[" Lissajous", run_lissajous,None], + [" Demos", SUBMENU, submenu] , + [" Sound", toggle_sound, None], + [" Reboot",reboot,False], + ] + +# comment next line for default font + amenu.set_font("*") # set default vector font + amenu.set_callback(menu_custom) + await amenu.do_menu(mainmenu) + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,f"Menu waiting {vos_state.show_menu}") + while vos_state.show_menu==False: # wait until we have to be seen again + await asyncio.sleep_ms(0) + + +def main(): + asyncio.run(vos_main()) + # this never runs + +if __name__=="__main__": + import vectoros + vectoros.run() + diff --git a/timer.py b/timer.py new file mode 100644 index 0000000..58f3c1d --- /dev/null +++ b/timer.py @@ -0,0 +1,277 @@ +import vos_launch +import asyncio +import vos_debug + + +# if you don't care about the asyncio aspect of this +# you can try using machine.Timer + + +class Timer: + """ + A class that manages a timer for VectorOS. + + Attributes: + clients (dict): Each item is [reset value, value, callback, sync/async, oneshot]. + baserate (int): The base rate in milliseconds. + _next_id (int): The next id to use. + current_id (int): The current id. + task (Task): The task for the timer. + gc_delay (int): The delay for garbage collection. + """ + + clients={} + baserate=vos_launch.timer_base_rate + _next_id=1 + current_id=None + task=None + gc_delay=0 + _cancel=False + + @classmethod + async def _run(cls): + """ + Class method to run the class level "server". + + Returns: + Task: The created task. + """ + + cls.task=asyncio.create_task(cls._job()) + + @classmethod + def run(cls): + """ + Class method to launch the event loop without having to create a task yourself. + + Returns: + Task: The created task. + """ + + return asyncio.create_task(cls._run()) + + @classmethod + async def _job(cls): + """ + Class method for the actual polling task. + + This method runs a loop that sleeps for a specified timeout and then ticks the timer. + + Returns: + Task: The created task. + """ + + ctr=0 + while cls._cancel==False: + await asyncio.sleep_ms(cls.baserate) + await cls._tick() + ctr+=1 + if cls.gc_delay!=0 and ctr>cls.gc_delay: + ctr=0 + gc.collect() + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,"Timer exit") + + @classmethod + def cancel(cls): + """ + Class method to cancel the polling task. + """ + cls._cancel=True + cls.task.cancel() + + @classmethod + async def _tick(cls): + """ + Class method to tick the timer. + + This method ticks the timer and calls the appropriate callback function for each timer event. + """ + + for item in cls.clients: + cls.clients[item][1]+=1 + if cls.clients[item][0]<=cls.clients[item][1]: + cls.clients[item][1]=0 + cls.current_id=item + try: + await cls.clients[item][2]() + except TypeError: + pass + try: + if cls.clients[item][3]: + del cls.clients[item] + except Exception: + pass + cls.current_id=None + + @classmethod + def remove_timer(cls,id): + """ + Class method to remove a timer. + + Args: + id (int): The id of the timer to remove. + """ + if id in cls.clients: + cls._next_id=id # try to recycle timer IDs (note we search "up" if one is in use already) + del cls.clients[id] + + @classmethod + def add_timer(cls,ticks, callback, oneshot=False): + """ + Class method to add a timer. + + Args: + ticks (int): The number of ticks before the timer triggers. + callback (function): The function to call when the timer triggers. + oneshot (bool): A flag to indicate if the timer should only trigger once. Default is False. + + Returns: + int: The id of the added timer. + """ + + # we search for a free timerID starting from _next_id + # normally that means we get an ascending number + # but if you delete a timer ID we will reuse it unless + # you delete two or more without creating any + # then you may "leak" lower number IDs but you + # should run out of resources before you run out of IDs + # anyway This is just a hedge for the case where you + # constantly create/remove a timer + while cls._next_id in cls.clients: + cls._next_id+=1 + + rv=cls._next_id + cls.clients[cls._next_id]=[ticks,0,callback,oneshot] + cls._next_id+=1 + + return rv + + def __init__(self,ticks,paused=False,oneshot=False): + """ + The constructor for Timer class. + + Args: + ticks (int): The number of ticks before the timer triggers. + paused (bool): A flag to indicate if the timer should start paused. Default is False. + oneshot (bool): A flag to indicate if the timer should only trigger once. Default is False. + """ + + self.ticks=ticks + self.paused=paused + self.oneshot=oneshot + + if paused: + self.id=None + else: + self.id=self.add_timer(ticks,self.action,oneshot) + + def __enter__(self): + return + + def __exit__(self,exc_type,exc_val,exc_tb): + if self.id!=None: + self.remove_timer(id) + + def action(self): + print("unhandled action") + + def pause(self): + if self.id==None: + return + + try: + self.remove_timer(self.id) + except Exception: + pass + + finally: + self.id=None + + def resume(self): + try: + self.remove_timer(self.id) + except Exception: + pass + + self.id=self.add_timer(self.ticks,self.self.action,True,self.oneshot) + + return self.id + +if __name__=="__main__": + import gc + onesecid=0 + + Timer.gc_delay=500 + + class Test(Timer): + def __init__(self): + super().__init__(20) + self.ct=0 + + def action(self): + self.ct=self.ct+1 + print("**",self.ct) + if (self.ct>=10): + self.pause() + + + twosec = Test() + + + def callback1sec(): + """ + Function to print a message every second. + """ + + print("Tick 1") + + def callback5sec(): + """ + Function to print a message and the amount of free memory every 5 seconds. + """ + + print("Tick 5",gc.mem_free()) + + def once(): + """ + Function to print a message and remove the 1 second tick. This function only runs once. + """ + + global onesecid + print("I only run once",onesecid) + Timer.remove_timer(onesecid) + + async def acallback_worker(): + """ + Asynchronous function to print a start and end message with a delay of 5 seconds. + """ + + print("async start") + await asyncio.sleep(5) + print("async done") + + # This is an async callback. However, the timer will stall until it completes + # so we just kick off a new task to run in the background and then the timer does its thing + async def acallback(): + asyncio.create_task(acallback_worker()) + + async def amain(): + """ + Asynchronous main function to run the timer and add several tasks to it. + """ + + global onesecid + Timer.run() + + + onesecid=Timer.add_timer(10,callback1sec) # every one second + Timer.add_timer(50,callback5sec) # 5 second synchronous repeating + Timer.add_timer(100,once,True) # one shot and remove the 1 second tick + Timer.add_timer(55,acallback,True) # one shot + + while True: + await asyncio.sleep(0) + + asyncio.run(amain()) + + diff --git a/vectoros.py b/vectoros.py new file mode 100644 index 0000000..1f511d4 --- /dev/null +++ b/vectoros.py @@ -0,0 +1,364 @@ +import aiorepl +import asyncio +import keyboardio +import screennorm +import timer +from vos_launch import launch_list, auto_launch_list, auto_launch_repl, key_scan_rate, gc_thread_rate, timer_base_rate, vectorscope_slots +from vos_state import vos_state +import gc +from machine import RTC +from machine import reset as m_reset, soft_reset as m_soft_reset +import vos_debug +from vectorscope import Vectorscope + + +_VERSION=20231001 + +_screen=screennorm.ScreenNorm() + + +async def _sleeper(): + """ + Asynchronous function to sleep forever. + + This function runs a loop that sleeps for 2 seconds and then collects garbage. + """ + + while True: + await asyncio.sleep(2) + if vos_state.gc_suspend==False: + gc.collect() + +def reset(): + m_reset() + +def soft_reset(): + m_soft_reset() + + +def sleep_forever(): + """ + Function to let non async function wait forever. + """ + + asyncio.run(_sleeper()) + +async def _delayer(n): + """ + Asynchronous function to delay for n seconds. + + Args: + n (int): The number of milliseconds to delay. + """ + + await asyncio.sleep_ms(n) + +def sleep(n): + """ + Function to delay for n seconds. + + Args: + n (int): The number of milliseconds to delay. + """ + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_WARNING,"sleep called which uses asyncio.run") + asyncio.run(_delayer(n)) + +def get_screen(): + """ + Function to get the one screen object. + + Returns: + ScreenNorm: The screen object. + """ + + global _screen + return _screen + +async def launch_repl(): + """ + Asynchronous function to start a repl. + """ + + vos_state.task_dict['$repl']=asyncio.create_task(aiorepl.task()) + +async def launch(task_tag): + """ + Asynchronous function to launch a program by its tag. + + Args: + task_tag (str): The tag of the program to launch. + + Returns: + Task: The created task. + """ + if vos_state.gc_suspend==False: + gc.collect() + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,f"launching {task_tag}") + mod=__import__(launch_list[task_tag]) + try: + fn=getattr(mod,'vos_main') + except Exception: + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_WARNING,f"launch could not find vos_main for {task_tag}. Trying main()") + fn=getattr(mod,'main') + try: + await fn() + except TypeError: + pass + + + +def launch_task(task_tag): + """ + Function to create async task to launch. + + Args: + task_tag (str): The tag of the program to launch. + + Returns: + Task: The created task. + """ + vos_state.task_dict[task_tag]=asyncio.create_task(launch(task_tag)) + + +async def launch_vecslot(slot): + import vectorscope + get_screen().idle() + gc.collect() + vos_state.gc_suspend=True + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,f"Launching slot {slot}:{vectorscope_slots[slot]}") + mod=__import__(vectorscope_slots[slot]) + fn=getattr(mod,'slot_main') + v = Vectorscope(screen_running = True) + try: + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,"launching") + await fn(v) + except TypeError: + pass + except Exception as e: + print("launch exception",e) + finally: + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,"Slot done, reboot!") + # await asyncio.sleep(5) + reset() + + +def remove_task(t): + """ + Function to remove a task. Note that this does not stop the task, just takes it out of the list + + Args: + t (str): The tag of the task to remove. + """ + + try: + vos_state.task_dict.pop(t) + except Exception: + pass + +_gc_exit=False + +async def _gc_thread(ms): + """ + Asynchronous function for optional thread to garbage collect occasionally. + + Args: + ms (int): The number of milliseconds to sleep between garbage collections. + """ + global _gc_exit + while _gc_exit==False: + await asyncio.sleep_ms(ms) + if vos_state.gc_suspend: + continue + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,"Garbage collection starting") + gc.collect() + gc.threshold(gc.mem_free() // 4 + gc.mem_alloc()) + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,"Garbage collection thread exit") + + +def vectoros_active(): + """ + Function to test if we are active. + + Returns: + bool: True if active, False otherwise. + """ + + return vos_state.active + +_vectoros_runafter=None + +def set_global_exception(): + """ + Function to catch exceptions. + """ + def handle_exception(loop,context): + import sys + if context["exception"].args[0]=="__vectoros-exit__": + vos_state.run_after=context["exception"].args[1] + else: + sys.print_exception(context["exception"]) + sys.exit() + + + loop=asyncio.get_event_loop() + loop.set_exception_handler(handle_exception) + +async def vectoros_startup(autolaunch=True): + """ + Function to start services (called by main) + + Args: + autolaunch (bool): True to launch autostart programs (default) + """ + global _VERSION + vos_state.version=_VERSION + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,f"VectorOS {_VERSION} starting",RTC().datetime()) +# honor gc thread request + if gc_thread_rate!=0: + gc.disable() + vos_state.task_dict['$gc']=asyncio.create_task(_gc_thread(gc_thread_rate)) +# spin up system-level keyboard polling (see keyboardcb and joystick) + if key_scan_rate!=0: + vos_state.task_dict['$key']=keyboardio.KeyboardIO.run(key_scan_rate) +# spin up timer infrastructure + if timer_base_rate!=0: + vos_state.task_dict['$timer']=timer.Timer.run() +# at this point, we consider ourselves running + vos_state.active=True +# launch repl if requested + if autolaunch: + if (auto_launch_repl): + await launch_repl() +# run auto launch stuff from vos_launch + for t in auto_launch_list: + vos_state.task_dict[t]=asyncio.create_task(launch(t)) + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,"VectorOS started",RTC().datetime()) + + +# shut down our service (but not apps) +def vectoros_shutdown(deactivate=True): + """ + Function to shut down vectoros services + """ + global _screen, _gc_exit + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,"VectorOS shutting down",RTC().datetime()) + _screen.idle() + _screen=None + keyboardio.KeyboardIO.cancel() + del vos_state.task_dict['$key'] + timer.Timer.cancel() + del vos_state.task_dict['$timer'] + _gc_exit=True +# vos_state.task_dict['$gc'].cancel() + del vos_state.task_dict['$gc'] + for x in vos_state.task_dict: + vos_state.task_dict[x].cancel() + if (deactivate): + vos_state.active=False + asyncio.get_event_loop().set_exception_handler(None) + gc.collect() + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,"VectorOS shut down",RTC().datetime()) + +def ext_run(cmd): + """ + Function to exit VectorOS and run a program + """ + gc.collect() + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,f"external run {cmd}") + raise Exception("__vectoros-exit__",cmd) + + + +# get all set up +async def main(): + """ + Asynchronous main function to set up the system. + + This function sets up exception handling, starts the garbage collection thread, keyboard polling, and timer infrastructure, + launches the repl if requested, imports modules from vos_launch, and runs auto launch stuff from vos_launch. + """ +# catch any strange exceptions + set_global_exception() + await vectoros_startup() + await _sleeper() + +# This is the main entry point that starts everything +def run(): + """ + Function to run the main function. + + This function runs the main function and resets the event loop. + """ + global _vectoros_runafter, _vectoros_runaftermod + cmd=None + while True: + try: + asyncio.run(main()) # do not create tasks before this point! + except SystemExit as se: + break # catch sys.exit + except Exception as e: + print(e) # shouldn't really run + print(hasattr(e,'arg')) + if hasattr(e,'arg'): + if e.arg[0]=='__vectoros-exit__': + _vectoros_runafter=e.args[1] + else: + print(e) + else: + print(e) +# This code launches a program after vectoros shutdown +# The "single core" method works more reliably but if it is +# in the second core causes stack errors (vos_state._xthreading==0) +# The vos_state._xthreading==1 case works for multicore but +# requrires a small server on the main core +#This mostly works in single core mode + finally: + if vos_state._xthreading==0: # single core mode + if vos_state.run_after != None: # as we exit, set up any pending command + cmd=vos_state.run_after + vos_state.run_after=None + else: + vos_debug.debug_print(vos_debug.DEBUG_LEVEL_INFO,"reset event loop") + asyncio.new_event_loop() + if cmd!=None: + vectoros_shutdown() + vos_state.gc_suspend=True + asyncio.sleep_ms(250) # hope the gc thread dies if it hasn't already + import sys + del sys.modules['screennorm'] + del sys.modules['aiorepl'] + del sys.modules['romans'] + del sys.modules['vga1_16x32'] + gc.collect() + exec(cmd) + else: # multicore mode (requires start w/split_vos.py) + if vos_state.run_after != None: # as we exit, set up any pending command + print("core 1 passing back to zero") + import sys + del sys.modules['screennorm'] + del sys.modules['aiorepl'] + del sys.modules['romans'] + del sys.modules['vga1_16x32'] + del sys.modules['keyboardio'] + del sys.modules['timer'] + vos_state.gc_suspend=True + asyncio.sleep_ms(250) # hope the gc thread dies if it hasn't already + gc.collect() + vectoros_shutdown(False) + gc.collect() + else: + print("Resetting event loop") + asyncio.new_event_loop() + if vos_state._xthreading==1: + gc.collect() + vos_state.active=False + else: + pass + +if __name__=="__main__": + run() + + + + + diff --git a/vectorscope.py b/vectorscope.py new file mode 100644 index 0000000..6ea6463 --- /dev/null +++ b/vectorscope.py @@ -0,0 +1,112 @@ +import gc +import time +import gc9a01 +import uctypes +import machine +import _thread + +## Badge-specific classes +from codec import Codec +from screen import Screen +from waveform import Waveform +from adc_reader import ADC_Reader +from pixel_pusher import Pixel_Pusher + +## Misc helpers and defines +import dma_defs +import pin_defs + +class Vectorscope(): + + def __init__(self, screen_running = False): + + ## Couple buttons if you want to play with them + # self.audio_shutdown_pin = machine.Pin(pin_defs.audio_shutdown, machine.Pin.OUT, value=1) + self.user_button = machine.Pin(pin_defs.user_button, machine.Pin.IN) + + ## Turn up the heat! + machine.freq(250_000_000) + + if not screen_running: + ## We actually only use the raster screen for the init routine. + ## So don't need to re-init if coming from the main menu + self.screen = Screen() + self.screen.tft.fill(gc9a01.BLACK) + ## deinit here since we don't need screen around + self.screen.deinit() + gc.collect() + + ## start up I2S state machines + self.codec = Codec() + gc.collect() + + ## Fire up the I2S output feeder + self.wave = Waveform() + gc.collect() + + ## sets up memory, DMAs to continuously read in ADC data into a 16-stage buffer + self.adc_reader = ADC_Reader() + gc.collect() + + ## automatically blits memory out to screen + ## needs adc_reader b/c needs to know where samples go + ## this is the real house of cards... + self.pixel_pusher = Pixel_Pusher(self.adc_reader) + gc.collect() + + ## start up the phosphor effect feeder on the other core, + ## b/c it's a ridiculous CPU hog with precise timing requirements + self.kill_phosphor = False + _thread.start_new_thread(self.phosphor, [()]) + + + + def phosphor(self, thread_callback_stuff): + previous_frame = self.adc_reader.current_frame + ## end of frame counter for pixel pusher, used to trigger next frame + end_of_pixel_counter = uctypes.addressof(self.pixel_pusher.frame_counter_lookup)+1024*4 + while not self.kill_phosphor: + ## wait for ADC frame change to sync up + while self.adc_reader.current_frame == previous_frame: + pass ## (@_@) this could be an async wait: should have ~10 ms of CPU time + previous_frame = self.adc_reader.current_frame + + ## While reading this ADC frame, push out all the others to the screen + ## starting with the oldest frame, + ## i.e. the next one in line. (circular buffer and all that.) + frame_counter = (self.adc_reader.current_frame + 1) & 0x0F + phosphor_counter = 1 ## this is the dimmest / off phosphor level + for i in range(15): + ## Start off a frame's worth of pixels off to the screen + self.pixel_pusher.boop(phosphor_counter, (frame_counter+i) & 0x0F) + ## next brighter color up next + phosphor_counter = phosphor_counter + 1 + ## wait for pixel frame to finish -- this is happening in a DMA/PIO chain asynchronously + while self.pixel_pusher.pixel_frame_counter.read != end_of_pixel_counter: + pass ## this one should be a busy-wait. + ## It's on the order of microseconds, depending on screen speed. + + gc.collect() ## doing this preemptively here where we have time prevents it from happening when we don't want + ## One gc.collect per 35 ms is excessive. But it makes the beast happy, and we're stalling anyway. + _thread.exit() + + def deinit(self): + + self.kill_phosphor = True + machine.freq(125_000_000) + + self.pixel_pusher.deinit() + self.adc_reader.deinit() + self.wave.deinit() + self.codec.deinit() + + ## doesn't seem to work. + ## Get OS Error 16 on next run + ## brute force... grrr... + machine.reset() + + + def call_out(self): + pass + + diff --git a/vga1_16x32.py b/vga1_16x32.py new file mode 100644 index 0000000..849069d --- /dev/null +++ b/vga1_16x32.py @@ -0,0 +1,104 @@ +WIDTH = 16 +HEIGHT = 32 +FIRST = 0x20 +LAST = 0x7f +_FONT = \ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x7f\xfe\x7f\xfe\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x7f\xfe\x7f\xfe\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x01\x80\x01\x80\x0f\xf0\x0f\xf0\x39\x9c\x39\x9c\x71\x8e\x71\x8e\x71\x80\x71\x80\x39\x80\x39\x80\x0f\xf0\x0f\xf0\x01\x9c\x01\x9c\x01\x8e\x01\x8e\x71\x8e\x71\x8e\x39\x9c\x39\x9c\x0f\xf0\x0f\xf0\x01\x80\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1e\x1c\x1e\x1c\x1e\x38\x1e\x38\x00\x70\x00\x70\x00\xe0\x00\xe0\x01\xc0\x01\xc0\x03\x80\x03\x80\x07\x00\x07\x00\x0e\x3c\x0e\x3c\x1c\x3c\x1c\x3c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xc0\x07\xc0\x1c\x70\x1c\x70\x38\x38\x38\x38\x1c\x70\x1c\x70\x07\xc0\x07\xc0\x0f\xce\x0f\xce\x38\xfc\x38\xfc\x70\x78\x70\x78\x70\x78\x70\x78\x38\xfc\x38\xfc\x0f\xce\x0f\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\xe0\x00\xe0\x01\xc0\x01\xc0\x03\x80\x03\x80\x07\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\xe0\x01\xc0\x01\xc0\x03\x80\x03\x80\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x03\x80\x03\x80\x01\xc0\x01\xc0\x00\xe0\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x07\x00\x03\x80\x03\x80\x01\xc0\x01\xc0\x00\xe0\x00\xe0\x00\xe0\x00\xe0\x00\xe0\x00\xe0\x00\xe0\x00\xe0\x00\xe0\x00\xe0\x01\xc0\x01\xc0\x03\x80\x03\x80\x07\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x38\x0e\x38\x03\xe0\x03\xe0\x3f\xfe\x3f\xfe\x03\xe0\x03\xe0\x0e\x38\x0e\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x3f\xfe\x3f\xfe\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x03\x80\x03\x80\x07\x00\x07\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfe\x3f\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xc0\x03\xc0\x03\xc0\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x1c\x00\x38\x00\x38\x00\x70\x00\x70\x00\xe0\x00\xe0\x01\xc0\x01\xc0\x03\x80\x03\x80\x07\x00\x07\x00\x0e\x00\x0e\x00\x1c\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xe0\x07\xe0\x1c\x38\x1c\x38\x38\x3c\x38\x3c\x38\x7c\x38\x7c\x38\xdc\x38\xdc\x39\x9c\x39\x9c\x3b\x1c\x3b\x1c\x3e\x1c\x3e\x1c\x3c\x1c\x3c\x1c\x1c\x38\x1c\x38\x07\xe0\x07\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x01\xc0\x03\xc0\x03\xc0\x0f\xc0\x0f\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xf0\x0f\xf0\x38\x1c\x38\x1c\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x1c\x00\x1c\x00\x70\x00\x70\x01\xc0\x01\xc0\x07\x00\x07\x00\x1c\x00\x1c\x00\x38\x00\x38\x00\x3f\xfe\x3f\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xf0\x0f\xf0\x38\x1c\x38\x1c\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x1c\x00\x1c\x01\xf0\x01\xf0\x00\x1c\x00\x1c\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x38\x1c\x38\x1c\x0f\xf0\x0f\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x01\xf0\x01\xf0\x03\xf0\x03\xf0\x07\x70\x07\x70\x0e\x70\x0e\x70\x1c\x70\x1c\x70\x38\x70\x38\x70\x3f\xfc\x3f\xfc\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfe\x3f\xfe\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x3f\xf0\x3f\xf0\x00\x1c\x00\x1c\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x38\x1c\x38\x1c\x0f\xf0\x0f\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x07\xf0\x1c\x00\x1c\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x3f\xf0\x3f\xf0\x38\x1c\x38\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x1c\x1c\x1c\x1c\x07\xf0\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xf8\x3f\xf8\x00\x38\x00\x38\x00\x38\x00\x38\x00\x70\x00\x70\x00\xe0\x00\xe0\x01\xc0\x01\xc0\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x07\xf0\x1c\x1c\x1c\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x1c\x1c\x1c\x1c\x07\xf0\x07\xf0\x1c\x1c\x1c\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x1c\x1c\x1c\x1c\x07\xf0\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x07\xf0\x1c\x1c\x1c\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x1c\x0e\x1c\x0e\x07\xfe\x07\xfe\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x1c\x00\x1c\x0f\xf0\x0f\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x80\x03\x80\x03\x80\x03\x80\x07\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\xe0\x01\xc0\x01\xc0\x03\x80\x03\x80\x07\x00\x07\x00\x0e\x00\x0e\x00\x1c\x00\x1c\x00\x0e\x00\x0e\x00\x07\x00\x07\x00\x03\x80\x03\x80\x01\xc0\x01\xc0\x00\xe0\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfc\x3f\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfc\x3f\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x07\x00\x03\x80\x03\x80\x01\xc0\x01\xc0\x00\xe0\x00\xe0\x00\x70\x00\x70\x00\x38\x00\x38\x00\x70\x00\x70\x00\xe0\x00\xe0\x01\xc0\x01\xc0\x03\x80\x03\x80\x07\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xe0\x07\xe0\x1c\x38\x1c\x38\x38\x1c\x38\x1c\x00\x38\x00\x38\x00\x70\x00\x70\x00\xe0\x00\xe0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xf0\x0f\xf0\x38\x1c\x38\x1c\x70\x0e\x70\x0e\x71\xfe\x71\xfe\x73\x8e\x73\x8e\x73\x8e\x73\x8e\x73\x8e\x73\x8e\x71\xfc\x71\xfc\x70\x00\x70\x00\x38\x00\x38\x00\x0f\xfc\x0f\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x03\xc0\x03\xc0\x07\xe0\x07\xe0\x0e\x70\x0e\x70\x1c\x38\x1c\x38\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x3f\xfc\x3f\xfc\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xf0\x3f\xf0\x38\x1c\x38\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x1c\x38\x1c\x3f\xf0\x3f\xf0\x38\x1c\x38\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x1c\x38\x1c\x3f\xf0\x3f\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x07\xf0\x1c\x1c\x1c\x1c\x38\x0e\x38\x0e\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x0e\x38\x0e\x1c\x1c\x1c\x1c\x07\xf0\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xf0\x3f\xf0\x38\x1c\x38\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x1c\x38\x1c\x3f\xf0\x3f\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfc\x3f\xfc\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x3f\xe0\x3f\xe0\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x3f\xfc\x3f\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfc\x3f\xfc\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x3f\xe0\x3f\xe0\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x07\xf0\x1c\x1c\x1c\x1c\x38\x0e\x38\x0e\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x3e\x38\x3e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x1c\x1c\x1c\x1c\x07\xf0\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x3f\xfe\x3f\xfe\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x00\x1c\x1c\x1c\x1c\x1c\x0e\x38\x0e\x38\x03\xe0\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x38\x1c\x38\x1c\x70\x1c\x70\x1c\xe0\x1c\xe0\x1d\xc0\x1d\xc0\x1f\x80\x1f\x80\x1f\x80\x1f\x80\x1d\xc0\x1d\xc0\x1c\xe0\x1c\xe0\x1c\x70\x1c\x70\x1c\x38\x1c\x38\x1c\x1c\x1c\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x3f\xfc\x3f\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x78\x1e\x78\x1e\x7c\x3e\x7c\x3e\x7e\x7e\x7e\x7e\x77\xee\x77\xee\x73\xce\x73\xce\x71\x8e\x71\x8e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x38\x0e\x38\x0e\x3c\x0e\x3c\x0e\x3e\x0e\x3e\x0e\x3f\x0e\x3f\x0e\x3b\x8e\x3b\x8e\x39\xce\x39\xce\x38\xee\x38\xee\x38\x7e\x38\x7e\x38\x3e\x38\x3e\x38\x1e\x38\x1e\x38\x0e\x38\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x07\xf0\x1c\x1c\x1c\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x1c\x1c\x1c\x1c\x07\xf0\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xf0\x3f\xf0\x38\x1c\x38\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x1c\x38\x1c\x3f\xf0\x3f\xf0\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x07\xf0\x1c\x1c\x1c\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\xee\x38\xee\x1c\x7c\x1c\x7c\x07\xf8\x07\xf8\x00\x1c\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xf0\x3f\xf0\x38\x1c\x38\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x1c\x38\x1c\x3f\xf0\x3f\xf0\x38\xe0\x38\xe0\x38\x70\x38\x70\x38\x38\x38\x38\x38\x1c\x38\x1c\x38\x0e\x38\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xf0\x0f\xf0\x38\x1c\x38\x1c\x70\x0e\x70\x0e\x70\x00\x70\x00\x38\x00\x38\x00\x0f\xf0\x0f\xf0\x00\x1c\x00\x1c\x00\x0e\x00\x0e\x70\x0e\x70\x0e\x38\x1c\x38\x1c\x0f\xf0\x0f\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfe\x3f\xfe\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x1c\x1c\x1c\x1c\x07\xf0\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x1c\x38\x1c\x38\x0e\x70\x0e\x70\x07\xe0\x07\xe0\x03\xc0\x03\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x70\x0e\x71\x8e\x71\x8e\x73\xce\x73\xce\x77\xee\x77\xee\x3e\x7c\x3e\x7c\x1c\x38\x1c\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x1c\x38\x1c\x38\x0e\x70\x0e\x70\x07\xe0\x07\xe0\x03\xc0\x03\xc0\x07\xe0\x07\xe0\x0e\x70\x0e\x70\x1c\x38\x1c\x38\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x38\x0e\x38\x0e\x1c\x1c\x1c\x1c\x0e\x38\x0e\x38\x07\x70\x07\x70\x03\xe0\x03\xe0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfe\x3f\xfe\x00\x1c\x00\x1c\x00\x38\x00\x38\x00\x70\x00\x70\x00\xe0\x00\xe0\x01\xc0\x01\xc0\x03\x80\x03\x80\x07\x00\x07\x00\x0e\x00\x0e\x00\x1c\x00\x1c\x00\x3f\xfe\x3f\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x07\xf0\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\x00\x07\xf0\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x1c\x00\x0e\x00\x0e\x00\x07\x00\x07\x00\x03\x80\x03\x80\x01\xc0\x01\xc0\x00\xe0\x00\xe0\x00\x70\x00\x70\x00\x38\x00\x38\x00\x1c\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x07\xf0\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x07\xf0\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x03\xc0\x03\xc0\x07\xe0\x07\xe0\x0e\x70\x0e\x70\x1c\x38\x1c\x38\x38\x1c\x38\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x07\x00\x07\x00\x03\x80\x03\x80\x01\xc0\x01\xc0\x00\xe0\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xf8\x0f\xf8\x00\x0e\x00\x0e\x0f\xfe\x0f\xfe\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x0f\xfe\x0f\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x3f\xf0\x3f\xf0\x38\x1c\x38\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x3f\xf8\x3f\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xf8\x0f\xf8\x38\x0e\x38\x0e\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x0e\x38\x0e\x0f\xf8\x0f\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x07\xfe\x07\xfe\x1c\x0e\x1c\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x0f\xfe\x0f\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xf8\x0f\xf8\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x3f\xfe\x3f\xfe\x38\x00\x38\x00\x38\x00\x38\x00\x0f\xfc\x0f\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x00\xf8\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x0f\xf0\x0f\xf0\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xf8\x0f\xf8\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x0f\xfe\x0f\xfe\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x1f\xf8\x1f\xf8\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x3b\xf8\x3b\xf8\x3c\x0e\x3c\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x00\x70\x00\x70\x00\x70\x00\x00\x00\x00\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\x70\x00\xe0\x00\xe0\x0f\x80\x0f\x80\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x38\x0e\x38\x0e\x70\x0e\x70\x0e\xe0\x0e\xe0\x0f\xc0\x0f\xc0\x0e\xe0\x0e\xe0\x0e\x70\x0e\x70\x0e\x38\x0e\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3e\x78\x3e\x78\x39\xce\x39\xce\x39\xce\x39\xce\x39\xce\x39\xce\x39\xce\x39\xce\x39\xce\x39\xce\x39\xce\x39\xce\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xe0\x3f\xe0\x38\x38\x38\x38\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xf0\x07\xf0\x1c\x1c\x1c\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x1c\x1c\x1c\x1c\x07\xf0\x07\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xf0\x3f\xf0\x38\x1c\x38\x1c\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x1c\x38\x1c\x3f\xf0\x3f\xf0\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07\xfe\x07\xfe\x1c\x0e\x1c\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x1c\x0e\x1c\x0e\x07\xfe\x07\xfe\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xf0\x3f\xf0\x38\x1c\x38\x1c\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\xfc\x0f\xfc\x38\x00\x38\x00\x38\x00\x38\x00\x0f\xf8\x0f\xf8\x00\x0e\x00\x0e\x00\x0e\x00\x0e\x1f\xf8\x1f\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x1f\xfc\x1f\xfc\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x38\x1c\x0f\xfc\x0f\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x70\x0e\x70\x0e\x38\x1c\x38\x1c\x1c\x38\x1c\x38\x0e\x70\x0e\x70\x07\xe0\x07\xe0\x03\xc0\x03\xc0\x01\x80\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x38\x0e\x39\xce\x39\xce\x3b\xee\x3b\xee\x1f\x7c\x1f\x7c\x0e\x38\x0e\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c\x38\x1c\x38\x0e\x70\x0e\x70\x07\xe0\x07\xe0\x03\xc0\x03\xc0\x07\xe0\x07\xe0\x0e\x70\x0e\x70\x1c\x38\x1c\x38\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\x0e\x38\x0e\x1c\x1c\x1c\x1c\x0e\x38\x0e\x38\x07\x70\x07\x70\x03\xe0\x03\xe0\x01\xc0\x01\xc0\x03\x80\x03\x80\x07\x00\x07\x00\x0e\x00\x0e\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x3f\xfe\x3f\xfe\x00\x1c\x00\x1c\x00\x70\x00\x70\x01\xc0\x01\xc0\x07\x00\x07\x00\x1c\x00\x1c\x00\x3f\xfe\x3f\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x00\xf8\x01\xc0\x01\xc0\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x1e\x00\x1e\x00\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x03\x80\x01\xc0\x01\xc0\x00\xf8\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x1f\x00\x03\x80\x03\x80\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x00\x78\x00\x78\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x01\xc0\x03\x80\x03\x80\x1f\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x07\x9e\x07\x9e\x3c\xf0\x3c\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ +b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x01\xc0\x07\x70\x07\x70\x1c\x1c\x1c\x1c\x70\x07\x70\x07\x70\x07\x70\x07\x7f\xff\x7f\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'\ + +FONT = memoryview(_FONT) + diff --git a/vos_debug.py b/vos_debug.py new file mode 100644 index 0000000..75696f7 --- /dev/null +++ b/vos_debug.py @@ -0,0 +1,17 @@ + + +DEBUG_LEVEL_SILENT=-1 +DEBUG_LEVEL_SEVERE=0 +DEBUG_LEVEL_ERROR=10 +DEBUG_LEVEL_WARNING=20 +DEBUG_LEVEL_INFO=30 + +from vos_launch import debug_level + +def debug_print(level,*args): + """ + Function to print debug messages that are lower than debug level (set in vos_launch.py) + """ + if level<=debug_level: + return print(*args) + \ No newline at end of file diff --git a/vos_launch.py b/vos_launch.py new file mode 100644 index 0000000..6892840 --- /dev/null +++ b/vos_launch.py @@ -0,0 +1,40 @@ +# list of things to launch from vectoros + +# dictionary of tags to imports (will look for .vos_main() or .main() here) +launch_list={ "menu": "supercon_menu", 'sketch': 'sketch', "demo": "examples", "planets":"planets", "lissajous":"lissajous"} + +# list what you want to start auto (maybe just one thing?) need tag +auto_launch_list=["menu"] + +vectorscope_slots={"slotA": "A", "slotB": "B", "slotC": "C", "slotD": "D"} + +auto_launch_repl=False # to get out: import sys followed by sys.exit() + +key_scan_rate = 100 # how often to scan the keyboard globally (ms; 0 to do it yourself) + +# how often to garbage collect +# if you set this to zero and do nothing else +# garbage collection will be automatic as usual and before new tasks launch +gc_thread_rate = 5000 + +# Base rate for the timer (ms) +timer_base_rate=100 + +# Debug level (messages must be < this level to print) +# That is, at level 0 only level 0 messages print +# at level 1 then level 1 and level 0 messages print +# Set level to -1 to stop all messages (assuming you only call debug_print with positive values) + +# if you want to use symbols for debug level, these are defined in vos_debug: +DEBUG_LEVEL_SILENT=-1 +DEBUG_LEVEL_SEVERE=0 +DEBUG_LEVEL_ERROR=10 +DEBUG_LEVEL_WARNING=20 +DEBUG_LEVEL_INFO=30 + +debug_level=DEBUG_LEVEL_INFO + + +if __name__=="__main__": + import vectoros + vectoros.run() diff --git a/vos_state.py b/vos_state.py new file mode 100644 index 0000000..a282282 --- /dev/null +++ b/vos_state.py @@ -0,0 +1,18 @@ +# state for vector os + +class vos_state: + task_dict={} # tasks created (not removed, though, unless you do it yourself + active=False # are we active? + gc_suspend=False # do you want to suspend the gc? + show_menu=True # Used to restart main menu + run_after=None # Run after OS is done + version=None # Version (filled in on init) + _xthreading=0 + + +# put any globals you want for your application here (nice to put them "in" something like a dictionary + +# global my_task_vars={"exit_flag": False, "rate": 200} + + + \ No newline at end of file diff --git a/waveform.py b/waveform.py new file mode 100644 index 0000000..2e36fe7 --- /dev/null +++ b/waveform.py @@ -0,0 +1,132 @@ +import dma_defs +import pin_defs +import codec +import math +import struct +import time +import array +import rp2 +import machine +from uctypes import addressof + + +## Set up sample memory arrays + +_DEBUG = const(False) + +class Waveform(): + def __init__(self, num_samples_per_frame=256): + + self.outBuffer_ready = False ## flag raised when a sample gets stored and the outBuffers can be written to + ## your code needs to clear this from outside, then wait for next True to sync up + ## at 30 kHz it's about every 38 ms. + self.num_samples = num_samples_per_frame + self.outBufferX = bytearray(self.num_samples * 2) ## 2 bytes, 1 channel + self.outBufferY = bytearray(self.num_samples * 2) + self.outBuffer = bytearray(self.num_samples * 4) ## interleave + self.outBuffer_addr = array.array("L", [addressof(self.outBuffer)]) + + ## This DMA takes the whole block of samples and feeds them off to + ## the codec's write PIO state machine + ## It fires off an IRQ (feed_dac_irq_handler) when it's done with a round + ## feed_dac_irq_handler interleaves the two sample channels and queues them up + self.feed_dac_transfer = rp2.DMA() + ## And this DMA is chained to the above, resets it back to the beginning + self.feed_dac_control = rp2.DMA() + ## Control defs: + ## {'inc_read': 0, 'high_pri': 0, 'ring_sel': 0, 'size': 0, + ## 'enable': 0, 'treq_sel': 0, 'sniff_en': 0, 'chain_to': 0, + ## 'inc_write': 0, 'ring_size': 0, 'bswap': 0, 'IRQ_quiet': 0} + self.feed_dac_transfer.ctrl = self.feed_dac_transfer.pack_ctrl(default = 0, + size = dma_defs.SIZE_4BYTES, + enable = 1, + treq_sel = dma_defs.DREQ_PIO0_TX1, + chain_to = self.feed_dac_control.channel_id, + bswap = 1, + IRQ_quiet = 0, + inc_read = 1) + self.feed_dac_transfer.config(count = self.num_samples, write = codec.WRITE_FIFO) + self.feed_dac_transfer.irq(handler=self.feed_dac_irq_handler, hard=False) + + self.feed_dac_control.ctrl = self.feed_dac_control.pack_ctrl(default = 0, + size = dma_defs.SIZE_4BYTES, ## addresses + enable = 1, + chain_to = self.feed_dac_control.channel_id, ## no chain + treq_sel = dma_defs.TREQ_PERMANENT, ## always on + IRQ_quiet = 1) + self.feed_dac_control.config(count = 1, + write = self.feed_dac_transfer.registers[15:], + read = addressof(self.outBuffer_addr), + trigger = True) + if _DEBUG: + self.debug_pin = machine.Pin(28, machine.Pin.OUT, value=0) + + def init(self): + self.__init__() + + def deinit(self): + """unwind all of the above""" + print("(@_@) TODO: verify DMA shuts down") + self.feed_dac_control.ctrl = 0 + time.sleep_ms(10) ## (@_@) replace with asyncio when necessary + self.feed_dac_transfer.ctrl = 0 + self.feed_dac_control.close() + time.sleep_ms(10) ## (@_@) replace with asyncio when necessary + self.feed_dac_transfer.close() + + ## 175 us? not horrible -- roughly 6 sample frames, have 256 + @micropython.viper + def interleave_buffers(self): + bufX_p = ptr16(self.outBufferX) + bufY_p = ptr16(self.outBufferY) + out_buffer_p = ptr32(self.outBuffer) + num_samples = int(self.num_samples) + for i in range(num_samples): + out_buffer_p[i] = (bufY_p[i] << 16) + bufX_p[i] + + @micropython.viper + def feed_dac_irq_handler(self, calling_dma): + ## this is where the magic happens + ## roughly every 8.5 ms @ 256 samples + if _DEBUG: + self.debug_pin.high() + self.interleave_buffers() + self.outBuffer_ready = True + ## Ping the user to load up their data + if _DEBUG: + self.debug_pin.low() + + ## Get data into the buffers + @micropython.viper + def _constant(self, value:int, buffer): + buffer_p = ptr8(buffer) + num_samples = int(self.num_samples) + for i in range(num_samples): + buffer_p[2*i+0] = (value & 0xFF00) >> 8 + buffer_p[2*i+1] = value & 0x00FF + + @micropython.viper + def _pack_wave(self, wavelist, buffer): + """takes a list of integers, +/- 15 bits worth, and packs it into a buffer""" + buffer_p = ptr8(buffer) + num_samples = int(self.num_samples) + for i in range(num_samples): + sample = int(wavelist[i]) + buffer_p[2*i+0] = (sample & 0xFF00) >> 8 + buffer_p[2*i+1] = sample & 0x00FF + + ## Convenience functions + def packX(self, wavelist): + self._pack_wave(wavelist, self.outBufferX) + def packY(self, wavelist): + self._pack_wave(wavelist, self.outBufferY) + def constantX(self, value:int): + self._constant(value, self.outBufferX) + def constantY(self, value:int): + self._constant(value, self.outBufferY) + def point(self, x:int, y:int): + self._constant(x, self.outBufferX) + self._constant(y, self.outBufferY) + + +