示例#1
0
class MAX6675Temperature:
    def __init__(self):
        from machine import SPI, Pin

        self.spi = SPI(1,
                       baudrate=2000000,
                       polarity=1,
                       phase=0,
                       bits=8,
                       firstbit=SPI.MSB,
                       sck=Pin(14),
                       mosi=Pin(13),
                       miso=Pin(12))
        self.cs = Pin(27, Pin.OUT)
        self.cs.on()
        self.tempC = 0

    def getTemperature(self):
        self.cs.off()

        result = self.spi.read(2)
        result = result[0] << 8 | result[1]
        result >>= 4
        self.tempC = result & 0b0000111111111111  # 12 LSB after we have shifted it

        return self.tempC

    def startConversion(self):
        #        self.cs.off() #Not using this as we can call startConversion many times for the same comversion
        self.cs.on()
示例#2
0
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
示例#3
0
文件: osd.py 项目: emard/ulx3s_mac128
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)
示例#4
0
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
示例#5
0
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)
read = spi.read(10, write=0xFF)
print(len(read) == 10)
buffer_w = bytearray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])
print(spi.write_readinto(buffer_w, buffer_r) == 10)
print(buffer_w == buffer_r)

# test all polaritiy and phase combinations
spi.init(polarity=1, phase=0, pins=None)
buffer_r = bytearray(10)
spi.write_readinto(buffer_w, buffer_r)
print(buffer_w == buffer_r)

spi.init(polarity=1, phase=1, pins=None)
buffer_r = bytearray(10)
示例#6
0
#importing machine and spi
from machine import Pin, SPI

#SPI functions#

#Constructing the SPI bus using the following pins
# polarity is the idle state of SCK
# phase=0 means sample on the first edge of SCK, phase=1 means the second
spi = SPI(baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))

spi.init(baudrate=200000) #Setting the baudrate

spi.read(10) #Reading 10 bytes from the baudrate

spi.read(10, 0xff) #read 10 bytes while outputting 0xff on MOSI

buf = bytearray(50)     # create a buffer
spi.readinto(buf)       # read into the given buffer (reads 50 bytes in this case)
spi.readinto(buf, 0xff) # read into the given buffer and output 0xff on MOSI

spi.write(b'12345')     # write 5 bytes on MOSI

buf = bytearray(4)      # create a buffer
spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer
spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf

while True:
    #Input your code that runs continually
示例#7
0
class machx02_spi(object):
    # bit12:busy, bit13:failed, bit9:enabled
    status = {"busy": 4096, "failed": 8192, "enabled": 512, "done": 256}
    mask = 0x00000000FFFFFFFF

    def __init__(self, baudrate, deviceid):
        self.cs = Pin(15, Pin.OUT)
        self.cs.on()
        self.hspi = SPI(1,
                        baudrate=400000,
                        sck=Pin(14),
                        mosi=Pin(13),
                        miso=Pin(12))
        self.deviceid = deviceid

    # transfert spi
    def spiTrans(self, cmd, size):
        resp_machx02_spi = bytearray(size)
        self.hspi.init(baudrate=400000,
                       sck=Pin(14),
                       mosi=Pin(13),
                       miso=Pin(12),
                       firstbit=SPI.MSB)  # set the baudrate*
        self.cs.off()
        self.hspi.write_readinto(cmd, resp_machx02_spi)
        self.cs.on()
        return resp_machx02_spi

    # check idcode
    def check_idcode(self):
        cmd = bytearray([
            MACHXO2_CMD_READ_DEVICEID, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        ])
        resp_machx02_spi = self.spiTrans(cmd, 8)
        resp_machx02_spi_int = self.from_bytes_big(bytes(resp_machx02_spi))
        result = resp_machx02_spi_int & self.mask
        return (self.deviceid == result)

    # disable
    def disable(self):
        #disable configuration
        cmd = bytearray([MACHXO2_CMD_DISABLE, 0x00, 0x00])
        resp_machx02_spi = self.spiTrans(cmd, 3)
        # nop
        cmd = bytearray([MACHXO2_CMD_NOP, 0xFF, 0xFF, 0xFF])
        resp_machx02_spi = self.spiTrans(cmd, 4)

        # refresh
        cmd = bytearray([MACHXO2_CMD_REFRESH, 0x00, 0x00])
        resp_machx02_spi = self.spiTrans(cmd, 3)
        utime.sleep_ms(10000)

    def wakeup_device(self):
        # refresh
        cmd = bytearray([MACHXO2_CMD_REFRESH, 0x00, 0x00])
        resp_machx02_spi = self.spiTrans(cmd, 3)
        utime.sleep_ms(10000)

    # enable offline configuration
    def enable(self):
        cmd = bytearray([MACHXO2_CMD_ENABLE_OFFLINE, 0x08, 0x00, 0x00])
        resp_machx02_spi = self.spiTrans(cmd, 4)
        self.waitidle()

        # erase SRAM
        cmd = bytearray([MACHXO2_CMD_ERASE, 0x01, 0x00, 0x00])
        resp_machx02_spi = self.spiTrans(cmd, 4)
        self.waitidle()

        # bit 13 = fail
        # bit 9 = enabled
        resp = self.readstatus()
        print("status enable", resp)
        status_failed = self.from_bytes_big(resp) & self.status["failed"]
        status_enabled = self.from_bytes_big(resp) & self.status["enabled"]
        #print(status_failed,status_enabled)
        return (status_failed != self.status["failed"]) and (
            status_enabled == self.status["enabled"])

    # busy = bit12
    def waitidle(self):
        while True:
            resp = self.readstatus()
            # print("status=",resp)
            status_busy = self.from_bytes_big(resp) & self.status["busy"]
            #print("busy ",status_busy,type(status_busy))
            if status_busy == self.status["busy"]:
                #print("busy")
                utime.sleep_ms(1)  # datasheet = 200 us
            else:
                break

    def waitdone(self):
        while True:
            resp = self.readstatus()
            status_done = self.from_bytes_big(resp) & self.status["done"]
            print("wait done status=", status_done)
            if status_done != self.status["done"]:
                print("wait done")
                utime.sleep_ms(1)  # datasheet = 200 us
            else:
                break

    def waitrefresh(self):
        while True:
            resp = self.readstatus()
            print("wait refresh=", resp)
            status_done = self.from_bytes_big(resp) & self.status["done"]
            print("status_done=", status_done)
            status_busy = self.from_bytes_big(resp) & self.status["busy"]
            print("status_busy=", status_busy)
            if status_busy == self.status["busy"]:
                cmd = bytearray([MACHXO2_CMD_REFRESH, 0x00, 0x00])
                resp_machx02_spi = self.spiTrans(cmd, 3)
                print("wait refresh")
                utime.sleep_ms(1)  # datasheet = 200 us
            else:
                break

    # read status
    def readstatus(self):
        cmd = bytearray([
            MACHXO2_CMD_READ_STATUS, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
        ])
        resp_machx02_spi = self.spiTrans(cmd, 8)
        return resp_machx02_spi

    # read features
    def readfeatures(self):
        cmd = bytearray([
            MACHXO2_CMD_READ_FEATURE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00
        ])
        feature_row = self.spiTrans(cmd, 12)
        #  read FEABITS
        cmd = bytearray(
            [MACHXO2_CMD_READ_FEABITS, 0x00, 0x00, 0x00, 0x00, 0x00])
        feabits = self.spiTrans(cmd, 6)
        return self.from_bytes_big(feature_row), self.from_bytes_big(feabits)

    # programm jedec file
    def program(self, fusetable):
        # erase flash
        cmd = bytearray([MACHXO2_CMD_ERASE, 0x04, 0x00, 0x00])
        resp_machx02_spi = self.spiTrans(cmd, 4)
        print("erase flash ...")
        self.waitidle()
        resp = self.readstatus()
        status_failed = self.from_bytes_big(resp) & self.status["failed"]
        if status_failed == self.status["failed"]:
            return False

    # set address to zero
        cmd = bytearray([MACHXO2_CMD_INIT_ADDRESS, 0x00, 0x00, 0x00])
        resp_machx02_spi = self.spiTrans(cmd, 4)
        #print("set adress to 0")
        self.waitidle()

        # program pages
        sizefile = len(fusetable)
        nb_bit = sizefile * 128
        # not implemented, because ufm not programmed
        # if nb_bit != int(MACHXO2_SIZE_FUSETABLE_7000):
        # print("error size fusetable",nb_bit)
        # sys.exit()
        # else:
        # print("size fusetable",nb_bit)
        #lines = [i.strip() for i in fusetable]
        numbit = 0
        crc = 0
        nbdata = 16
        countline = 0
        req = bytearray(20)
        for line in fusetable:
            #before = gc.mem_free()
            line_strip = line.strip()
            size_line = len(line_strip)
            # print("count",countline,size_line)
            countline = countline + 1
            for countbit_128 in range(size_line):
                valbit = line_strip[countbit_128]
                if valbit == "1":
                    val = 1
                else:
                    val = 0
                crc += val << (numbit % 8)
                numbit = numbit + 1
            line_bytes = [line_strip[i:i + 8] for i in range(0, size_line, 8)]

            # transmit data with format  : cmd,0,0,1 <16* 8 bytes data>
            req[0] = MACHXO2_CMD_PROG_INCR_NV
            req[1] = 0x00
            req[2] = 0x00
            req[3] = 0x01
            # transmit Y*16 bytes
            for i in range(nbdata):
                req[4 + i] = self.str_to_byte(line_bytes[i])
            resp_machx02_spi = self.spiTrans(req, nbdata + 4)
            #after = gc.mem_free()
            #print("mem =",before - after ,"bytes")
            self.waitidle()
        print("numbit programmed = ", numbit)
        #  program DONE bit
        cmd = bytearray([MACHXO2_CMD_PROGRAM_DONE, 0x00, 0x00, 0x00])
        resp_machx02_spi = self.spiTrans(cmd, 4)
        self.waitdone()
        status = self.readstatus()
        status_failed = self.from_bytes_big(status) & self.status["failed"]
        error = (status_failed != self.status["failed"])
        return error, crc

    # read flash

    def checkflash(self):
        countpage = 0x0100  # 14 bits counter page
        cmd = bytearray([MACHXO2_CMD_READ_INCR_NV, 0x01, 0x01, 0x00])
        self.cs.off()
        self.hspi.write(cmd)
        self.cs.on()
        utime.sleep_us(500)
        self.cs.off()
        resp_machx02_spi = self.hspi.read(int(countpage))
        self.cs.on()
        return resp_machx02_spi

    # read ufm
    def readufm(self):
        cmd = bytearray([MACHXO2_CMD_READ_UFM, 0x01, 0x00, 0x00])
        resp_machx02_spi = self.spiTrans(cmd, 4)
        return resp_machx02_spi

    def from_bytes_big(self, b):
        n = 0
        for x in b:
            n <<= 8
            n |= x
        return n

    def str_to_byte(self, s):
        b = 0
        for i in range(len(s)):
            b |= int(s[i]) << 7 - i
        return b
示例#8
0
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 == 'esp32' or board == 'LoPy' or board == 'FiPy':
			self.spi = SPI(1, 10000000, sck=self.sck, mosi=self.mosi, miso=self.miso)
			self.spi.init()
		elif board == '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)
		#print("send:")
		#print([hex(x) for x in send])
		for c in send:
			self._wreg(0x09, c)
		self._wreg(0x01, cmd)

		if cmd == 0x0C:
			self._sflags(0x0D, 0x80)

		i = 500 #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
		#print("recv:")
		#print(stat,[hex(x) for x in recv],bits)
		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 requestRawAnswer(self, mode):

		self._wreg(0x0D, 0x07)
		(stat, recv, bits) = self._tocard(0x0C, [mode])

		if (stat != self.OK):
			stat = self.ERR

		return stat, recv, 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
	#PICC_HALT https://www.rubydoc.info/gems/mfrc522/0.0.1/Mfrc522#picc_halt-instance_method:
	def halt(self):
		PICC_HALT = 0x50
		buf = [PICC_HALT, 0x00]
		buf += self._crc(buf)
		(stat, recv, bits) = self._tocard(0x0C, buf)
		return self.OK if (stat == self.OK) and (bits == 0x18) else self.ERR	

	#PICC_WUPA =0x52
	#REQuest command, Type A. Invites PICCs in state IDLE to go to READY and prepare for anticollision or selection. 7 bit frame.
	def wake(self):
		PICC_WUPA = 0x52
		(stat, recv, bits) = self._tocard(0x0C, [PICC_WUPA])
		return self.OK if (stat == self.OK) and (bits == 0x18) else self.ERR


	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 checkChinaUID(self):
		answer = False
		#try to send magic command to the sector 0 
		self.halt()
		(stat, data, bits) = self.requestRawAnswer(0x40) # request is 7 bits
		#print(stat, data, bits)
		if stat == self.OK and data[0] == 0xA:
			#if answer is 0xA, we check further... maybe this is a china changeable UID card
			answer=True 
			#--------------
			#if the next command didn't work, we're pretty sure that is a china card
			#disabled this as the above is enough to detect a china card
			#--------------
			#self._wreg(0x0D, 0x08) #send 8 bytes
			#(stat, data, bytes) = self._tocard(0x0C,[0x43])
			#if stat == self.OK and data[0] == 0xA:
				#sector unlocked. this is a china card
				#from here we can write sector 0 without authentication
			#	answer=True
			#--------------
		self.wake()
		return answer
		
	#https://learn.adafruit.com/adafruit-pn532-rfid-nfc/ndef
	def setKey(self,sector,keya,keyb):
		#https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/zugangsbeschrankung-zu-geraten-per-contactless-card-mit-der-nodemcu-und-dem-rc522-modul-vierter-teil-down-the-rabbit-hole?ls=de&cache=false
		sectorkeytable = [3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63]
		key = []
		key.extend(keya[:6])
		key.append(0x78) #Data Block 0-3 Access Conditions: Key B write / Key A Read
		key.append(0x77) #KEY A & KEY B & Acces Bits Write:Key B  / Key A Read Access Bits
		key.append(0x88) #Calculator: http://calc.gmss.ru/Mifare1k/
		key.append(0x69) #Fixer Wert - > default hex 69
		key.extend(keyb[:6])
		
		#print(key)
		self.write(sectorkeytable[sector], key)
	def reSetKeyOpen(self,sector,keya,keyb):
		#https://www.az-delivery.de/blogs/azdelivery-blog-fur-arduino-und-raspberry-pi/zugangsbeschrankung-zu-geraten-per-contactless-card-mit-der-nodemcu-und-dem-rc522-modul-vierter-teil-down-the-rabbit-hole?ls=de&cache=false
		sectorkeytable = [3,7,11,15,19,23,27,31,35,39,43,47,51,55,59,63]
		key = []
		key.extend(keya[:6])
		key.append(0xFF) #Data Block 0-3 Access Conditions: Key B write / Key A Read
		key.append(0x07) #KEY A & KEY B & Acces Bits Write:Key B  / Key A Read Access Bits
		key.append(0x80) #Calculator: http://calc.gmss.ru/Mifare1k/
		key.append(0x69) #Fixer Wert - > default hex 69
		key.extend(keyb[:6])
		
		#print(key)
		self.write(sectorkeytable[sector], key)		
示例#9
0
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()
示例#10
0
from machine import SPI,SoftSPI,Pin

# configure the SPI master @ 2MHz
# this uses the SPI non-default pins for CLK, MOSI and MISO (``P19``, ``P20`` and ``P21``)
spi = SPI(2, baudrate=80000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(18), mosi=Pin(23), miso=Pin(19))
spi.write(bytes([0x01, 0x02, 0x03, 0x04, 0x05])) # send 5 bytes on the bus
spi.read(5) # receive 5 bytes on the bus
rbuf = bytearray(5)
spi.write_readinto(bytes([0x01, 0x02, 0x03, 0x04, 0x05]), rbuf) # send a receive 5 bytes
int_val = int.from_bytes(spi.read(5), "big")
print(int_val)
print(spi.read(5))
示例#11
0
class RFM69(RFM69_CONST_VARS):
    
    def __init__(self, cspin, ISRPin, nodeID, networkID, freqBand=868, isRFM69HW=False):
        RFM69_CONST_VARS.__init__(self)
        self._isRFM69HW = isRFM69HW
        
        tREG_FRFMSB = self.RF_FRFMSB_868
        tREG_FRFMID = self.RF_FRFMID_868
        tREG_FRFLSB = self.RF_FRFLSB_868
        if freqBand==433:
            tREG_FRFMSB = self.RF_FRFMSB_433
            tREG_FRFMID = self.RF_FRFMID_433
            tREG_FRFLSB = self.RF_FRFLSB_433
        
        if freqBand==315:
            tREG_FRFMSB = self.RF_FRFMSB_315
            tREG_FRFMID = self.RF_FRFMID_315
            tREG_FRFLSB = self.RF_FRFLSB_315
        
        if freqBand==915:
            tREG_FRFMSB = self.RF_FRFMSB_915
            tREG_FRFMID = self.RF_FRFMID_915
            tREG_FRFLSB = self.RF_FRFLSB_915
            
        self.CONFIG = [[self.REG_OPMODE, self.RF_OPMODE_SEQUENCER_ON | self.RF_OPMODE_LISTEN_OFF | self.RF_OPMODE_STANDBY], 
              [self.REG_DATAMODUL, self.RF_DATAMODUL_DATAMODE_PACKET | self.RF_DATAMODUL_MODULATIONTYPE_FSK | self.RF_DATAMODUL_MODULATIONSHAPING_00], 
              [self.REG_BITRATEMSB, self.RF_BITRATEMSB_55555], 
              [self.REG_BITRATELSB, self.RF_BITRATELSB_55555], 
              [self.REG_FDEVMSB, self.RF_FDEVMSB_50000], 
              [self.REG_FDEVLSB, self.RF_FDEVLSB_50000], 
              [self.REG_FRFMSB, tREG_FRFMSB ], 
              [self.REG_FRFMID, tREG_FRFMID], 
              [self.REG_FRFLSB, tREG_FRFLSB], 
              [self.REG_RXBW, self.RF_RXBW_DCCFREQ_010 | self.RF_RXBW_MANT_16 | self.RF_RXBW_EXP_2 ], 
              [self.REG_DIOMAPPING1, self.RF_DIOMAPPING1_DIO0_01], 
              [self.REG_DIOMAPPING2, self.RF_DIOMAPPING2_CLKOUT_OFF], 
              [self.REG_IRQFLAGS2, self.RF_IRQFLAGS2_FIFOOVERRUN], 
              [self.REG_RSSITHRESH, 220], 
              [self.REG_SYNCCONFIG, self.RF_SYNC_ON | self.RF_SYNC_FIFOFILL_AUTO | self.RF_SYNC_SIZE_2 | self.RF_SYNC_TOL_0], 
              [self.REG_SYNCVALUE1, 0x2D], 
              [self.REG_SYNCVALUE2, networkID ], 
              [self.REG_PACKETCONFIG1, self.RF_PACKET1_FORMAT_VARIABLE | self.RF_PACKET1_DCFREE_OFF | self.RF_PACKET1_CRC_ON | self.RF_PACKET1_CRCAUTOCLEAR_ON | self.RF_PACKET1_ADRSFILTERING_OFF], 
              [self.REG_FIFOTHRESH, self.RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | self.RF_FIFOTHRESH_VALUE], 
              [self.REG_PACKETCONFIG2, self.RF_PACKET2_RXRESTARTDELAY_2BITS | self.RF_PACKET2_AUTORXRESTART_ON | self.RF_PACKET2_AES_OFF], 
              [self.REG_TESTDAGC, self.RF_DAGC_IMPROVED_LOWBETA0]]
              
        self.cspin = Pin(cspin, mode=Pin.OUT)
        self.cspin.value(1)
        self.isrpin = Pin(ISRPin, mode=Pin.IN)
        
        self.isrpin.callback(trigger=Pin.IRQ_RISING, handler=self.isr0)
        self.spi = SPI(0, mode=SPI.MASTER, baudrate=1000000, polarity=0, phase=0, firstbit=SPI.MSB)
    
        start = millis()
        timeout = 50
        while millis()-start < timeout:
            self.writeReg(self.REG_SYNCVALUE1, 0xAA)
            if self.readReg(self.REG_SYNCVALUE1) == 0xaa:
                break
        
        start = utime.ticks_ms()
        while utime.ticks_ms()-start < timeout:
            self.writeReg(self.REG_SYNCVALUE1, 0x55)
            if self.readReg(self.REG_SYNCVALUE1) == 0x55:
                break
        for item in self.CONFIG:
            self.writeReg(item[0], item[1])
            
        self.encrypt(0)
        
    def getFrequency(self):
        return self.RF69_FSTEP * (self.readReg(self.REG_FRFMSB) << 16) + self.readReg(self.REG_FRFMID) + self.readReg(self.REG_FRFLSB)
            
    def setFrequency(self, freqHz):
        oldMode = self._mode
        if oldMode == self.RF69_MODE_TX:
            self.setMode(self.RF69_MODE_RX)
            
        freqHz /= self.RF69_FSTEP
        self.writeReg(self.REG_FRFMSB, freqHz >> 16)
        self.writeReg(self.REG_FRFMID, freqHz >> 8)
        self.writeReg(self.REG_FRFLSB, freqHz)
        if oldMode == self.RF69_MODE_RX:
            self.setMode(self.RF69_MODE_SYNTH)
            
        self.setMode(oldMode)
    def setMode(self, new_mode):
        if self._mode == new_mode:
            return
        
        if new_mode == self.RF69_MODE_TX:
            self.writeReg(self.REG_OPMODE, (self.readReg(self.REG_OPMODE) & 0xE3) | self.RF_OPMODE_TRANSMITTER)
            if self._isRFM69HW:
                self.setHighPowerRegs(True)
                
        if new_mode == self.RF69_MODE_RX:
            self.writeReg(self.REG_OPMODE, (self.readReg(self.REG_OPMODE) & 0xE3) | self.RF_OPMODE_RECEIVER)
            if self._isRFM69HW:
                self.setHighPowerRegs(False)

        if new_mode == self.RF69_MODE_SYNTH:
            self.writeReg(self.REG_OPMODE, (self.readReg(self.REG_OPMODE) & 0xE3) | self.RF_OPMODE_SYNTHESIZER)

        if new_mode == self.RF69_MODE_STANDBY:
            self.writeReg(self.REG_OPMODE, (self.readReg(self.REG_OPMODE) & 0xE3) | self.RF_OPMODE_STANDBY)
        
        if new_mode == self.RF69_MODE_SLEEP:
            self.writeReg(self.REG_OPMODE, (self.readReg(self.REG_OPMODE) & 0xE3) | self.RF_OPMODE_SLEEP)
            while self._mode == self.RF69_MODE_SLEEP and (self.readReg(self.REG_IRQFLAGS1) & self.RF_IRQFLAGS1_MODEREADY) == 0x00:
                pass
        self._mode = new_mode

    def sleep(self):
        self.setMode(self.RF69_MODE_SLEEP)
    def setAddress(self, addr):
        self._address = addr;
        self.writeReg(self.REG_NODEADRS, self._address)
    def setNetwork(self, networkID):
        self.writeReg(self.REG_SYNCVALUE2, networkID)

    def setPowerLevel(self, powerLevel):
        self._powerLevel = powerLevel
        if self._powerLevel > 31:
            self._powerLevel = 31
        self.writeReg(self.REG_PALEVEL, (self.readReg(self.REG_PALEVEL) & 0xE0) | self._powerLevel);
        
    def canSend(self):
        if self._mode == self.RF69_MODE_RX and self.PAYLOADLEN == 0 and self.readRSSI() < self.CSMA_LIMIT:
            self.setMode(self.RF69_MODE_STANDBY)
            return True
        return False
    def send(self, toAddress, buffer, bufferSize, requestACK):
        self.writeReg(self.REG_PACKETCONFIG2, (self.readReg(self.REG_PACKETCONFIG2) & 0xFB) | self.RF_PACKET2_RXRESTART)
        now = millis()
        while self.canSend()==False and millis() - now < self.RF69_CSMA_LIMIT_MS:
            self.receiveDone()
        self.sendFrame(toAddress, buffer, bufferSize, requestACK, False)
        
    def sendWithRetry(self, toAddress, buffer, bufferSize, retries, retryWaitTime):
        for i in range(retries+1):
            self.send(toAddress, buffer, bufferSize, False)
            sentTime = millis()
            while millis() - sentTime < retryWaitTime:
                if self.ACKReceived(toAddress):
                    return True
            return False
    def ACKReceived(self, fromNodeID):
        if self.receiveDone():
            return (self.SENDERID == fromNodeID or fromNodeID == self.RF69_BROADCAST_ADDR) and self.ACK_RECEIVED
        return False
    def ACKRequested(self):
        return self.ACK_REQUESTED and (self.TARGETID != self.RF69_BROADCAST_ADDR)
    def sendACK(self, buffer, bufferSize):
        self.ACK_REQUESTED = 0
        sender = self.SENDERID
        _RSSI = self.RSSI
        self.writeReg(self.REG_PACKETCONFIG2, (self.readReg(self.REG_PACKETCONFIG2) & 0xFB) | self.RF_PACKET2_RXRESTART)
        now = millis()
        while not self.canSend() and millis() - now < self.RF69_CSMA_LIMIT_MS:
           self.receiveDone()
        self.SENDERID = sender
        self.sendFrame(sender, buffer, bufferSize, False, True)
        self.RSSI = _RSSI
    def sendFrame(self, toAddress, buffer, bufferSize, requestACK, sendACK):
      
        self.setMode(self.RF69_MODE_STANDBY)
        while self.readReg(self.REG_IRQFLAGS1) & self.RF_IRQFLAGS1_MODEREADY == 0x00:
            pass
        
        self.writeReg(self.REG_DIOMAPPING1, self.RF_DIOMAPPING1_DIO0_00)
        if bufferSize > self.RF69_MAX_DATA_LEN:
            bufferSize = self.RF69_MAX_DATA_LEN

        CTLbyte = 0x00;
        if sendACK:
            CTLbyte = self.RFM69_CTL_SENDACK
        else:
            if requestACK:
                CTLbyte = self.RFM69_CTL_REQACK

        self.select();
        self.spi.write(self.REG_FIFO | 0x80)
        self.spi.write(bufferSize + 3)
        self.spi.write(toAddress)
        self.spi.write(self._address)
        self.spi.write(CTLbyte)
        for i in range(bufferSize):
            self.spi.write(buffer[i])
        self.unselect()

        self.setMode(self.RF69_MODE_TX)
        txStart = millis();
        while (self.isrpin.value() == 0 and millis() - txStart < self.RF69_TX_LIMIT_MS):
            pass
        self.setMode(self.RF69_MODE_STANDBY);
        
    def interruptHandler(self, id):
       
        if self._mode == self.RF69_MODE_RX and (self.readReg(self.REG_IRQFLAGS2) & self.RF_IRQFLAGS2_PAYLOADREADY):
            self.setMode(self.RF69_MODE_STANDBY)
            self.select()
            self.spi.write(self.REG_FIFO & 0x7F)
            self.PAYLOADLEN = self.spi.read(1)
            self.PAYLOADLEN = self.PAYLOADLEN
            if self.PAYLOADLEN > 66: self.PAYLOADLEN = 66
            self.TARGETID = self.spi.read(1)
            if not (self._promiscuousMode or self.TARGETID == self._address or self.TARGETID == self.RF69_BROADCAST_ADDR) or self.PAYLOADLEN < 3:
                self.PAYLOADLEN = 0
                self.unselect()
                self.receiveBegin()
                return
            self.DATALEN = self.PAYLOADLEN - 3
            self.SENDERID = self.spi.read(1)
            CTLbyte = self.spi.read(1)
            self.ACK_RECEIVED = CTLbyte & self.RFM69_CTL_SENDACK
            self.ACK_REQUESTED = CTLbyte & self.RFM69_CTL_REQACK
            self.interruptHook(CTLbyte)
            for i in range(self.DATALEN):
                self.DATA[i] = self.spi.read(1)
            if self.DATALEN < self.RF69_MAX_DATA_LEN: self.DATA[self.DATALEN] = 0
            self.unselect()
            self.setMode(self.RF69_MODE_RX)
            
        self.RSSI = self.readRSSI()

    def isr0(self, id):
        self._inISR=True
        self.interruptHandler(id)
        self._inISR=False
    def receiveBegin(self):
        self.DATALEN = 0
        self.SENDERID = 0
        self.TARGETID = 0
        self.PAYLOADLEN = 0
        self.ACK_REQUESTED = 0
        self.ACK_RECEIVED = 0
        self.RSSI = 0
        if self.readReg(self.REG_IRQFLAGS2) & self.RF_IRQFLAGS2_PAYLOADREADY:
            self.writeReg(self.REG_PACKETCONFIG2, (self.readReg(self.REG_PACKETCONFIG2) & 0xFB) |self.RF_PACKET2_RXRESTART)
        self.writeReg(self.REG_DIOMAPPING1, self.RF_DIOMAPPING1_DIO0_01)
        self.setMode(self.RF69_MODE_RX)
    def receiveDone(self):
        noInterrupts()
        if self._mode == self.RF69_MODE_RX and self.PAYLOADLEN > 0:
            self.setMode(self.RF69_MODE_STANDBY) 
            return True
        else:
            if self._mode==self.RF69_MODE_RX:
                interrupts()
                return False
                
        self.receiveBegin()
        return False
    def encrypt(self, key):
        self.setMode(self.RF69_MODE_STANDBY)
        if key != 0:
            self.select()
            self.spi.write(self.REG_AESKEY1 | 0x80)
            for i in range(16):
                self.spi.write(key[i])
            self.unselect()
            
        val = 1
        if key==None:
            val = 0
            
        self.writeReg(self.REG_PACKETCONFIG2, (self.readReg(self.REG_PACKETCONFIG2) & 0xFE) | val)
        
    def readRSSI(self, forceTrigger):
        rssi = 0
        if forceTrigger:
            self.writeReg(self.REG_RSSICONFIG, self.RF_RSSI_START)
            while (self.readReg(self.REG_RSSICONFIG) & self.RF_RSSI_DONE) == 0x00:
                pass
        rssi = -self.readReg(self.REG_RSSIVALUE)
        rssi = rssi >> 1
        return rssi
    def readReg(self, addr):
        self.select()
        self.spi.write(addr & 0x7F)
        regValue = self.spi.read(1)
        self.unselect()
        return regValue    
    def writeReg(self, addr, value):
        self.select()
        self.spi.write(addr | 0x80)
        self.spi.write(value)
        self.unselect()
         
    def select(self):
        self.cspin.value(0)
    def unselect(self):
        self.cspin.value(1)    
    def promiscuous(self, onOff):
        self._promiscuousMode = onOff
        
    def setHighPower(self, onOff):
        self._isRFM69HW = onOff
        if self._isRFM69HW:
            self.writeReg(self.REG_OCP, self.RF_OCP_OFF)
            self.writeReg(self.REG_PALEVEL, (self.readReg(self.REG_PALEVEL) & 0x1F) | self.RF_PALEVEL_PA1_ON | self.RF_PALEVEL_PA2_ON)
            
        else:
            self.writeReg(self.REG_OCP, self.RF_OCP_ON)
            self.writeReg(self.REG_PALEVEL, self.RF_PALEVEL_PA0_ON | self.RF_PALEVEL_PA1_OFF | self.RF_PALEVEL_PA2_OFF | self._powerLevel)
        
    def setHighPowerRegs(self, onOff):
        if onOff:
            self.writeReg(self.REG_TESTPA1, 0x5D)
            self.writeReg(self.REG_TESTPA2, 0x7C)
        else:    
            self.writeReg(self.REG_TESTPA1, 0x55)
            self.writeReg(self.REG_TESTPA2, 0x70)
            
    def setCS(self, newSPISlaveSelect):
        self._slaveSelectPin = newSPISlaveSelect  
        self.cspin = Pin(self._slaveSelectPin, mode=Pin.OUT)
        self.cspin.value(1)
    def readAllRegs(self):
        regVal = 0
       
        print("Address - HEX - BIN")
        for regAddr in range(1, 0x4F):
            self.select()
            self.spi.write(regAddr & 0x7F)
            regVal = self.spi.read(1)
            self.unselect()
            print(regAddr, " - ", regVal)
           
    def readTemperature(self, calFactor):
        self.setMode(self.RF69_MODE_STANDBY);
        self.writeReg(self.REG_TEMP1, self.RF_TEMP1_MEAS_START)
        while self.readReg(self.REG_TEMP1) & self.RF_TEMP1_MEAS_RUNNING:
            pass
        return ~self.readReg(self.REG_TEMP2) + self.COURSE_TEMP_COEF + calFactor
    def rcCalibration(self):
        self.writeReg(self.REG_OSC1, self.RF_OSC1_RCCAL_START)
        while (self.readReg(self.REG_OSC1) & self.RF_OSC1_RCCAL_DONE) == 0x00: pass
    def maybeInterrupts(self):
        if not self._inISR:
           interrupts()
    def initialize(self):
        pass    
示例#12
0
class spiram:
  def __init__(self):
    self.led = Pin(5, Pin.OUT)
    self.led.off()
    self.rom="48.rom"
    #self.rom="opense.rom"
    #self.rom="/sd/zxspectrum/48.rom"
    self.spi_channel = const(2)
    self.init_pinout_sd()
    self.spi_freq = const(4000000)
    self.hwspi=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))

  @micropython.viper
  def init_pinout_sd(self):
    self.gpio_sck  = const(16)
    self.gpio_mosi = const(4)
    self.gpio_miso = const(12)

  # read from file -> write to SPI RAM
  def load_stream(self, filedata, addr=0, maxlen=0x10000, blocksize=1024):
    block = bytearray(blocksize)
    # Request load
    self.led.on()
    self.hwspi.write(bytearray([0,(addr >> 24) & 0xFF, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF]))
    bytes_loaded = 0
    while bytes_loaded < maxlen:
      if filedata.readinto(block):
        self.hwspi.write(block)
        bytes_loaded += blocksize
      else:
        break
    self.led.off()

  # read from SPI RAM -> write to file
  def save_stream(self, filedata, addr=0, length=1024, blocksize=1024):
    bytes_saved = 0
    block = bytearray(blocksize)
    # Request save
    self.led.on()
    self.hwspi.write(bytearray([1,(addr >> 24) & 0xFF, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF, 0]))
    while bytes_saved < length:
      self.hwspi.readinto(block)
      filedata.write(block)
      bytes_saved += len(block)
    self.led.off()

  def ctrl(self,i):
    self.led.on()
    self.hwspi.write(bytearray([0, 0xFF, 0xFF, 0xFF, 0xFF, i]))
    self.led.off()

  def cpu_halt(self):
    self.ctrl(2)

  def cpu_continue(self):
    self.ctrl(0)

  def load_z80_compressed_stream(self, filedata, length=0xFFFF):
    b=bytearray(1)
    escbyte=bytearray([0xED])
    s=0
    repeat=0
    bytes_loaded=0
    while bytes_loaded < length:
      if filedata.readinto(b):
        nexts=s
        if s==0:
          if b[0]==escbyte[0]:
            nexts=1
          else:
            self.hwspi.write(b)
        if s==1:
          if b[0]==escbyte[0]:
            nexts=2
          else:
            self.hwspi.write(escbyte)
            self.hwspi.write(b)
            nexts=0
        if s==2:
          repeat=b[0]
          if repeat==0:
            print("end")
            break
          nexts=3
        if s==3:
          self.hwspi.read(repeat,b[0])
          nexts=0
        s=nexts
        bytes_loaded += 1
      else:
        break
    print("bytes loaded %d" % bytes_loaded)

  def load_z80_v1_compressed_block(self, filedata):
    self.led.on()
    self.hwspi.write(bytearray([0,0,0,0x40,0])) # from 0x4000
    self.load_z80_compressed_stream(filedata)
    self.led.off()

  def load_z80_v23_block(self, filedata):
    header = bytearray(3)
    if filedata.readinto(header):
      length,page = unpack("<HB",header)
      print("load z80 block: length=%d, page=%d" % (length,page))
    else:
      return False
    addr = -1
    if page==4:
      addr=0x8000
    if page==5:
      addr=0xC000
    if page==8:
      addr=0x4000
    if addr < 0:
      print("unsupported page ignored")
      filedata.seek(length,1)
      return True
    if length==0xFFFF:
      compress=0
      length=0x4000
    else:
      compress=1
    #print("addr=%04X compress=%d" % (addr,compress))
    if compress:
      # Request load
      self.led.on()
      self.hwspi.write(bytearray([0,(addr >> 24) & 0xFF, (addr >> 16) & 0xFF, (addr >> 8) & 0xFF, addr & 0xFF]))
      self.load_z80_compressed_stream(filedata,length)
      self.led.off()
    else:
      print("uncompressed v2/v3 may need FIXME")
      self.load_stream(filedata,addr,16384)
    return True
  
  def patch_rom(self,pc,header):
    # overwrite tape saving code in original ROM
    # with restore code and data from header
    code_addr = 0x4C2
    header_addr = 0x500
    self.led.on()
    self.hwspi.write(bytearray([0, 0,0,0,0, 0xF3, 0xAF, 0x11, 0xFF, 0xFF, 0xC3, code_addr&0xFF, (code_addr>>8)&0xFF])) # overwrite start of ROM to JP 0x04C2
    self.led.off()
    self.led.on()
    self.hwspi.write(bytearray([0, 0,0,(code_addr>>8)&0xFF,code_addr&0xFF])) # overwrite 0x04C2
    # Z80 code that POPs REGs from header as stack data at 0x500
    # z80asm restore.z80asm; hexdump -v -e '/1 "0x%02X,"' a.bin
    # restores border color, registers I, AFBCDEHL' and AFBCDEHL
    self.hwspi.write(bytearray([0x31,(header_addr+9)&0xFF,((header_addr+9)>>8)&0xFF,0xF1,0xED,0x47,0xF1,0x1F,0xD3,0xFE,0xD1,0xD9,0xC1,0xD1,0xE1,0xD9,0xF1,0x08,0xFD,0xE1,0xDD,0xE1,0x21,0xE5,0xFF,0x39,0xF9,0xF1,0xC1,0xE1]));
    self.hwspi.write(bytearray([0x31])) # LD SP, ...
    self.hwspi.write(header[8:10])
    self.hwspi.write(bytearray([0xED])) # IM ...
    imarg = bytearray([0x46,0x56,0x5E,0x5E])
    self.hwspi.write(bytearray([imarg[header[29]&3]])) # IM mode
    if header[27]:
      self.hwspi.write(bytearray([0xFB])) # EI
    header[6]=pc&0xFF
    header[7]=(pc>>8)&0xFF
    self.hwspi.write(bytearray([0xC3])) # JP ...
    self.hwspi.write(header[6:8]) # PC address of final JP
    self.led.off()
    self.led.on()
    self.hwspi.write(bytearray([0, 0,0,(header_addr>>8)&0xFF,header_addr&0xFF])) # overwrite 0x0500 with header
    # header fix: exchange A and F, A' and F' to become POPable
    x=header[0]
    header[0]=header[1]
    header[1]=x
    x=header[21]
    header[21]=header[22]
    header[22]=x
    if header[12]==255:
      header[12]=1
    #header[12] ^= 7<<1 # FIXME border color
    self.hwspi.write(header) # AF and AF' now POPable
    self.led.off()

  def loadz80(self,filename):
    z=open(filename,"rb")
    header1 = bytearray(30)
    z.readinto(header1)
    pc=unpack("<H",header1[6:8])[0]
    self.cpu_halt()
    self.load_stream(open(self.rom, "rb"), addr=0)
    if pc: # V1 format
      print("Z80 v1")
      self.patch_rom(pc,header1)
      if header1[12] & 32:
        self.load_z80_v1_compressed_block(z)
      else:
        self.load_stream(z,0x4000)
    else: # V2 or V3 format
      word = bytearray(2)
      z.readinto(word)
      length2 = unpack("<H", word)[0]
      if length2 == 23:
        print("Z80 v2")
      else:
        if length2 == 54 or length2 == 55:
          print("Z80 v3")
        else:
          print("unsupported header2 length %d" % length2)
          return
      header2 = bytearray(length2)
      z.readinto(header2)
      pc=unpack("<H",header2[0:2])[0]
      self.patch_rom(pc,header1)
      while self.load_z80_v23_block(z):
        pass
    self.ctrl(3) # reset and halt
    self.ctrl(1) # only reset
    self.cpu_continue()
    # restore original ROM after image starts
    self.cpu_halt()
    self.load_stream(open(self.rom, "rb"), addr=0)
    self.cpu_continue() # release reset

# _________________________________________________________
# Software SPI bus
# There are two SPI drivers. One is implemented in software (bit-banging) and works on all pins:

from machine import Pin, SPI

# construct an SPI bus on the given pins
# polarity is the idle state of SCK
# phase=0 means sample on the first edge of SCK, phase=1 means the second
spi = SPI(-1, baudrate=100000, polarity=1, phase=0, sck=Pin(0), mosi=Pin(2), miso=Pin(4))

spi.init(baudrate=200000) # set the baudrate

spi.read(10)            # read 10 bytes on MISO
spi.read(10, 0xff)      # read 10 bytes while outputing 0xff on MOSI

buf = bytearray(50)     # create a buffer
spi.readinto(buf)       # read into the given buffer (reads 50 bytes in this case)
spi.readinto(buf, 0xff) # read into the given buffer and output 0xff on MOSI

spi.write(b'12345')     # write 5 bytes on MOSI

buf = bytearray(4)      # create a buffer
spi.write_readinto(b'1234', buf) # write to MOSI and read from MISO into the buffer
spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf



# _________________________________________________________
示例#14
0
文件: epd.py 项目: widget/iot-display
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))
示例#15
0
class RFM69(object):
    def __init__(self,
                 freqBand,
                 nodeID,
                 networkID,
                 isRFM69HW=False,
                 intPin='P9',
                 rstPin='P22',
                 spiBus=0,
                 spiDevice=0,
                 wakeup=False):
        if wakeup == False:
            self.freqBand = freqBand
            self.address = nodeID
            self.networkID = networkID
            self.isRFM69HW = isRFM69HW
            self.intPin = intPin
            self.rstPin = rstPin
            self.spiBus = spiBus
            self.spiDevice = spiDevice
            self.intLock = False
            self.mode = ""
            self.promiscuousMode = False
            self.DATASENT = False
            self.DATALEN = 0
            self.SENDERID = 0
            self.TARGETID = 0
            self.PAYLOADLEN = 0
            self.ACK_REQUESTED = 0
            self.ACK_RECEIVED = 0
            self.RSSI = 0
            self.DATA = []
            self.sendSleepTime = 0.05

            pinInt = Pin(self.intPin, mode=Pin.IN)
            pinRst = Pin(self.rstPin, mode=Pin.OUT)

            frfMSB = {
                RF69_315MHZ: RF_FRFMSB_315,
                RF69_433MHZ: RF_FRFMSB_433,
                RF69_868MHZ: RF_FRFMSB_868,
                RF69_915MHZ: RF_FRFMSB_915
            }
            frfMID = {
                RF69_315MHZ: RF_FRFMID_315,
                RF69_433MHZ: RF_FRFMID_433,
                RF69_868MHZ: RF_FRFMID_868,
                RF69_915MHZ: RF_FRFMID_915
            }
            frfLSB = {
                RF69_315MHZ: RF_FRFLSB_315,
                RF69_433MHZ: RF_FRFLSB_433,
                RF69_868MHZ: RF_FRFLSB_868,
                RF69_915MHZ: RF_FRFLSB_915
            }

            self.CONFIG = {
                0x01: [
                    REG_OPMODE, RF_OPMODE_SEQUENCER_ON | RF_OPMODE_LISTEN_OFF
                    | RF_OPMODE_STANDBY
                ],
                #no shaping
                0x02: [
                    REG_DATAMODUL, RF_DATAMODUL_DATAMODE_PACKET
                    | RF_DATAMODUL_MODULATIONTYPE_FSK
                    | RF_DATAMODUL_MODULATIONSHAPING_00
                ],
                #default:4.8 KBPS
                0x03: [REG_BITRATEMSB, RF_BITRATEMSB_55555],
                0x04: [REG_BITRATELSB, RF_BITRATELSB_55555],
                #default:5khz, (FDEV + BitRate/2 <= 500Khz)
                0x05: [REG_FDEVMSB, RF_FDEVMSB_50000],
                0x06: [REG_FDEVLSB, RF_FDEVLSB_50000],
                0x07: [REG_FRFMSB, frfMSB[freqBand]],
                0x08: [REG_FRFMID, frfMID[freqBand]],
                0x09: [REG_FRFLSB, frfLSB[freqBand]],

                # looks like PA1 and PA2 are not implemented on RFM69W, hence the max output power is 13dBm
                # +17dBm and +20dBm are possible on RFM69HW
                # +13dBm formula: Pout=-18+OutputPower (with PA0 or PA1**)
                # +17dBm formula: Pout=-14+OutputPower (with PA1 and PA2)**
                # +20dBm formula: Pout=-11+OutputPower (with PA1 and PA2)** and high power PA settings (section 3.3.7 in datasheet)
                #0x11: [REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF | RF_PALEVEL_PA2_OFF | RF_PALEVEL_OUTPUTPOWER_11111],
                #over current protection (default is 95mA)
                #0x13: [REG_OCP, RF_OCP_ON | RF_OCP_TRIM_95],

                # RXBW defaults are { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_5} (RxBw: 10.4khz)
                #//(BitRate < 2 * RxBw)
                0x19: [
                    REG_RXBW,
                    RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_16 | RF_RXBW_EXP_2
                ],
                #for BR-19200: //* 0x19 */ { REG_RXBW, RF_RXBW_DCCFREQ_010 | RF_RXBW_MANT_24 | RF_RXBW_EXP_3 },
                #DIO0 is the only IRQ we're using
                0x25: [REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01],
                #must be set to dBm = (-Sensitivity / 2) - default is 0xE4=228 so -114dBm
                0x29: [REG_RSSITHRESH, 220],
                #/* 0x2d */ { REG_PREAMBLELSB, RF_PREAMBLESIZE_LSB_VALUE } // default 3 preamble bytes 0xAAAAAA
                0x2e: [
                    REG_SYNCCONFIG, RF_SYNC_ON | RF_SYNC_FIFOFILL_AUTO
                    | RF_SYNC_SIZE_2 | RF_SYNC_TOL_0
                ],
                #attempt to make this compatible with sync1 byte of RFM12B lib
                0x2f: [REG_SYNCVALUE1, 0x2D],
                #NETWORK ID
                0x30: [REG_SYNCVALUE2, networkID],
                0x37: [
                    REG_PACKETCONFIG1, RF_PACKET1_FORMAT_VARIABLE
                    | RF_PACKET1_DCFREE_OFF | RF_PACKET1_CRC_ON
                    | RF_PACKET1_CRCAUTOCLEAR_ON | RF_PACKET1_ADRSFILTERING_OFF
                ],
                #in variable length mode: the max frame size, not used in TX
                0x38: [REG_PAYLOADLENGTH, 66],
                #* 0x39 */ { REG_NODEADRS, nodeID }, //turned off because we're not using address filtering
                #TX on FIFO not empty
                0x3C: [
                    REG_FIFOTHRESH,
                    RF_FIFOTHRESH_TXSTART_FIFONOTEMPTY | RF_FIFOTHRESH_VALUE
                ],
                #RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
                0x3d: [
                    REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_2BITS
                    | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF
                ],
                #for BR-19200: //* 0x3d */ { REG_PACKETCONFIG2, RF_PACKET2_RXRESTARTDELAY_NONE | RF_PACKET2_AUTORXRESTART_ON | RF_PACKET2_AES_OFF }, //RXRESTARTDELAY must match transmitter PA ramp-down time (bitrate dependent)
                #* 0x6F */ { REG_TESTDAGC, RF_DAGC_CONTINUOUS }, // run DAGC continuously in RX mode
                # run DAGC continuously in RX mode, recommended default for AfcLowBetaOn=0
                0x6F: [REG_TESTDAGC, RF_DAGC_IMPROVED_LOWBETA0],
                0x00: [255, 0]
            }

            #initialize SPI
            # this uses the SPI default pins for CLK, MOSI and MISO (``P10``, ``P11`` and ``P14``)
            self.spi = SPI(0,
                           mode=SPI.MASTER,
                           baudrate=400000,
                           polarity=0,
                           phase=0,
                           firstbit=SPI.MSB)
            self.p_out = Pin('P21', mode=Pin.OUT)

            # Hard reset the RFM module
            pinRst.value(1)
            time.sleep(0.1)
            pinRst.value(0)
            self.p_out.value(1)

            #verify chip is syncing?
            while self.readReg(REG_SYNCVALUE1) != 0xAA:
                self.writeReg(REG_SYNCVALUE1, 0xAA)

            while self.readReg(REG_SYNCVALUE1) != 0x55:
                self.writeReg(REG_SYNCVALUE1, 0x55)

            #write config
            for value in self.CONFIG.values():
                self.writeReg(value[0], value[1])

            self.encrypt(0)
            self.setHighPower(self.isRFM69HW)
            # Wait for ModeReady
            while (self.readReg(REG_IRQFLAGS1)
                   & RF_IRQFLAGS1_MODEREADY) == 0x00:
                pass

            #interrupt if a message arrives
            pinInt.callback(Pin.IRQ_RISING, self.interruptHandler)
        else:
            self.freqBand = freqBand
            self.address = nodeID
            self.networkID = networkID
            self.isRFM69HW = isRFM69HW
            self.intPin = intPin
            self.rstPin = rstPin
            self.spiBus = spiBus
            self.spiDevice = spiDevice
            self.intLock = False
            self.mode = RF69_MODE_RX
            self.promiscuousMode = False
            self.DATASENT = False
            self.DATALEN = 0
            self.SENDERID = 0
            self.TARGETID = 0
            self.PAYLOADLEN = 0
            self.ACK_REQUESTED = 0
            self.ACK_RECEIVED = 0
            self.RSSI = 0
            self.DATA = []
            self.sendSleepTime = 0.05

            pinInt = Pin(self.intPin, mode=Pin.IN)
            pinRst = Pin(self.rstPin, mode=Pin.OUT)

            frfMSB = {
                RF69_315MHZ: RF_FRFMSB_315,
                RF69_433MHZ: RF_FRFMSB_433,
                RF69_868MHZ: RF_FRFMSB_868,
                RF69_915MHZ: RF_FRFMSB_915
            }
            frfMID = {
                RF69_315MHZ: RF_FRFMID_315,
                RF69_433MHZ: RF_FRFMID_433,
                RF69_868MHZ: RF_FRFMID_868,
                RF69_915MHZ: RF_FRFMID_915
            }
            frfLSB = {
                RF69_315MHZ: RF_FRFLSB_315,
                RF69_433MHZ: RF_FRFLSB_433,
                RF69_868MHZ: RF_FRFLSB_868,
                RF69_915MHZ: RF_FRFLSB_915
            }

            #initialize SPI
            # this uses the SPI default pins for CLK, MOSI and MISO (``P10``, ``P11`` and ``P14``)
            self.spi = SPI(0,
                           mode=SPI.MASTER,
                           baudrate=400000,
                           polarity=0,
                           phase=0,
                           firstbit=SPI.MSB)
            self.p_out = Pin('P21', mode=Pin.OUT)

            #interrupt if a message arrives
            pinInt.callback(Pin.IRQ_RISING, self.interruptHandler)

    def setFreqeuncy(self, FRF):
        self.writeReg(REG_FRFMSB, FRF >> 16)
        self.writeReg(REG_FRFMID, FRF >> 8)
        self.writeReg(REG_FRFLSB, FRF)

    def setMode(self, newMode):
        if newMode == self.mode:
            return

        if newMode == RF69_MODE_TX:
            self.writeReg(REG_OPMODE, (self.readReg(REG_OPMODE) & 0xE3)
                          | RF_OPMODE_TRANSMITTER)
            if self.isRFM69HW:
                self.setHighPowerRegs(True)
        elif newMode == RF69_MODE_RX:
            self.writeReg(REG_OPMODE, (self.readReg(REG_OPMODE) & 0xE3)
                          | RF_OPMODE_RECEIVER)
            if self.isRFM69HW:
                self.setHighPowerRegs(False)
        elif newMode == RF69_MODE_SYNTH:
            self.writeReg(REG_OPMODE, (self.readReg(REG_OPMODE) & 0xE3)
                          | RF_OPMODE_SYNTHESIZER)
        elif newMode == RF69_MODE_STANDBY:
            self.writeReg(REG_OPMODE, (self.readReg(REG_OPMODE) & 0xE3)
                          | RF_OPMODE_STANDBY)
        elif newMode == RF69_MODE_SLEEP:
            self.writeReg(REG_OPMODE,
                          (self.readReg(REG_OPMODE) & 0xE3) | RF_OPMODE_SLEEP)
        else:
            return

        # we are using packet mode, so this check is not really needed
        # but waiting for mode ready is necessary when going from sleep because the FIFO may not be immediately available from previous mode
        while self.mode == RF69_MODE_SLEEP and self.readReg(
                REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY == 0x00:
            pass

        self.mode = newMode

    def sleep(self):
        self.setMode(RF69_MODE_SLEEP)

    def setAddress(self, addr):
        self.address = addr
        self.writeReg(REG_NODEADRS, self.address)

    def setNetwork(self, networkID):
        self.networkID = networkID
        self.writeReg(REG_SYNCVALUE2, networkID)

    def setPowerLevel(self, powerLevel):
        if powerLevel > 31:
            powerLevel = 31
        self.powerLevel = powerLevel
        self.writeReg(REG_PALEVEL,
                      (self.readReg(REG_PALEVEL) & 0xE0) | self.powerLevel)

    def canSend(self):
        if self.mode == RF69_MODE_STANDBY:
            self.receiveBegin()
            return True
        #if signal stronger than -100dBm is detected assume channel activity
        elif self.mode == RF69_MODE_RX and self.PAYLOADLEN == 0 and self.readRSSI(
        ) < CSMA_LIMIT:
            self.setMode(RF69_MODE_STANDBY)
            return True
        return False

    def send(self, toAddress, buff="", requestACK=False):
        self.writeReg(REG_PACKETCONFIG2,
                      (self.readReg(REG_PACKETCONFIG2) & 0xFB)
                      | RF_PACKET2_RXRESTART)
        now = time.time()
        while (not self.canSend()) and time.time() - now < RF69_CSMA_LIMIT_S:
            self.receiveDone()
        self.sendFrame(toAddress, buff, requestACK, False)

#    to increase the chance of getting a packet across, call this function instead of send
#    and it handles all the ACK requesting/retrying for you :)
#    The only twist is that you have to manually listen to ACK requests on the other side and send back the ACKs
#    The reason for the semi-automaton is that the lib is ingterrupt driven and
#    requires user action to read the received data and decide what to do with it
#    replies usually take only 5-8ms at 50kbps@915Mhz

    def sendWithRetry(self, toAddress, buff="", retries=3, retryWaitTime=10):
        for i in range(0, retries):
            self.send(toAddress, buff, True)
            sentTime = time.time()
            while (time.time() - sentTime) < retryWaitTime:
                if self.ACKReceived(toAddress):
                    return True
        return False

    def ACKReceived(self, fromNodeID):
        if self.receiveDone():
            return (self.SENDERID == fromNodeID
                    or fromNodeID == RF69_BROADCAST_ADDR) and self.ACK_RECEIVED
        return False

    def ACKRequested(self):
        return self.ACK_REQUESTED and self.TARGETID != RF69_BROADCAST_ADDR

    def sendACK(self, toAddress=0, buff=""):
        toAddress = toAddress if toAddress > 0 else self.SENDERID
        while not self.canSend():
            self.receiveDone()
        self.sendFrame(toAddress, buff, False, True)

    def sendFrame(self, toAddress, buff, requestACK, sendACK):
        #turn off receiver to prevent reception while filling fifo
        self.setMode(RF69_MODE_STANDBY)
        #wait for modeReady
        while (self.readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00:
            pass
        # DIO0 is "Packet Sent"
        self.writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_00)

        if (len(buff) > RF69_MAX_DATA_LEN):
            buff = buff[0:RF69_MAX_DATA_LEN]

        ack = 0
        if sendACK:
            ack = 0x80
        elif requestACK:
            ack = 0x40
        if isinstance(buff, str):  #original basestr
            self.spiWriteMultipleBytes(
                [REG_FIFO | 0x80,
                 len(buff) + 3, toAddress, self.address, ack] +
                [int(ord(i)) for i in list(buff)])
        else:
            self.spiWriteMultipleBytes(
                [REG_FIFO | 0x80,
                 len(buff) + 3, toAddress, self.address, ack] + buff)

        self.DATASENT = False
        self.setMode(RF69_MODE_TX)
        slept = 0
        while not self.DATASENT:
            time.sleep(self.sendSleepTime)
            slept += self.sendSleepTime
            if slept > 1.0:
                break
        self.setMode(RF69_MODE_RX)

    def interruptHandler(self, pin):
        self.intLock = True
        self.DATASENT = True
        if self.mode == RF69_MODE_RX and self.readReg(
                REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY:
            self.setMode(RF69_MODE_STANDBY)
            self.PAYLOADLEN, self.TARGETID, self.SENDERID, CTLbyte = self.readFifo(
                [REG_FIFO & 0x7f, 0, 0, 0, 0])[1:]

            if self.PAYLOADLEN > 66:
                self.PAYLOADLEN = 66
            if not (self.promiscuousMode or self.TARGETID == self.address
                    or self.TARGETID == RF69_BROADCAST_ADDR):
                self.PAYLOADLEN = 0
                self.intLock = False
                return
            self.DATALEN = self.PAYLOADLEN - 3
            self.ACK_RECEIVED = CTLbyte & 0x80
            self.ACK_REQUESTED = CTLbyte & 0x40

            self.DATA = self.readFifo([REG_FIFO & 0x7f] +
                                      [0 for i in range(0, self.DATALEN)])[1:]

            self.RSSI = self.readRSSI()
        self.intLock = False

    def receiveBegin(self):

        while self.intLock:
            time.sleep(.1)
        self.DATALEN = 0
        self.SENDERID = 0
        self.TARGETID = 0
        self.PAYLOADLEN = 0
        self.ACK_REQUESTED = 0
        self.ACK_RECEIVED = 0
        self.RSSI = 0
        if (self.readReg(REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY):
            # avoid RX deadlocks
            self.writeReg(REG_PACKETCONFIG2,
                          (self.readReg(REG_PACKETCONFIG2) & 0xFB)
                          | RF_PACKET2_RXRESTART)
        #set DIO0 to "PAYLOADREADY" in receive mode
        self.writeReg(REG_DIOMAPPING1, RF_DIOMAPPING1_DIO0_01)
        self.setMode(RF69_MODE_RX)

    def receiveDone(self):
        if (self.mode == RF69_MODE_RX
                or self.mode == RF69_MODE_STANDBY) and self.PAYLOADLEN > 0:
            self.setMode(RF69_MODE_STANDBY)
            return True
        if self.readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_TIMEOUT:
            # https://github.com/russss/rfm69-python/blob/master/rfm69/rfm69.py#L112
            # Russss figured out that if you leave alone long enough it times out
            # tell it to stop being silly and listen for more packets
            self.writeReg(REG_PACKETCONFIG2,
                          (self.readReg(REG_PACKETCONFIG2) & 0xFB)
                          | RF_PACKET2_RXRESTART)

        elif self.mode == RF69_MODE_RX:
            # already in RX no payload yet
            return False
        self.receiveBegin()
        return False

    def readRSSI(self, forceTrigger=False):
        rssi = 0
        if forceTrigger:
            self.writeReg(REG_RSSICONFIG, RF_RSSI_START)
            while self.readReg(REG_RSSICONFIG) & RF_RSSI_DONE == 0x00:
                pass
        rssi = self.readReg(REG_RSSIVALUE) * -1
        rssi = rssi >> 1
        return rssi

    def encrypt(self, key):
        self.setMode(RF69_MODE_STANDBY)
        if key != 0 and len(key) == 16:
            self.writeReg(REG_AESKEY1, int(ord(key[0])))
            self.writeReg(REG_AESKEY2, int(ord(key[1])))
            self.writeReg(REG_AESKEY3, int(ord(key[2])))
            self.writeReg(REG_AESKEY4, int(ord(key[3])))
            self.writeReg(REG_AESKEY5, int(ord(key[4])))
            self.writeReg(REG_AESKEY6, int(ord(key[5])))
            self.writeReg(REG_AESKEY7, int(ord(key[6])))
            self.writeReg(REG_AESKEY8, int(ord(key[7])))
            self.writeReg(REG_AESKEY9, int(ord(key[8])))
            self.writeReg(REG_AESKEY10, int(ord(key[9])))
            self.writeReg(REG_AESKEY11, int(ord(key[10])))
            self.writeReg(REG_AESKEY12, int(ord(key[11])))
            self.writeReg(REG_AESKEY13, int(ord(key[12])))
            self.writeReg(REG_AESKEY14, int(ord(key[13])))
            self.writeReg(REG_AESKEY15, int(ord(key[14])))
            self.writeReg(REG_AESKEY16, int(ord(key[15])))
            self.writeReg(REG_PACKETCONFIG2,
                          (self.readReg(REG_PACKETCONFIG2) & 0xFE)
                          | RF_PACKET2_AES_ON)
        else:
            self.writeReg(REG_PACKETCONFIG2,
                          (self.readReg(REG_PACKETCONFIG2) & 0xFE)
                          | RF_PACKET2_AES_OFF)

    def readReg(self, addr):
        addrbytes = bytes([addr & 0x7F])
        self.p_out.value(0)
        self.spi.write(addrbytes)
        temp = self.spi.read(1)
        self.p_out.value(1)
        return ord(temp)

    def writeReg(self, addr, value):
        addrbytes = bytes([addr | 0x80, value])
        self.p_out.value(0)
        self.spi.write(addrbytes)
        self.p_out.value(1)

    def spiWriteMultipleBytes(self, values):
        valuebytes = bytes(values)
        self.p_out.value(0)
        self.spi.write(valuebytes)
        self.p_out.value(1)

    def readFifo(self, values):
        addr = values[0]
        addrbytes = bytes(addr)
        self.p_out.value(0)
        self.spi.write(addrbytes)
        recstring = self.spi.read(len(values))
        self.p_out.value(1)
        returnval = []
        for i in recstring:
            returnval.append(i)
        return returnval

    def promiscuous(self, onOff):
        self.promiscuousMode = onOff

    def setHighPower(self, onOff):
        if onOff:
            self.writeReg(REG_OCP, RF_OCP_OFF)
            #enable P1 & P2 amplifier stages
            self.writeReg(REG_PALEVEL, (self.readReg(REG_PALEVEL) & 0x1F)
                          | RF_PALEVEL_PA1_ON | RF_PALEVEL_PA2_ON)
        else:
            self.writeReg(REG_OCP, RF_OCP_ON)
            #enable P0 only
            self.writeReg(
                REG_PALEVEL, RF_PALEVEL_PA0_ON | RF_PALEVEL_PA1_OFF
                | RF_PALEVEL_PA2_OFF | powerLevel)

    def setHighPowerRegs(self, onOff):
        if onOff:
            self.writeReg(REG_TESTPA1, 0x5D)
            self.writeReg(REG_TESTPA2, 0x7C)
        else:
            self.writeReg(REG_TESTPA1, 0x55)
            self.writeReg(REG_TESTPA2, 0x70)

    def readAllRegs(self):
        results = []
        for address in range(1, 0x50):
            results.append(
                [str(hex(address)),
                 str(bin(self.readReg(address)))])
        return results

    def readTemperature(self, calFactor):
        self.setMode(RF69_MODE_STANDBY)
        self.writeReg(REG_TEMP1, RF_TEMP1_MEAS_START)
        while self.readReg(REG_TEMP1) & RF_TEMP1_MEAS_RUNNING:
            pass
        # COURSE_TEMP_COEF puts reading in the ballpark, user can add additional correction
        #'complement'corrects the slope, rising temp = rising val
        return (int(~self.readReg(REG_TEMP2)) *
                -1) + COURSE_TEMP_COEF + calFactor

    def rcCalibration(self):
        self.writeReg(REG_OSC1, RF_OSC1_RCCAL_START)
        while self.readReg(REG_OSC1) & RF_OSC1_RCCAL_DONE == 0x00:
            pass

    def shutdown(self):
        self.setHighPower(False)
        self.sleep()

    def receiveMessage(self):
        self.intLock = True
        self.DATASENT = True
        if self.mode == RF69_MODE_RX and self.readReg(
                REG_IRQFLAGS2) & RF_IRQFLAGS2_PAYLOADREADY:
            self.setMode(RF69_MODE_STANDBY)
            self.PAYLOADLEN, self.TARGETID, self.SENDERID, CTLbyte = self.readFifo(
                [REG_FIFO & 0x7f, 0, 0, 0, 0])[1:]

            if self.PAYLOADLEN > 66:
                self.PAYLOADLEN = 66
            if not (self.promiscuousMode or self.TARGETID == self.address
                    or self.TARGETID == RF69_BROADCAST_ADDR):
                self.PAYLOADLEN = 0
                self.intLock = False
                return
            self.DATALEN = self.PAYLOADLEN - 3
            self.ACK_RECEIVED = CTLbyte & 0x80
            self.ACK_REQUESTED = CTLbyte & 0x40

            self.DATA = self.readFifo([REG_FIFO & 0x7f] +
                                      [0 for i in range(0, self.DATALEN)])[1:]

            self.RSSI = self.readRSSI()
        self.intLock = False
示例#16
0
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
示例#17
0
class ADXL362:
    def _init__(self, cspin):
        self.cspin = Pin(cspin, mode=Pin.OUT)
        self.cspin.value(1)
        self.x = 0
        self.y = 0
        self.z = 0
        self.t = 0
        self.spi = SPI(0,
                       mode=SPI.MASTER,
                       baudrate=1000000,
                       polarity=0,
                       phase=0,
                       firstbit=SPI.MSB)
        time.sleep_ms(1000)
        self.SPIwriteOneRegister(0x1F, 0x52)  #RESET
        time.sleep_ms(10)
        self.DEVICEID = self.SPIreadOneRegister(0x00)
        self.DEVID_MST = self.SPIreadOneRegister(0x01)
        self.PART_ID = self.SPIreadOneRegister(0x02)
        self.REV_ID = self.SPIreadOneRegister(0x03)
        self.STATUS = self.getStatus()

    def getStatus(self):
        return self.SPIreadOneRegister(0x0B)

    def beginMeasure(self):
        temp = self.SPIreadOneRegister(0x2D)
        tempwrite = temp | 0x02
        self.SPIwriteOneRegister(0x2D, tempwrite)
        time.sleep_ms(10)

    def readXData(self):
        XDATA = self.SPIreadTwoRegisters(0x0E)
        return XDATA

    def readYData(self):
        YDATA = self.SPIreadTwoRegisters(0x10)
        return YDATA

    def readZData(self):
        ZDATA = self.SPIreadTwoRegisters(0x12)
        return ZDATA

    def readTemp(self):
        TEMP = self.SPIreadTwoRegisters(0x14)
        return TEMP

    def readXYZTData(self):
        ret = {}
        self.select()
        self.spi.write(0x0B)
        self.spi.write(0x0E)
        ret['x'] = self.spi.read(1)
        ret['x'] += self.spi.read(1) << 8
        ret['y'] = self.spi.read(1)
        ret['y'] += self.spi.read(1) << 8
        ret['z'] = self.spi.read(1)
        ret['z'] += self.spi.read(1) << 8
        ret['t'] = self.spi.read(1)
        ret['t'] += self.spi.read(1) << 8
        self.deselect()
        self.x = ret['x']
        self.y = ret['y']
        self.z = ret['z']
        self.t = ret['t']
        return ret

    def setupACActivityInterrupt(self, threshold, time):
        self.SPIwriteTwoRegisters(0x20, threshold)
        self.SPIwriteOneRegister(0x22, time)
        ACT_INACT_CTL_Reg = self.SPIreadOneRegister(0x27)
        ACT_INACT_CTL_Reg = ACT_INACT_CTL_Reg | (0x03)
        self.SPIwriteOneRegister(0x27, ACT_INACT_CTL_Reg)
        ACT_INACT_CTL_Reg = self.SPIreadOneRegister(0x27)

    def setupACInactivityInterrupt(self, threshold, time):
        self.SPIwriteTwoRegisters(0x23, threshold)
        self.SPIwriteTwoRegisters(0x25, time)
        ACT_INACT_CTL_Reg = self.SPIreadOneRegister(0x27)
        ACT_INACT_CTL_Reg = ACT_INACT_CTL_Reg | (0x0C)
        self.SPIwriteOneRegister(0x27, ACT_INACT_CTL_Reg)
        ACT_INACT_CTL_Reg = self.SPIreadOneRegister(0x27)

    def setupDCActivityInterrupt(self, threshold, time):
        self.SPIwriteTwoRegisters(0x20, threshold)
        self.SPIwriteOneRegister(0x22, time)
        ACT_INACT_CTL_Reg = self.SPIreadOneRegister(0x27)
        ACT_INACT_CTL_Reg = ACT_INACT_CTL_Reg | (0x01)
        self.SPIwriteOneRegister(0x27, ACT_INACT_CTL_Reg)
        ACT_INACT_CTL_Reg = self.SPIreadOneRegister(0x27)

    def setupDCInactivityInterrupt(self, threshold, time):
        self.SPIwriteTwoRegisters(0x23, threshold)
        self.SPIwriteTwoRegisters(0x25, time)
        ACT_INACT_CTL_Reg = self.SPIreadOneRegister(0x27)
        ACT_INACT_CTL_Reg = ACT_INACT_CTL_Reg | (0x04)
        self.SPIwriteOneRegister(0x27, ACT_INACT_CTL_Reg)
        ACT_INACT_CTL_Reg = self.SPIreadOneRegister(0x27)

    def SPIreadOneRegister(self, regAddress):
        self.select()
        self.spi.write(0x0B)
        self.spi.write(regAddress)
        regValue = self.spi.read(1)
        self.deselect()
        return regValue

    def SPIwriteOneRegister(self, regAddress, regValue):
        self.select()
        self.spi.write(0x0A)
        self.spi.write(regAddress)
        self.spi.write(regValue)
        self.deselect()

    def SPIwriteTwoRegisters(self, regAddress, twoRegValue):
        twoRegValueH = twoRegValue >> 8
        twoRegValueL = twoRegValue
        self.select()
        self.spi.write(0x0A)
        self.spi.write(regAddress)
        self.spi.write(twoRegValueL)
        self.spi.write(twoRegValueH)
        self.deselect()

    def SPIreadTwoRegisters(self, regAddress):
        self.select()
        self.spi.write(0x0B)
        self.spi.write(regAddress)
        twoRegValue = self.read(1)
        twoRegValue += self.read(1) << 8
        self.deselect()
        return twoRegValue

    def select(self):
        self.cspin.value(0)

    def deselect(self):
        self.cspin.value(1)
示例#18
0
class ATM90e32:
    ##############################################################################

    def __init__(self, linefreq, pgagain, ugain, igainA, igainB, igainC):
        self._linefreq = linefreq
        self._pgagain = pgagain
        self._ugain = ugain
        self._igainA = igainA
        self._igainB = igainB
        self._igainC = igainC

        # Chip select pin
        self.cs = Pin(15, Pin.OUT)
        self.cs.on()
        # Doc on esp8266 SPI hw init: http://bit.ly/2ZhqeRB
        self.spi = SPI(1, baudrate=200000, polarity=1, phase=1)

        self._init_config()

    def _init_config(self):
        # CurrentGainCT2 = 25498  #25498 - SCT-013-000 100A/50mA
        if (self._linefreq == 4485 or self._linefreq == 5231):
            # North America power frequency
            FreqHiThresh = 61 * 100
            FreqLoThresh = 59 * 100
            sagV = 90
        else:
            FreqHiThresh = 51 * 100
            FreqLoThresh = 49 * 100
            sagV = 190

        # calculation for voltage sag threshold - assumes we do not want to go under 90v for split phase and 190v otherwise
        # sqrt(2) = 1.41421356
        fvSagTh = (sagV * 100 * 1.41421356) / (2 * self._ugain / 32768)
        # convert to int for sending to the atm90e32.
        vSagTh = self._round_number(fvSagTh)

        self._spi_rw(SPI_WRITE, SoftReset, 0x789A)  # Perform soft reset
        # enable register config access
        self._spi_rw(SPI_WRITE, CfgRegAccEn, 0x55AA)
        self._spi_rw(SPI_WRITE, MeterEn, 0x0001)  # Enable Metering

        self._spi_rw(SPI_WRITE, SagTh, vSagTh)  # Voltage sag threshold
        # High frequency threshold - 61.00Hz
        self._spi_rw(SPI_WRITE, FreqHiTh, FreqHiThresh)
        # Lo frequency threshold - 59.00Hz
        self._spi_rw(SPI_WRITE, FreqLoTh, FreqLoThresh)
        self._spi_rw(SPI_WRITE, EMMIntEn0, 0xB76F)  # Enable interrupts
        self._spi_rw(SPI_WRITE, EMMIntEn1, 0xDDFD)  # Enable interrupts
        self._spi_rw(SPI_WRITE, EMMIntState0, 0x0001)  # Clear interrupt flags
        self._spi_rw(SPI_WRITE, EMMIntState1, 0x0001)  # Clear interrupt flags
        # ZX2, ZX1, ZX0 pin config
        self._spi_rw(SPI_WRITE, ZXConfig, 0x0A55)

        # Set metering config values (CONFIG)
        # PL Constant MSB (default) - Meter Constant = 3200 - PL Constant = 140625000
        self._spi_rw(SPI_WRITE, PLconstH, 0x0861)
        # PL Constant LSB (default) - this is 4C68 in the application note, which is incorrect
        self._spi_rw(SPI_WRITE, PLconstL, 0xC468)
        # Mode Config (frequency set in main program)
        self._spi_rw(SPI_WRITE, MMode0, self._linefreq)
        # PGA Gain Configuration for Current Channels - 0x002A (x4) # 0x0015 (x2) # 0x0000 (1x)
        self._spi_rw(SPI_WRITE, MMode1, self._pgagain)
        # Active Startup Power Threshold - 50% of startup current = 0.9/0.00032 = 2812.5
        self._spi_rw(SPI_WRITE, PStartTh, 0x0AFC)
        # Reactive Startup Power Threshold
        self._spi_rw(SPI_WRITE, QStartTh, 0x0AEC)
        # Apparent Startup Power Threshold
        self._spi_rw(SPI_WRITE, SStartTh, 0x0000)
        # Active Phase Threshold = 10% of startup current = 0.06/0.00032 = 187.5
        self._spi_rw(SPI_WRITE, PPhaseTh, 0x00BC)
        self._spi_rw(SPI_WRITE, QPhaseTh, 0x0000)  # Reactive Phase Threshold
        # Apparent  Phase Threshold
        self._spi_rw(SPI_WRITE, SPhaseTh, 0x0000)

        # Set metering calibration values (CALIBRATION)
        self._spi_rw(SPI_WRITE, PQGainA, 0x0000)  # Line calibration gain
        self._spi_rw(SPI_WRITE, PhiA, 0x0000)  # Line calibration angle
        self._spi_rw(SPI_WRITE, PQGainB, 0x0000)  # Line calibration gain
        self._spi_rw(SPI_WRITE, PhiB, 0x0000)  # Line calibration angle
        self._spi_rw(SPI_WRITE, PQGainC, 0x0000)  # Line calibration gain
        self._spi_rw(SPI_WRITE, PhiC, 0x0000)  # Line calibration angle
        # A line active power offset
        self._spi_rw(SPI_WRITE, PoffsetA, 0x0000)
        # A line reactive power offset
        self._spi_rw(SPI_WRITE, QoffsetA, 0x0000)
        # B line active power offset
        self._spi_rw(SPI_WRITE, PoffsetB, 0x0000)
        # B line reactive power offset
        self._spi_rw(SPI_WRITE, QoffsetB, 0x0000)
        # C line active power offset
        self._spi_rw(SPI_WRITE, PoffsetC, 0x0000)
        # C line reactive power offset
        self._spi_rw(SPI_WRITE, QoffsetC, 0x0000)

        # Set metering calibration values (HARMONIC)
        # A Fund. active power offset
        self._spi_rw(SPI_WRITE, POffsetAF, 0x0000)
        # B Fund. active power offset
        self._spi_rw(SPI_WRITE, POffsetBF, 0x0000)
        # C Fund. active power offset
        self._spi_rw(SPI_WRITE, POffsetCF, 0x0000)
        # A Fund. active power gain
        self._spi_rw(SPI_WRITE, PGainAF, 0x0000)
        # B Fund. active power gain
        self._spi_rw(SPI_WRITE, PGainBF, 0x0000)
        # C Fund. active power gain
        self._spi_rw(SPI_WRITE, PGainCF, 0x0000)

        # Set measurement calibration values (ADJUST)
        self._spi_rw(SPI_WRITE, UgainA, self._ugain)  # A Voltage rms gain
        # A line current gain
        self._spi_rw(SPI_WRITE, IgainA, self._igainA)
        self._spi_rw(SPI_WRITE, UoffsetA, 0x0000)  # A Voltage offset
        self._spi_rw(SPI_WRITE, IoffsetA, 0x0000)  # A line current offset
        self._spi_rw(SPI_WRITE, UgainB, self._ugain)  # B Voltage rms gain
        # B line current gain
        self._spi_rw(SPI_WRITE, IgainB, self._igainB)
        self._spi_rw(SPI_WRITE, UoffsetB, 0x0000)  # B Voltage offset
        self._spi_rw(SPI_WRITE, IoffsetB, 0x0000)  # B line current offset
        self._spi_rw(SPI_WRITE, UgainC, self._ugain)  # C Voltage rms gain
        # C line current gain
        self._spi_rw(SPI_WRITE, IgainC, self._igainC)
        self._spi_rw(SPI_WRITE, UoffsetC, 0x0000)  # C Voltage offset
        self._spi_rw(SPI_WRITE, IoffsetC, 0x0000)  # C line current offset

        self._spi_rw(SPI_WRITE, CfgRegAccEn, 0x0000)  # end configuration

    #####################################################################################
    @property
    def lastSpiData(self):
        reading = self._spi_rw(SPI_READ, LastSPIData, 0xFFFF)
        return reading

    #####################################################################################
    @property
    def sys_status0(self):
        reading = self._spi_rw(SPI_READ, EMMIntState0, 0xFFFF)
        return reading

    #####################################################################################
    @property
    def sys_status1(self):
        reading = self._spi_rw(SPI_READ, EMMIntState1, 0xFFFF)
        return reading

    #####################################################################################

    @property
    def meter_status0(self):
        reading = self._spi_rw(SPI_READ, EMMState0, 0xFFFF)
        return reading

    #####################################################################################
    @property
    def meter_status1(self):
        reading = self._spi_rw(SPI_READ, EMMState1, 0xFFFF)
        return reading

    #####################################################################################
    @property
    def line_voltageA(self):
        reading = self._spi_rw(SPI_READ, UrmsA, 0xFFFF)
        return reading / 100.0

    #####################################################################################
    @property
    def line_voltageB(self):
        reading = self._spi_rw(SPI_READ, UrmsB, 0xFFFF)
        return reading / 100.0

    #####################################################################################
    @property
    def line_voltageC(self):
        reading = self._spi_rw(SPI_READ, UrmsC, 0xFFFF)
        return reading / 100.0

    #####################################################################################
    @property
    def line_currentA(self):
        reading = self._spi_rw(SPI_READ, IrmsA, 0xFFFF)
        return reading / 1000.0

    #####################################################################################
    @property
    def line_currentC(self):
        reading = self._spi_rw(SPI_READ, IrmsC, 0xFFFF)
        return reading / 1000.0

    #####################################################################################
    @property
    def frequency(self):
        reading = self._spi_rw(SPI_READ, Freq, 0xFFFF)
        return reading / 100.0

    #####################################################################################
    @property
    def active_power(self):
        reading = self._read32Register(PmeanT, PmeanTLSB)
        return reading * 0.00032

    #####################################################################################
    # do the SPI read or write request.
    #####################################################################################
    def _spi_rw(self, rw, address, val):

        # Set read/write flag
        address |= rw << 15
        # Enable SPI and wait for SPI to activate
        self.cs.off()
        time.sleep_us(10)
        # pack the address into a the bytearray.  It is an unsigned short(H) that needs to be in MSB(>)
        two_byte_buf = struct.pack('>H', address)
        # send address
        self.spi.write(two_byte_buf)
        # wait for data to become valid (4uS) - see http://bit.ly/2Zh6VI9
        time.sleep_us(4)
        if (rw):  # read
            # Get the unsigned short register values sent from the atm90e32
            results_buf = self.spi.read(2)
            result = struct.unpack('>H', results_buf)[0]
        else:
            # pack the address into a the bytearray.  It is an unsigned short(H) that needs to be in MSB(>)
            two_byte_buf = struct.pack('>H', val)
            self.spi.write(two_byte_buf)
            result = 0
        # Put cs back to HIGH - SPI bytes have been written/read.
        self.cs.on()
        return result

    ###################################################################################

    def _round_number(self, f_num):
        if f_num - math.floor(f_num) < 0.5:
            return math.floor(f_num)
        return math.ceil(f_num)

    ###################################################################################
    def _read32Register(self, regh_addr, regl_addr):
        val_h = self._spi_rw(SPI_READ, regh_addr, 0xFFFF)
        val_l = self._spi_rw(SPI_READ, regl_addr, 0xFFFF)
        val = val_h << 16
        val |= val_l  # concatenate the 2 registers to make 1 32 bit number
        # flip the bits...different than Arduino...
        val = val ^ 0xffffffff
        return (val)
示例#19
0
from machine import SPI

spi1 = SPI(SPI.SPI1,
           mode=SPI.MODE_MASTER,
           baudrate=10000000,
           polarity=0,
           phase=0,
           bits=8,
           firstbit=SPI.MSB,
           sck=28,
           mosi=29,
           miso=30,
           cs0=27)
w = b'1234'
r = bytearray(4)
spi1.write(w)
spi1.write(w, cs=SPI.CS0)
spi1.write_readinto(w, r)
spi1.read(5, write=0x00)
spi1.readinto(r, write=0x00)
示例#20
0
class ch376:
  def __init__(self):
    self.led = Pin(5, Pin.OUT)
    self.led.off()
    self.spi_channel = const(1)
    self.hwspi=SPI(self.spi_channel, baudrate=6000000, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, sck=Pin(16), mosi=Pin(4), miso=Pin(12))
    self.busy=Pin(0, Pin.IN)
    self.exist=0
    self.reset_data01()

  def reset_data01(self):
    self.data01in=bytearray(16) # track DATA0/DATA1 tokens for each endpoint
    self.data01out=bytearray(16) # track DATA0/DATA1 tokens for each endpoint

  def wait(self):
    while self.busy.value():
      pass
  
  def reset(self):
    self.reset_data01()
    self.led.on()
    self.hwspi.write(bytearray([0x05]))
    self.led.off()
    self.wait()

  def get_ic_ver(self) -> int:
    self.led.on()
    self.hwspi.write(bytearray([0x01]))
    response = self.hwspi.read(1)[0]
    self.led.off()
    return response & 0x3F

  def check_exist(self,value:int) -> int:
    self.led.on()
    self.hwspi.write(bytearray([0x06,value]))
    response = self.hwspi.read(1)[0]
    self.led.off()
    if response == value ^ 0xFF:
      return 1
    else:
      return 0

  def set_usb_mode(self,mode:int) -> int:
    self.led.on()
    self.hwspi.write(bytearray([0x15,mode]))
    sleep_us(10)
    response = self.hwspi.read(1)[0]
    self.led.off()
    return response

  # works only during set_usb_mode(5)
  # 0x44: no device
  # 0x10: low-speed
  # 0x20: full-speed
  def get_dev_rate(self) -> int:
    self.led.on()
    self.hwspi.write(bytearray([0x0A,0x07]))
    response = self.hwspi.read(1)[0]
    self.led.off()
    return response

  # 0:full-speed 12Mbps, 2:low-speed 1.5 Mbps
  def set_usb_speed(self,speed:int):
    self.led.on()
    self.hwspi.write(bytearray([0x04,speed]))
    self.led.off()

  def set_usb_low_speed(self):
    self.led.on()
    self.hwspi.write(bytearray([0x0B,0x17,0xD8]))
    self.led.off()

  def auto_setup(self):
    self.led.on()
    self.hwspi.write(bytearray([0x4D]))
    self.led.off()

  # sets remote address
  def set_address(self,addr:int) -> int:
    self.led.on()
    self.hwspi.write(bytearray([0x45,addr]))
    response = self.hwspi.read(1)[0]
    self.led.off()
    return response

  # sets our address
  def set_our_address(self,addr:int):
    self.led.on()
    self.hwspi.write(bytearray([0x13,addr]))
    self.led.off()

  def set_config(self,config:int):
    self.led.on()
    self.hwspi.write(bytearray([0x49,config]))
    self.led.off()

  def get_status(self) -> int:
    self.led.on()
    self.hwspi.write(bytearray([0x22]))
    status = self.hwspi.read(1)[0]
    self.led.off()
    return status

  def rd_usb_data0(self):
    self.led.on()
    self.hwspi.write(bytearray([0x27]))
    len = self.hwspi.read(1)[0]
    if len:
      data = self.hwspi.read(len)
    else:
      data = bytearray()
    self.led.off()
    return data

  def rd_usb_data(self):
    self.led.on()
    self.hwspi.write(bytearray([0x28]))
    len = self.hwspi.read(1)[0]
    if len:
      data = self.hwspi.read(len)
    else:
      data = bytearray()
    self.led.off()
    return data

  def wr_usb_data(self,buffer):
    self.led.on()
    self.hwspi.write(bytearray([0x2C,len(buffer)]))
    if len(buffer):
      self.hwspi.write(buffer)
    self.led.off()

  # token alternate 0x00/0x80
  # x: high 4 bits: endpoint, low 4 bits: operation 9=read
  def issue_token_x(self,token:int,x:int):
    self.led.on()
    self.hwspi.write(bytearray([0x4E,token,x]))
    self.led.off()

  def clr_stall(self,ep:int):
    self.led.on()
    self.hwspi.write(bytearray([0x41,ep]))
    self.led.off()

  def test_connect(self) -> int:
    self.led.on()
    self.hwspi.write(bytearray([0x16]))
    response = self.hwspi.read(1)[0]
    self.led.off()
    return response

  # enumerates but has some problem with reading
  def start(self):
    self.reset()
    self.wait()
    while True:
      sleep_ms(100)
      self.exist+=1
      if self.check_exist(self.exist):
        break
    print("CH376 v%d waits for hotplug of USB HID device" % self.get_ic_ver()) # my module is v3, albiero is v4
    self.set_usb_mode(5)  # host mode: CH376 turns module LED ON
    hotplug = 0x44
    while hotplug == 0x44:
      self.wait()
      hotplug = self.get_dev_rate()
    self.set_usb_mode(7)  # reset and host mode, mouse turns bottom LED ON
    sleep_ms(20)
    self.set_usb_mode(6)  # release from reset
    self.wait()
    if hotplug == 0x10: # low-speed device
      self.set_usb_speed(2) # 2:low-speed 1.5 Mbps
      print("hot-plugged USB low-speed 1.5 Mbps device")
    if hotplug == 0x20: # full-speed device
      self.set_usb_speed(0) # 0:full-speed 12Mbps
      print("hot-plugged USB full-speed 12 Mbps device")
    self.wait()
    self.auto_setup()
    self.wait()
    self.set_config(1) # turns ON USB mouse LED
    self.wait()
    #self.set_config(0) # verify that this turns OFF USB mouse LED
    #sleep_ms(200)
    #self.set_config(1) # turns ON USB mouse LED
    #sleep_ms(200)
    #self.wait()
    #self.wr_usb_data(bytearray([0x21,0x0B,0,0,0,0,0,0])) # BOOTP compatible mouse, no wheel
    #self.issue_token_x(0,0x0D)
    #self.wait
    # HID request for device not to send reports if IDLE
    # only when user presses something the report will be send
    # some HID devices ignore this command and send idle reports anyway
    #self.wr_usb_data(bytearray([0x21,0x0A,0,0,0,0,0,0])) # SET IDLE 0
    #self.issue_token_x(0,0x0D) # 0x0D -> 0:EP0 D:WRITE
    #self.wait

  def prhex(self,d):
    if d:
      if len(d) > 0:
        print(len(d), end=":")
        for i in range(len(d)):
          print(" %02X" % d[i], end="")
        print("")

  def ctrl(self,type,request,value,index):
    self.wr_usb_data(bytearray([type,request,value&0xFF,(value>>8)&0xFF,index&0xFF,(index>>8)&0xFF,0,0]))
    self.issue_token_x(0,0xD) # 0x0D -> 0:EP0 D:WRITE
    self.wait()
    self.wr_usb_data(bytearray())
    self.issue_token_x(0x80,1) # 0:EP0 1:OUT status
    self.wait()

  # data phase host to device
  def ctrlout(self,type,request,value,index,data):
    self.wr_usb_data(bytearray([type,request,value&0xFF,(value>>8)&0xFF,index&0xFF,(index>>8)&0xFF,len(data)&0xFF,(len(data)>>8)&0xFF]))
    #print("data phase")
    #sleep_ms(5000)
    self.issue_token_x(0,0xD) # 0x0D -> 0:EP0 D:SETUP
    self.wait()
    token = 0x80
    i = 0
    while i < len(data):
      self.wr_usb_data(data[i:i+8])
      #self.prhex(data[i:i+8])
      self.issue_token_x(token,1) # 0x01 -> 0:EP0 1:OUT
      token ^= 0x80
      i += 8
      self.wait()
    self.issue_token_x(0x80,9) # 0:EP0 9:IN read status
    self.wait()
    return self.rd_usb_data0()

  # data phase device to host
  def ctrlin(self,type,request,value,index,rdlen):
    self.wr_usb_data(bytearray([type,request,value&0xFF,(value>>8)&0xFF,index&0xFF,(index>>8)&0xFF,rdlen&0xFF,(rdlen>>8)&0xFF]))
    self.issue_token_x(0,0xD) # 0x0D -> 0:EP0 D:WRITE
    self.wait()
    data = bytearray()
    token = 0x80
    while rdlen > 0:
      self.issue_token_x(token,9) # 0x09 -> 0:EP0 9:IN
      token ^= 0x80
      self.wait()
      d = self.rd_usb_data0() # 8 bytes max
      if len(d):
        data += d
        rdlen -= len(d)
      else:
        rdlen = 0
    self.wr_usb_data(bytearray())
    self.issue_token_x(0x80,1) # 0:EP0 1:OUT status
    self.wait()
    return data

  def epin(self,ep=1):
      self.issue_token_x(self.data01in[ep],(ep<<4)|9) # 0x19 -> 1:EP1 9:READ
      self.data01in[ep]^=0x80
      self.wait()
      return self.rd_usb_data0()

  def epout(self,data,ep=2):
      self.wr_usb_data(data)
      self.issue_token_x(self.data01out[ep],(ep<<4)|1) # 0x11 -> 1:EP1 1:OUT
      self.data01out[ep]^=0x80
      self.wait()

  def reading(self,ep=1):
    token = 0
    while self.get_status() == 0x14:
      sleep_ms(10)
      self.prhex(self.epin(ep))
      collect()
示例#21
0
from machine import Pin, SPI
import time
import ubinascii

vref = 3.3
cs = Pin(15, Pin.OUT)
cs.high()
hspi = SPI(1, baudrate=1600000, polarity=0, phase=0)
value = bytearray(2)

while True:
    data = bytearray(2)
    wget = b'\xA0\x00'
    cs.low()
    hspi.write(b'\x01')
    hspi.write(b'\xA0')
    data = hspi.read(1)
    # data = hspi.write_readinto(wget, data)
    cs.high()
    print(str(int(ubinascii.hexlify(data & b'\x0fff'))*vref/4096))
    time.sleep(1)
    # data = data*vref/4096
    # time.sleep(1)
    # print(str(data & b'\x0fff'))
示例#22
0
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=False
    self.data_buf=bytearray(554)
    self.mdv_byte=bytearray(1)
    self.mdv_phase=bytearray([1])
    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_blktyp = 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_send_mdv_bram = bytearray([0,0xD1,0,0,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_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_led  = const(5)

  @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&1: # microdrive 1 request
      #self.cs.on()
      #self.spi.write_readinto(self.spi_read_blktyp,self.spi_result)
      #self.cs.off()
      #blktyp=p8result[6]
      if self.diskfile:
        self.mdv_read()
    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
            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(".mdv") or filename.endswith(".MDV"):
        self.diskfile = open(filename,"rb")
        self.mdv_refill_buf()
        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()
        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"))
        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

  def mdv_skip_preamble(self,n:int)->int:
    i=0
    j=0
    found=0
    while j<n:
      if self.diskfile.readinto(self.mdv_byte):
        if self.mdv_byte[0]==0xFF:
          self.diskfile.readinto(self.mdv_byte)
          if self.mdv_byte[0]==0xFF and i>=10:
            found=1
            i+=2
            break
          else:
            i=0
        else:
          if self.mdv_byte[0]==0:
            i+=1
          else:
            i=0
        j+=1
      else: # EOF, make it circular
        self.diskfile.seek(0)
        print("MDV: wraparound",self.data_buf[2:12].decode("utf-8"))
    if found:
      return i
    return 0
  
  def mdv_refill_buf(self):
    if self.mdv_skip_preamble(1000):
      self.diskfile.readinto(self.data_buf)
      # skip block if header doesn't start with 0xFF
      #i=0
      #while self.data_buf[0]!=0xFF and i<254:
      #  self.mdv_skip_preamble(1000)
      #  self.diskfile.readinto(self.data_buf)
      #  i+=1
      #print(self.data_buf[1],self.data_buf[2:12]) # block number, volume name
      #print(self.data_buf[0:16],self.data_buf[28:32],self.data_buf[40:44]) # block number, volume name
    else:
      print("MDV: preamble not found")

  @micropython.viper
  def mdv_checksum(self,a:int,b:int)->int:
    p8b=ptr8(addressof(self.data_buf))
    c=0xF0F
    i=a
    while i<b:
      c+=p8b[i]
      i+=1
    return c&0xFFFF

  def mdv_read(self):
    if self.mdv_phase[0]:
      self.ctrl(8) # R_cpu_control[3]=1
      self.cs.on()
      self.spi.write(self.spi_send_mdv_bram)
      self.spi.write(self.data_buf[0:16])
      self.cs.off()
      self.ctrl(0)
    else:
      self.ctrl(8)
      self.cs.on()
      self.spi.write(self.spi_send_mdv_bram)
      self.spi.write(self.data_buf[28:32])
      self.spi.write(self.data_buf[40:554])
      self.cs.off()
      self.ctrl(0)
      self.led.on()
      self.mdv_refill_buf()
      # fix checksum in broken MDV images
      #c=self.mdv_checksum(0,14)
      #self.data_buf[14]=c
      #self.data_buf[15]=c>>8
      c=self.mdv_checksum(28,30)
      self.data_buf[30]=c
      self.data_buf[31]=c>>8
      #c=self.mdv_checksum(40,552)
      #self.data_buf[552]=c
      #self.data_buf[553]=c>>8
      self.led.off()
    self.mdv_phase[0]^=1

  # 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)
示例#23
0
#
# Copyright (c) 2006-2019, RT-Thread Development Team
#
# SPDX-License-Identifier: MIT License
#
# Change Logs:
# Date           Author       Notes
# 2019-06-13     SummerGift   first version
#

from machine import Pin, SPI

clk = Pin(("clk", 43), Pin.OUT_PP)
mosi = Pin(("mosi", 44), Pin.OUT_PP)
miso = Pin(("miso", 45), Pin.IN)
spi = SPI(-1,
          500000,
          polarity=0,
          phase=0,
          bits=8,
          firstbit=0,
          sck=clk,
          mosi=mosi,
          miso=miso)
print(spi)
spi.write("hello rt-thread!")
spi.read(10)
class MAX31865():
    def __init__(self, clk=14, mosi=13, miso=12, cs=27):
        self.SCK = Pin(clk, Pin.OUT)
        self.MOSI = Pin(mosi, Pin.OUT)
        self.MISO = Pin(miso, Pin.IN)
        self.CS = Pin(cs, Pin.OUT)
        # HSPI is MOSI=GPIO13, MISO=GPIO12 and SCK=GPIO14
        # HSPI(1)
        self.spi = SPI(1)
        self.spi.init(baudrate=100000,
                      sck=self.SCK,
                      miso=self.MISO,
                      mosi=self.MOSI,
                      polarity=0,
                      phase=1)
        """
            Configuration bits:
            Vbias           1=on
            Conversion mode 1=auto,0=normally off
            1-shot          1=1-shot (auto-clear)
            3-wire          1=3-wire,0=2/4 wire
            Fault detection
            Fault detection
            Fault Status    1=clear
            Filter          1=50Hz,2=60Hz
        """
        config = 0xb2
        buf = bytearray(2)
        buf[0] = 0x80  # configuration write addr
        buf[1] = config
        self.CS.value(0)
        self.spi.write(buf)
        self.CS.value(1)
        time.sleep(.2)

    # Re-implementing:
    # https://github.com/frogshead/MAX31865/blob/master/max31865.py
    def read_temperature(self):
        print("Entering read_temp function")
        time.sleep(.2)
        buf = bytearray(1)
        buf[0] = 0x00
        self.CS.value(0)
        self.spi.write(buf)
        register_values = self.spi.read(8)
        self.CS.value(1)
        print("Configuration Register Value: {:02x}".format(
            register_values[0]))
        print("RTD MSB Register Value: {:02x}".format(register_values[1]))
        print("RTD LSB Register Value: {:02x}".format(register_values[2]))
        print("High Fault MSB Treshold Register Value: {:02x}".format(
            register_values[3]))
        print("High Fault LSB Treshold Register Value: {:02x}".format(
            register_values[4]))
        print("Low Fault MSB Register Value: {:02x}".format(
            register_values[5]))
        print("Low Fault LSB Register Value: {:02x}".format(
            register_values[6]))
        print("Fault Status Register Value: {:02x}".format(register_values[0]))

        adc = ((register_values[1] << 8) | register_values[2]) >> 1
        print("ADC value: ", adc)
        print("Linear Temperature: {}".format((adc / 32) - 256))
class LIGHT_Sensor:
    '''
	Represents a light sensor
	'''
    def __init__(self, freq, port, csbpin, sckpin=18, mosipin=23, misopin=19):
        print("CSB pin = %d" % csbpin)
        self.csb = machine.Pin(csbpin, machine.Pin.OUT)
        self.csb.value(1)  # disable

        # construct an SPI bus on the given pins
        # polarity is the idle state of SCK
        # phase=0 means sample on the first edge of SCK, phase=1 means the second
        # 1M, 10M, 20M ok (1M is more stable)
        if (port == 1):
            print("Use hardware spi port 1: sck 14, mosi 13, miso 12")
            self.spi = SPI(1,
                           baudrate=freq,
                           polarity=1,
                           phase=1,
                           bits=8,
                           firstbit=0,
                           sck=Pin(14),
                           mosi=Pin(13),
                           miso=Pin(12))
        elif (port == 2):
            print("Use hardware spi port 2: sck 18, mosi 23, miso 19")
            self.spi = SPI(2,
                           baudrate=freq,
                           polarity=1,
                           phase=1,
                           bits=8,
                           firstbit=0,
                           sck=Pin(18),
                           mosi=Pin(23),
                           miso=Pin(19))
        else:
            print("Use software spi port : sck %d, mosi %d, miso %d" %
                  (sckpin, mosipin, misopin))
            self.spi = SPI(baudrate=freq,
                           polarity=1,
                           phase=1,
                           sck=Pin(sckpin),
                           mosi=Pin(mosipin),
                           miso=Pin(misopin))  # software spi

    def get_light_sensor_data(self):
        #print ("Read 2 bytes from SPI light sensor.")
        self.csb.value(0)  # enable
        buf = self.spi.read(2)  # read 2 bytes on MISO
        self.csb.value(1)  # disable

        print("Raw Data from the sensor:")
        for x in buf:
            print("%x" % x)
        #print ("MSB data")
        data_msb = (buf[0] & 0x1f) << 3
        #print ("%x" % data_msb)

        #print ("LSB data")
        data_lsb = (buf[1] & 0xe0) >> 5
        #print ("%x" % data_lsb)

        #print ("8 bit sensor data:")
        data = data_msb | data_lsb
        #print ("%x" % data)
        return data
示例#26
0
class MAX31865():

   ### Register constants, see data sheet for info.
   # Read Addresses
   MAX31865_REG_READ_CONFIG  = 0x00
   MAX31865_REG_READ_RTD_MSB = 0x01
   MAX31865_REG_READ_RTD_LSB = 0x02
   MAX31865_REG_READ_HFT_MSB = 0x03
   MAX31865_REG_READ_HFT_LSB = 0x04
   MAX31865_REG_READ_LFT_MSB = 0x05
   MAX31865_REG_READ_LFT_LSB = 0x06
   MAX31865_REG_READ_FAULT   = 0x07

   # Write Addresses
   MAX31865_REG_WRITE_CONFIG  = 0x80
   MAX31865_REG_WRITE_HFT_MSB = 0x83
   MAX31865_REG_WRITE_HFT_LSB = 0x84
   MAX31865_REG_WRITE_LFT_MSB = 0x85
   MAX31865_REG_WRITE_LFT_LSB = 0x86

   # Configuration Register
   MAX31865_CONFIG_50HZ_FILTER = 0x01
   MAX31865_CONFIG_CLEAR_FAULT = 0x02
   MAX31865_CONFIG_3WIRE       = 0x10
   MAX31865_CONFIG_ONE_SHOT    = 0x20
   MAX31865_CONFIG_AUTO        = 0x40
   MAX31865_CONFIG_BIAS_ON     = 0x80

   def __init__(self, wires=2, cs_pin='P9'):
      # initialize ``P9`` in gpio mode and make it an CS output
      self.CS = Pin(cs_pin, mode=Pin.OUT)
      self.CS(True)  # init chip select
      self.spi = SPI(0, mode=SPI.MASTER, baudrate=100000, polarity=0, phase=1, firstbit=SPI.MSB)

      # set configuration register
      config = self.MAX31865_CONFIG_BIAS_ON + self.MAX31865_CONFIG_AUTO + self.MAX31865_CONFIG_CLEAR_FAULT + self.MAX31865_CONFIG_50HZ_FILTER
      if (wires == 3):
          config = config + MAX31865_CONFIG_3WIRE

      buf = bytearray(2)
      buf[0] = self.MAX31865_REG_WRITE_CONFIG  # config write address
      buf[1] = config
      self.CS(False)                      # Select chip
      nw=self.spi.write(buf)              # write config
      self.CS(True)

      self.RefR = 430.0
      self.R0  = 100.0

   def _RawToTemp(self, raw):
      RTD = (raw * self.RefR) / (32768)
      A = 3.908e-3
      B = -5.775e-7
      return (-A + math.sqrt(A*A - 4*B*(1-RTD/self.R0))) / (2*B), RTD

   def read(self):
      temp = self._read()
      return temp

   def _read(self):
       self.CS(False)
       nw=self.spi.write(bytes([0x01])) # first read address
       MSB = self.spi.read(1)           # multi-byte transfer
       LSB = self.spi.read(1)
       self.CS(True)

       raw = (MSB[0] << 8) + LSB[0]
       raw = raw >> 1
       # print( 'raw: ', raw)
       temp, RTD = self._RawToTemp(raw)
       return temp
示例#27
0
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 time import sleep_ms

# UEXT wiring on the Pyboard.
# https://github.com/mchobby/pyboard-driver/tree/master/UEXT
spi = SPI(2)  # MOSI=Y8, MISO=Y7, SCK=Y6, SS=Y5
spi.init(baudrate=5000000, phase=0, polarity=0)
# We must manage the SS signal ourself
ss = Pin(Pin.board.Y5, Pin.OUT)
ss.value(1)
sleep_ms(10)  # Wait 10ms before new transaction!

# Start a new SPI transaction
ss.value(0)

print("Read IDCode from GameDuino (0x6d expected)")
spi.write(bytes([0x28, 0x00]))

buf = spi.read(1)  # read 1 byte

print("Response:")
print(buf)  # bytes
print("0x%02x" % buf[0])  # print as Hexa
class MFRC522_Custom:
    def __init__(self, rst, cs):

        self.OK = 0
        self.NOTAGERR = 1
        self.ERR = 2

        self.REQIDL = 0x26
        self.REQALL = 0x52
        self.AUTHENT1A = 0x60
        self.AUTHENT1B = 0x61

        self.rst = Pin(rst, Pin.OUT)
        self.cs = Pin(cs, Pin.OUT)

        self.rst.value(0)
        self.cs.value(1)

        self.spi = SPI(1, baudrate=100000, polarity=0, phase=0)
        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)
#MUDANDO AQUI!
        i = 100
        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 lerCartao(self):
        (stat, tag_type) = self.request(self.REQIDL)
        saida = ""
        if stat == self.OK:
            (stat, raw_uid) = self.anticoll()
            if stat == self.OK:
                saida = "0x%02x%02x%02x%02x" % (raw_uid[0], raw_uid[1],
                                                raw_uid[2], raw_uid[3])
        return saida
示例#29
0
class NRF:
    def __init__(self, port=1, miso=12, mosi=11, sck=10, csn=9, ce = 8):
        self.csn = Pin(csn, 1)
        self.ce = Pin(ce,1)
        
        self.spi = SPI(port, 1000000, miso=Pin(miso), mosi=Pin(mosi), sck=Pin(sck))
        
        self.csnHigh()
        self.ceLow()
        
        utime.sleep_ms(11)
        
    def csnHigh(self): self.csn(1)
    def csnLow(self): self.csn(0)
    def ceHigh(self): self.ce(1)
    def ceLow(self): self.ce(0)
    
    def readReg(self, reg, size=1):
        reg = [0b00011111 & reg]
        self.csnLow()
        self.spi.write(bytearray(reg))
        
        result = self.spi.read(size)
        
        self.csnHigh()
        
        return result
    
    def writeReg(self, reg, data):
        reg = [0b00100000 | (0b00011111 & reg)]
        self.csnLow()
        self.spi.write(bytearray(reg))
        
        data = [data] if type(data) == type(1) else data
        self.spi.write(bytearray(data))
        
        self.csnHigh()
        
    def config(self, channel=60, channelName ="gyroc", packetSize = 32):
        self.csnHigh()
        self.ceLow()
        
        utime.sleep_ms(11)
        
        self.writeReg(0,0b00001010) # config
        utime.sleep_us(1500)
        self.writeReg(1,0b00000011) #no ack
        
    
        self.writeReg(5, channel)
    
        self.writeReg(0x0a, channelName)
        self.writeReg(0x10, channelName)
        
        self.writeReg(0x11, packetSize) #
        
    def modeTX(self):
        reg = self.readReg(0)[0]
        reg &= ~(1<<0)
        self.writeReg(0,reg)
        self.ceLow()
        utime.sleep_us(130)
    def modeRX(self):
        reg = self.readReg(0)[0]
        reg |= (1<<0)
        self.writeReg(0,reg)
        self.ceHigh()
        utime.sleep_us(130)
    
        
    def sendMessage(self, data,size = 32):
        reg = [0b10100000]

        
        
        self.csnLow()
        self.spi.write(bytearray([0b11100001]))
        self.csnHigh()
        
        self.csnLow()
        self.spi.write(bytearray(reg))
        
        localData = bytearray(data)
        localData.extend(bytearray(size - len(localData)))
        
        self.spi.write(bytearray(localData))
        
        self.csnHigh()
        
        self.ceHigh()
        utime.sleep_us(10)
        for i in range(0,10000):
            reg = self.readReg(7)[0]
            if reg & 0b00110000:
                break
        self.ceLow()
        self.writeReg(7,0b00110000) # Clear status flags.
        
        
        
    def readMessage(self,size=32):
        reg = [0b01100001]
        
        self.csnLow()
        self.spi.write(bytearray(reg))
        result = self.spi.read(size)
        self.csnHigh()
        self.writeReg(0x07,0b01000000) # clear status flags
        return result
        
    def newMessage(self):
        regfs = self.readReg(0x17)[0]
        regs = self.readReg(7)[0]
        return  (not (0b00000001 & regfs)) or (0b01000000 & regs) 
示例#30
0
文件: slides.py 项目: emard/hdl4fpga
class osd:
    def __init__(self):
        alloc_emergency_exception_buf(100)
        self.screen_x = const(64)
        self.screen_y = const(20)
        self.cwd = "/sd/slides"  # shown on startup
        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()
        self.enable = bytearray(1)
        self.timer = Timer(3)
        self.init_slides()
        self.files2slides()
        self.start_bgreader()
        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()


# 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:  # btn5 cursor left
                        self.updir()
                    if btn == 65:  # btn6 cursor right
                        self.select_entry()
                else:
                    if btn == 33:  # btn5 cursor left
                        self.change_slide(-1)
                    if btn == 65:  # btn6 cursor right
                        self.change_slide(1)
                    self.show_slide()

    @micropython.viper
    def show_slide(self):
        addr = int(self.xres) * int(
            self.yres) * (int(self.vi) % int(self.ncache))
        self.cs.on()
        self.rgtr(0x19, self.i24(addr))
        self.cs.off()

    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(".ppm"):
                self.files2slides()
                self.start_bgreader()
                self.enable[0] = 0
                self.osd_enable(0)

    @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
        self.file0 = len(self.direntries)
        for fname in ls:
            stat = os.stat(self.fullpath(fname))
            if stat[0] & 0o170000 != 0o040000:
                self.direntries.append([fname, 0, stat[6]])  # file
        self.nfiles = len(self.direntries) - self.file0
        gc.collect()

    # *** SLIDESHOW ***
    # self.direntries, self.file0
    def init_slides(self):
        self.xres = 800
        self.yres = 600
        self.bpp = 16
        membytes = 32 * 1024 * 1024
        self.slide_pixels = self.xres * self.yres
        self.ncache = membytes // (self.slide_pixels * self.bpp // 8)
        #self.ncache=7 # NOTE debug
        self.priority_forward = 2
        self.priority_backward = 1
        self.nbackward = self.ncache * self.priority_backward // (
            self.priority_forward + self.priority_backward)
        self.nforward = self.ncache - self.nbackward
        #print(self.nforward, self.nbackward, self.nbackward+self.nforward)
        self.rdi = 0  # currently reading image
        self.prev_rdi = -1
        self.vi = 0  # currently viewed image
        self.cache_li = []  # image to be loaded
        self.cache_ti = []  # top image
        self.cache_ty = []  # top good lines 0..(y-1)
        self.cache_tyend = []  # top y load max
        self.cache_bi = []  # bot image
        self.cache_by = []  # bot good lines y..yres
        for i in range(self.ncache):
            self.cache_li.append(i)
            self.cache_ti.append(-1)
            self.cache_ty.append(0)
            self.cache_tyend.append(self.yres)
            self.cache_bi.append(-1)
            self.cache_by.append(0)
        self.bg_file = None
        self.PPM_line_buf = bytearray(3 * self.xres)
        self.rb = bytearray(256)  # reverse bits
        self.init_reverse_bits()
        self.finished = 1

    def files2slides(self):
        self.finished = 1
        self.bg_file = None
        self.rdi = 0
        self.prev_rdi = -1
        self.vi = 0
        self.show_slide()
        self.nslides = 0
        self.slide_fi = []  # file index in direntries
        self.slide_xres = []
        self.slide_yres = []
        self.slide_pos = []
        for i in range(self.nfiles):
            filename = self.fullpath(self.direntries[self.file0 + i][0])
            f = open(filename, "rb")
            line = f.readline(1000)
            if line[0:2] == b"P6":  # PPM header
                line = b"#"
                while line[0] == 35:  # skip commented lines
                    line = f.readline(1000)
                xystr = line.split(b" ")
                xres = int(xystr[0])
                yres = int(xystr[1])
                line = f.readline(1000)
                if int(line) == 255:  # 255 levels supported only
                    self.slide_fi.append(self.file0 + i)
                    self.slide_xres.append(xres)
                    self.slide_yres.append(yres)
                    self.slide_pos.append(f.tell())
                    self.nslides += 1
                    #if self.nslides>=256:
                    #  break
        # discard cache
        for i in range(self.ncache):
            ci = i % self.nslides
            if i < self.nslides:
                self.cache_li[ci] = i
            else:
                self.cache_li[ci] = -1
            self.cache_ti[ci] = -1
            self.cache_ty[ci] = 0
            self.cache_tyend[ci] = self.yres
            self.cache_bi[ci] = -1
            self.cache_by[ci] = 0

    # choose next, ordered by priority
    def next_to_read(self):
        before_first = self.nbackward - self.vi
        if before_first < 0:
            before_first = 0
        after_last = self.vi + self.nforward - self.nslides
        if after_last < 0:
            after_last = 0
        #print("before_first=%d after_last=%d" % (before_first,after_last))
        next_forward_slide = -1
        i = self.vi
        n = i + self.nforward + before_first - after_last
        if n < 0:
            n = 0
        if n > self.nslides:
            n = self.nslides
        while i < n:
            ic = i % self.ncache
            if self.cache_ti[ic]!=self.cache_li[ic] \
            or self.cache_ty[ic]<self.yres:
                next_forward_slide = i
                break
            i += 1
        next_backward_slide = -1
        i = self.vi - 1
        n = i - self.nbackward - after_last + before_first
        if n < 0:
            n = 0
        if n > self.nslides:
            n = self.nslides
        while i >= n:
            ic = i % self.ncache
            if self.cache_ti[ic]!=self.cache_li[ic] \
            or self.cache_ty[ic]<self.yres:
                next_backward_slide = i
                break
            i -= 1
        next_reading_slide = -1
        if next_forward_slide >= 0 and next_backward_slide >= 0:
            if (next_forward_slide-self.vi)*self.priority_backward < \
              (self.vi-next_backward_slide)*self.priority_forward:
                next_reading_slide = next_forward_slide
            else:
                next_reading_slide = next_backward_slide
        else:
            if next_forward_slide >= 0:
                next_reading_slide = next_forward_slide
            else:
                if next_backward_slide >= 0:
                    next_reading_slide = next_backward_slide
        return next_reading_slide

    # image to be discarded at changed view
    def next_to_discard(self) -> int:
        return (self.vi + self.nforward - 1) % self.ncache

    # which image to replace after changing slide
    def replace(self, mv):
        dc_replace = -1
        if mv > 0:
            dc_replace = self.vi + self.nforward - 1
            if dc_replace >= self.nslides:
                dc_replace -= self.ncache
        if mv < 0:
            dc_replace = (self.vi - self.nbackward - 1)
            if dc_replace < 0:
                dc_replace += self.ncache
        return dc_replace

    # change currently viewed slide
    # discard images in cache
    def change_slide(self, mv):
        vi = self.vi + mv
        if vi < 0 or vi >= self.nslides or mv == 0:
            return
        self.cache_li[self.next_to_discard()] = self.replace(mv)
        self.vi = vi
        self.cache_li[self.next_to_discard()] = self.replace(mv)
        self.rdi = self.next_to_read()
        if self.rdi >= 0:
            self.start_bgreader()

    @micropython.viper
    def init_reverse_bits(self):
        p8rb = ptr8(addressof(self.rb))
        for i in range(256):
            v = i
            r = 0
            for j in range(8):
                r <<= 1
                r |= v & 1
                v >>= 1
            p8rb[i] = r

    # convert PPM line RGB888 to RGB565, bits reversed
    @micropython.viper
    def ppm2pixel(self):
        p8 = ptr8(addressof(self.PPM_line_buf))
        p8rb = ptr8(addressof(self.rb))
        xi = 0
        yi = 0
        yn = 2 * int(self.xres)
        while yi < yn:
            r = p8[xi]
            g = p8[xi + 1]
            b = p8[xi + 2]
            p8[yi] = p8rb[(r & 0xF8) | ((g & 0xE0) >> 5)]
            p8[yi + 1] = p8rb[((g & 0x1C) << 3) | ((b & 0xF8) >> 3)]
            xi += 3
            yi += 2

    def read_scanline(self):
        bytpp = self.bpp // 8  # on screen
        rdi = self.rdi % self.ncache
        self.bg_file.readinto(self.PPM_line_buf)
        if self.slide_xres[self.rdi] != self.xres:
            self.bg_file.seek(self.slide_pos[self.rdi] +
                              3 * self.slide_xres[self.rdi] *
                              (self.cache_ty[rdi] + 1))
        self.ppm2pixel()
        # write PPM_line_buf to screen
        addr = self.xres * (rdi * self.yres + self.cache_ty[rdi])
        # DMA transfer <= 2048 bytes each
        # DMA transfer must be divided in N buffer uploads
        # buffer upload <= 256 bytes each
        nbuf = 8
        astep = 200
        abuf = 0
        self.cs.on()
        self.rgtr(0x16, self.i24(addr))
        for j in range(nbuf):
            self.rgtr(0x18, self.PPM_line_buf[abuf:abuf + astep])
            abuf += astep
        self.rgtr(0x17, self.i24(nbuf * astep // bytpp - 1))
        self.cs.off()

    # file should be already closed when calling this
    def next_file(self):
        #print("next_file")
        filename = self.fullpath(self.direntries[self.slide_fi[self.rdi]][0])
        self.bg_file = open(filename, "rb")
        rdi = self.rdi % self.ncache
        # Y->seek to first position to read from
        self.bg_file.seek(self.slide_pos[self.rdi] +
                          3 * self.slide_xres[self.rdi] * self.cache_ty[rdi])
        print("%d RD %s" % (self.rdi, filename))

    # background read, call it periodically
    def bgreader(self, timer):
        if self.rdi < 0:
            self.finished = 1
            self.timer.deinit()
            return
        rdi = self.rdi % self.ncache
        if self.cache_ti[rdi] != self.cache_li[rdi]:
            # cache contains different image than the one to be loaded
            # y begin from top
            self.cache_ti[rdi] = self.cache_li[rdi]
            self.cache_ty[rdi] = 0
            # y end depends on cache content
            # if bottom part is already in cache, reduce tyend
            if self.cache_bi[rdi] == self.cache_ti[rdi]:
                self.cache_tyend[rdi] = self.cache_by[rdi]
            else:
                self.cache_tyend[rdi] = self.yres
            # update self.rdi after cache_ti[rdi] has changed
            self.rdi = self.cache_ti[rdi]
            rdi = self.rdi % self.ncache
        # after self.rdi and cache_ty has been updated
        # call next file
        if self.prev_rdi != self.rdi or self.bg_file == None:
            # file changed, close and reopen
            if self.bg_file:  # maybe not needed, python will auto-close?
                self.bg_file.close()
                self.bg_file = None
            self.next_file()
            self.prev_rdi = self.rdi
        if self.cache_ty[rdi] < self.cache_tyend[rdi]:
            # file read
            self.read_scanline()
            self.cache_ty[rdi] += 1
            if self.cache_ty[rdi] > self.cache_by[rdi]:
                self.cache_by[rdi] = self.cache_ty[rdi]
        if self.cache_ty[rdi] >= self.cache_tyend[rdi]:
            # slide complete, close file, find next
            self.cache_ty[rdi] = self.yres
            self.cache_bi[rdi] = self.cache_li[rdi]
            self.cache_by[rdi] = 0
            self.bg_file = None
            self.rdi = self.next_to_read()
            if self.rdi < 0:
                self.finished = 1
                return
        self.timer.init(mode=Timer.ONE_SHOT, period=0, callback=self.bgreader)

    def start_bgreader(self):
        if self.finished:
            self.finished = 0
            self.timer.init(mode=Timer.ONE_SHOT,
                            period=1,
                            callback=self.bgreader)

    # convert integer to 24-bit RGTR parameter
    def i24(self, i: int):
        return bytearray([
            self.rb[(i >> 16) & 0xFF], self.rb[(i >> 8) & 0xFF],
            self.rb[i & 0xFF]
        ])

    # x is bytearray, length 1-256
    def rgtr(self, cmd, x):
        self.spi.write(bytearray([self.rb[cmd], self.rb[len(x) - 1]]))
        self.spi.write(x)

    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(2)
        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(0)
        return b

    def poke(self, addr, data):
        self.ctrl(2)
        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(0)
示例#31
0
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()
示例#32
0
class Display:
    def __init__(self):
        self.en_5V = Pin(5, Pin.OUT)
        self.pin_hrdy = Pin(21, mode=Pin.IN)
        self.pin_reset = Pin(22, mode=Pin.OUT)
        self.pin_cs = Pin(15, mode=Pin.OUT)
        self.spi = SPI(baudrate=2400000,
                       polarity=0,
                       phase=0,
                       bits=8,
                       firstbit=SPI.MSB,
                       sck=Pin(14),
                       mosi=Pin(13),
                       miso=Pin(12))

    def On(self):
        self.en_5V.on()
        self.en_5V.value(1)
        self.pin_cs.on()
        self.pin_reset.on()
        print("Display enabled")

    def Off(self):
        self.en_5V.off()
        self.pin_cs.off()
        self.pin_reset.off()
        print("Display disabled")

    def WaitforReady(self):
        while self.pin_hrdy.value() == 0:
            machine.idle()

    def WriteCmd(self, Cmd1, Cmd2):
        self.WaitforReady()
        self.pin_cs.value(0)
        self.WaitforReady()
        self.spi.write(bytearray([0x60, 0x00]))  #Praeamble Cmd
        self.WaitforReady()
        self.spi.write(bytearray([Cmd1, Cmd2]))
        self.pin_cs.value(1)

    def WriteData(self, Data, AnzData):
        self.WaitforReady()
        self.pin_cs.value(0)
        self.WaitforReady()
        self.spi.write(bytes([0x00, 0x00]))  #Praeamble Write
        self.WaitforReady()
        a = 0
        while a < AnzData:
            self.spi.write(bytearray([Data[a], Data[a + 1]]))
            self.WaitforReady()
            a += 2  #Immer 2 Schritte pro Runde
        self.pin_cs.value(1)
        self.WaitforReady()

    def WriteReg(self, Addr, Data, AnzData):
        self.WaitforReady()
        self.pin_cs.value(0)
        self.WaitforReady()
        self.spi.write(bytes([0x60, 0x00]))  #Praeamble Write
        self.WaitforReady()
        self.spi.write(bytes([0x00, 0x11]))  #CMD Write Reg
        self.pin_cs.value(1)
        self.WaitforReady()
        self.pin_cs.value(0)
        self.WaitforReady()
        self.spi.write(bytes([0x00, 0x00]))  #Praeamble Write
        self.WaitforReady()
        self.spi.write(Addr)  #write address of register
        self.WaitforReady()
        a = 0
        while a < AnzData:
            self.spi.write(bytearray([Data[a], Data[a + 1]]))
            self.WaitforReady()
            a += 2  #Immer 2 Schritte pro Runde
        self.pin_cs.value(1)
        self.WaitforReady()

    def ReadReg(self, Addr, AnzData, Data):
        self.WriteCmd(0x00, 0x10)  #Read Register Command
        self.WriteData(Addr, 2)  #read Address Packet
        self.ReadData(Data, AnzData)

    def ReadData(self, Data, AnzData):
        self.WaitforReady()
        self.pin_cs.value(0)
        self.WaitforReady()
        self.spi.write(bytes([0x10, 0x00]))  #Praeamble Read
        self.WaitforReady()
        print('Start Read')
        self.spi.read(1)
        self.WaitforReady()

        for a in range(AnzData):
            self.WaitforReady()
            Data.append(self.spi.read(1))
        #print(Data)
        self.pin_cs.value(1)
        self.WaitforReady()

    def send_data_over_spi(self, picture_data_spi):
        #Auflösung
        PixB = 1200
        PixBx = [0x04, 0xB0]
        PixH = 825
        PixHx = [0x03, 0x39]
        BpP = 4  # Bit per Pixel

        self.pin_cs.value(1)

        #Display Initialisation
        #--------------------------------------------------

        #Reset
        print('ResetSPI')
        self.pin_reset.value(0)
        time.sleep(0.5)
        self.pin_reset.value(1)
        self.WaitforReady()

        print('reset')
        #Cmd SYS_RUN
        print('System_Run')
        self.WriteCmd(0x00, 0x01)

        #-Load Picture-----------------------------------------
        print('Load Picture')

        #Write Image Buffer Adress in Register Command
        print('Load Picture -Buffer Adress')

        LISAR = bytes([0x02, 0x0A])
        WordH = [0x00, 0x11]
        self.WriteReg(LISAR, WordH, 2)

        LISAR = bytes([0x02, 0x08])
        WordL = [0xA1, 0xE0]
        self.WriteReg(LISAR, WordL, 2)

        #Write Area Image Info
        print('Load Picture -Area Info')
        #AreaImgInfo=[0+EndianType, BpP+Rotate, X, X, Y, Y, PixB, PixB, PixH, PixH,]
        BitperPix = {2: 0x00, 4: 0x20, 8: 0x30}
        AreaImgInfo = [
            0x01,
            BitperPix.get(4), 0x00, 0x00, 0x00, 0x00, 0x04, 0xB0, 0x03, 0x39
        ]

        self.WriteCmd(0x00, 0x21)  #LD_IMAGE_AREA
        self.WriteData(AreaImgInfo, 10)

        #Write Picture Data
        print('Load Picture -Data')

        self.pin_cs.value(0)
        #Praeamble Data
        self.spi.write(bytes([0x00, 0x00]))
        self.WaitforReady()

        #print(len(picture_data_spi))
        pix = int(PixB * BpP / 8)
        foo = bytes(1200)

        # for i in range(PixH):
        #     line = picture_data_spi[(i*pix):((i+1)*pix)]
        #     print(str((i*(pix+1)+1))+ ":"  + str((i+1)*(pix+1)))
        #     self.spi.write(line) #eine Zeile=1200 pixel
        #     #if(i%10==0):
        #         #print(str(i/PixH*100) + " %")

        #Send the data
        self.spi.write(picture_data_spi)

        self.pin_cs.value(1)

        #Send Load Image End
        print('Load Picture -End')
        print('picture end')
        self.WriteCmd(0x00, 0x22)

        #Display Area Command
        print('Disp Area Cmd')
        #AreaImgInfo = [X, X, Y, Y, PixB, PixB, PixH, PixH, Mode, Mode]
        AreaCmd = [
            0x00, 0x00, 0x00, 0x00, PixBx[0], PixBx[1], PixHx[0], PixHx[1],
            0x00, 0x02
        ]
        self.WriteCmd(0x00, 0x34)  #Disp Area Cmd
        self.WriteData(AreaCmd, 10)
示例#33
0
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")
示例#34
0
class MFRC522:

    GAIN_REG = 0x26
    MAX_GAIN = 0x07

    OK = 0
    NOTAGERR = 1
    ERR = 2

    REQIDL = 0x26
    REQALL = 0x52
    AUTHENT1A = 0x60
    AUTHENT1B = 0x61

    def __init__(self, spi=None, gpioRst=None, gpioCs=None):

        if gpioRst is not None:
            self.rst = Pin(gpioRst, Pin.OUT)
        else:
            self.rst = None
        assert(gpioCs is not None, "Needs gpioCs") # TODO fails without cableSelect
        if gpioCs is not None:
            self.cs = Pin(gpioCs, Pin.OUT)
        else:
            self.cs = None

        # TODO CH rationalise which of these are referenced, which can be identical
        self.regBuf = bytearray(4)
        self.blockWriteBuf = bytearray(18)
        self.authBuf = bytearray(12)
        self.wregBuf = bytearray(2)
        self.rregBuf = bytearray(1)
        self.recvBuf = bytearray(16)
        self.recvMv = memoryview(self.recvBuf)

        if self.rst is not None:
            self.rst.value(0)
        if self.cs is not None:
            self.cs.value(1)

        if spi is not None:
            self.spi = spi
        else:
            sck = Pin(14, Pin.OUT)
            mosi = Pin(13, Pin.OUT)
            miso = Pin(12, Pin.IN)
            if uname()[0] == 'WiPy':
                self.spi = SPI(0)
                self.spi.init(SPI.MASTER, baudrate=1000000, pins=(sck, mosi, miso))
            elif uname()[0] == 'esp8266': # TODO update to match https://github.com/cefn/avatap/blob/master/python/host/cockle.py #prepareHost()
                self.spi = SPI(baudrate=100000, polarity=0, phase=0, sck=sck, mosi=mosi, miso=miso)
                self.spi.init()
            else:
                raise RuntimeError("Unsupported platform")

        if self.rst is not None:
            self.rst.value(1)
        self.init()

    def _wreg(self, reg, val):
        if self.cs is not None:
            self.cs.value(0)
        buf = self.wregBuf
        buf[0]=0xff & ((reg << 1) & 0x7e)
        buf[1]=0xff & val
        self.spi.write(buf)
        if self.cs is not None:
            self.cs.value(1)

    def _rreg(self, reg):
        if self.cs is not None:
            self.cs.value(0)
        buf = self.rregBuf
        buf[0]=0xff & (((reg << 1) & 0x7e) | 0x80)
        self.spi.write(buf)
        val = self.spi.read(1)
        if self.cs is not None:
            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, into=None):

        recv = emptyRecv
        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

                    if into is None:
                        recv = self.recvBuf
                    else:
                        recv = into
                    pos = 0
                    while pos < n:
                        recv[pos] = self._rreg(0x09)
                        pos += 1
                    if into is None:
                        recv = self.recvMv[:n]
                    else:
                        recv = into

            else:
                stat = self.ERR

        return stat, recv, bits

    def _assign_crc(self, data, count):

        self._cflags(0x05, 0x04)
        self._sflags(0x0A, 0x80)

        dataPos = 0
        while dataPos < count:
            self._wreg(0x09, data[dataPos])
            dataPos += 1

        self._wreg(0x01, 0x03)

        i = 0xFF
        while True:
            n = self._rreg(0x05)
            i -= 1
            if not ((i != 0) and not (n & 0x04)):
                break

        data[count] = self._rreg(0x22)
        data[count + 1] = 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.set_gain(self.MAX_GAIN)
        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

        # CH Note bytearray allocation here
        return stat, bytearray(recv)

    def select_tag(self, ser):
        # TODO CH normalise all list manipulation to bytearray, avoid below allocation
        buf = bytearray(9)
        buf[0] = 0x93
        buf[1] = 0x70
        buf[2:7] = ser
        self._assign_crc(buf, 7)
        (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):
        # TODO CH void ser[:4] implicit list allocation
        buf = self.authBuf
        buf[0]=mode # A or B
        buf[1]=addr # block
        buf[2:8]=sect # key bytes
        buf[8:12]=ser[:4] # 4 bytes of id
        return self._tocard(0x0E, buf)[0]

    # TODO this may well need to be implemented for vault to properly back out from a card session
    # TODO how, why, when is 'HaltA' needed? see https://github.com/cefn/micropython-mfrc522/issues/1
    def halt_a(self):
        pass

    def stop_crypto1(self):
        self._cflags(0x08, 0x08)

    def set_gain(self, gain):
        assert gain <= self.MAX_GAIN
        # clear bits
        self._cflags(self.GAIN_REG, 0x07<< 4)
        # set bits according to gain
        self._sflags(self.GAIN_REG, gain << 4)

    def read(self, addr, into = None):
        buf = self.regBuf
        buf[0]=0x30
        buf[1]=addr
        self._assign_crc(buf, 2)
        (stat, recv, _) = self._tocard(0x0C, buf, into=into)
        # TODO this logic probably wrong (should be 'into is None'?)
        if into is None: # superstitiously avoid returning read buffer memoryview
            # CH Note bytearray allocation here
            recv = bytearray(recv)
        return recv if stat == self.OK else None

    def write(self, addr, data):
        buf = self.regBuf
        buf[0] = 0xA0
        buf[1] = addr
        self._assign_crc(buf, 2)
        (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 = self.blockWriteBuf

            i = 0
            while i < 16:
                buf[i] = data[i]  # TODO CH eliminate this, accelerate it?
                i += 1

            self._assign_crc(buf, 16)
            (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