#/usr/bin/env python # Jacob Joseph # 16 Feb 2010 # A class to talk to the LED Control PWM board. # See PIC16F887 firmware for the other side of these communications import libftdi #import libftdipy #import ftdi #import pyftdi #from ctypes import c_int class ledComm(object): ft = None def __init__(self): self.ft = libftdi.ftdi() #self.ft.write_data_set_chunksize(1) #self.ft.set_latency_timer(1) #self.ft = pyftdi.FTDI() #self.usb_open() #def usb_open(self): # self.ft.usb_open( 0x0403, 0x6001) def close(self): self.ft.close() def senddata(self, command, bytearr=None): """Send a command and optional data to the board. 0x02 - raw grayscale, followed by 24 bytes 0x03 - raw dot correction, followed by 12 bytes 0x80 - reset data reception. This might screw up the blank syncronization 0x81 - disable GIE (turn lights off) 0x82 - enable GIE (turn lights on)""" if bytearr is None: bytearr = [] data = [command]+bytearr #print "sending", [hex(a) for a in data] self.ft.write_data( data) #for d in data: # # FIXME: sending all at once doesn't seem to work right now. # self.ft.write_data( [d]) #Arr = c_int * len(data) #cbuf = Arr( *data) #self.ft.write_data( cbuf) return def toggle(self, on): if on: self.senddata(0x82) else: self.senddata(0x81) return def reset(self): self.ft.purge_buffers() for i in range(24): self.senddata(0x80) return def update_leds( self, *ledrgb): """From 5 tuples of (r,g,b) floats, send the color values to the board.""" assert len(ledrgb) == 5, "update_leds() requires a list of five (r,g,b) float tuples" # convert color intensities to integer fractions of 4095, and # build a list of them out_values = [ int(f*4095) for tup in ledrgb for f in tup] # the PIC currently expects 16 values. Pad this array out_values += (16 - len(out_values)) * [0] # ports should be ordered greatest to least out_values.reverse() # 16 12-bit values should be sent. Build the 24-byte value rf = 24*[0x0] # algorithm from website ? for i,val in enumerate(out_values): bit_num = i * 12 byte_num = bit_num / 8 start_nibble = (bit_num & 7) > 0 if not start_nibble: rf[byte_num] = val >> 4 rf[byte_num+1] = (rf[byte_num+1] & 0x0F) | (( val & 0x0F) << 4) else: rf[byte_num] = (rf[byte_num] & 0xF0) | (val >> 8) rf[byte_num+1] = val & 0xFF self.senddata(0x02, rf) return out_values, rf def binary( b, bits=8): s = '' for i in range(bits-1, -1, -1): s += str(b >> i & 1) return s def print_vals( *ledrgb): out, rf = lc.update_leds( *ledrgb) vals = [0x00] * len(out) for i in range(len(vals)): bytei = int(i * 12 / 8) # lower nibble complete if i % 2 == 1: vals[i] = ((rf[bytei] & 0x0F) << 8 ) | (rf[bytei + 1] & 0xFF) # upper nibble complete else: vals[i] = ( (rf[ bytei ] & 0xFF) << 4) | ((rf[ bytei + 1] & 0xF0) >> 4) return out, [binary(b) for b in rf], vals, vals==out if __name__ == "__main__": lc = ledComm()