class SPI: def __init__(self, dev): self.d = SPIDriver(dev) self.d.unsel() self.d.seta(1) self.d.setb(1) print('reset') self.d.setb(0) time.sleep(.1) self.d.setb(1) def transfer(self, wr, rd = 0): self.d.sel() self.d.write(wr) r = self.d.read(rd) self.d.unsel() return r
class GameduinoSPIDriver(gameduino.Gameduino): def __init__(self): self.d = SPIDriver( "/dev/serial/by-id/usb-FTDI_FT230X_Basic_UART_DO01HE8Q-if00-port0") self.d.unsel() self.d.seta(1) self.d.setb(1) if 0: print('reset') self.d.setb(0) time.sleep(.1) self.d.setb(1) def transfer(self, wr, rd=0): self.d.sel() self.d.write(wr) r = self.d.read(rd) self.d.unsel() return r
class GD(gameduino2.base.GD2): def __init__(self, dev): self.spi = SPIDriver(dev) self.spi.setb(1) if False: self.spi.setb(0) time.sleep(1) self.spi.setb(1) time.sleep(1) self.coldstart() t0 = time.time() while self._rd32(gd3.REG_ID) != 0x7c: assert (time.time() - t0) < 1.0, "No response - is GD attached?" if 0: time.sleep(1) print("ID %8x" % self._rd32(gd3.REG_ID)) print("CMD_READ %8x" % self._rd32(gd3.REG_CMD_READ)) print("CMD_WRITE %8x" % self._rd32(gd3.REG_CMD_WRITE)) print("CMD_SPACE %8x" % self._rd32(gd3.REG_CMDB_SPACE)) while self._rd32(gd3.REG_ID) != 0x7c: time.sleep(.1) self.getspace() self.stream() def coldstart(self): self.host_cmd(0x00) # Wake up self.host_cmd(0x48) # int clock self.host_cmd(0x68) # Core reset time.sleep(.25) def host_cmd(self, a, b = 0, c = 0): self.spi.sel() self.spi.write(bytes([a, b, c])) self.spi.unsel() def start(self, a): self.spi.sel() self.spi.write(bytes([ 0xff & (a >> 16), 0xff & (a >> 8), 0xff & a])) def _rd(self, a, n): self.start(a) r = self.spi.read(1 + n) self.spi.unsel() return r[1:] def _rd32(self, a): return struct.unpack("<I", self._rd(a, 4))[0] def _wr32(self, a, v): self.start(0x800000 | a) self.spi.write(struct.pack("I", v)) self.spi.unsel() def _wr(self, a, v): self.start(0x800000 | a) self.spi.write(v) self.spi.unsel() def getspace(self): self.space = self._rd32(gd3.REG_CMDB_SPACE) if self.space & 1: raise CoprocessorException def stream(self): self.start(0x800000 | gd3.REG_CMDB_WRITE) def unstream(self): self.spi.unsel() def reserve(self, n): if self.space < n: self.unstream() while self.space < n: self.getspace() self.stream() def c4(self, v): ''' Write 32-bit value v to the command FIFO ''' self.reserve(4) self.spi.write(struct.pack("I", v)) self.space -= 4 def c(self, ss): ''' Write s to the command FIFO ''' for i in range(0, len(ss), 64): s = ss[i:i + 64] self.reserve(len(s)) self.spi.write(s) self.space -= len(s) def flush(self): pass def finish(self): self.reserve(4092) def is_idle(self): self.unstream() self.getspace() self.stream() return self.space == 4092 def rd32(self, a): self.unstream() r = self._rd32(a) self.stream() return r def rd(self, a, n): self.unstream() r = self._rd(a, n) self.stream() return r def wr(self, a, v): self.unstream() r = self._wr(a, v) self.stream() def result(self, n=1): # Return the result field of the preceding command self.finish() self.unstream() wp = self._rd32(gd3.REG_CMD_READ) r = self._rd32(gd3.RAM_CMD + (4095 & (wp - 4 * n))) self.stream() return r def setup_480x272(self): b = 6 setup = [ (gd3.REG_OUTBITS, b * 73), (gd3.REG_DITHER, 1), (gd3.REG_GPIO, 0x83), (gd3.REG_PCLK_POL, 1), (gd3.REG_ROTATE, 0), (gd3.REG_SWIZZLE, 3), ] self.Clear() self.swap() for (a, v) in setup: self.cmd_regwrite(a, v) self.cmd_regwrite(gd3.REG_PCLK, 5) # Enable display self.finish() self.w = 480 self.h = 272 def setup_800x480(self): b = 6 setup = [ (gd3.REG_OUTBITS, b * 73), (gd3.REG_DITHER, 1), (gd3.REG_GPIO, 0x83), (gd3.REG_ROTATE, 0), (gd3.REG_SWIZZLE, 3), (gd3.REG_HCYCLE, 928), (gd3.REG_HOFFSET, 88), (gd3.REG_HSIZE, 800), (gd3.REG_HSYNC0, 0), (gd3.REG_HSYNC1, 48), (gd3.REG_VCYCLE, 525), (gd3.REG_VOFFSET, 32), (gd3.REG_VSIZE, 480), (gd3.REG_VSYNC0, 0), (gd3.REG_VSYNC1, 3), (gd3.REG_CSPREAD, 0), (gd3.REG_PCLK_POL, 0), ] for (a, v) in setup: self.cmd_regwrite(a, v) self.Clear() self.swap() self.finish() self.cmd_regwrite(gd3.REG_PCLK, 2) # Enable display self.w = 800 self.h = 480 def calibrate(self): self.Clear() self.cmd_text(240, 135, 29, gd3.OPT_CENTER, "Tap the dot") self.cmd_calibrate(0) self.cmd_dlstart() def screenshot(self, dest): REG_SCREENSHOT_EN = 0x302010 # Set to enable screenshot mode REG_SCREENSHOT_Y = 0x302014 # Y line register REG_SCREENSHOT_START = 0x302018 # Screenshot start trigger REG_SCREENSHOT_BUSY = 0x3020e8 # Screenshot ready flags REG_SCREENSHOT_READ = 0x302174 # Set to enable readout RAM_SCREENSHOT = 0x3c2000 # Screenshot readout buffer self.finish() self.unstream() self._wr32(REG_SCREENSHOT_EN, 1) self._wr32(0x0030201c, 32) self._wr32(REG_SCREENSHOT_READ, 1) for ly in range(self.h): self._wr32(REG_SCREENSHOT_Y, ly) self._wr32(REG_SCREENSHOT_START, 1) time.sleep(.002) # while (self.raw_read(REG_SCREENSHOT_BUSY) | self.raw_read(REG_SCREENSHOT_BUSY + 4)): pass while self._rd(REG_SCREENSHOT_BUSY, 8) != bytes(8): pass self._wr32(REG_SCREENSHOT_READ, 1) bgra = self._rd(RAM_SCREENSHOT, 4 * self.w) (b,g,r,a) = [bgra[i::4] for i in range(4)] line = bytes(sum(zip(r,g,b), ())) dest(line) self._wr32(REG_SCREENSHOT_READ, 0) self._wr32(REG_SCREENSHOT_EN, 0) self.stream() def screenshot_im(self): self.ssbytes = b"" def appender(s): self.ssbytes += s self.screenshot(appender) from PIL import Image return Image.frombytes("RGB", (self.w, self.h), self.ssbytes)
class Frame(wx.Frame): def __init__(self): self.sd = None def widepair(a, b): r = wx.BoxSizer(wx.HORIZONTAL) r.Add(a, 1, wx.LEFT) r.AddStretchSpacer(prop=1) r.Add(b, 1, wx.RIGHT) return r def pair(a, b): r = wx.BoxSizer(wx.HORIZONTAL) r.Add(a, 1, wx.LEFT) r.Add(b, 0, wx.RIGHT) return r def rpair(a, b): r = wx.BoxSizer(wx.HORIZONTAL) r.Add(a, 0, wx.LEFT) r.Add(b, 1, wx.RIGHT) return r def label(s): return wx.StaticText(self, label = s) def hbox(items): r = wx.BoxSizer(wx.HORIZONTAL) [r.Add(i, 0, wx.EXPAND) for i in items] return r def hcenter(i): r = wx.BoxSizer(wx.HORIZONTAL) r.AddStretchSpacer(prop=1) r.Add(i, 2, wx.CENTER) r.AddStretchSpacer(prop=1) return r def vbox(items): r = wx.BoxSizer(wx.VERTICAL) [r.Add(i, 0, wx.EXPAND) for i in items] return r wx.Frame.__init__(self, None, -1, "SPIDriver") self.label_serial = wx.StaticText(self, label = "-", style = wx.ALIGN_RIGHT) self.label_voltage = wx.StaticText(self, label = "-", style = wx.ALIGN_RIGHT) self.label_current = wx.StaticText(self, label = "-", style = wx.ALIGN_RIGHT) self.label_temp = wx.StaticText(self, label = "-", style = wx.ALIGN_RIGHT) self.label_uptime = wx.StaticText(self, label = "-", style = wx.ALIGN_RIGHT) self.Bind(EVT_PING, self.refresh) self.ckCS = wx.CheckBox(self, label = "CS") self.ckA = wx.CheckBox(self, label = "A") self.ckB = wx.CheckBox(self, label = "B") self.ckCS.Bind(wx.EVT_CHECKBOX, self.check_cs) self.ckA.Bind(wx.EVT_CHECKBOX, self.check_a) self.ckB.Bind(wx.EVT_CHECKBOX, self.check_b) ps = self.GetFont().GetPointSize() fmodern = wx.Font(ps, wx.MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL) def logger(): r = wx.TextCtrl(self, style=wx.TE_READONLY | wx.TE_RIGHT | wx.TE_DONTWRAP) r.SetBackgroundColour(wx.Colour(224, 224, 224)) r.SetFont(fmodern) return r self.txMISO = logger() self.txMOSI = logger() self.txVal = HexTextCtrl(self, size=wx.DefaultSize, style=0) self.txVal.SetMaxLength(2) self.txVal.SetFont(wx.Font(14 * ps // 10, wx.MODERN, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)) txButton = wx.Button(self, label = "Transfer") txButton.Bind(wx.EVT_BUTTON, partial(self.transfer, self.txVal)) txButton.SetDefault() self.allw = [self.ckCS, self.ckA, self.ckB, self.txVal, txButton, self.txMISO, self.txMOSI] [w.Enable(False) for w in self.allw] self.devs = self.devices() cb = wx.ComboBox(self, choices = sorted(self.devs.keys()), style = wx.CB_READONLY) cb.Bind(wx.EVT_COMBOBOX, self.choose_device) vb = vbox([ label(""), hcenter(cb), label(""), hcenter(pair( vbox([ label("Serial"), label("Voltage"), label("Current"), label("Temp."), label("Running"), ]), vbox([ self.label_serial, self.label_voltage, self.label_current, self.label_temp, self.label_uptime, ]) )), label(""), rpair(label("MISO"), self.txMISO), rpair(label("MOSI"), self.txMOSI), label(""), hcenter(pair(self.ckCS, hbox([self.ckA, self.ckB]))), label(""), hcenter(pair(self.txVal, txButton)), label(""), ]) self.SetSizerAndFit(vb) self.SetAutoLayout(True) if len(self.devs) > 0: d1 = min(self.devs) self.connect(self.devs[d1]) cb.SetValue(d1) t = threading.Thread(target=ping_thr, args=(self, )) t.setDaemon(True) t.start() def devices(self): if sys.platform == 'darwin': devdir = "/dev/" pattern = "^tty.usbserial-(........)" else: devdir = "/dev/serial/by-id/" pattern = "^usb-FTDI_FT230X_Basic_UART_(........)-" if not os.access(devdir, os.R_OK): return {} devs = os.listdir(devdir) def filter(d): m = re.match(pattern, d) if m: return (m.group(1), devdir + d) seldev = [filter(d) for d in devs] return dict([d for d in seldev if d]) def connect(self, dev): self.sd = SPIDriver(dev) [w.Enable(True) for w in self.allw] self.ckCS.SetValue(not self.sd.cs) self.ckA.SetValue(self.sd.a) self.ckB.SetValue(self.sd.b) self.refresh(None) def refresh(self, e): if self.sd: self.sd.getstatus() self.label_serial.SetLabel(self.sd.serial) self.label_voltage.SetLabel("%.2f V" % self.sd.voltage) self.label_current.SetLabel("%d mA" % self.sd.current) self.label_temp.SetLabel("%.1f C" % self.sd.temp) days = self.sd.uptime // (24 * 3600) rem = self.sd.uptime % (24 * 3600) hh = rem // 3600 mm = (rem / 60) % 60 ss = rem % 60; self.label_uptime.SetLabel("%d:%02d:%02d:%02d" % (days, hh, mm, ss)) def choose_device(self, e): self.connect(self.devs[e.EventObject.GetValue()]) def check_cs(self, e): if e.EventObject.GetValue(): self.sd.sel() else: self.sd.unsel() def check_a(self, e): self.sd.seta(e.EventObject.GetValue()) def check_b(self, e): self.sd.setb(e.EventObject.GetValue()) def transfer(self, htc, e): if htc.GetValue(): txb = int(htc.GetValue(), 16) rxb = struct.unpack("B", self.sd.writeread(struct.pack("B", txb)))[0] self.txMOSI.AppendText(" %02X" % txb) self.txMISO.AppendText(" %02X" % rxb) htc.ChangeValue("")
return [rnd(256) for i in range(n)] if __name__ == '__main__': if len(sys.argv) > 1: s = SPIDriver(sys.argv[1]) else: s = SPIDriver() # print(s) # t1 = time.time() + float(sys.argv[2]) while True: # time.time() < t1: for i in range(50): random.choice([ lambda: s.seta(rnd(2)), lambda: s.setb(rnd(2)), lambda: s.sel(), lambda: s.unsel(), lambda: s.writeread(pattern(1 + rnd(1))), # lambda: s.read(1 + rnd(12)), # lambda: s.getstatus() ])() os.system("outlet.py 8 on ; outlet.py 8 off") time.sleep(3) print(hex(s.debug)) while 0: s.sel() s.write(b'ABCDEF') s.unsel() time.sleep(.050)
import getopt if __name__ == '__main__': try: optlist, args = getopt.getopt(sys.argv[1:], "h:") except getopt.GetoptError as reason: print() print('usage: iceprog [ -h device ] bitstream...') print() print() sys.exit(1) optdict = dict(optlist) s = SPIDriver(optdict.get('-h', "/dev/ttyUSB0")) s.sel() # Hold FPGA in reset s.seta(0) # Some primitives for the N25Q flash def command(b): s.unsel() s.sel() s.write(b) def idcode(): command([0x9f]) return s.read(3) def write_enable(): command([0x06])
if __name__ == '__main__': try: optlist, args = getopt.getopt(sys.argv[1:], "h:") except getopt.GetoptError as reason: print() print('usage: st7735 [ -h device ] image...') print() print() sys.exit(1) optdict = dict(optlist) s = SPIDriver(optdict.get('-h', "/dev/ttyUSB0")) s.unsel() while True: s.sel() # start command s.write(b'\x9f') # command 9F is READ JEDEC ID ids = s.read(3) (id1, id2, id3) = struct.unpack("BBB", ids) print ("JEDEC ID: %02x %02x %02x" % (id1, id2, id3)) s.unsel() # end command time.sleep(.02) if id1 not in (0x00, 0xff): break for c in (0x66, 0x99): s.sel() # start command s.write(bytes([c])) s.unsel() time.sleep(.2)