+class PicResponseThunk(object):
+ """A holder for a response value from the PIC, eg from a REGOUT
+ command.
+
+ To retrieve the value, simply call the object. If the value has
+ not yet been retrieved, any pending commands in the command buffer
+ will be executed. You can determine whether the response has been
+ recieved by calling the have_response function.
+
+ Objects of this class should only be created by the PicCmdBuffer
+ class"""
+
+ def __init__(self, cmdbuf):
+ self.holder = cmdbuf
+ self.value = None
+
+ def _set_value(self, value):
+ self.value = value
+ def have_response(self):
+ return self.value is not None
+ def __call__(self):
+ if self.value is None:
+ self.holder.force()
+ assert self.value is not None
+ return self.value
+
+class PicCmdBuffer(object):
+ def __init__(self, client):
+ self.client = client
+ self.buffered_commands = []
+ self.response_buffer = []
+ data = client.writecmd(MONITORAPP, 0xc2)
+ assert data is not None and len(data) is 2
+ # buffer size is the size of the goodfet's recieve buffer, in
+ # instructions
+ self.buffer_size = (ord(data[0]) + (ord(data[1]) << 8)) >> 2
+ def force(self):
+ assert len(self.buffered_commands) <= self.buffer_size
+ command = ''.join(self.buffered_commands)
+ self.buffered_commands = []
+ #print "Running: " + command.encode('hex')
+ data = self.client.writecmd(PICAPP, VERB_CMDLIST,
+ len(command), map(ord, command))
+ #print "Recieved: " + data.encode('hex')
+ assert len(data) == (len(self.response_buffer) + 1) * 2
+ orig_data = data
+ checksum = 0
+ for resp in self.response_buffer:
+ wd, data = data[0:2],data[2:]
+ val = ord(wd[0]) + (ord(wd[1]) << 8)
+ checksum += val
+ resp._set_value(val)
+ assert len(data) == 2
+ checksum += ord(data[0]) + (ord(data[1]) << 8)
+ checksum &= 0xffff
+ assert checksum == 0
+ self.response_buffer = []
+ def _add_command(self, command, data):
+ assert command in (0,1)
+ assert (data >> 24) == 0
+ full_cmd = [chr(command)]
+ for i in (0,1,2):
+ full_cmd.append(chr((data >> (8*i)) & 0xff))
+ if len(self.buffered_commands) >= self.buffer_size:
+ self.force()
+ self.buffered_commands.append(''.join(full_cmd))
+ def SIX(self, *insns):
+ """Run a list of instructions"""
+ for insn in insns:
+ self._add_command(0, insn)
+ return self
+ def REGOUT(self):
+ "Read the VISI register. Returns a PicResponseThunk"
+ thunk = PicResponseThunk(self)
+ self.response_buffer.append(thunk)
+ self._add_command(1, 0)
+ return thunk
+