def get_spi(self): spi = None id = 1 try: if config_sensorboard.SOFT_SPI: id = 1 #LoBo id = -1 #spi = SPI(id, baudrate = 10000000, polarity = 0, phase = 0, bits = 8, firstbit = SPI.MSB, # LoBo spi = SPI(id, baudrate=10000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(self.PIN_ID_SCK, Pin.OUT, Pin.PULL_DOWN), mosi=Pin(self.PIN_ID_MOSI, Pin.OUT, Pin.PULL_UP), miso=Pin(self.PIN_ID_MISO, Pin.IN, Pin.PULL_UP)) spi.init() except Exception as e: print(e) if spi: spi.deinit() spi = None reset() # in case SPI is already in use, need to reset. return spi
def main(): ''' Decode and draw the jpg on the display ''' try: # Turn display power axp = axp202c.PMU(address=0x34) axp.enablePower(axp202c.AXP192_LDO2) # Set backlight voltage axp.setDC3Voltage(3000) spi = SPI(2, baudrate=60000000, sck=Pin(18), mosi=Pin(23)) # initialize display tft = ili9342c.ILI9342C(spi, 320, 240, reset=Pin(33, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(15, Pin.OUT), rotation=0) # enable display and clear screen tft.init() # display jpg tft.jpg("bigbuckbunny.jpg", 0, 0, ili9342c.SLOW) finally: # shutdown spi if 'spi' in locals(): spi.deinit()
def main(): try: spi = SPI(2, baudrate=30000000, sck=Pin(18), mosi=Pin(19)) tft = st7789.ST7789(spi, 135, 240, reset=Pin(23, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(16, Pin.OUT), backlight=Pin(4, Pin.OUT), rotation=3) # enable display and clear screen tft.init() tft.fill(st7789.BLACK) row = 0 tft.write(font_16, "abcdefghijklmnopqrst", 0, row) row += font_16.HEIGHT tft.write(font_32, "abcdefghij", 0, row) row += font_32.HEIGHT tft.write(font_64, "abcd", 0, row) row += font_64.HEIGHT finally: # shutdown spi if 'spi' in locals(): spi.deinit()
def main(): ''' Decode and draw jpg on display ''' try: spi = SPI(2, baudrate=30000000, sck=Pin(18), mosi=Pin(19)) tft = st7789.ST7789(spi, 135, 240, reset=Pin(23, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(16, Pin.OUT), backlight=Pin(4, Pin.OUT), rotation=3) # enable display and clear screen tft.init() # display jpg tft.jpg("bigbuckbunny.jpg", 0, 0, st7789.SLOW) finally: # shutdown spi spi.deinit()
def main(): ''' Decode and draw jpg on display ''' try: # Turn on display backlight axp = axp202c.PMU() axp.enablePower(axp202c.AXP202_LDO2) # initialize display spi port spi = SPI( 2, baudrate=32000000, sck=Pin(18, Pin.OUT), mosi=Pin(19, Pin.OUT)) # configure display tft = st7789.ST7789( spi, 240, 240, cs=Pin(5, Pin.OUT), dc=Pin(27, Pin.OUT), backlight=Pin(12, Pin.OUT), rotation=2) # enable display and clear screen tft.init() # display jpg tft.jpg("bigbuckbunny.jpg", 0, 0, st7789.SLOW) finally: # shutdown spi spi.deinit()
def get_spi(self): spi = None id = 1 if config_lora.IS_ESP8266: spi = SPI(id, baudrate=10000000, polarity=0, phase=0) spi.init() if config_lora.IS_ESP32: try: if config_lora.SOFT_SPI: id = -1 #soft spi else: id = 1 #hardware spi spi = SPI(id, baudrate=10000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(self.PIN_ID_SCK, Pin.OUT, Pin.PULL_DOWN), mosi=Pin(self.PIN_ID_MOSI, Pin.OUT, Pin.PULL_UP), miso=Pin(self.PIN_ID_MISO, Pin.IN, Pin.PULL_UP)) spi.init() except Exception as e: print(e) if spi: spi.deinit() spi = None reset() # in case SPI is already in use, need to reset. return spi
class MAX6675: def __init__(self, sck, mosi, miso, cs): ''' self.spi = SPI(1, baudrate=200000, polarity=0, phase=0) self.spi.init(baudrate=200000) # set the baudrate # (SPI(0) 仅用于内部的 FlashROM。) ''' self.cs = cs self.cs.on() # 使能引脚拉高self.cs = cs self.spi = SPI(1, baudrate=100000, polarity=1, phase=0) # self.spi = SPI(-1, baudrate=1000000, polarity=1, # phase=0, sck=sck, mosi=mosi, miso=miso) self.connect = False def read_temperature(self, ): """ 读取一次温度(摄氏度),读取错误或者热电偶异常均返回4095 """ self.cs.off() # CS引脚检测到下降沿后停止转换。随后在sck时钟控制下输出16位数据 value = self.spi.read(2) # 读取两个字节 self.cs.on() temp = value[0] << 8 | value[1] self.connect = True if (temp & MAX6675_CONNECT) == 0 else False gc.collect() if self.connect == True: # 没检测到电热偶 return ((temp & 0x7FFF) >> 3) >> 2 # 测得的温度单位是0.25,所以要乘以0.25(即除以4) else: return 4095 def __del__(self, ): self.spi.deinit() # 关闭spi
def main(): ''' Decode and draw jpg on display ''' try: spi = SPI(2, baudrate=30000000, sck=Pin(18), mosi=Pin(19)) tft = st7789.ST7789(spi, 135, 240, reset=Pin(23, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(16, Pin.OUT), backlight=Pin(4, Pin.OUT), rotation=3, buffer_size=30 * 30 * 2) # enable display and clear screen tft.init() # display jpg in random locations while True: tft.rotation(random.randint(0, 4)) tft.jpg("alien.jpg", random.randint(0, tft.width() - 30), random.randint(0, tft.height() - 30), st7789.FAST) finally: # shutdown spi spi.deinit()
def load_bitstream(bitstream): filestream = None if type(bitstream) == str: filestream = open(bitstream, "rb") elif type(bitstream) == FileIO: filestream = bitstream else: raise ValueError("bitstream must be filename name or file handle") spi = SPI(hwice40.SPI_ID, TRANSFER_RATE) hwice40.chip_select(False) hwice40.reset(True) sleep(0.1) hwice40.reset(False) hwice40.chip_select(True) spi.write(b"\x00") hwice40.chip_select(False) sleep(0.1) if hwice40.done_state(): print("Error resetting fpga") return False while True: bitstreampart = filestream.read( TRANSFER_SIZE) #TODO: change to readinto to resuse single buffer if not bitstreampart: break spi.write(bitstreampart) hwice40.chip_select(True) spi.write(bytes(10 * [0])) spi.deinit() del (spi) return hwice40.done_state()
def get_spi(self): if config.CONFIG.SOFT_SPI: spi_id = -1 else: spi_id = 1 try: spi = SPI(spi_id, baudrate=10000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(self.LORA_SCK, Pin.OUT, Pin.PULL_DOWN), mosi=Pin(self.LORA_MOSI, Pin.OUT, Pin.PULL_UP), miso=Pin(self.LORA_MISO, Pin.IN, Pin.PULL_UP)) spi.init() except Exception as e: print(e) if spi: spi.deinit() reset() # in case SPI is already in use, need to reset. raise return spi
def main(): ''' Draw and move sprite ''' try: spi = SPI(1, baudrate=30000000, sck=Pin(18), mosi=Pin(19)) # initialize display tft = st7789.ST7789( spi, 135, 240, reset=Pin(23, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(16, Pin.OUT), backlight=Pin(4, Pin.OUT), rotation=0, buffer_size=64*64*2) # enable display and clear screen tft.init() tft.fill(st7789.BLACK) # create toast spites in random positions sprites = [ toast(TOASTERS, 135-64, 0), toast(TOAST, 135-64*2, 80), toast(TOASTERS, 135-64*4, 160) ] # move and draw sprites while True: for man in sprites: bitmap = man.sprites[man.step] tft.fill_rect( man.x+bitmap.WIDTH-man.speed, man.y, man.speed, bitmap.HEIGHT, st7789.BLACK) man.move() if man.x > 0: tft.bitmap(bitmap, man.x, man.y) else: tft.fill_rect( 0, man.y, bitmap.WIDTH, bitmap.HEIGHT, st7789.BLACK) time.sleep(0.05) finally: # shutdown spi spi.deinit()
class MicroPython: # Pin definition RST_PIN_NO = 26 DC_PIN_NO = 27 CS_PIN_NO = 15 BUSY_PIN_NO = 25 SCK_PIN_NO = 13 MOSI_PIN_NO = 14 def __init__(self): # preimport utime import utime # pylint: disable=C0415, W0611 from machine import Pin # pylint: disable=C0415 self.DC_PIN = Pin(self.DC_PIN_NO, Pin.OUT) self.CS_PIN = Pin(self.CS_PIN_NO, Pin.OUT, Pin.PULL_UP) self.RST_PIN = Pin(self.RST_PIN_NO, Pin.OUT) self.BUSY_PIN = Pin(self.BUSY_PIN_NO, Pin.IN) self.spi = None def digital_write(self, pin, value): pin.value(value) def digital_read(self, pin): return pin.value() def spi_writebyte(self, data): self.spi.write(data) def delay_ms(self, delaytime): import utime # pylint: disable=C0415 utime.sleep_ms(delaytime) def module_init(self): if self.spi is None: from machine import Pin, SPI # pylint: disable=C0415 sck = Pin(self.SCK_PIN_NO, Pin.OUT) mosi = Pin(self.MOSI_PIN_NO, Pin.OUT) self.spi = SPI(2, baudrate=32000000, polarity=0, phase=0, sck=sck, mosi=mosi) return 0 def module_exit(self): self.spi.deinit() self.spi = None logger.debug("close 5V, Module enters 0 power consumption ...") self.RST_PIN.value(0) self.DC_PIN.value(0)
def main(): try: # Turn on display backlight axp = axp202c.PMU() axp.enablePower(axp202c.AXP202_LDO2) # initialize display spi port spi = SPI( 2, baudrate=32000000, polarity=1, phase=0, bits=8, firstbit=0, sck=Pin(18), mosi=Pin(19)) # configure display tft = st7789.ST7789( spi, 240, 240, cs=Pin(5, Pin.OUT), dc=Pin(27, Pin.OUT), backlight=Pin(12, Pin.OUT), rotation=2) tft.init() while True: for font in (font1, font2, font3, font4): tft.fill(st7789.BLUE) line = 0 col = 0 for char in range(font.FIRST, font.LAST): tft.text(font, chr(char), col, line, st7789.WHITE, st7789.BLUE) col += font.WIDTH if col > tft.width() - font.WIDTH: col = 0 line += font.HEIGHT if line > tft.height()-font.HEIGHT: utime.sleep(3) tft.fill(st7789.BLUE) line = 0 col = 0 utime.sleep(3) finally: # shutdown spi spi.deinit() # turn off display backlight axp.disablePower(axp202c.AXP202_LDO2)
def main(): fast = False def display_font(font): tft.fill(st7789.BLUE) column = 0 row = 0 for char in font.MAP: tft.bitmap(font, column, row, font.MAP.index(char)) column += font.WIDTH if column >= tft.width() - font.WIDTH: row += font.HEIGHT column = 0 if row > tft.height() - font.HEIGHT: row = 0 if not fast: time.sleep(0.05) try: # Turn power on display power axp = axp202c.PMU() axp.enablePower(axp202c.AXP202_LDO2) # initialize spi port spi = SPI(1, baudrate=32000000, sck=Pin(18, Pin.OUT), mosi=Pin(19, Pin.OUT)) # configure display tft = st7789.ST7789(spi, 240, 240, cs=Pin(5, Pin.OUT), dc=Pin(27, Pin.OUT), backlight=Pin(12, Pin.OUT), rotation=2, buffer_size=66 * 32 * 2) tft.init() while True: for font in [font_16, font_32, font_64]: display_font(font) fast = not fast finally: # shutdown spi spi.deinit() # turn off display power axp.disablePower(axp202c.AXP202_LDO2)
def main(): ''' Draw and move sprite ''' try: # Turn display power axp = axp202c.PMU(address=0x34) axp.enablePower(axp202c.AXP192_LDO2) # Set backlight voltage axp.setDC3Voltage(3000) spi = SPI(2, baudrate=60000000, sck=Pin(18), mosi=Pin(23)) # initialize display tft = ili9342c.ILI9342C(spi, 320, 240, reset=Pin(33, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(15, Pin.OUT), rotation=0) # enable display and clear screen tft.init() tft.fill(ili9342c.BLACK) # create toast spites in random positions sprites = [ toast(TOASTERS, 320 - 64, 0), toast(TOAST, 320 - 64 * 2, 80), toast(TOASTERS, 320 - 64 * 4, 160) ] # move and draw sprites while True: for man in sprites: bitmap = man.sprites[man.step] tft.fill_rect(man.x + bitmap.WIDTH - man.speed, man.y, man.speed, bitmap.HEIGHT, ili9342c.BLACK) man.move() if man.x > 0: tft.bitmap(bitmap, man.x, man.y) else: tft.fill_rect(0, man.y, bitmap.WIDTH, bitmap.HEIGHT, ili9342c.BLACK) finally: # shutdown spi if 'spi' in locals(): spi.deinit()
def main(): def center(font, s, row, color=st7789.WHITE): screen = tft.width() # get screen width width = tft.write_len(font, s) # get the width of the string if width and width < screen: # if the string < display col = tft.width() // 2 - width // 2 # find the column to center else: # otherwise col = 0 # left justify tft.write(font, s, col, row, color) # and write the string try: # Turn power on display power axp = axp202c.PMU() axp.enablePower(axp202c.AXP202_LDO2) # initialize spi port spi = SPI(1, baudrate=32000000, sck=Pin(18, Pin.OUT), mosi=Pin(19, Pin.OUT)) # configure display tft = st7789.ST7789(spi, 240, 240, cs=Pin(5, Pin.OUT), dc=Pin(27, Pin.OUT), backlight=Pin(12, Pin.OUT), rotation=2, buffer_size=16 * 32 * 2) # enable display tft.init() tft.fill(st7789.BLACK) # center the name of the first font, using the font row = 16 center(noto_sans, "NotoSans", row, st7789.RED) row += noto_sans.HEIGHT # center the name of the second font, using the font center(noto_serif, "NotoSerif", row, st7789.GREEN) row += noto_serif.HEIGHT # center the name of the third font, using the font center(noto_mono, "NotoSansMono", row, st7789.BLUE) row += noto_mono.HEIGHT finally: # shutdown spi if 'spi' in locals(): spi.deinit()
def initSD(): counter = 0 vext_pin = Pin(21, Pin.OUT, value=0) cs_lora = Pin(18, Pin.OUT, value=1) #para desactivar LoRa while counter < 3: spi = SPI(sck=Pin(5), mosi=Pin(27), miso=Pin(19)) try: sd = sdcard.SDCard(spi, Pin(2, Pin.OUT)) return sd except Exception as e: print("Error al montar sd, intento " + str(counter) + " excepcion: " + str(e)) spi.deinit() counter += 1 return None
def main(): ''' Draw greetings on display cycling thru hershey fonts and colors ''' try: # Turn power on display power axp = axp202c.PMU() axp.enablePower(axp202c.AXP202_LDO2) axp.enablePower(axp202c.AXP202_DCDC3) # initialize spi port spi = SPI(2, baudrate=32000000, polarity=1, phase=0, bits=8, firstbit=0, sck=Pin(18, Pin.OUT), mosi=Pin(19, Pin.OUT)) # configure display tft = st7789.ST7789(spi, 240, 240, cs=Pin(5, Pin.OUT), dc=Pin(27, Pin.OUT), backlight=Pin(12, Pin.OUT), rotation=2) tft.init() tft.fill(st7789.BLACK) width = tft.width() row = 0 while True: row += 32 color = next(COLORS) tft.fill_rect(0, row - 16, width, 32, st7789.BLACK) tft.draw(next(FONTS), next(GREETINGS), 0, row, color) if row > 192: row = 0 utime.sleep(0.25) finally: # shutdown spi spi.deinit()
def main(): def center(font, s, row, color=st7789.WHITE): screen = tft.width() # get screen width width = tft.write_len(font, s) # get the width of the string if width and width < screen: # if the string < display col = tft.width() // 2 - width // 2 # find the column to center else: # otherwise col = 0 # left justify tft.write(font, s, col, row, color) # and write the string try: # initialize the SPI spi = SPI(1, baudrate=30000000, sck=Pin(18), mosi=Pin(19)) # confgure the display tft = st7789.ST7789(spi, 135, 240, reset=Pin(23, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(16, Pin.OUT), backlight=Pin(4, Pin.OUT), rotation=3) # enable display and clear screen tft.init() tft.fill(st7789.BLACK) # center the name of the first font, using the font row = 16 center(noto_sans, "NotoSans", row, st7789.RED) row += noto_sans.HEIGHT # center the name of the second font, using the font center(noto_serif, "NotoSerif", row, st7789.GREEN) row += noto_serif.HEIGHT # center the name of the third font, using the font center(noto_mono, "NotoSansMono", row, st7789.BLUE) row += noto_mono.HEIGHT finally: # shutdown spi if 'spi' in locals(): spi.deinit()
def test_max7219(): from machine import Pin, SPI import time spi = SPI(baudrate=100000, polarity=1, phase=0, mosi=Pin(27), sck=Pin(25), miso=Pin(33)) display = Matrix8x8(spi, Pin(26), 1) letters = 'abcdefghijklmnopqrstuvwxyz' for c in letters + letters.upper(): display.fill(0) display.text(c, 0, 0, 1) display.show() time.sleep(1) spi.deinit()
class MicroPython: def __init__(self): # preimport utime import utime # pylint: disable=C0415, W0611 from machine import Pin # pylint: disable=C0415 self.DC_PIN = self.dc = Pin('P20') self.dc.mode(Pin.OUT) self.CS_PIN = self.cs = Pin('P4') self.cs.mode(Pin.OUT) self.cs.pull(Pin.PULL_UP) self.RST_PIN = self.rst = Pin('P19') self.rst.mode(Pin.OUT) self.BUSY_PIN = self.busy = Pin('P18') self.busy.mode(Pin.IN) def digital_write(self, pin, value): pin.value(value) def digital_read(self, pin): return pin.value() def spi_writebyte(self, data): self.spi.write(bytes(c & 0xff for c in data)) def delay_ms(self, delaytime): import utime # pylint: disable=C0415 utime.sleep_ms(delaytime) def module_init(self): from machine import Pin, SPI # pylint: disable=C0415 clk = Pin('P21') mosi = Pin('P22') self.spi = SPI(0, mode=SPI.MASTER, baudrate=20000000, polarity=0, phase=0, pins=(clk, mosi, None)) return 0 def module_exit(self): self.spi.deinit()
def get_spi(self): spi = None try: spi = SPI(baudrate = 5000000, polarity = 0, phase = 0, bits = 8, firstbit = SPI.MSB, sck = Pin(self.PIN_ID_SCK, Pin.OUT, Pin.PULL_DOWN), mosi = Pin(self.PIN_ID_MOSI, Pin.OUT, Pin.PULL_UP), miso = Pin(self.PIN_ID_MISO, Pin.IN, Pin.PULL_UP)) #spi.init() except Exception as e: print(e) if spi: spi.deinit() spi = None reset() # in case SPI is already in use, need to reset. return spi
def main(): try: # Turn power on display power axp = axp202c.PMU() axp.enablePower(axp202c.AXP202_LDO2) # initialize spi port spi = SPI(1, baudrate=32000000, sck=Pin(18, Pin.OUT), mosi=Pin(19, Pin.OUT)) # configure display tft = st7789.ST7789(spi, 240, 240, cs=Pin(5, Pin.OUT), dc=Pin(27, Pin.OUT), backlight=Pin(12, Pin.OUT), rotation=2) tft.init() tft.fill(st7789.BLUE) row = font_16.HEIGHT tft.write(font_16, "abcdefghijklmnopqrst", 0, row, st7789.WHITE, st7789.BLUE) row += font_16.HEIGHT tft.write(font_32, "abcdefghij", 0, row, st7789.WHITE, st7789.BLUE) row += font_32.HEIGHT tft.write(font_32, "klmnopqrs", 0, row, st7789.WHITE, st7789.BLUE) row += font_32.HEIGHT tft.write(font_32, "tuvwxyz", 0, row, st7789.WHITE, st7789.BLUE) row += font_32.HEIGHT tft.write(font_64, "abcd", 0, row, st7789.WHITE, st7789.BLUE) row += font_64.HEIGHT finally: # shutdown spi spi.deinit()
def main(): ''' Draw greetings on display cycling thru hershey fonts and colors ''' try: # Turn display power axp = axp202c.PMU(address=0x34) axp.enablePower(axp202c.AXP192_LDO2) # Set backlight voltage axp.setDC3Voltage(3000) spi = SPI(2, baudrate=60000000, sck=Pin(18), mosi=Pin(23)) # Configure display tft = ili9342c.ILI9342C(spi, 320, 240, reset=Pin(33, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(15, Pin.OUT), rotation=0) tft.init() tft.fill(ili9342c.BLACK) height = tft.height() width = tft.width() row = 0 while True: row += 32 tft.fill_rect(0, row - 16, width, 32, ili9342c.BLACK) tft.draw(next(FONTS), next(GREETINGS), 0, row, next(COLORS)) if row > 192: row = 0 utime.sleep(0.25) finally: # shutdown spi if 'spi' in locals(): spi.deinit()
class SPIBus(object): """SPI bus access.""" def __init__(self, freq, sc, mo, mi=None, spidev=2): self._spi = SPI(spidev) if mi == None: self._spi.init(baudrate=freq, sck=Pin(sc), mosi=Pin(mo)) else: self._spi.init(baudrate=freq, sck=Pin(sc), mosi=Pin(mo), miso=Pin(mi)) def deinit(self): self._spi.deinit() @property def bus(self): return self._spi def write_readinto(self, wbuf, rbuf): self._spi.write_readinto(wbuf, rbuf) def write(self, wbuf): self._spi.write(wbuf)
def main(): try: # Turn display power axp = axp202c.PMU(address=0x34) axp.enablePower(axp202c.AXP192_LDO2) # Set backlight voltage axp.setDC3Voltage(3000) spi = SPI(2, baudrate=20000000, sck=Pin(18), miso=Pin(38), mosi=Pin(23)) # initialize and mount the sdcard sd_device = sdcard.SDCard(spi, cs=Pin(4), baudrate=20000000) uos.mount(sd_device, '/sd') # initialize display tft = ili9342c.ILI9342C(spi, 320, 240, cs=Pin(5, Pin.OUT), dc=Pin(15, Pin.OUT), rotation=0, buffer_size=38400) tft.init() for i in range(1, 2387): frame = "/sd/160x120/{:04d}.jpg".format(i) tft.jpg(frame, 80, 60, ili9342c.FAST) finally: # shutdown spi if 'spi' in locals(): spi.deinit()
class ST7735R(GFX_): """""" # ---------------------------------------------------------------------- def __init__(self, dc, cs, rst, sclk, mosi, miso, size=(128, 128), offset=(0, 3)): """""" self.spi = SPI(2) self.spi.init(mosi=Pin(mosi), sck=Pin(sclk), miso=Pin(miso), baudrate=32000000) self.display = ST7735R_(self.spi, dc=Pin(dc), cs=Pin(cs), rst=Pin(rst), width=size[0], height=size[1], ofx=offset[0], ofy=offset[1]) super().__init__(self.display.pixel, size) # ---------------------------------------------------------------------- def close(self): """""" self.spi.deinit()
class DotStar: """ A sequence of APA102 (dotstar) LEDs. :param ~microcontroller.Pin clock: The pin to output dotstar clock on. :param ~microcontroller.Pin data: The pin to output dotstar data on. :param int n: The number of dotstars in the chain :param float brightness: Brightness of the pixels between 0.0 and 1.0 :param bool auto_write: True if the dotstars should immediately change when set. If False, `show` must be called explicitly. :param tuple pixel_order: Set the pixel order on the strip - different strips implement this differently. If you send red, and it looks blue or green on the strip, modify this! It should be one of the values above Example for ESP32: .. code-block:: python import generic_dotstar import time from board import * RED = 0x100000 with generic_dotstar.DotStar(APA102_SCK, APA102_MOSI, 1) as pixels: pixels[0] = RED time.sleep(2) """ def __init__(self, clock, data, n, *, brightness=1.0, auto_write=True, pixel_order=BGR, baudrate=1000000, spi_bus=1, apa102_cmp=False, spip=None): self._spi = None try: if spip: self._spi = spip else: self._spi = SPI(spi_bus) self._spi.init(sck=clock, mosi=data, baudrate=baudrate) except (NotImplementedError, ValueError): if self._spi: self._spi.deinit() self.dpin = data self.cpin = clock self.dpin.mode(Pin.OUT) self.cpin.mode(Pin.OUT) self.cpin.value = False self._n = n # Supply one extra clock cycle for each two pixels in the strip. self.end_header_size = n // 16 if n % 16 != 0: self.end_header_size += 1 self._buf = bytearray(n * 4 + START_HEADER_SIZE + self.end_header_size) self.end_header_index = len(self._buf) - self.end_header_size self.pixel_order = pixel_order # Four empty bytes to start. for i in range(START_HEADER_SIZE): self._buf[i] = 0x00 # Mark the beginnings of each pixel. for i in range(START_HEADER_SIZE, self.end_header_index, 4): self._buf[i] = 0xff # 0xff bytes at the end. for i in range(self.end_header_index, len(self._buf)): self._buf[i] = 0xff self._brightness = 1.0 # Set auto_write to False temporarily so brightness setter does _not_ # call show() while in __init__. self.auto_write = False self.brightness = brightness self.auto_write = auto_write self.apa102_cmp = apa102_cmp if self.apa102_cmp: self.auto_write = False def deinit(self): """Blank out the DotStars and release the resources.""" self.auto_write = False for i in range(START_HEADER_SIZE, self.end_header_index): if i % 4 != 0: self._buf[i] = 0 self.show() if self._spi: self._spi.deinit() else: self.dpin.deinit() self.cpin.deinit() def __enter__(self): return self def __exit__(self, exception_type, exception_value, traceback): self.deinit() def __repr__(self): return "[" + ", ".join([str(x) for x in self]) + "]" def _set_item(self, index, value): """ value can be one of three things: a (r,g,b) list/tuple a (r,g,b, brightness) list/tuple a single, longer int that contains RGB values, like 0xFFFFFF brightness, if specified should be a float 0-1, or an int 0-31 Set a pixel value. You can set per-pixel brightness here, if it's not passed it will use the max value for pixel brightness value, which is a good default. Important notes about the per-pixel brightness - it's accomplished by PWMing the entire output of the LED, and that PWM is at a much slower clock than the rest of the LEDs. This can cause problems in Persistence of Vision Applications """ offset = (index * 4) + START_HEADER_SIZE rgb = value if isinstance(value, int): rgb = (value >> 16, (value >> 8) & 0xff, value & 0xff) if len(rgb) == 4: brightness = value[3] # Ignore value[3] below. else: brightness = 1.0 # LED startframe is three "1" bits, followed by 5 brightness bits # then 8 bits for each of R, G, and B. The order of those 3 are configurable and # vary based on hardware # same as math.ceil(brightness * 31) & 0b00011111 # Idea from https://www.codeproject.com/Tips/700780/Fast-floor-ceiling-functions if type(brightness) is float: if brightness > 1.0 or brightness < 0.0: raise ValueError( "brightness must be float between 0.0 and 1.0") elif type(brightness) is int: if brightness > 31 or brightness < 0: raise ValueError("brightness must be int between 0 and 31") brightness = brightness / 31 # convert to float brightness_byte = 32 - int(32 - brightness * 31) & 0b00011111 self._buf[offset] = brightness_byte | LED_START self._buf[offset + 1] = rgb[self.pixel_order[0]] self._buf[offset + 2] = rgb[self.pixel_order[1]] self._buf[offset + 3] = rgb[self.pixel_order[2]] @staticmethod def _indices_workaound(myslice, myint): """Implementation of slice.indices() for workaround""" start = 0 if myslice.start is None else myslice.start stop = myint if myslice.stop is None else myslice.stop step = 1 if myslice.step is None else myslice.step start = myint + start if start < 0 else start stop = myint + stop if stop < 0 else stop start = min(max(start, 0), myint) stop = min(max(stop, 0), myint) return start, stop, step def __setitem__(self, index, val): if isinstance(index, slice): # The line below should work, but did not for me ESP32 Micropython 1.9.4 # start, stop, step = index.indices(self._n) # Workaround start, stop, step = self._indices_workaound(index, self._n) # End Workaround length = stop - start if step != 0: # same as math.ceil(length / step) # Idea from https://fizzbuzzer.com/implement-a-ceil-function/ length = (length + step - 1) // step if len(val) != length: raise ValueError( "Slice {} and input sequence size {} do not match.".format( length, len(val))) for val_i, in_i in enumerate(range(start, stop, step)): self._set_item(in_i, val[val_i]) else: self._set_item(index, val) if self.auto_write: self.show() def __getitem__(self, index): if isinstance(index, slice): out = [] # The line below should work, but did not for me: ESP32 Micropython 1.9.4 # for in_i in range(*index.indices(self._n)): # Workaround for in_i in range(*self._indices_workaound(index, self._n)): if self.apa102_cmp: offset = in_i * 4 out.append( tuple([ self._buf[offset + 3 + START_HEADER_SIZE], self._buf[offset + 2 + START_HEADER_SIZE], self._buf[offset + 1 + START_HEADER_SIZE], self._buf[offset + START_HEADER_SIZE] & 0b00011111 ])) else: out.append( tuple(self._buf[(in_i * 4) + (3 - i) + START_HEADER_SIZE] for i in range(3))) return out if index < 0: index += len(self) if index >= self._n or index < 0: raise IndexError offset = index * 4 if self.apa102_cmp: return tuple([ self._buf[offset + 3 + START_HEADER_SIZE], self._buf[offset + 2 + START_HEADER_SIZE], self._buf[offset + 1 + START_HEADER_SIZE], self._buf[offset + START_HEADER_SIZE] & 0b00011111 ]) else: return tuple(self._buf[offset + (3 - i) + START_HEADER_SIZE] for i in range(3)) def __len__(self): return self._n @property def brightness(self): """Overall brightness of the pixel""" return self._brightness @brightness.setter def brightness(self, brightness): self._brightness = min(max(brightness, 0.0), 1.0) if self.auto_write: self.show() def fill(self, color): """Colors all pixels the given ***color***.""" auto_write = self.auto_write self.auto_write = False for i in range(self._n): self[i] = color if auto_write: self.show() self.auto_write = auto_write def _ds_writebytes(self, buf): for b in buf: for _ in range(8): self.cpin.value = True self.dpin.value = (b & 0x80) self.cpin.value = False b = b << 1 def show(self): """Shows the new colors on the pixels themselves if they haven't already been autowritten. The colors may or may not be showing after this function returns because it may be done asynchronously.""" # Create a second output buffer if we need to compute brightness buf = self._buf if self.brightness < 1.0: buf = bytearray(self._buf) # Four empty bytes to start. for i in range(START_HEADER_SIZE): buf[i] = 0x00 for i in range(START_HEADER_SIZE, self.end_header_index): buf[i] = self._buf[i] if i % 4 == 0 else int(self._buf[i] * self._brightness) # Four 0xff bytes at the end. for i in range(self.end_header_index, len(buf)): buf[i] = 0xff if self._spi: self._spi.write(buf) else: self._ds_writebytes(buf) self.cpin.value = False # Added for compatibility with esp8266 apa102 def write(self): self.show()
class osd: def __init__(self): self.screen_x = const(64) self.screen_y = const(20) self.cwd = "/" self.init_fb() self.exp_names = " KMGTE" self.mark = bytearray([32, 16, 42]) # space, right triangle, asterisk self.read_dir() self.spi_read_irq = bytearray([1, 0xF1, 0, 0, 0, 0, 0]) self.spi_read_btn = bytearray([1, 0xFB, 0, 0, 0, 0, 0]) self.spi_result = bytearray(7) self.spi_enable_osd = bytearray([0, 0xFE, 0, 0, 0, 1]) self.spi_write_osd = bytearray([0, 0xFD, 0, 0, 0]) self.spi_channel = const(2) self.spi_freq = const(3000000) self.init_pinout_sd() #self.spi=SPI(self.spi_channel, baudrate=self.spi_freq, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(self.gpio_sck), mosi=Pin(self.gpio_mosi), miso=Pin(self.gpio_miso)) self.init_spi() alloc_emergency_exception_buf(100) self.enable = bytearray(1) self.timer = Timer(3) self.irq_handler(0) self.irq_handler_ref = self.irq_handler # allocation happens here self.spi_request = Pin(0, Pin.IN, Pin.PULL_UP) self.spi_request.irq(trigger=Pin.IRQ_FALLING, handler=self.irq_handler_ref) def init_spi(self): self.spi = SPI(self.spi_channel, baudrate=self.spi_freq, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(self.gpio_sck), mosi=Pin(self.gpio_mosi), miso=Pin(self.gpio_miso)) self.cs = Pin(self.gpio_cs, Pin.OUT) self.cs.off() def get_spi_result(self): return self.spi_result def get_spi_result2(self): self.cs.on() self.spi.write_readinto(self.spi_read_btn, self.spi_result) self.cs.off() return self.spi_result # A couple of shortcut functions to change directories, useful for TI-99/4A core development. # After running "import osd", these can be accessed with osd.run.ti_cart() for example. def change_dir(self, dir): os.chdir(dir) print("Current directory changed to {}".format(dir)) def ti_cart(self): self.change_dir("/sd/ti99_4a/cart") def ti_grom(self): self.change_dir("/sd/ti99_4a/grom") def ti_bit(self): self.change_dir("/sd/ti99_4a/bitstreams") # init file browser def init_fb(self): self.fb_topitem = 0 self.fb_cursor = 0 self.fb_selected = -1 @micropython.viper def init_pinout_sd(self): self.gpio_cs = const(5) self.gpio_sck = const(16) self.gpio_mosi = const(4) self.gpio_miso = const(12) @micropython.viper def irq_handler(self, pin): p8result = ptr8(addressof(self.spi_result)) self.cs.on() self.spi.write_readinto(self.spi_read_irq, self.spi_result) self.cs.off() btn_irq = p8result[6] if btn_irq & 0x80: # btn event IRQ flag self.cs.on() self.spi.write_readinto(self.spi_read_btn, self.spi_result) self.cs.off() btn = p8result[6] p8enable = ptr8(addressof(self.enable)) if p8enable[0] & 2: # wait to release all BTNs if btn == 1: p8enable[ 0] &= 1 # clear bit that waits for all BTNs released else: # all BTNs released if (btn & 0x78 ) == 0x78: # all cursor BTNs pressed at the same time self.show_dir() # refresh directory p8enable[0] = (p8enable[0] ^ 1) | 2 self.osd_enable(p8enable[0] & 1) if p8enable[0] == 1: if btn == 9: # btn3 cursor up self.start_autorepeat(-1) if btn == 17: # btn4 cursor down self.start_autorepeat(1) if btn == 1: self.timer.deinit() # stop autorepeat if btn == 33: # btn6 cursor left self.updir() if btn == 65: # btn6 cursor right self.select_entry() def start_autorepeat(self, i: int): self.autorepeat_direction = i self.move_dir_cursor(i) self.timer_slow = 1 self.timer.init(mode=Timer.PERIODIC, period=500, callback=self.autorepeat) def autorepeat(self, timer): if self.timer_slow: self.timer_slow = 0 self.timer.init(mode=Timer.PERIODIC, period=30, callback=self.autorepeat) self.move_dir_cursor(self.autorepeat_direction) self.irq_handler(0) # catch stale IRQ def select_entry(self): if self.direntries[self.fb_cursor][1]: # is it directory oldselected = self.fb_selected - self.fb_topitem self.fb_selected = self.fb_cursor try: self.cwd = self.fullpath(self.direntries[self.fb_cursor][0]) except: self.fb_selected = -1 self.show_dir_line(oldselected) self.show_dir_line(self.fb_cursor - self.fb_topitem) self.init_fb() self.read_dir() self.show_dir() else: self.change_file() def updir(self): if len(self.cwd) < 2: self.cwd = "/" else: s = self.cwd.split("/")[:-1] self.cwd = "" for name in s: if len(name) > 0: self.cwd += "/" + name self.init_fb() self.read_dir() self.show_dir() def fullpath(self, fname): if self.cwd.endswith("/"): return self.cwd + fname else: return self.cwd + "/" + fname def change_file(self): oldselected = self.fb_selected - self.fb_topitem self.fb_selected = self.fb_cursor try: filename = self.fullpath(self.direntries[self.fb_cursor][0]) except: filename = False self.fb_selected = -1 self.show_dir_line(oldselected) self.show_dir_line(self.fb_cursor - self.fb_topitem) if filename: if filename.endswith(".bit"): self.spi_request.irq(handler=None) self.timer.deinit() self.enable[0] = 0 self.osd_enable(0) self.spi.deinit() tap = ecp5.ecp5() tap.prog_stream(open(filename, "rb"), blocksize=1024) if filename.endswith("_sd.bit"): os.umount("/sd") for i in bytearray([2, 4, 12, 13, 14, 15]): p = Pin(i, Pin.IN) a = p.value() del p, a result = tap.prog_close() del tap gc.collect() #os.mount(SDCard(slot=3),"/sd") # BUG, won't work self.init_spi() # because of ecp5.prog() spi.deinit() self.spi_request.irq(trigger=Pin.IRQ_FALLING, handler=self.irq_handler_ref) self.irq_handler(0) # handle stuck IRQ if filename.endswith(".nes") \ or filename.endswith(".snes") \ or filename.endswith(".smc") \ or filename.endswith(".sfc"): import ld_nes s = ld_nes.ld_nes(self.spi, self.cs) s.ctrl(1) s.ctrl(0) s.load_stream(open(filename, "rb"), addr=0, maxlen=0x101000) del s gc.collect() self.enable[0] = 0 self.osd_enable(0) if filename.startswith( "/sd/ti99_4a/") and filename.lower().endswith(".bin"): import ld_ti99_4a s = ld_ti99_4a.ld_ti99_4a(self.spi, self.cs) s.load_rom_auto(open(filename, "rb"), filename) del s gc.collect() self.enable[0] = 0 self.osd_enable(0) if (filename.startswith("/sd/msx") and filename.endswith(".rom")) \ or filename.endswith(".mx1"): import ld_msx s = ld_msx.ld_msx(self.spi, self.cs) s.load_msx_rom(open(filename, "rb")) del s gc.collect() self.enable[0] = 0 self.osd_enable(0) if filename.endswith(".z80"): self.enable[0] = 0 self.osd_enable(0) import ld_zxspectrum s = ld_zxspectrum.ld_zxspectrum(self.spi, self.cs) s.loadz80(filename) del s gc.collect() if filename.endswith(".ora") or filename.endswith(".orao"): self.enable[0] = 0 self.osd_enable(0) import ld_orao s = ld_orao.ld_orao(self.spi, self.cs) s.loadorao(filename) del s gc.collect() if filename.endswith(".vsf"): self.enable[0] = 0 self.osd_enable(0) import ld_vic20 s = ld_vic20.ld_vic20(self.spi, self.cs) s.loadvsf(filename) del s gc.collect() if filename.endswith(".prg"): self.enable[0] = 0 self.osd_enable(0) import ld_vic20 s = ld_vic20.ld_vic20(self.spi, self.cs) s.loadprg(filename) del s gc.collect() if filename.endswith(".cas"): self.enable[0] = 0 self.osd_enable(0) import ld_trs80 s = ld_trs80.ld_trs80(self.spi, self.cs) s.loadcas(filename) del s gc.collect() if filename.endswith(".cmd"): self.enable[0] = 0 self.osd_enable(0) import ld_trs80 s = ld_trs80.ld_trs80(self.spi, self.cs) s.loadcmd(filename) del s gc.collect() @micropython.viper def osd_enable(self, en: int): pena = ptr8(addressof(self.spi_enable_osd)) pena[5] = en & 1 self.cs.on() self.spi.write(self.spi_enable_osd) self.cs.off() @micropython.viper def osd_print(self, x: int, y: int, i: int, text): p8msg = ptr8(addressof(self.spi_write_osd)) a = 0xF000 + (x & 63) + ((y & 31) << 6) p8msg[2] = i p8msg[3] = a >> 8 p8msg[4] = a self.cs.on() self.spi.write(self.spi_write_osd) self.spi.write(text) self.cs.off() @micropython.viper def osd_cls(self): p8msg = ptr8(addressof(self.spi_write_osd)) p8msg[3] = 0xF0 p8msg[4] = 0 self.cs.on() self.spi.write(self.spi_write_osd) self.spi.read(1280, 32) self.cs.off() # y is actual line on the screen def show_dir_line(self, y): if y < 0 or y >= self.screen_y: return mark = 0 invert = 0 if y == self.fb_cursor - self.fb_topitem: mark = 1 invert = 1 if y == self.fb_selected - self.fb_topitem: mark = 2 i = y + self.fb_topitem if i >= len(self.direntries): self.osd_print(0, y, 0, "%64s" % "") return if self.direntries[i][1]: # directory self.osd_print( 0, y, invert, "%c%-57s D" % (self.mark[mark], self.direntries[i][0])) else: # file mantissa = self.direntries[i][2] exponent = 0 while mantissa >= 1024: mantissa >>= 10 exponent += 1 self.osd_print( 0, y, invert, "%c%-57s %4d%c" % (self.mark[mark], self.direntries[i][0], mantissa, self.exp_names[exponent])) def show_dir(self): for i in range(self.screen_y): self.show_dir_line(i) def move_dir_cursor(self, step): oldcursor = self.fb_cursor if step == 1: if self.fb_cursor < len(self.direntries) - 1: self.fb_cursor += 1 if step == -1: if self.fb_cursor > 0: self.fb_cursor -= 1 if oldcursor != self.fb_cursor: screen_line = self.fb_cursor - self.fb_topitem if screen_line >= 0 and screen_line < self.screen_y: # move cursor inside screen, no scroll self.show_dir_line(oldcursor - self.fb_topitem) # no highlight self.show_dir_line(screen_line) # highlight else: # scroll if screen_line < 0: # cursor going up screen_line = 0 if self.fb_topitem > 0: self.fb_topitem -= 1 self.show_dir() else: # cursor going down screen_line = self.screen_y - 1 if self.fb_topitem + self.screen_y < len(self.direntries): self.fb_topitem += 1 self.show_dir() def read_dir(self): self.direntries = [] ls = sorted(os.listdir(self.cwd)) for fname in ls: stat = os.stat(self.fullpath(fname)) if stat[0] & 0o170000 == 0o040000: self.direntries.append([fname, 1, 0]) # directory else: self.direntries.append([fname, 0, stat[6]]) # file gc.collect() # NOTE: this can be used for debugging #def osd(self, a): # if len(a) > 0: # enable = 1 # else: # enable = 0 # self.cs.on() # self.spi.write(bytearray([0,0xFE,0,0,0,enable])) # enable OSD # self.cs.off() # if enable: # self.cs.on() # self.spi.write(bytearray([0,0xFD,0,0,0])) # write content # self.spi.write(bytearray(a)) # write content # self.cs.off() def load_console_grom(self): gromfile = "/sd/ti99_4a/grom/994AGROM.Bin" import ld_ti99_4a s = ld_ti99_4a.ld_ti99_4a(self.spi, self.cs) s.reset_on() print("GROM file: {}".format(gromfile)) bytes = s.load_stream(open(gromfile, "rb"), 0x10000) print("Loaded {} bytes".format(bytes)) s.reset_off() del s gc.collect() def load_console_rom(self): romfile = "/sd/ti99_4a/rom/994AROM.Bin" import ld_ti99_4a s = ld_ti99_4a.ld_ti99_4a(self.spi, self.cs) s.reset_on() print("System ROM file: {}".format(romfile)) bytes = s.load_stream(open(romfile, "rb"), 0) print("Loaded {} bytes".format(bytes)) s.reset_off() del s gc.collect() def load_roms(self): romfile = "/sd/ti99_4a/rom/994AROM.Bin" gromfile = "/sd/ti99_4a/grom/994AGROM.Bin" import ld_ti99_4a s = ld_ti99_4a.ld_ti99_4a(self.spi, self.cs) s.reset_on() # Load ROM print("System ROM file: {}".format(romfile)) bytes = s.load_stream(open(romfile, "rb"), 0) print("Loaded {} bytes".format(bytes)) # Load GROM print("GROM file: {}".format(gromfile)) bytes = s.load_stream(open(gromfile, "rb"), 0x10000) print("Loaded {} bytes".format(bytes)) # remove reset s.reset_off() del s gc.collect() def save_mem(self, filename, addr, length): import ld_ti99_4a old_freq = self.spi_freq self.spi_freq = const(100000) self.init_spi() s = ld_ti99_4a.ld_ti99_4a(self.spi, self.cs) print("Saving memory from {} length {} file: {}".format( addr, length, filename)) s.save_stream(open(filename, "wb"), addr, length) del s self.spi_freq = old_freq self.init_spi() gc.collect()
class osd: def __init__(self): self.screen_x = const(64) self.screen_y = const(20) self.cwd = "/" self.init_fb() self.exp_names = " KMGTE" self.mark = bytearray([32, 16, 42]) # space, right triangle, asterisk self.diskfile = [open("main.py", "rb"), open("main.py", "rb")] # any dummy file that can open self.imgtype = bytearray( 2) # [0]=0:.mac/.bin 1638400 bytes, [0]=1:.dsk 819200 bytes self.drive = bytearray(1) # [0]=0:1st drive, [0]=1:2nd drive self.conv_dataIn12K = bytearray(12 * 1024) # memoryview for each track//16 datainmv = memoryview(self.conv_dataIn12K) self.conv_dataIn = [] for i in range(5): self.conv_dataIn.append(memoryview(datainmv[0:(12 - i) * 1024])) self.conv_nibsOut = bytearray(1024) dsk2mac.init_nibsOut(self.conv_nibsOut) self.track2sector = bytearray(81 * 2) self.init_track2sector() self.read_dir() self.spi_read_irq = bytearray([1, 0xF1, 0, 0, 0, 0, 0]) self.spi_read_btn = bytearray([1, 0xFB, 0, 0, 0, 0, 0]) self.spi_read_trackno = bytearray([1, 0xD0, 0, 0, 0, 0, 0]) self.spi_result = bytearray(7) self.spi_enable_osd = bytearray([0, 0xFE, 0, 0, 0, 1]) self.spi_write_osd = bytearray([0, 0xFD, 0, 0, 0]) self.spi_write_track = [ bytearray([0, 0xD1, 0, 0, 0]), bytearray([0, 0xD1, 0, 0x60, 0]) ] self.spi_channel = const(2) self.spi_freq = const(3000000) self.init_pinout_sd() self.init_spi() alloc_emergency_exception_buf(100) self.enable = bytearray(1) self.timer = Timer(3) self.irq_handler(0) self.irq_handler_ref = self.irq_handler # allocation happens here self.spi_request = Pin(0, Pin.IN, Pin.PULL_UP) self.spi_request.irq(trigger=Pin.IRQ_FALLING, handler=self.irq_handler_ref) def init_spi(self): self.spi = SPI(self.spi_channel, baudrate=self.spi_freq, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(self.gpio_sck), mosi=Pin(self.gpio_mosi), miso=Pin(self.gpio_miso)) self.cs = Pin(self.gpio_cs, Pin.OUT) self.cs.off() self.led = Pin(self.gpio_led, Pin.OUT) self.led.off() # init file browser def init_fb(self): self.fb_topitem = 0 self.fb_cursor = 0 self.fb_selected = -1 @micropython.viper def init_track2sector(self): p16t2s = ptr16(addressof(self.track2sector)) offset = 0 for i in range(0, 81): p16t2s[i] = offset offset += 12 - i // 16 @micropython.viper def init_pinout_sd(self): self.gpio_cs = const(17) self.gpio_sck = const(16) #self.gpio_mosi = const(4) #self.gpio_miso = const(12) self.gpio_mosi = const(25) self.gpio_miso = const(26) self.gpio_led = const(5) @micropython.viper def update_track(self): p8result = ptr8(addressof(self.spi_result)) p16t2s = ptr16(addressof(self.track2sector)) p8it = ptr8(addressof(self.imgtype)) # ask FPGA for current track number self.ctrl(4) # stop cpu self.cs.on() self.spi.write_readinto(self.spi_read_trackno, self.spi_result) self.cs.off() drive = 0 if p8result[6] & 0x80: drive = 1 track = p8result[6] & 0x7F if track > 79: track = 79 trackdiv16 = track // 16 #print("Fetching drive " + str(drive) + " track " + str(track)) sectors = 12 - trackdiv16 self.diskfile[drive].seek((2 - p8it[drive]) * p16t2s[track] * 1024) # upload data self.cs.on() self.spi.write(self.spi_write_track[drive]) if p8it[drive]: # .dsk self.diskfile[drive].readinto(self.conv_dataIn[trackdiv16]) offset = 0 for side in range(2): for sector in range(sectors): dsk2mac.convert_sector(self.conv_dataIn12K, offset, self.conv_nibsOut, track, side, sector) offset += 512 self.spi.write(self.conv_nibsOut) else: # .mac for side in range(2): self.diskfile[drive].readinto(self.conv_dataIn[trackdiv16]) self.spi.write(self.conv_dataIn[trackdiv16]) self.cs.off() self.ctrl(0) # resume cpu @micropython.viper def irq_handler(self, pin): p8result = ptr8(addressof(self.spi_result)) p8drive = ptr8(addressof(self.drive)) self.cs.on() self.spi.write_readinto(self.spi_read_irq, self.spi_result) self.cs.off() btn_irq = p8result[6] if btn_irq & 1: # drive 1 request self.update_track() if btn_irq & 0x80: # btn event IRQ flag self.cs.on() self.spi.write_readinto(self.spi_read_btn, self.spi_result) self.cs.off() btn = p8result[6] p8enable = ptr8(addressof(self.enable)) if p8enable[0] & 2: # wait to release all BTNs if btn == 1: p8enable[ 0] &= 1 # clear bit that waits for all BTNs released else: # all BTNs released if (btn & 0x78 ) == 0x78: # all cursor BTNs pressed at the same time self.show_dir() # refresh directory p8enable[0] = (p8enable[0] ^ 1) | 2 self.osd_enable(p8enable[0] & 1) if p8enable[0] == 1: if btn == 9: # btn3 cursor up self.start_autorepeat(-1) if btn == 17: # btn4 cursor down self.start_autorepeat(1) if btn == 1: self.timer.deinit() # stop autorepeat if btn == 33: # btn5 cursor left self.updir() if btn == 65: # btn6 cursor right 1st drive p8drive[0] = 0 self.select_entry() if btn == 3: # btn1 2nd drive p8drive[0] = 1 self.select_entry() def start_autorepeat(self, i: int): self.autorepeat_direction = i self.move_dir_cursor(i) self.timer_slow = 1 self.timer.init(mode=Timer.PERIODIC, period=500, callback=self.autorepeat) def autorepeat(self, timer): if self.timer_slow: self.timer_slow = 0 self.timer.init(mode=Timer.PERIODIC, period=30, callback=self.autorepeat) self.move_dir_cursor(self.autorepeat_direction) self.irq_handler(0) # catch stale IRQ def select_entry(self): if self.direntries[self.fb_cursor][1]: # is it directory oldselected = self.fb_selected - self.fb_topitem self.fb_selected = self.fb_cursor try: self.cwd = self.fullpath(self.direntries[self.fb_cursor][0]) except: self.fb_selected = -1 self.show_dir_line(oldselected) self.show_dir_line(self.fb_cursor - self.fb_topitem) self.init_fb() self.read_dir() self.show_dir() else: self.change_file() def updir(self): if len(self.cwd) < 2: self.cwd = "/" else: s = self.cwd.split("/")[:-1] self.cwd = "" for name in s: if len(name) > 0: self.cwd += "/" + name self.init_fb() self.read_dir() self.show_dir() def fullpath(self, fname): if self.cwd.endswith("/"): return self.cwd + fname else: return self.cwd + "/" + fname def change_file(self): oldselected = self.fb_selected - self.fb_topitem self.fb_selected = self.fb_cursor try: filename = self.fullpath(self.direntries[self.fb_cursor][0]) except: filename = False self.fb_selected = -1 self.show_dir_line(oldselected) self.show_dir_line(self.fb_cursor - self.fb_topitem) if filename: if filename.endswith(".mac") or filename.endswith( ".MAC") or filename.endswith(".dsk") or filename.endswith( ".DSK"): self.diskfile[self.drive[0]] = open(filename, "rb") self.imgtype[self.drive[0]] = 0 if filename.endswith(".dsk") or filename.endswith(".DSK"): self.imgtype[self.drive[0]] = 1 #self.update_track() self.ctrl(16 << self.drive[0]) # set insert_disk self.enable[0] = 0 self.osd_enable(0) if filename.endswith(".bit"): self.spi_request.irq(handler=None) self.timer.deinit() self.enable[0] = 0 self.osd_enable(0) self.spi.deinit() import ecp5 ecp5.prog_stream(open(filename, "rb"), blocksize=1024) if filename.endswith("_sd.bit"): os.umount("/sd") for i in bytearray([2, 4, 12, 13, 14, 15]): p = Pin(i, Pin.IN) a = p.value() del p, a result = ecp5.prog_close() del tap gc.collect() #os.mount(SDCard(slot=3),"/sd") # BUG, won't work self.init_spi() # because of ecp5.prog() spi.deinit() self.spi_request.irq(trigger=Pin.IRQ_FALLING, handler=self.irq_handler_ref) self.irq_handler(0) # handle stuck IRQ if filename.endswith(".nes") \ or filename.endswith(".snes") \ or filename.endswith(".smc") \ or filename.endswith(".sfc"): import ld_nes s = ld_nes.ld_nes(self.spi, self.cs) s.ctrl(1) s.ctrl(0) s.load_stream(open(filename, "rb")) del s gc.collect() self.enable[0] = 0 self.osd_enable(0) if filename.startswith("/sd/ti99_4a/") and filename.endswith( ".bin"): import ld_ti99_4a s = ld_ti99_4a.ld_ti99_4a(self.spi, self.cs) s.load_rom_auto(open(filename, "rb"), filename) del s gc.collect() self.enable[0] = 0 self.osd_enable(0) if (filename.startswith("/sd/msx") and filename.endswith(".rom")) \ or filename.endswith(".mx1"): import ld_msx s = ld_msx.ld_msx(self.spi, self.cs) s.load_msx_rom(open(filename, "rb")) del s gc.collect() self.enable[0] = 0 self.osd_enable(0) if filename.endswith(".z80"): self.enable[0] = 0 self.osd_enable(0) import ld_zxspectrum s = ld_zxspectrum.ld_zxspectrum(self.spi, self.cs) s.loadz80(filename) del s gc.collect() if filename.endswith(".ora") or filename.endswith(".orao"): self.enable[0] = 0 self.osd_enable(0) import ld_orao s = ld_orao.ld_orao(self.spi, self.cs) s.loadorao(filename) del s gc.collect() if filename.endswith(".vsf"): self.enable[0] = 0 self.osd_enable(0) import ld_vic20 s = ld_vic20.ld_vic20(self.spi, self.cs) s.loadvsf(filename) del s gc.collect() if filename.endswith(".prg"): self.enable[0] = 0 self.osd_enable(0) import ld_vic20 s = ld_vic20.ld_vic20(self.spi, self.cs) s.loadprg(filename) del s gc.collect() if filename.endswith(".cas"): self.enable[0] = 0 self.osd_enable(0) import ld_trs80 s = ld_trs80.ld_trs80(self.spi, self.cs) s.loadcas(filename) del s gc.collect() if filename.endswith(".cmd"): self.enable[0] = 0 self.osd_enable(0) import ld_trs80 s = ld_trs80.ld_trs80(self.spi, self.cs) s.loadcmd(filename) del s gc.collect() @micropython.viper def osd_enable(self, en: int): pena = ptr8(addressof(self.spi_enable_osd)) pena[5] = en & 1 self.cs.on() self.spi.write(self.spi_enable_osd) self.cs.off() @micropython.viper def osd_print(self, x: int, y: int, i: int, text): p8msg = ptr8(addressof(self.spi_write_osd)) a = 0xF000 + (x & 63) + ((y & 31) << 6) p8msg[2] = i p8msg[3] = a >> 8 p8msg[4] = a self.cs.on() self.spi.write(self.spi_write_osd) self.spi.write(text) self.cs.off() @micropython.viper def osd_cls(self): p8msg = ptr8(addressof(self.spi_write_osd)) p8msg[3] = 0xF0 p8msg[4] = 0 self.cs.on() self.spi.write(self.spi_write_osd) self.spi.read(1280, 32) self.cs.off() # y is actual line on the screen def show_dir_line(self, y): if y < 0 or y >= self.screen_y: return mark = 0 invert = 0 if y == self.fb_cursor - self.fb_topitem: mark = 1 invert = 1 if y == self.fb_selected - self.fb_topitem: mark = 2 i = y + self.fb_topitem if i >= len(self.direntries): self.osd_print(0, y, 0, "%64s" % "") return if self.direntries[i][1]: # directory self.osd_print( 0, y, invert, "%c%-57s D" % (self.mark[mark], self.direntries[i][0])) else: # file mantissa = self.direntries[i][2] exponent = 0 while mantissa >= 1024: mantissa >>= 10 exponent += 1 self.osd_print( 0, y, invert, "%c%-57s %4d%c" % (self.mark[mark], self.direntries[i][0], mantissa, self.exp_names[exponent])) def show_dir(self): for i in range(self.screen_y): self.show_dir_line(i) def move_dir_cursor(self, step): oldcursor = self.fb_cursor if step == 1: if self.fb_cursor < len(self.direntries) - 1: self.fb_cursor += 1 if step == -1: if self.fb_cursor > 0: self.fb_cursor -= 1 if oldcursor != self.fb_cursor: screen_line = self.fb_cursor - self.fb_topitem if screen_line >= 0 and screen_line < self.screen_y: # move cursor inside screen, no scroll self.show_dir_line(oldcursor - self.fb_topitem) # no highlight self.show_dir_line(screen_line) # highlight else: # scroll if screen_line < 0: # cursor going up screen_line = 0 if self.fb_topitem > 0: self.fb_topitem -= 1 self.show_dir() else: # cursor going down screen_line = self.screen_y - 1 if self.fb_topitem + self.screen_y < len(self.direntries): self.fb_topitem += 1 self.show_dir() def read_dir(self): self.direntries = [] ls = sorted(os.listdir(self.cwd)) for fname in ls: stat = os.stat(self.fullpath(fname)) if stat[0] & 0o170000 == 0o040000: self.direntries.append([fname, 1, 0]) # directory for fname in ls: stat = os.stat(self.fullpath(fname)) if stat[0] & 0o170000 != 0o040000: self.direntries.append([fname, 0, stat[6]]) # file # NOTE: this can be used for debugging #def osd(self, a): # if len(a) > 0: # enable = 1 # else: # enable = 0 # self.cs.on() # self.spi.write(bytearray([0,0xFE,0,0,0,enable])) # enable OSD # self.cs.off() # if enable: # self.cs.on() # self.spi.write(bytearray([0,0xFD,0,0,0])) # write content # self.spi.write(bytearray(a)) # write content # self.cs.off() def ctrl(self, i): self.cs.on() self.spi.write(bytearray([0, 0xFF, 0xFF, 0xFF, 0xFF, i])) self.cs.off() def peek(self, addr, length): self.ctrl(4) self.ctrl(6) self.cs.on() self.spi.write( bytearray([ 1, (addr >> 24) & 0xFF, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF, 0 ])) b = bytearray(length) self.spi.readinto(b) self.cs.off() self.ctrl(4) self.ctrl(0) return b def poke(self, addr, data): self.ctrl(4) self.ctrl(6) self.cs.on() self.spi.write( bytearray([ 0, (addr >> 24) & 0xFF, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF ])) self.spi.write(data) self.cs.off() self.ctrl(4) self.ctrl(0)
spi.init(SPI.MASTER, baudrate=10000000, bits=16, polarity=0, phase=0, pins=None) print(spi.write_readinto(buffer_w, buffer_r) == 12) print(buffer_w == buffer_r) buffer_r = bytearray(12) spi.init(SPI.MASTER, baudrate=10000000, bits=32, polarity=0, phase=0, pins=None) print(spi.write_readinto(buffer_w, buffer_r) == 12) print(buffer_w == buffer_r) # check for memory leaks... for i in range (0, 1000): spi = SPI(0, SPI.MASTER, baudrate=1000000) # test deinit spi = SPI(0, SPI.MASTER, baudrate=1000000) spi.deinit() print(spi) spi = SPI(0, SPI.MASTER, baudrate=1000000) # next ones must fail try: spi = SPI(0, 10, baudrate=10000000, polarity=0, phase=0) except: print("Exception") try: spi = SPI(0, mode=SPI.MASTER, baudrate=10000000, polarity=1, phase=2) except: print("Exception") try: