def main(): ''' SPI demo for ece49022 skills assessment SCK => Pin 25 => A1 CS => Pin 26 => A0 MOSI => Pin 13 => 13 MISO => Pin 12 => 12 ''' message = ['a', 'b', 'c'] spi = SPI(-1, sck=Pin(25), mosi=Pin(13), miso=Pin(12), polarity=1, phase=0, bits=8, firstbit=SPI.MSB) chip_select = Pin(26, Pin.OUT, 1) # baud rate, polarity, phase, bits, firstbit spi.init(baudrate=1_000_000) sleep(1) for char in message: print(char) chip_select.off() spi.write(bytes(char, 'utf-8')) chip_select.on() sleep(5)
def get_spi(self): spi = None spi_id = 1 spi = SPI(spi_id, baudrate=10000000, polarity=0, phase=0) spi.init() return spi
class Lcd: """Display control Nokia 5110""" def __init__(self, spi=1, cs=2, dc=15, rst=0, bl=12): self.spi = SPI(spi) self.cs = Pin(cs) self.dc = Pin(dc) self.rst = Pin(rst) self.bl = bl self.spi.init(baudrate=2000000, polarity=0, phase=0) self.lcd = pcd8544.PCD8544_FRAMEBUF(self.spi, self.cs, self.dc, self.rst) def light(self, status): if status == 'on': # backlight on Pin(self.bl, Pin.OUT, value=0) elif status == 'off': # backlight off Pin(self.bl, Pin.OUT, value=1) def text(self, line1='', line2='', line3='', line4='', line5=''): # Can show five line of text # text(string, x, y, color) self.clear() self.lcd.text(line1, 0, 0, 1) self.lcd.text(line2, 0, 10, 1) self.lcd.text(line3, 0, 20, 1) self.lcd.text(line4, 0, 30, 1) self.lcd.text(line5, 0, 40, 1) self.lcd.show() def clear(self): self.lcd.fill(0) self.lcd.show()
def __init__(self): print("Building EPD:") # Load modules and set constants from display import epd42b as epaper from machine import SPI, Pin # Initializes SPI spi = SPI(1) spi.init(baudrate=2000000, polarity=0, phase=0, sck=Pin(pins.SCK), mosi=Pin(pins.MOSI), miso=Pin(pins.MISO)) cs = Pin(pins.CS) dc = Pin(pins.DC) rst = Pin(pins.RST) busy = Pin(pins.BUSY) print("\tSPI - [ OK ]") # Create EPD epaper driver epd = epaper.EPD(spi, cs, dc, rst, busy) self.dim = Vect(epd.width, epd.height) self.ofs = Vect(0, 0) print("\tEPD - [ OK ]") self.fb = (Fb(BLACK, epd), Fb(YELLOW, epd))
class SPI(Lockable): def __init__(self, clock, MOSI=None, MISO=None): from machine import SPI self._spi = SPI(-1) self._pins = (clock, MOSI, MISO) def configure(self, baudrate=100000, polarity=0, phase=0, bits=8): from machine import SPI, Pin if self._locked: # TODO verify if _spi obj 'caches' sck, mosi, miso to avoid storing in _attributeIds (duplicated in busio) # i.e. #init ignores MOSI=None rather than unsetting self._spi.init( baudrate=baudrate, polarity=polarity, phase=phase, bits=bits, firstbit=SPI.MSB, sck=Pin(self._pins[0].id), mosi=Pin(self._pins[1].id), miso=Pin(self._pins[2].id), ) else: raise RuntimeError("First call try_lock()") def write(self, buf): return self._spi.write(buf) def readinto(self, buf): return self.readinto(buf) def write_readinto(self, buffer_out, buffer_in): return self.write_readinto(buffer_out, buffer_in)
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 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 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
def __init__: sckPin = Pin(18) mosiPin = Pin(23) misoPin = Pin(19) spi = SPI(1, baudrate=328125, bits=8, polarity=0, phase=1, sck=sckPin, mosi=mosiPin, miso=misoPin) spi.init() cs = Pin(2) dc = Pin(15) rst = Pin(0) # backlight on bl = Pin(12, Pin.OUT, value=1) lcd = pcd8544.PCD8544(spi, cs, dc, rst) lcd.contrast(0x3c, pcd8544.BIAS_1_40, pcd8544.TEMP_COEFF_0) lcd.reset() lcd.init() lcd.clear() buffer = bytearray((lcd.height // 8) * lcd.width) framebuf = framebuf.FrameBuffer1(buffer, lcd.width, lcd.height) framebuf.fill(0) lcd.data(buffer)
def init_SD(): spi = SPI(2, baudrate = 10000000, polarity = 0, phase = 0, bits = 8, firstbit = SPI.MSB, sck = Pin(18, Pin.OUT, Pin.PULL_DOWN), mosi = Pin(23, Pin.OUT, Pin.PULL_UP), miso = Pin(19, Pin.IN, Pin.PULL_UP)) spi.init() # Ensure right baudrate sd = sdcard.SDCard(spi, Pin(22)) # Compatible with PCB return sd
def setup(hardware_spi=True): if hardware_spi: spi = SPI(2) spi.init(baudrate=2000000, polarity=0, phase=0) lcd = HX1230_FB_SPI(spi, cs, rst) else: mosi = Pin('B15', Pin.OUT) sck = Pin('B13', Pin.OUT) lcd = HX1230_FB_BBSPI(mosi, sck, cs, rst) return lcd
class Px(object): '''init with n pixels, set color''' def __init__(self, count=16, clk=14, data=13): # 14:D5, 13:D7 self.spi = None # NOTE miso not used but still required by SPI(), so watch out when using D6 a.k.a. Pin(12) self.spi = SPI(-1, baudrate=100000, polarity=1, phase=0, sck=Pin(clk), mosi=Pin(data), miso=Pin(12)) self.spi.init() self.count = count # number of LEDs per strip self.pixels = [[128, 128, 128]] * count # list of GRB-lists self.latch = ( count + 31 ) // 32 # LPD8806 quirk; requires extra latch 0 for every 32 LEDs self.show() def one(self, n, r, g, b): # Nth led: red, green, and blue 7-bit values (0-127) if n >= self.count: return clr = [128, 128, 128] # GRB clr[0] |= g & 0xff clr[1] |= r & 0xff clr[2] |= b & 0xff self.pixels[n] = clr self.show() def all(self, r, g, b): self.pixels = [[128 | (g & 0xff), 128 | (r & 0xff), 128 | (b & 0xff)]] * self.count self.show() def clear(self): self.pixels = [[128, 128, 128]] * self.count self.show() def show(self): # draw entire strip flat = sum(self.pixels, []) for _ in range(0, self.latch): flat.append(0) bts = bytes(flat) self.spi.write(bts) # flatten -> convert to bytes -> write SPI
def do_write(): spi = SPI(1, baudrate=2500000, polarity=0, phase=0) spi.init() rdr = mfrc522.MFRC522(spi=spi, gpioRst=0, gpioCs=2) print("") print("Place card before reader to write address 0x08") print("") try: while True: (stat, tag_type) = rdr.request(rdr.REQIDL) if stat == rdr.OK: (stat, raw_uid) = rdr.anticoll() if stat == rdr.OK: print("New card detected") print(" - tag type: 0x%02x" % tag_type) print(" - uid : 0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])) print("") if rdr.select_tag(raw_uid) == rdr.OK: key = b'\xff\xff\xff\xff\xff\xff' if rdr.auth(rdr.AUTHENT1A, 8, key, raw_uid) == rdr.OK: stat = rdr.write( 8, b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f" ) rdr.stop_crypto1() if stat == rdr.OK: print("Data written to card") else: print("Failed to write data to card") else: print("Authentication error") else: print("Failed to select tag") except KeyboardInterrupt: print("Bye")
def init(): global lcd global bl spi = SPI(1) spi.init(baudrate=2000000, polarity=0, phase=0) cs = Pin(2) dc = Pin(15) rst = Pin(0) # backlight on bl = Pin(12, Pin.OUT, value=1) lcd = pcd8544.PCD8544(spi, cs, dc, rst) lcd.init() print('LCD init') lcd.contrast(50)
def do_read(): spi = SPI(1, baudrate=2500000, polarity=0, phase=0) spi.init() rdr = mfrc522.MFRC522(spi=spi, gpioRst=0, gpioCs=2) while True: print("Place card") (stat, tag_type) = rdr.request(rdr.REQIDL) if stat == rdr.OK: (stat, raw_uid) = rdr.anticoll() if stat == rdr.OK: print("Detected") print("type: 0x%02x" % tag_type) print("uid: 0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])) print("") if rdr.select_tag(raw_uid) == rdr.OK: key = b'\xff\xff\xff\xff\xff\xff' ms = ticks_ms() blockArray = bytearray(16) for sector in range(1, 64): if rdr.auth(rdr.AUTHENT1A, sector, key, raw_uid) == rdr.OK: rdr.read(sector, into=blockArray) print("data@%d: %s" % (sector, blockArray)) else: print("Auth err") rdr.stop_crypto1() print("Read in " + str(ticks_ms() - ms)) # took 4594 ms else: print("Select failed")
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)
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 LCD5110: def __init__(self, spi=0, cs=5, dc=4, rst=8, bl=28): self.spi = SPI(spi) self.spi.init(baudrate=2000000, polarity=0, phase=0) self.cs = Pin(cs) self.dc = Pin(dc) self.rst = Pin(rst) self.bl = Pin(bl, Pin.OUT, value=1) self.lcd = pcd8544_fb.PCD8544_FB(self.spi, self.cs, self.dc, self.rst) self.buffer = bytearray((pcd8544_fb.HEIGHT // 8) * pcd8544_fb.WIDTH) self.framebuf = framebuf.FrameBuffer(self.buffer, pcd8544_fb.WIDTH, pcd8544_fb.HEIGHT, framebuf.MONO_VLSB) self.HEIGHT = pcd8544_fb.HEIGHT self.WIDTH = pcd8544_fb.WIDTH self.clear() def clear(self): # clear self.framebuf.fill(0) self.update() def text(self, string, x, y, color, update=False): self.framebuf.text(string, x, y, color) if update: self.update() def fill_rect(self, x, y, w, h, c, update=False): self.framebuf.fill_rect(x, y, w, h, c) if update: self.update() def update(self): self.lcd.data(self.buffer)
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 RADIO: def __init__( self, mode=LORA, # 0 - LoRa, 1 - FSK, 2 - OOK pars={ 'freq_kHz': 434000, # kHz 'freq_Hz': 0, # Hz 'power': 10, # 2...17 dBm 'crc': True, # CRC on/off # LoRa mode: 'bw': 125, # BW: 7.8...500 kHz 'sf': 10, # SF: 6..12 'cr': 5, # CR: 5...8 'ldro': None, # Low Data Rate Optimize (None - automatic) 'sw': 0x12, # Sync Word (allways 0x12) 'preamble': 8, # 6...65535 'implicit_header': False, # FSK/OOK mode: 'bitrate': 4800., # bit/s 'fdev': 5000., # frequency deviation [Hz] 'rx_bw': 10.4, # 2.6...250 kHz 'afc_bw': 2.6, # 2.6...250 kHz 'afc': False, # AFC on/off 'fixed': False, # fixed packet size or variable 'dcfree': 0 }, # 0=None, 1=Manchester or 2=Whitening gpio={ 'led': 2, # blue LED GPIO number on board 'reset': 5, # reset pin from GPIO5 (or may be None) 'dio0': 4, # DIO0 line to GPIO4 'cs': 15, # SPI CS 'sck': 14, # SPI SCK 'mosi': 13, # SPI MOSI 'miso': 12 }, # SPI MISO spi_hardware=True, spi_baudrate=None, onReceive=None): # receive callback # init GPIO self.pin_led = Pin(gpio['led'], Pin.OUT) self.led(0) # LED off if gpio['reset'] != None: self.pin_reset = Pin(gpio['reset'], Pin.OUT, Pin.PULL_UP) self.pin_reset.value(1) else: self.pin_reset = None self.pin_dio0 = Pin(gpio['dio0'], Pin.IN, Pin.PULL_UP) self.pin_cs = Pin(gpio['cs'], Pin.OUT, Pin.PULL_UP) self.pin_cs.value(1) # init SPI if spi_hardware: if spi_baudrate == None: spi_baudrate = 5000000 # 5MHz if ESP32: self.spi = SPI(1, baudrate=spi_baudrate, polarity=0, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) else: self.spi = SPI(1, baudrate=spi_baudrate, polarity=0, phase=0) else: if spi_baudrate == None: spi_baudrate = 500000 # 500kHz self.spi = SPI(-1, baudrate=spi_baudrate, polarity=0, phase=0, sck=Pin(gpio['sck']), mosi=Pin(gpio['mosi']), miso=Pin(gpio['miso'])) #bits=8, firstbit=SPI.MSB, # FIXME #sck=Pin(gpio['sck'], Pin.OUT, Pin.PULL_DOWN), #mosi=Pin(gpio['mosi'], Pin.OUT, Pin.PULL_UP), #miso=Pin(gpio['miso'], Pin.IN, Pin.PULL_UP)) self.spi.init() self.onReceive(onReceive) #self._lock = False self.reset() self._mode = 0 # LoRa mode by default self.init(mode, pars) def __exit__(self): self.pin_dio0.irq(trigger=0, handler=None) self.spi.close() def spiTransfer(self, address, value=0x00): response = bytearray(1) self.pin_cs.value(0) self.spi.write(bytes([address])) self.spi.write_readinto(bytes([value]), response) self.pin_cs.value(1) return response def readReg(self, address, byteorder='big', signed=False): """read 8-bit register by SPI""" response = self.spiTransfer(address & 0x7F) return int.from_bytes(response, byteorder) def writeReg(self, address, value): """write 8-bit register by SPI""" self.spiTransfer(address | 0x80, value) def led(self, on=True): """on/off LED on GPIO pin""" self.pin_led.value(not LED_ON ^ on) def blink(self, times=1, on_ms=100, off_ms=20): """short blink LED on GPIO pin""" for i in range(times): self.led(1) sleep_ms(on_ms) self.led(0) sleep_ms(off_ms) def reset(self, low_ms=100, high_ms=100, times=1): """hard reset SX127x chip""" if self.pin_reset: for i in range(times): self.pin_reset.value(1) sleep_ms(high_ms) self.pin_reset.value(0) sleep_ms(low_ms) self.pin_reset.value(1) sleep_ms(high_ms) def version(self): """get SX127x crystal revision""" return self.readReg(REG_VERSION) def setMode(self, mode): """set mode""" self.writeReg(REG_OP_MODE, (self.readReg(REG_OP_MODE) & ~MODES_MASK) | mode) def getMode(self): """get mode""" return self.readReg(REG_OP_MODE) & MODES_MASK def lora(self, lora=True): """switch to LoRa mode""" mode = self.readReg(REG_OP_MODE) # read mode sleep = (mode & ~MODES_MASK) | MODE_SLEEP self.writeReg(REG_OP_MODE, sleep) # go to sleep if lora: sleep |= MODE_LONG_RANGE mode |= MODE_LONG_RANGE else: sleep &= ~MODE_LONG_RANGE mode &= ~MODE_LONG_RANGE self.writeReg(REG_OP_MODE, sleep) # write "long range" bit self.writeReg(REG_OP_MODE, mode) # restore old mode def isLora(self): """check LoRa (or FSK/OOK) mode""" mode = self.readReg(REG_OP_MODE) # read mode return True if (mode & MODE_LONG_RANGE) else False def fsk(self, fsk=True): """switch to FSK mode""" self.lora(not fsk) if fsk: self.writeReg(REG_OP_MODE, (self.readReg(REG_OP_MODE) & ~MODES_MASK2) | MODE_FSK) def ook(self, ook=True): """switch to OOK mode""" self.lora(not ook) if ook: self.writeReg(REG_OP_MODE, (self.readReg(REG_OP_MODE) & ~MODES_MASK2) | MODE_OOK) def sleep(self): """switch to Sleep Mode:""" self.setMode(MODE_SLEEP) def standby(self): """switch ro Standby mode""" self.setMode(MODE_STDBY) def tx(self, on=True): """on/off TX mode (off = standby)""" if on: self.setMode(MODE_TX) else: self.setMode(MODE_STDBY) def rx(self, on=True): """on/off RX (continuous) mode (off = standby)""" if on: self.setMode(MODE_RX_CONTINUOUS) else: self.setMode(MODE_STDBY) def cad(self, on=True): """on/off CAD (LoRa) mode (off = standby)""" if self._mode == 0: # LoRa mode if on: self.setMode(MODE_CAD) else: self.setMode(MODE_STDBY) def init(self, mode=None, pars=None): """init chip""" if mode is not None: self._mode = mode if pars: self._pars = pars # check version version = self.version() print("SX127x selicon revision = 0x%02X" % version) if version != 0x12: raise Exception('Invalid SX127x selicon revision') # switch mode if self._mode == 1: self.fsk() # FSK elif self._mode == 2: self.ook() # OOK else: self.lora() # LoRa # set RF frequency self.setFrequency(self._pars['freq_kHz'], self._pars['freq_Hz']) # set LNA boost: `LnaBoostHf`->3 (Boost on, 150% LNA current) self.setLnaBoost(True) # set output power level self.setPower(self._pars['power']) # enable/disable CRC self.enableCRC(self._pars["crc"]) if self._mode == 0: # set LoRaTM options self.setBW(self._pars['bw']) self._implicitHeaderMode = None self.setImplicitHeaderMode(self._pars['implicit_header']) sf = self._pars['sf'] self.setSF(sf) ldro = self._pars['ldro'] if ldro == None: ldro = True if sf >= 10 else False # FIXME self.setLDRO(ldro) self.setCR(self._pars['cr']) self.setPreamble(self._pars['preamble']) self.setSW(self._pars['sw']) # set AGC auto on (internal AGC loop) self.writeReg(REG_MODEM_CONFIG_3, self.readReg(REG_MODEM_CONFIG_3) | 0x04) # `AgcAutoOn` # set base addresses self.writeReg(REG_FIFO_TX_BASE_ADDR, FIFO_TX_BASE_ADDR) self.writeReg(REG_FIFO_RX_BASE_ADDR, FIFO_RX_BASE_ADDR) # set DIO0 mapping (`RxDone`) self.writeReg(REG_DIO_MAPPING_1, 0x00) else: # set FSK/OOK options self.continuous(False) # packet mode by default self.setBitrate(self._pars["bitrate"]) self.setFdev(self._pars["fdev"]) self.setRxBW(self._pars["rx_bw"]) self.setAfcBW(self._pars["afc_bw"]) self._fixedLen = None self.setFixedLen(self._pars["fixed"]) self.enableAFC(self._pars["afc"]) self.setDcFree(self._pars["dcfree"]) self.writeReg(REG_RSSI_TRESH, 0xFF) # default self.writeReg(REG_PREAMBLE_LSB, 8) # 3 by default self.writeReg(REG_SYNC_VALUE_1, 0x69) # 0x01 by default self.writeReg(REG_SYNC_VALUE_2, 0x81) # 0x01 by default self.writeReg(REG_SYNC_VALUE_3, 0x7E) # 0x01 by default self.writeReg(REG_SYNC_VALUE_4, 0x96) # 0x01 by default # set `DataMode` to Packet (and reset PayloadLength(10:8) to 0) self.writeReg(REG_PACKET_CONFIG_2, 0x40) # set TX start FIFO condition self.writeReg(REG_FIFO_THRESH, TX_START_FIFO_NOEMPTY) # set DIO0 mapping (by default): # in RxContin - `SyncAddres` # in TxContin - `TxReady` # in RxPacket - `PayloadReady` <- used signal # in TxPacket - `PacketSent` self.writeReg(REG_DIO_MAPPING_1, 0x00) # RSSI and IQ callibrate self.rxCalibrate() self.standby() def setFrequency(self, freq_kHz, freq_Hz=0): """set RF frequency [kHz * 1000 + Hz]""" self._freq = int(freq_kHz) * 1000 + freq_Hz # kHz + Hz -> Hz freq_code = int(round(self._freq / FSTEP)) self.writeReg(REG_FRF_MSB, (freq_code >> 16) & 0xFF) self.writeReg(REG_FRF_MID, (freq_code >> 8) & 0xFF) self.writeReg(REG_FRF_LSB, freq_code & 0xFF) mode = self.readReg(REG_OP_MODE) if self._freq < 600000000: # LF <= 525 < _600_ < 779 <= HF [MHz] mode |= MODE_LOW_FREQ_MODE_ON # LF else: mode &= ~MODE_LOW_FREQ_MODE_ON # HF self.writeReg(REG_OP_MODE, mode) def setPower(self, level, PA_BOOST=True, MaxPower=7): """set TX Power level 2...17 dBm, select PA_BOOST pin""" MaxPower = min(max(MaxPower, 0), 7) if PA_BOOST: # Select PA_BOOST pin: Pout is limited to ~17..20 dBm # Pout = 17 - (15 - OutputPower) dBm OutputPower = min(max(level - 2, 0), 15) self.writeReg(REG_PA_CONFIG, PA_SELECT | OutputPower) else: # Select RFO pin: Pout is limited to ~14..15 dBm # Pmax = 10.8 + 0.6 * MaxPower [dBm] # Pout = Pmax - (15 - OutputPower)) = 0...15 dBm if MaxPower=7 OutputPower = min(max(level, 0), 15) self.writeReg(REG_PA_CONFIG, (MaxPower << 4) | OutputPower) def setHighPower(self, on=True): """set high power on PA_BOOST up to +20 dBm""" if on: # +3dB self.writeReg(REG_PA_DAC, 0x87) # power on PA_BOOST pin up to +20 dBm else: self.writeReg(REG_PA_DAC, 0x84) # default mode def setOCP(self, trim_mA=100., on=True): """set trimming of OCP current (45...240 mA)""" if trim_mA <= 120.: OcpTrim = round((trim_mA - 45.) / 5.) else: OcpTrim = round((trim_mA + 30.) / 10.) OcpTrim = min(max(OcpTrim, 0), 27) if on: OcpTrim |= 0x20 # `OcpOn` self.writeReg(REG_OCP, OcpTrim) def setLnaBoost(self, LnaBoost=True): """set LNA boost on/off (only for high frequency band)""" reg = self.readReg(REG_LNA) if LnaBoost: reg |= 0x03 # set `LnaBoostHf` to 3 (boost on, 150% LNA current) else: reg &= ~0x03 # set `LnaBoostHf` to 0 (default LNA current) self.writeReg(REG_LNA, reg) def setRamp(self, shaping=0, ramp=0x09): """set modulation shaping code 0..3 (FSK/OOK) and PA rise/fall time code 0..15 (FSK/Lora)""" shaping = min(max(shaping, 0), 3) ramp = min(max(ramp, 0), 15) reg = self.readReg(REG_PA_RAMP) reg = (reg & 0x90) | (shaping << 5) | ramp self.writeReg(REG_PA_RAMP, reg) def enableCRC(self, crc=True, crcAutoClearOff=True): """enable/disable CRC (and set CrcAutoClearOff in FSK/OOK mode)""" self._crc = crc if self._mode == 0: # LoRa mode reg = self.readReg(REG_MODEM_CONFIG_2) reg = (reg | 0x04) if crc else (reg & ~0x04) # `RxPayloadCrcOn` self.writeReg(REG_MODEM_CONFIG_2, reg) else: # FSK/OOK mode reg = self.readReg(REG_PACKET_CONFIG_1) & ~0x18 if crc: reg |= 0x10 # `CrcOn` if crcAutoClearOff: reg |= 0x08 # `CrcAutoClearOff` self.writeReg(REG_PACKET_CONFIG_1, reg) def getRxGain(self): """get current RX gain code [1..6] from `RegLna` (1 - maximum gain)""" return (self.readReg(REG_LNA) >> 5) & 0x07 # `LnaGain` def getPktRSSI(self): """get Packet RSSI [dB] (LoRa)""" if self._mode == 0: # LoRa mode return self.readReg(REG_PKT_RSSI_VALUE) - \ (164. if self._freq < 600000000 else 157.) else: # FSK/OOK mode return -0.5 * self.readReg(REG_RSSI_VALUE) def getRSSI(self): """get RSSI [dB]""" if self._mode == 0: # LoRa mode return self.readReg(REG_LR_RSSI_VALUE) - \ (164. if self._freq < 600000000 else 157.) else: # FSK/OOK mode return -0.5 * self.readReg(REG_RSSI_VALUE) def getSNR(self): """get SNR [dB] (LoRa)""" if self._mode == 0: # LoRa mode snr = self.readReg(REG_PKT_SNR_VALUE) if snr & 0x80: # sign bit is 1 snr -= 256 return snr * 0.25 else: # FSK/OOK mode return 0. def getIrqFlags(self): """get IRQ flags for debug""" if self._mode == 0: # LoRa mode irqFlags = self.readReg(REG_IRQ_FLAGS) self.writeReg(REG_IRQ_FLAGS, irqFlags) return irqFlags else: # FSK/OOK mode irqFlags1 = self.readReg(REG_IRQ_FLAGS_1) irqFlags2 = self.readReg(REG_IRQ_FLAGS_2) return (irqFlags2 << 8) | irqFlags1 def enableRxIrq(self, enable=True): """enable/disable interrupt by RX done for debug (LoRa)""" if self._mode == 0: # LoRa mode reg = self.readReg(REG_IRQ_FLAGS_MASK) if enable: reg &= ~IRQ_RX_DONE_MASK else: reg |= IRQ_RX_DONE_MASK self.writeReg(REG_IRQ_FLAGS_MASK, reg) def invertIQ(self, invert=True): """invert IQ channels (LoRa)""" if self._mode == 0: reg = self.readReg(REG_INVERT_IQ) if invert: reg |= 0x40 # `InvertIq` = 1 else: reg &= ~0x40 # `InvertIq` = 0 self.writeReg(REG_INVERT_IQ, reg) def setSF(self, sf=10): """set Spreading Factor 6...12 (LoRa)""" if self._mode == 0: sf = min(max(sf, 6), 12) self.writeReg(REG_DETECT_OPTIMIZE, 0xC5 if sf == 6 else 0xC3) self.writeReg(REG_DETECTION_THRESHOLD, 0x0C if sf == 6 else 0x0A) self.writeReg(REG_MODEM_CONFIG_2, (self.readReg(REG_MODEM_CONFIG_2) & 0x0F) | ((sf << 4) & 0xF0)) def setLDRO(self, ldro): """set Low Data Rate Optimisation (LoRa)""" if self._mode == 0: self.writeReg( REG_MODEM_CONFIG_3, # `LowDataRateOptimize` (self.readReg(REG_MODEM_CONFIG_3) & ~0x08) | 0x08 if ldro else 0) def setBW(self, sbw): """set signal Band Width 7.8-500 kHz (LoRa)""" if self._mode == 0: bw = len(BW_TABLE) - 1 for i in range(bw + 1): if sbw <= BW_TABLE[i]: bw = i break self.writeReg(REG_MODEM_CONFIG_1, \ (self.readReg(REG_MODEM_CONFIG_1) & 0x0F) | (bw << 4)) def setCR(self, denominator): """set Coding Rate [5..8] (LoRa)""" if self._mode == 0: denominator = min(max(denominator, 5), 8) cr = denominator - 4 self.writeReg(REG_MODEM_CONFIG_1, (self.readReg(REG_MODEM_CONFIG_1) & 0xF1) | (cr << 1)) def setPreamble(self, length): """set preamble length [6...65535] (LoRa)""" if self._mode == 0: self.writeReg(REG_PREAMBLE_MSB, (length >> 8) & 0xFF) self.writeReg(REG_PREAMBLE_LSB, (length) & 0xFF) def setSW(self, sw): # LoRa mode only """set Sync Word (LoRa)""" if self._mode == 0: self.writeReg(REG_SYNC_WORD, sw) def setImplicitHeaderMode(self, implicitHeaderMode=True): """set ImplicitHeaderModeOn (LoRa)""" if self._mode == 0: if self._implicitHeaderMode != implicitHeaderMode: # set value only if different self._implicitHeaderMode = implicitHeaderMode modem_config_1 = self.readReg(REG_MODEM_CONFIG_1) config = modem_config_1 | 0x01 if implicitHeaderMode else \ modem_config_1 & 0xFE self.writeReg(REG_MODEM_CONFIG_1, config) def setBitrate(self, bitrate=4800.): """set bitrate [bit/s] (FSK/OOK)""" if self._mode == 1: # FSK code = int(round((FXOSC * 16.) / bitrate)) # bit/s -> code/frac self.writeReg(REG_BITRATE_MSB, (code >> 12) & 0xFF) self.writeReg(REG_BITRATE_LSB, (code >> 4) & 0xFF) self.writeReg(REG_BITRATE_FRAC, code & 0x0F) elif self._mode == 2: # OOK code = int(round(FXOSC / bitrate)) # bit/s -> code self.writeReg(REG_BITRATE_MSB, (code >> 8) & 0xFF) self.writeReg(REG_BITRATE_LSB, code & 0xFF) self.writeReg(REG_BITRATE_FRAC, 0) def setFdev(self, fdev=5000.): """set frequency deviation (FSK)""" if self._mode: code = int(round(fdev / FSTEP)) # Hz -> code code = min(max(code, 0), 0x3FFF) self.writeReg(REG_FDEV_MSB, (code >> 8) & 0xFF) self.writeReg(REG_FDEV_LSB, code & 0xFF) def setRxBW(self, bw=10.4): """set RX BW [kHz] (FSK/OOK)""" if self._mode: m, e = getRxBw(bw) self.writeReg(REG_RX_BW, (m << 3) | e) def setAfcBW(self, bw=2.6): """set AFC BW [kHz] (FSK/OOK)""" if self._mode: m, e = getRxBw(bw) self.writeReg(REG_AFC_BW, (m << 3) | e) def enableAFC(self, afc=True): """enable/disable AFC (FSK/OOK)""" if self._mode: reg = self.readReg(REG_RX_CONFIG) if afc: reg |= 0x10 # bit 4: AfcAutoOn -> 1 else: reg &= ~0x10 # bit 4: AfcAutoOn -> 0 self.writeReg(REG_RX_CONFIG, reg) def setFixedLen(self, fixed=True): """set Fixed or Variable packet mode (FSK/OOK)""" if self._mode: if self._fixedLen != fixed: # set value only if different self._fixedLen = fixed reg = self.readReg(REG_PACKET_CONFIG_1) if fixed: reg &= ~0x80 # bit 7: PacketFormat -> 0 (fixed size) else: reg |= 0x80 # bit 7: PacketFormat -> 1 (variable size) self.writeReg(REG_PACKET_CONFIG_1, reg) def setDcFree(self, mode=0): """set DcFree mode: 0=Off, 1=Manchester, 2=Whitening (FSK/OOK)""" if self._mode: reg = self.readReg(REG_PACKET_CONFIG_1) reg = (reg & 0x9F) | ((mode & 3) << 5) # bit 6-5 `DcFree` self.writeReg(REG_PACKET_CONFIG_1, reg) def continuous(self, on=True): """select Continuous mode, must use DIO2->DATA, DIO1->DCLK (FSK/OOK)""" if self._mode: reg = self.readReg(REG_PACKET_CONFIG_2) if on: reg &= ~0x40 # bit 6: `DataMode` 0 -> Continuous mode else: reg |= 0x40 # bit 6: `DataMode` 1 -> Packet mode self.writeReg(REG_PACKET_CONFIG_2, reg) def rxCalibrate(self): """RSSI and IQ callibration (FSK/OOK)""" if self._mode: reg = self.readReg(REG_IMAGE_CAL) reg |= 0x40 # `ImageCalStart` bit self.writeReg(REG_IMAGE_CAL, reg) while (self.readReg(REG_IMAGE_CAL) & 0x20): # `ImageCalRunning` pass # FIXME: check timeout def setPllBW(self, bw=3): """set PLL bandwidth 0=75, 1=150, 2=225, 3=300 kHz (LoRa/FSK/OOK)""" bw = min(max(bw, 0), 3) reg = self.readReg(REG_PLL) reg = (reg & 0x3F) | (bw << 6) self.writeReg(REG_PLL, reg) def setFastHop(self, on=True): """on/off fast frequency PLL hopping (FSK/OOK)""" if self._mode: reg = self.readReg(REG_PLL_HOP) reg = reg | 0x80 if on else reg & 0x7F # `FastHopOn` self.writeReg(REG_PLL_HOP, reg) #def aquire_lock(self, lock=False): # if not MICROPYTHON: # MicroPython is single threaded, doesn't need lock. # if lock: # while self._lock: pass # self._lock = True # else: # self._lock = False def send(self, string, fixed=False): """send packet (LoRa/FSK/OOK)""" #self.aquire_lock(True) # wait until RX_Done, lock and begin writing. self.setMode(MODE_STDBY) buf = string.encode() size = len(buf) if self._mode == 0: # LoRa mode self.setImplicitHeaderMode(fixed) # set FIFO TX base address self.writeReg(REG_FIFO_ADDR_PTR, FIFO_TX_BASE_ADDR) # check size size = min(size, MAX_PKT_LENGTH) # write data for i in range(size): self.writeReg(REG_FIFO, buf[i]) # set length self.writeReg(REG_PAYLOAD_LENGTH, size) # start TX packet self.setMode(MODE_TX) # put in TX mode # wait for TX done, standby automatically on TX_DONE while (self.readReg(REG_IRQ_FLAGS) & IRQ_TX_DONE) == 0: pass # FIXME: check timeout # clear IRQ's self.writeReg(REG_IRQ_FLAGS, IRQ_TX_DONE) else: # FSK/OOK mode self.setFixedLen(fixed) size = min(size, MAX_PKT_LENGTH) # limit size # set TX start FIFO condition #self.writeReg(REG_FIFO_THRESH, TX_START_FIFO_NOEMPTY) # wait while FIFO is no empty while ((self.readReg(REG_IRQ_FLAGS_2) & IRQ2_FIFO_EMPTY) == 0): pass # FIXME: check timeout if self._fixedLen: self.writeReg(REG_PAYLOAD_LEN, size) # fixed length #add = 0 else: self.writeReg(REG_FIFO, size) # variable length #add = 1 # set TX start FIFO condition #self.writeReg(REG_FIFO_THRESH, TX_START_FIFO_LEVEL | (size + add)) # write data to FIFO for i in range(size): self.writeReg(REG_FIFO, buf[i]) # start TX packet self.setMode(MODE_TX) # wait `TxRaedy` (bit 5 in `RegIrqFlags1`) #while ((self.readReg(REG_IRQ_FLAGS_1) & IRQ1_TX_READY) == 0): # pass # FIXME: check timeout # wait `PacketSent` (bit 3 in `RegIrqFlags2`) while ((self.readReg(REG_IRQ_FLAGS_2) & IRQ2_PACKET_SENT) == 0): pass # FIXME: check timeout # switch to standby mode self.setMode(MODE_STDBY) self.collect() #self.aquire_lock(False) # unlock when done writing def onReceive(self, callback): """set callback on receive packet (Lora/FSK/OOK)""" self._onReceive = callback if callback: self.pin_dio0.irq(trigger=Pin.IRQ_RISING, handler=self._handleOnReceive) else: self.pin_dio0.irq(trigger=0, handler=None) def receive(self, size=0): """go to RX mode; wait callback by interrupt (LoRa/FSK/OOK)""" size = min(size, MAX_PKT_LENGTH) if self._mode == 0: # LoRa mode self.setImplicitHeaderMode(size > 0) if size > 0: self.writeReg(REG_PAYLOAD_LENGTH, size) # implicit header else: # FSK/OOK mode self.setFixedLen(size > 0) if size > 0: self.writeReg(REG_PAYLOAD_LEN, size) # fixed length else: self.writeReg(REG_PAYLOAD_LEN, MAX_PKT_LENGTH) # variable length self.setMode(MODE_RX_CONTINUOUS) def collect(self): """garbage collection""" gc.collect() #if MICROPYTHON: # print('[Memory - free: {} allocated: {}]'.format(gc.mem_free(), gc.mem_alloc())) def _handleOnReceive(self, event_source): #self.aquire_lock(True) if self._mode == 0: # LoRa mode irqFlags = self.readReg(REG_IRQ_FLAGS) # should be 0x50 self.writeReg(REG_IRQ_FLAGS, irqFlags) if (irqFlags & IRQ_RX_DONE) == 0: # check `RxDone` #self.aquire_lock(False) return # `RxDone` is not set print( "DIO0 interrupt in LoRa mode by `RxDone` (RegIrqFlags=0x%02X)" % irqFlags) # check `PayloadCrcError` bit crcOk = not bool(irqFlags & IRQ_PAYLOAD_CRC_ERROR) # set FIFO address to current RX address self.writeReg(REG_FIFO_ADDR_PTR, self.readReg(REG_FIFO_RX_CURRENT_ADDR)) # read packet length packetLen = self.readReg(REG_PAYLOAD_LENGTH) if self._implicitHeaderMode else \ self.readReg(REG_RX_NB_BYTES) else: # FSK/OOK mode irqFlags = self.readReg(REG_IRQ_FLAGS_2) # should be 0x26/0x24 if (irqFlags & IRQ2_PAYLOAD_READY) == 0: #self.aquire_lock(False) return # `PayloadReady` is not set print( "DIO0 interrupt in FSK/OOK mode by `PayloadReady` (RegIrqFlags2=0x%02X)" % irqFlags) # check `CrcOk` bit crcOk = bool(irqFlags & IRQ2_CRC_OK) # read packet length if self.readReg(REG_PACKET_CONFIG_1) & 0x80: # `PacketFormat` packetLen = self.readReg(REG_FIFO) # variable length else: packetLen = self.readReg(REG_PAYLOAD_LEN) # fixed length # read FIFO payload = bytearray(packetLen) for i in range(packetLen): payload[i] = self.readReg(REG_FIFO) payload = bytes(payload) self.collect() # run callback if self._onReceive: self._onReceive(self, payload, crcOk if self._crc else None) self.collect() #self.aquire_lock(False) def dump(self): for i in range(128): print("Reg[0x%02X] = 0x%02X" % (i, self.readReg(i)))
class MFRC522: OK = 0 NOTAGERR = 1 ERR = 2 REQIDL = 0x26 REQALL = 0x52 AUTHENT1A = 0x60 AUTHENT1B = 0x61 def __init__(self, sck, mosi, miso, rst, cs): self.sck = Pin(sck, Pin.OUT) self.mosi = Pin(mosi, Pin.OUT) self.miso = Pin(miso) self.rst = Pin(rst, Pin.OUT) self.cs = Pin(cs, Pin.OUT) self.rst.value(0) self.cs.value(1) if uname()[0] == 'WiPy': self.spi = SPI(0) self.spi.init(SPI.MASTER, baudrate=1000000, pins=(self.sck, self.mosi, self.miso)) elif uname()[0] == 'esp8266': self.spi = SPI(baudrate=100000, polarity=0, phase=0, sck=self.sck, mosi=self.mosi, miso=self.miso) self.spi.init() else: raise RuntimeError("Unsupported platform") self.rst.value(1) self.init() def _wreg(self, reg, val): self.cs.value(0) self.spi.write(b'%c' % int(0xff & ((reg << 1) & 0x7e))) self.spi.write(b'%c' % int(0xff & val)) self.cs.value(1) def _rreg(self, reg): self.cs.value(0) self.spi.write(b'%c' % int(0xff & (((reg << 1) & 0x7e) | 0x80))) val = self.spi.read(1) self.cs.value(1) return val[0] def _sflags(self, reg, mask): self._wreg(reg, self._rreg(reg) | mask) def _cflags(self, reg, mask): self._wreg(reg, self._rreg(reg) & (~mask)) def _tocard(self, cmd, send): recv = [] bits = irq_en = wait_irq = n = 0 stat = self.ERR if cmd == 0x0E: irq_en = 0x12 wait_irq = 0x10 elif cmd == 0x0C: irq_en = 0x77 wait_irq = 0x30 self._wreg(0x02, irq_en | 0x80) self._cflags(0x04, 0x80) self._sflags(0x0A, 0x80) self._wreg(0x01, 0x00) for c in send: self._wreg(0x09, c) self._wreg(0x01, cmd) if cmd == 0x0C: self._sflags(0x0D, 0x80) i = 2000 while True: n = self._rreg(0x04) i -= 1 if ~((i != 0) and ~(n & 0x01) and ~(n & wait_irq)): break self._cflags(0x0D, 0x80) if i: if (self._rreg(0x06) & 0x1B) == 0x00: stat = self.OK if n & irq_en & 0x01: stat = self.NOTAGERR elif cmd == 0x0C: n = self._rreg(0x0A) lbits = self._rreg(0x0C) & 0x07 if lbits != 0: bits = (n - 1) * 8 + lbits else: bits = n * 8 if n == 0: n = 1 elif n > 16: n = 16 for _ in range(n): recv.append(self._rreg(0x09)) else: stat = self.ERR return stat, recv, bits def _crc(self, data): self._cflags(0x05, 0x04) self._sflags(0x0A, 0x80) for c in data: self._wreg(0x09, c) self._wreg(0x01, 0x03) i = 0xFF while True: n = self._rreg(0x05) i -= 1 if not ((i != 0) and not (n & 0x04)): break return [self._rreg(0x22), self._rreg(0x21)] def init(self): self.reset() self._wreg(0x2A, 0x8D) self._wreg(0x2B, 0x3E) self._wreg(0x2D, 30) self._wreg(0x2C, 0) self._wreg(0x15, 0x40) self._wreg(0x11, 0x3D) self.antenna_on() def reset(self): self._wreg(0x01, 0x0F) def antenna_on(self, on=True): if on and ~(self._rreg(0x14) & 0x03): self._sflags(0x14, 0x03) else: self._cflags(0x14, 0x03) def request(self, mode): self._wreg(0x0D, 0x07) (stat, recv, bits) = self._tocard(0x0C, [mode]) if (stat != self.OK) | (bits != 0x10): stat = self.ERR return stat, bits def anticoll(self): ser_chk = 0 ser = [0x93, 0x20] self._wreg(0x0D, 0x00) (stat, recv, bits) = self._tocard(0x0C, ser) if stat == self.OK: if len(recv) == 5: for i in range(4): ser_chk = ser_chk ^ recv[i] if ser_chk != recv[4]: stat = self.ERR else: stat = self.ERR return stat, recv def select_tag(self, ser): buf = [0x93, 0x70] + ser[:5] buf += self._crc(buf) (stat, recv, bits) = self._tocard(0x0C, buf) return self.OK if (stat == self.OK) and (bits == 0x18) else self.ERR def auth(self, mode, addr, sect, ser): return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0] def stop_crypto1(self): self._cflags(0x08, 0x08) def read(self, addr): data = [0x30, addr] data += self._crc(data) (stat, recv, _) = self._tocard(0x0C, data) return recv if stat == self.OK else None def write(self, addr, data): buf = [0xA0, addr] buf += self._crc(buf) (stat, recv, bits) = self._tocard(0x0C, buf) if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): stat = self.ERR else: buf = [] for i in range(16): buf.append(data[i]) buf += self._crc(buf) (stat, recv, bits) = self._tocard(0x0C, buf) if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): stat = self.ERR return stat
def get_time(self): now = self.get_localtime() return (now[3], now[4], now[5]) @property def uptime(self): return time.time() - self._epoch def get_uptime_ms(self): return int(self.uptime * 1000) backlight = Backlight() spi = SPI(0) spi.init(polarity=1, phase=1, baudrate=8000000) display = ST7789_SPI(240, 240, spi, cs=Pin("DISP_CS", Pin.OUT, quiet=True), dc=Pin("DISP_DC", Pin.OUT, quiet=True), res=Pin("DISP_RST", Pin.OUT, quiet=True)) drawable = draw565.Draw565(display) accel = Accelerometer() battery = Battery() button = Pin('BUTTON', Pin.IN, quiet=True) rtc = RTC() touch = CST816S(I2C(0), Pin('TP_INT', Pin.IN, quiet=True), Pin('TP_RST', Pin.OUT, quiet=True)) vibrator = Vibrator(Pin('MOTOR', Pin.OUT, value=0), active_low=True)
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ import gc from machine import Pin, SPI from codepage import cp437_chr, cp437_pal, cp437_pic from gd import Gameduino, RAM_CHR, RAM_PAL # See the Gameduino General test for all MicroPython plateform support spi = SPI(2) # MOSI=Y8, MISO=Y7, SCK=Y6, SS=Y5 spi.init(SPI.MASTER, baudrate=2000000, phase=0, polarity=0) # We must manage the SS signal ourself ss = Pin(Pin.board.Y5, Pin.OUT) # Gameduino Lib gd = Gameduino(spi, ss) print("Initializing...") gd.begin() print("Uncompressing to RAM_CHR") gd.uncompress(RAM_CHR, cp437_chr) print("Uncompressing to RAM_PAL") gd.uncompress(RAM_PAL, cp437_pal) def atxy(x, y): """ Memory offset corresponding to a cursor position """
from machine import SPI, Pin from ws2812 import * spi = SPI(1) spi.init(baudrate=3200000, mosi=Pin(23)) chain = WS2812(spi, led_count=1) data = [(255, 0, 0) #red ] chain.show(data)
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ from machine import Pin, SPI from gd import * import os import urandom # on recent MicroPython Firmware v1.10+ # Initialize the SPI Bus (on ESP8266-EVB) # Software SPI # spi = SPI(-1, baudrate=4000000, polarity=1, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) # Hardware SPI spi = SPI(2) # MOSI=Y8, MISO=Y7, SCK=Y6, SS=Y5 spi.init( baudrate=20000000, phase=0, polarity=0 ) # raise @ 20 Mhz # We must manage the SS signal ourself ss = Pin( Pin.board.Y5, Pin.OUT ) # Gameduino Lib gd = Gameduino( spi, ss ) gd.begin() # === Toolbox ================================================================== def draw_ball( x, y, pal ): global gd gd.xsprite(x, y, -40, -56, 0, pal, 0) gd.xsprite(x, y, -24, -56, 1, pal, 0) gd.xsprite(x, y, -8, -56, 2, pal, 0) gd.xsprite(x, y, 8, -56, 3, pal, 0) gd.xsprite(x, y, 24, -56, 4, pal, 0)
class EPD(object): MAX_READ = 45 SW_NORMAL_PROCESSING = 0x9000 EP_FRAMEBUFFER_SLOT_OVERRUN = 0x6a84 # too much data fed in EP_SW_INVALID_LE = 0x6c00 # Wrong expected length EP_SW_INSTRUCTION_NOT_SUPPORTED = 0x6d00 # bad instr EP_SW_WRONG_PARAMETERS_P1P2 = 0x6a00 EP_SW_WRONG_LENGTH = 0x6700 DEFAULT_SLOT=0 # always the *oldest*, should wear-level then I think def __init__(self, debug=False, baud=100000): # From datasheet # Bit rate – up to 12 MHz1 # ▪ Polarity – CPOL = 1; clock transition high-to-low on the leading edge and low-to-high on the # trailing edge # ▪ Phase – CPHA = 1; setup on the leading edge and sample on the trailing edge # ▪ Bit order – MSB first # ▪ Chip select polarity – active low self.spi = SPI(0) try: self.spi.init(mode=SPI.MASTER, baudrate=baud, bits=8, polarity=1, phase=1, firstbit=SPI.MSB, pins=('GP31', 'GP16', 'GP30')) # CLK, MOSI, MISO except AttributeError: self.spi.init(baudrate=baud, bits=8, polarity=1, phase=1, firstbit=SPI.MSB, pins=('GP31', 'GP16', 'GP30')) # CLK, MOSI, MISO # These are all active low! self.tc_en_bar = Pin('GP4', mode=Pin.OUT) self.disable() self.tc_busy_bar = Pin('GP5', mode=Pin.IN) self.tc_busy_bar.irq(trigger=Pin.IRQ_RISING) # Wake up when it changes self.tc_cs_bar = Pin('GP17', mode=Pin.ALT, alt=7) self.debug = debug def enable(self): self.tc_en_bar.value(0) # Power up time.sleep_ms(5) while self.tc_busy_bar() == 0: machine.idle() # will it wake up here? # /tc_busy goes high during startup, low during init, then high when not busy def disable(self): self.tc_en_bar.value(1) # Off def send_command(self, ins, p1, p2, data=None, expected=None): # These command variables are always sent cmd = struct.pack('3B', ins, p1, p2) # Looks like data is only sent with the length (Lc) if data: assert len(data) <= 251 # Thus speaks the datasheet cmd += struct.pack('B', len(data)) cmd += data # Expected data is either not present at all, 0 for null-terminated, or a number for fixed if expected is not None: cmd += struct.pack('B', expected) if self.debug: print("Sending: " + hexlify(cmd).decode()) self.spi.write(cmd) # Wait for a little while time.sleep_us(15) # This should take at most 14.5us while self.tc_busy_bar() == 0: machine.idle() # Request a response if expected is not None: if expected > 0: result_bytes = self.spi.read(2 + expected) else: result_bytes = self.spi.read(EPD.MAX_READ) strlen = result_bytes.find(b'\x00') result_bytes = result_bytes[:strlen] + result_bytes[strlen+1:strlen+3] else: result_bytes = self.spi.read(2) if self.debug: print("Received: " + hexlify(result_bytes).decode()) (result,) = struct.unpack_from('>H', result_bytes[-2:]) if result != EPD.SW_NORMAL_PROCESSING: raise ValueError("Bad result code: 0x%x" % result) return result_bytes[:-2] @staticmethod def calculate_checksum(data, skip=16): """ Initial checksum value is 0x6363 :param data: :param skip: Skip some data as slices are expensive :return: """ acc = 0x6363 for byte in data: if skip > 0: skip -= 1 else: acc ^= byte acc = ((acc >> 8) | (acc << 8)) & 0xffff acc ^= ((acc & 0xff00) << 4) & 0xffff acc ^= (acc >> 8) >> 4 acc ^= (acc & 0xff00) >> 5 return acc def get_sensor_data(self): # GetSensorData val = self.send_command(0xe5, 1, 0, expected=2) (temp,) = struct.unpack(">H", val) return temp def get_device_id(self): return self.send_command(0x30, 2, 1, expected=0x14) def get_system_info(self): return self.send_command(0x31, 1, 1, expected=0) def get_system_version_code(self): return self.send_command(0x31, 2, 1, expected=0x10) def display_update(self, slot=0, flash=True): cmd = 0x86 if flash: cmd = 0x24 self.send_command(cmd, 1, slot) def reset_data_pointer(self): self.send_command(0x20, 0xd, 0) def image_erase_frame_buffer(self, slot=0): self.send_command(0x20, 0xe, slot) def get_checksum(self, slot): cksum_val = self.send_command(0x2e, 1, slot, expected=2) (cksum,) = struct.unpack(">H", cksum_val) return cksum def upload_image_data(self, data, slot=0, delay_us=1000): self.send_command(0x20, 1, slot, data) time.sleep_us(delay_us) def upload_whole_image(self, img, slot=0): """ Chop up chunks and send it :param img: Image to send in EPD format :param slot: Slot framebuffer number to use :param delay_us: Delay between packets? 450us and the Tbusy line never comes back :return: """ total = len(img) idx = 0 try: while idx < total - 250: chunk = img[idx:idx+250] self.upload_image_data(chunk, slot) del chunk idx += 250 self.upload_image_data(img[idx:], slot) except KeyboardInterrupt: print("Stopped at user request at position: %d (%d)" % (idx, (idx // 250))) except ValueError as e: print("Stopped at position: %d (%d) - %s" % (idx, (idx // 250), e))
def spi(): from machine import SPI from machine import Pin from utime import sleep def uart_handle(pin): print('irq') intr = Pin(2,Pin.IN) intr.irq(trigger=Pin.IRQ_RISING, handler=uart_handle) cspin = Pin(15,Pin.OUT) cspin.value(1) cs1pin = Pin(16,Pin.OUT) cs1pin.value(1) hspi = SPI(1,baudrate=4000000,polarity=0,phase=0) hspi.init() i,r,w,wfifo,rfifo,ruart = sc16is750(hspi,cspin) i() o = 0 def wr(): print('wfifo') ack = wfifo(b'\x00\x01\x02\x03\x04\x05\x06\x07\x10\x11\x12\x13\x14\x15\x16\x17') if ack==0: print('no room') #wfifo(b'\xaa\x66\x55\x99') def rd(): print('readback') lsr = r(5) print('x{0:x}'.format(int.from_bytes(lsr, 'big')) ) for i in range(8): lsr1 = r(5) lsr1 = int.from_bytes(lsr1,'big') lsr = lsr1 & 0x01 if lsr==1: print( '{:02x}'.format(lsr1) ) print(r(0)) lsr = r(5) print('x{0:x}'.format(int.from_bytes(lsr, 'big')) ) def rd1(): nonlocal o n,b = ruart() print( '{}:{}: {}'.format(o,n,b) ) o=o+1 def rd2(): nonlocal o print('readback2') lsr = r(5) lsr1 = int.from_bytes(lsr,'big') & 0x01 if lsr1==0x01: print( '{}: {}'.format(o,rfifo()) ) print('x{0:02x}'.format(int.from_bytes(lsr, 'big')) ) o=o+1 def write595(v): cs1pin.value(0) hspi.write(v.to_bytes(1,'big')) cs1pin.value(1) return write595,wr,rfifo
""" from machine import Pin, SPI from gd import * import urandom # on recent MicroPython Firmware v1.10+ import os from math import sqrt from time import sleep # Initialize the SPI Bus (on ESP8266-EVB) # Software SPI # spi = SPI(-1, baudrate=4000000, polarity=1, phase=0, sck=Pin(14), mosi=Pin(13), miso=Pin(12)) # Hardware SPI spi = SPI(2) # MOSI=Y8, MISO=Y7, SCK=Y6, SS=Y5 spi.init( baudrate=20000000, phase=0, polarity=0 ) # raise @ 20 Mhz # We must manage the SS signal ourself ss = Pin( Pin.board.Y5, Pin.OUT ) # Gameduino Lib gd = Gameduino( spi, ss ) gd.begin() # os.chdir( '/sd' ) # === Toolbox ================================================================== # readn() has been added to the gameduino library # void readn(byte *dst, unsigned int addr, int c) # Ported from random.h - MicroCode for the VGA controler random_code = [ 0x81,0x15,
def sdtest(): print("1") #hardware spi spi = SPI(2, baudrate=10000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(18, Pin.OUT, Pin.PULL_DOWN), mosi=Pin(23, Pin.OUT, Pin.PULL_UP), miso=Pin(19, Pin.IN, Pin.PULL_UP)) spi.init() # Ensure right baudrate sd = sdcard.SDCard(spi, Pin(22)) # Compatible with PCB vfs = os.VfsFat(sd) os.mount(vfs, "/fc") print("Filesystem check") print(os.listdir("/fc")) print("1") line = "abcdefghijklmnopqrstuvwxyz\n" lines = line * 200 # 5400 chars short = "1234567890\n" print("1") fn = "/fc/rats.txt" print() print("Multiple block read/write") with open(fn, "w") as f: n = f.write(lines) print(n, "bytes written") n = f.write(short) print(n, "bytes written") n = f.write(lines) print(n, "bytes written") with open(fn, "r") as f: result1 = f.read() print(len(result1), "bytes read") fn = "/fc/rats1.txt" print() print("Single block read/write") with open(fn, "w") as f: n = f.write(short) # one block print(n, "bytes written") with open(fn, "r") as f: result2 = f.read() print(len(result2), "bytes read") os.umount("/fc") print() print("Verifying data read back") success = True if result1 == "".join((lines, short, lines)): print("Large file Pass") else: print("Large file Fail") success = False if result2 == short: print("Small file Pass") else: print("Small file Fail") success = False print() print("Tests", "passed" if success else "failed")
else: raise Exception('Board not supported!') spi = SPI(0, SPI.MASTER, baudrate=2000000, polarity=0, phase=0, firstbit=SPI.MSB, pins=spi_pins) print(spi) spi = SPI(baudrate=5000000) print(spi) spi = SPI(0, SPI.MASTER, baudrate=200000, bits=16, polarity=0, phase=0) print(spi) spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=0, phase=1) print(spi) spi = SPI(0, SPI.MASTER, baudrate=5000000, bits=32, polarity=1, phase=0) print(spi) spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=1, phase=1) print(spi) spi.init(baudrate=20000000, polarity=0, phase=0) print(spi) spi=SPI() print(spi) SPI(mode=SPI.MASTER) SPI(mode=SPI.MASTER, pins=spi_pins) SPI(id=0, mode=SPI.MASTER, polarity=0, phase=0, pins=('GP14', 'GP16', 'GP15')) SPI(0, SPI.MASTER, polarity=0, phase=0, pins=('GP31', 'GP16', 'GP15')) spi = SPI(0, SPI.MASTER, baudrate=10000000, polarity=0, phase=0, pins=spi_pins) print(spi.write('123456') == 6) buffer_r = bytearray(10) print(spi.readinto(buffer_r) == 10) print(spi.readinto(buffer_r, write=0x55) == 10) read = spi.read(10) print(len(read) == 10)
class ILI9341: def __init__(self, width, height): self.width = width self.height = height self.pages = self.height // 8 self.buffer = bytearray(self.pages * self.width) self.framebuf = framebuf.FrameBuffer(self.buffer, self.width, self.height, framebuf.MONO_VLSB) self.spi = SPI(0) # chip select self.cs = Pin("P16", mode=Pin.OUT, pull=Pin.PULL_UP) # command self.dc = Pin("P17", mode=Pin.OUT, pull=Pin.PULL_UP) # initialize all pins high self.cs.high() self.dc.high() self.spi.init(baudrate=8000000, phase=0, polarity=0) self.init_display() def init_display(self): time.sleep_ms(500) self.write_cmd(0x01) time.sleep_ms(200) self.write_cmd(0xCF) self.write_data(bytearray([0x00, 0x8B, 0x30])) self.write_cmd(0xED) self.write_data(bytearray([0x67, 0x03, 0x12, 0x81])) self.write_cmd(0xE8) self.write_data(bytearray([0x85, 0x10, 0x7A])) self.write_cmd(0xCB) self.write_data(bytearray([0x39, 0x2C, 0x00, 0x34, 0x02])) self.write_cmd(0xF7) self.write_data(bytearray([0x20])) self.write_cmd(0xEA) self.write_data(bytearray([0x00, 0x00])) # Power control self.write_cmd(0xC0) # VRH[5:0] self.write_data(bytearray([0x1B])) # Power control self.write_cmd(0xC1) # SAP[2:0];BT[3:0] self.write_data(bytearray([0x10])) # VCM control self.write_cmd(0xC5) self.write_data(bytearray([0x3F, 0x3C])) # VCM control2 self.write_cmd(0xC7) self.write_data(bytearray([0xB7])) # Memory Access Control self.write_cmd(0x36) self.write_data(bytearray([0x08])) self.write_cmd(0x3A) self.write_data(bytearray([0x55])) self.write_cmd(0xB1) self.write_data(bytearray([0x00, 0x1B])) # Display Function Control self.write_cmd(0xB6) self.write_data(bytearray([0x0A, 0xA2])) # 3Gamma Function Disable self.write_cmd(0xF2) self.write_data(bytearray([0x00])) # Gamma curve selected self.write_cmd(0x26) self.write_data(bytearray([0x01])) # Set Gamma self.write_cmd(0xE0) self.write_data(bytearray([0x0F, 0x2A, 0x28, 0x08, 0x0E, 0x08, 0x54, 0XA9, 0x43, 0x0A, 0x0F, 0x00, 0x00, 0x00, 0x00])) # Set Gamma self.write_cmd(0XE1) self.write_data(bytearray([0x00, 0x15, 0x17, 0x07, 0x11, 0x06, 0x2B, 0x56, 0x3C, 0x05, 0x10, 0x0F, 0x3F, 0x3F, 0x0F])) # Exit Sleep self.write_cmd(0x11) time.sleep_ms(120) # Display on self.write_cmd(0x29) time.sleep_ms(500) self.fill(0) def show(self): # set col self.write_cmd(0x2A) self.write_data(bytearray([0x00, 0x00])) self.write_data(bytearray([0x00, 0xef])) # set page self.write_cmd(0x2B) self.write_data(bytearray([0x00, 0x00])) self.write_data(bytearray([0x01, 0x3f])) self.write_cmd(0x2c); num_of_pixels = self.height * self.width for row in range(0, self.pages): for pixel_pos in range(0, 8): for col in range(0, self.width): compressed_pixel = self.buffer[row * 240 + col] if ((compressed_pixel >> pixel_pos) & 0x1) == 0: self.write_data(bytearray([0x00, 0x00])) else: self.write_data(bytearray([0xFF, 0xFF])) def fill(self, col): self.framebuf.fill(col) def pixel(self, x, y, col): self.framebuf.pixel(x, y, col) def scroll(self, dx, dy): self.framebuf.scroll(dx, dy) def text(self, string, x, y, col=1): self.framebuf.text(string, x, y, col) def write_cmd(self, cmd): self.dc.low() self.cs.low() self.spi.write(bytearray([cmd])) self.cs.high() def write_data(self, buf): self.dc.high() self.cs.low() self.spi.write(buf) self.cs.high()
class MFRC522: RESET = 'GP22' CLK = 'GP14' MISO = 'GP15' MOSI = 'GP16' CS = 'GP17' MAX_LEN = 16 PCD_IDLE = 0x00 PCD_AUTHENT = 0x0E PCD_TRANSCEIVE = 0x0C PCD_RESETPHASE = 0x0F PCD_CALCCRC = 0x03 PICC_REQIDL = 0x26 PICC_REQALL = 0x52 PICC_ANTICOLL = 0x93 PICC_SElECTTAG = 0x93 PICC_AUTHENT1A = 0x60 PICC_READ = 0x30 PICC_WRITE = 0xA0 MI_OK = 0 MI_NOTAGERR = 1 MI_ERR = 2 MI_AUTH_ERROR_STATUS2REG = 3 CommandReg = 0x01 CommIEnReg = 0x02 CommIrqReg = 0x04 DivIrqReg = 0x05 ErrorReg = 0x06 Status2Reg = 0x08 FIFODataReg = 0x09 FIFOLevelReg = 0x0A WaterLevelReg = 0x0B ControlReg = 0x0C BitFramingReg = 0x0D ModeReg = 0x11 TxControlReg = 0x14 TxAutoReg = 0x15 CRCResultRegM = 0x21 CRCResultRegL = 0x22 TModeReg = 0x2A TPrescalerReg = 0x2B TReloadRegH = 0x2C TReloadRegL = 0x2D serNum = [] def __init__(self, spd=1000000): # first assign CLK, MISO, MOSI, CS to the correct pins self.pin_clk = Pin(self.CLK, mode=Pin.OUT) # CLK self.pin_miso = Pin(self.MISO) # MISO self.pin_mosi = Pin(self.MOSI, mode=Pin.OUT) # MOSI self.pin_cs = Pin(self.CS, mode=Pin.OUT) # NSS/CS self.pin_reset = Pin(self.RESET, mode=Pin.OUT) self.pin_reset.value(0) self.pin_cs.value(1) self.spi = SPI(0) self.spi.init(mode=SPI.MASTER, baudrate=spd, pins=(self.CLK, self.MOSI, self.MISO)) self.pin_reset.value(1) self.MFRC522_Init() def MFRC522_Reset(self): self.Write_MFRC522(self.CommandReg, self.PCD_RESETPHASE) def Write_MFRC522(self, addr, val): self.pin_cs.value(0) # 0(MSB = Write) ADDR1 ADDR2 ADDR3 ADDR4 ADDR5 ADDR6 0(LSB = 0) DATA spiBytes = bytearray(2) spiBytes[0] = ((addr<<1)&0x7E) spiBytes[1] = val self.spi.write(spiBytes) self.pin_cs.value(1) def Read_MFRC522(self, addr): self.pin_cs.value(0) # 1(MSB = Read) ADDR1 ADDR2 ADDR3 ADDR4 ADDR5 ADDR6 0(LSB = 0) self.spi.write((addr<<1)&0x7E|0x80) data = self.spi.read(1) self.pin_cs.value(1) return data[0] def SetBitMask(self, reg, mask): tmp = self.Read_MFRC522(reg) self.Write_MFRC522(reg, tmp | mask) def ClearBitMask(self, reg, mask): tmp = self.Read_MFRC522(reg); self.Write_MFRC522(reg, tmp & (~mask)) def AntennaOn(self): temp = self.Read_MFRC522(self.TxControlReg) if(~(temp & 0x03)): self.SetBitMask(self.TxControlReg, 0x03) def AntennaOff(self): self.ClearBitMask(self.TxControlReg, 0x03) def MFRC522_ToCard(self,command,sendData): backData = [] backLen = 0 status = self.MI_ERR irqEn = 0x00 waitIRq = 0x00 lastBits = None n = 0 i = 0 if command == self.PCD_AUTHENT: irqEn = 0x12 waitIRq = 0x10 if command == self.PCD_TRANSCEIVE: irqEn = 0x77 waitIRq = 0x30 self.Write_MFRC522(self.CommIEnReg, irqEn|0x80) self.ClearBitMask(self.CommIrqReg, 0x80) self.SetBitMask(self.FIFOLevelReg, 0x80) self.Write_MFRC522(self.CommandReg, self.PCD_IDLE); while(i<len(sendData)): self.Write_MFRC522(self.FIFODataReg, sendData[i]) i = i+1 self.Write_MFRC522(self.CommandReg, command) if command == self.PCD_TRANSCEIVE: self.SetBitMask(self.BitFramingReg, 0x80) i = 2000 while True: n = self.Read_MFRC522(self.CommIrqReg) i = i - 1 if ~((i!=0) and ~(n&0x01) and ~(n&waitIRq)): break self.ClearBitMask(self.BitFramingReg, 0x80) if i != 0: st = self.Read_MFRC522(self.ErrorReg) if (st & 0x1B)==0x00: status = self.MI_OK if n & irqEn & 0x01: status = self.MI_NOTAGERR elif command == self.PCD_TRANSCEIVE: n = self.Read_MFRC522(self.FIFOLevelReg) lastBits = self.Read_MFRC522(self.ControlReg) & 0x07 if lastBits != 0: backLen = (n-1)*8 + lastBits else: backLen = n*8 if n == 0: n = 1 if n > self.MAX_LEN: n = self.MAX_LEN i = 0 while i<n: backData.append(self.Read_MFRC522(self.FIFODataReg)) i = i + 1; else: status = self.MI_ERR return (status,backData,backLen) def MFRC522_Request(self, reqMode): status = None backBits = None TagType = [reqMode] self.Write_MFRC522(self.BitFramingReg, 0x07) (status,backData,backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, TagType) if ((status != self.MI_OK) | (backBits != 0x10)): status = self.MI_ERR return (status,backBits) def MFRC522_Anticoll(self): backData = [] serNumCheck = 0 serNum = [self.PICC_ANTICOLL, 0x20] self.Write_MFRC522(self.BitFramingReg, 0x00) (status,backData,backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,serNum) if(status == self.MI_OK): i = 0 if len(backData)==5: while i<4: serNumCheck = serNumCheck ^ backData[i] i = i + 1 if serNumCheck != backData[i]: status = self.MI_ERR else: status = self.MI_ERR return (status,backData) def CalulateCRC(self, pIndata): self.ClearBitMask(self.DivIrqReg, 0x04) self.SetBitMask(self.FIFOLevelReg, 0x80); i = 0 while i<len(pIndata): self.Write_MFRC522(self.FIFODataReg, pIndata[i]) i = i + 1 self.Write_MFRC522(self.CommandReg, self.PCD_CALCCRC) i = 0xFF while True: n = self.Read_MFRC522(self.DivIrqReg) i = i - 1 if not ((i != 0) and not (n&0x04)): break pOutData = [] pOutData.append(self.Read_MFRC522(self.CRCResultRegL)) pOutData.append(self.Read_MFRC522(self.CRCResultRegM)) return pOutData def MFRC522_SelectTag(self, serNum): backData = [] buf = [self.PICC_SElECTTAG, 0x70] + serNum[:5] buf += self.CalulateCRC(buf) (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf) if (status == self.MI_OK) and (backLen == 0x18): return self.MI_OK else: return self.MI_ERR def MFRC522_Auth(self, authMode, BlockAddr, Sectorkey, serNum): #First byte should be the authMode (A or B) #Second byte is the trailerBlock (usually 7) #Now we need to append the authKey which usually is 6 bytes of 0xFF #Next we append the first 4 bytes of the UID buff = [authMode, BlockAddr] + Sectorkey + serNum[:4] # Now we start the authentication itself (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_AUTHENT,buff) # Check if an error occurred # Return the status return status def MFRC522_StopCrypto1(self): self.ClearBitMask(self.Status2Reg, 0x08) def MFRC522_Read(self, blockAddr): recvData = [self.PICC_READ, blockAddr] recvData += self.CalulateCRC(recvData) (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, recvData) return (status, backData) def MFRC522_Write(self, blockAddr, writeData): buff = [self.PICC_WRITE, blockAddr] buff += self.CalulateCRC(buff) (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buff) if not(status == self.MI_OK) or not(backLen == 4) or not((backData[0] & 0x0F) == 0x0A): status = self.MI_ERR if status == self.MI_OK: i = 0 buf = [] while i < 16: buf.append(writeData[i]) i = i + 1 buf += self.CalulateCRC(buf) (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE,buf) if not(status == self.MI_OK) or not(backLen == 4) or not((backData[0] & 0x0F) == 0x0A): status = self.MI_ERR return status def MFRC522_Init(self): self.MFRC522_Reset(); self.Write_MFRC522(self.TModeReg, 0x8D) self.Write_MFRC522(self.TPrescalerReg, 0x3E) self.Write_MFRC522(self.TReloadRegL, 30) self.Write_MFRC522(self.TReloadRegH, 0) self.Write_MFRC522(self.TxAutoReg, 0x40) self.Write_MFRC522(self.ModeReg, 0x3D) self.AntennaOn()
class MFRC522: OK = 0 NOTAGERR = 1 ERR = 2 REQIDL = 0x26 REQALL = 0x52 AUTHENT1A = 0x60 AUTHENT1B = 0x61 def __init__(self, sck, mosi, miso, rst, cs): self.sck = Pin(sck, Pin.OUT) self.mosi = Pin(mosi, Pin.OUT) self.miso = Pin(miso) self.rst = Pin(rst, Pin.OUT) self.cs = Pin(cs, Pin.OUT) self.rst.value(0) self.cs.value(1) self.spi = SPI(baudrate=100000, polarity=0, phase=0, sck=self.sck, mosi=self.mosi, miso=self.miso) self.spi.init() self.rst.value(1) self.init() def _wreg(self, reg, val): self.cs.value(0) self.spi.write(b'%c' % int(0xff & ((reg << 1) & 0x7e))) self.spi.write(b'%c' % int(0xff & val)) self.cs.value(1) def _rreg(self, reg): self.cs.value(0) self.spi.write(b'%c' % int(0xff & (((reg << 1) & 0x7e) | 0x80))) val = self.spi.read(1) self.cs.value(1) return val[0] def _sflags(self, reg, mask): self._wreg(reg, self._rreg(reg) | mask) def _cflags(self, reg, mask): self._wreg(reg, self._rreg(reg) & (~mask)) def _tocard(self, cmd, send): recv = [] bits = irq_en = wait_irq = n = 0 stat = self.ERR if cmd == 0x0E: irq_en = 0x12 wait_irq = 0x10 elif cmd == 0x0C: irq_en = 0x77 wait_irq = 0x30 self._wreg(0x02, irq_en | 0x80) self._cflags(0x04, 0x80) self._sflags(0x0A, 0x80) self._wreg(0x01, 0x00) for c in send: self._wreg(0x09, c) self._wreg(0x01, cmd) if cmd == 0x0C: self._sflags(0x0D, 0x80) i = 200 while True: n = self._rreg(0x04) i -= 1 if ~((i != 0) and ~(n & 0x01) and ~(n & wait_irq)): break self._cflags(0x0D, 0x80) if i: if (self._rreg(0x06) & 0x1B) == 0x00: stat = self.OK if n & irq_en & 0x01: stat = self.NOTAGERR elif cmd == 0x0C: n = self._rreg(0x0A) lbits = self._rreg(0x0C) & 0x07 if lbits != 0: bits = (n - 1) * 8 + lbits else: bits = n * 8 if n == 0: n = 1 elif n > 16: n = 16 for _ in range(n): recv.append(self._rreg(0x09)) else: stat = self.ERR return stat, recv, bits def _crc(self, data): self._cflags(0x05, 0x04) self._sflags(0x0A, 0x80) for c in data: self._wreg(0x09, c) self._wreg(0x01, 0x03) i = 0xFF while True: n = self._rreg(0x05) i -= 1 if not ((i != 0) and not (n & 0x04)): break return [self._rreg(0x22), self._rreg(0x21)] def init(self): self.reset() self._wreg(0x2A, 0x8D) self._wreg(0x2B, 0x3E) self._wreg(0x2D, 30) self._wreg(0x2C, 0) self._wreg(0x15, 0x40) self._wreg(0x11, 0x3D) self.antenna_on() def reset(self): self._wreg(0x01, 0x0F) def antenna_on(self, on=True): if on and ~(self._rreg(0x14) & 0x03): self._sflags(0x14, 0x03) else: self._cflags(0x14, 0x03) def request(self, mode): self._wreg(0x0D, 0x07) (stat, recv, bits) = self._tocard(0x0C, [mode]) if (stat != self.OK) | (bits != 0x10): stat = self.ERR return stat, bits def anticoll(self): ser_chk = 0 ser = [0x93, 0x20] self._wreg(0x0D, 0x00) (stat, recv, bits) = self._tocard(0x0C, ser) if stat == self.OK: if len(recv) == 5: for i in range(4): ser_chk = ser_chk ^ recv[i] if ser_chk != recv[4]: stat = self.ERR else: stat = self.ERR return stat, recv def select_tag(self, ser): buf = [0x93, 0x70] + ser[:5] buf += self._crc(buf) (stat, recv, bits) = self._tocard(0x0C, buf) return self.OK if (stat == self.OK) and (bits == 0x18) else self.ERR def auth(self, mode, addr, sect, ser): return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0] def stop_crypto1(self): self._cflags(0x08, 0x08) def read(self, addr): data = [0x30, addr] data += self._crc(data) (stat, recv, _) = self._tocard(0x0C, data) return recv if stat == self.OK else None def write(self, addr, data): buf = [0xA0, addr] buf += self._crc(buf) (stat, recv, bits) = self._tocard(0x0C, buf) if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): stat = self.ERR else: buf = [] for i in range(16): buf.append(data[i]) buf += self._crc(buf) (stat, recv, bits) = self._tocard(0x0C, buf) if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): stat = self.ERR return stat def read_data(self, addresses=None): """ Wait for card and read data from 'addresses' :param addresses: list of addresses to read from (if you specify empty list, card data will contain only UID) :return: CardData instance with card data """ print("Place card before reader to read from addresses {}".format(addresses)) card = None while True: (stat, tag_type) = self.request(self.REQIDL) if stat != self.OK: continue (stat, raw_uid) = self.anticoll() if stat == self.OK: card = CardData(raw_uid, tag_type) if self.select_tag(card.uid) == self.OK: key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] addresses = addresses if addresses is not None else range(64) for i in addresses: if self.auth(self.AUTHENT1A, i, key, card.uid) == self.OK: data = bytes(self.read(i)) card.set_data(i, data) self.stop_crypto1() else: print("Authentication error for address {}".format(i)) else: print("Failed to select tag") return None return card def write_data(self, data): """ Writes specified "data" to card :param data: dict with key - address, value - 16 bytes of data in binary string (hex) :return: CardData instance """ print("Place card before reader to write to addresses {}".format(data.keys())) while True: (stat, tag_type) = self.request(self.REQIDL) if stat != self.OK: continue (stat, raw_uid) = self.anticoll() if stat == self.OK: print("Card detected") card = CardData(raw_uid, tag_type) if self.select_tag(card.uid) == self.OK: key = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF] for addr, value in data.items(): if self.auth(self.AUTHENT1A, addr, key, card.uid) == self.OK: card.set_data(addr, value) stat = self.write(addr, value) self.stop_crypto1() if stat == self.OK: print("Data written to card for address {}".format(addr)) else: print("Failed to write data to card for address {}".format(addr)) else: print("Authentication error for address {}".format(addr)) else: print("Failed to select tag")
class MFRC522: OK = 0 NOTAGERR = 1 ERR = 2 REQIDL = 0x26 REQALL = 0x52 AUTHENT1A = 0x60 AUTHENT1B = 0x61 def __init__(self, sck, mosi, miso, rst, cs): self.sck = Pin(sck, Pin.OUT) self.mosi = Pin(mosi, Pin.OUT) self.miso = Pin(miso) self.rst = Pin(rst, Pin.OUT) self.cs = Pin(cs, Pin.OUT) self.rst.value(0) self.cs.value(1) board = uname()[0] if board == 'WiPy' or board == 'LoPy' or board == 'FiPy': self.spi = SPI(0) self.spi.init(SPI.MASTER, baudrate=1000000, pins=(self.sck, self.mosi, self.miso)) elif board == 'esp8266' or board == 'esp32': self.spi = SPI(baudrate=100000, polarity=0, phase=0, sck=self.sck, mosi=self.mosi, miso=self.miso) self.spi.init() else: raise RuntimeError("Unsupported platform") self.rst.value(1) self.init() def _wreg(self, reg, val): self.cs.value(0) self.spi.write(b'%c' % int(0xff & ((reg << 1) & 0x7e))) self.spi.write(b'%c' % int(0xff & val)) self.cs.value(1) def _rreg(self, reg): self.cs.value(0) self.spi.write(b'%c' % int(0xff & (((reg << 1) & 0x7e) | 0x80))) val = self.spi.read(1) self.cs.value(1) return val[0] def _sflags(self, reg, mask): self._wreg(reg, self._rreg(reg) | mask) def _cflags(self, reg, mask): self._wreg(reg, self._rreg(reg) & (~mask)) def _tocard(self, cmd, send): recv = [] bits = irq_en = wait_irq = n = 0 stat = self.ERR if cmd == 0x0E: irq_en = 0x12 wait_irq = 0x10 elif cmd == 0x0C: irq_en = 0x77 wait_irq = 0x30 self._wreg(0x02, irq_en | 0x80) self._cflags(0x04, 0x80) self._sflags(0x0A, 0x80) self._wreg(0x01, 0x00) for c in send: self._wreg(0x09, c) self._wreg(0x01, cmd) if cmd == 0x0C: self._sflags(0x0D, 0x80) i = 2000 while True: n = self._rreg(0x04) i -= 1 if ~((i != 0) and ~(n & 0x01) and ~(n & wait_irq)): break self._cflags(0x0D, 0x80) if i: if (self._rreg(0x06) & 0x1B) == 0x00: stat = self.OK if n & irq_en & 0x01: stat = self.NOTAGERR elif cmd == 0x0C: n = self._rreg(0x0A) lbits = self._rreg(0x0C) & 0x07 if lbits != 0: bits = (n - 1) * 8 + lbits else: bits = n * 8 if n == 0: n = 1 elif n > 16: n = 16 for _ in range(n): recv.append(self._rreg(0x09)) else: stat = self.ERR return stat, recv, bits def _crc(self, data): self._cflags(0x05, 0x04) self._sflags(0x0A, 0x80) for c in data: self._wreg(0x09, c) self._wreg(0x01, 0x03) i = 0xFF while True: n = self._rreg(0x05) i -= 1 if not ((i != 0) and not (n & 0x04)): break return [self._rreg(0x22), self._rreg(0x21)] def init(self): self.reset() self._wreg(0x2A, 0x8D) self._wreg(0x2B, 0x3E) self._wreg(0x2D, 30) self._wreg(0x2C, 0) self._wreg(0x15, 0x40) self._wreg(0x11, 0x3D) self.antenna_on() def reset(self): self._wreg(0x01, 0x0F) def antenna_on(self, on=True): if on and ~(self._rreg(0x14) & 0x03): self._sflags(0x14, 0x03) else: self._cflags(0x14, 0x03) def request(self, mode): self._wreg(0x0D, 0x07) (stat, recv, bits) = self._tocard(0x0C, [mode]) if (stat != self.OK) | (bits != 0x10): stat = self.ERR return stat, bits def anticoll(self): ser_chk = 0 ser = [0x93, 0x20] self._wreg(0x0D, 0x00) (stat, recv, bits) = self._tocard(0x0C, ser) if stat == self.OK: if len(recv) == 5: for i in range(4): ser_chk = ser_chk ^ recv[i] if ser_chk != recv[4]: stat = self.ERR else: stat = self.ERR return stat, recv def select_tag(self, ser): buf = [0x93, 0x70] + ser[:5] buf += self._crc(buf) (stat, recv, bits) = self._tocard(0x0C, buf) return self.OK if (stat == self.OK) and (bits == 0x18) else self.ERR def auth(self, mode, addr, sect, ser): return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0] def stop_crypto1(self): self._cflags(0x08, 0x08) def read(self, addr): data = [0x30, addr] data += self._crc(data) (stat, recv, _) = self._tocard(0x0C, data) return recv if stat == self.OK else None def write(self, addr, data): buf = [0xA0, addr] buf += self._crc(buf) (stat, recv, bits) = self._tocard(0x0C, buf) if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): stat = self.ERR else: buf = [] for i in range(16): buf.append(data[i]) buf += self._crc(buf) (stat, recv, bits) = self._tocard(0x0C, buf) if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): stat = self.ERR return stat
loader.loadAll() import agnostic from faces.font_5x7 import font from st7920 import Screen from mfrc522 import MFRC522 from machine import Pin,SPI from engines import dictToCard, cardToDict from engines import Engine from regimes.console import ConsoleHost from vault import BankVault #TODO CH normalise this story module info into one place (e.g. loader, or via milecastles.loadStory) from stories.corbridge import story agnostic.collect() spi = SPI(1, baudrate=1000000, polarity=0, phase=0) spi.init() agnostic.collect() reader = MFRC522(spi=spi, gpioRst=0, gpioCs=2) agnostic.collect() vault = BankVault(reader) agnostic.collect() screen = Screen(spi=spi, slaveSelectPin=Pin(15)) agnostic.collect() # TODO CH remove this test function (actual plotter is in avatap engine) def plotter(x,y): screen.plot(x,y)
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ from machine import Pin, SPI from gd import * # Initialize the SPI Bus (on Pyboard) # Hardware SPI spi = SPI(2) # MOSI=Y8, MISO=Y7, SCK=Y6, SS=Y5 spi.init( SPI.MASTER, baudrate=2000000, phase=0, polarity=0 ) # We must manage the SS signal ourself ss = Pin( Pin.board.Y5, Pin.OUT ) # Gameduino Lib gd = Gameduino( spi, ss ) gd.begin() gd.ascii() gd.putstr( 5 , 0, " *** DEMOs ***" ) gd.putstr( 5 , 1, " 04_demo/ascii/scrsize.py " ) gd.putstr( 0, 5, ''.join(["%s " % i for i in range(6)]) ) gd.putstr( 0, 6, '0123456789'*6 ) for line in range( 38 ): gd.putstr( 0,line, "%2s:" % line )
# Drawing shapes using the Framebuffer # VCC GND STM32F407ZGT6 from machine import Pin, SPI spi = SPI(2) spi.init(baudrate=2000000, polarity=0, phase=0) cs = Pin('B12', Pin.OUT) rst = Pin('B11', Pin.OUT) bl = Pin('B1', Pin.OUT, value=1) # backlight on # with framebuffer import hx1230_fb lcd = hx1230_fb.HX1230_FB_SPI(spi, cs, rst) # 8x8 circles, repeated using blit # ..####.. # .#....#. # #......# # #......# # #......# # #......# # .#....#. # ..####.. import framebuf lcd.clear() circle_buf = bytearray(8) circle_fbuf = framebuf.FrameBuffer(circle_buf, 8, 8, framebuf.MONO_VLSB) circle_fbuf.hline(2,0,4,1) circle_fbuf.pixel(1,1,1) circle_fbuf.pixel(6,1,1) circle_fbuf.vline(0,2,4,1)
all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ import gc from machine import Pin, SPI from gd import Gameduino, RAM_CHR, RAM_PAL # Initialize the SPI Bus (on Pyboard) spi = SPI(2) # MOSI=Y8, MISO=Y7, SCK=Y6, SS=Y5 spi.init( baudrate=2000000, phase=0, polarity=0 ) # We must manage the SS signal ourself sel = Pin( Pin.board.Y5, Pin.OUT ) # Gameduino Lib gd = Gameduino( spi, sel ) print( "Initializing...") gd.begin() print( "Initializing ASCII...") gd.ascii() # Print a string gd.putstr( 5 , 0, " *** DEMOs ***" ) gd.putstr( 5 , 1, "04_demo/ascii/dump.py" ) gd.putstr( 10, 10, "MicroPython goes VGA !" )