#!/usr/bin/env python # (C) 2008 Jacob Joseph # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import libftdi, time, kdeui # commands: # 0x02 - raw grayscale, followed by 72 bytes # 0x03 - raw dot correction, followed by 36 bytes # 0x80 - reset data reception. this might screw up the blank syncronization # 0x81 - disable GIE (turn lights off) # 0x82 - enable GIE (turn lights on) # LED TI5940 ports # ------------------------------------ # led0_r TI0 OUT0 TI0 OUT1 TI0 OUT2 # led0_g TI0 OUT3 TI0 OUT4 TI0 OUT5 # led0_b TI0 OUT6 TI0 OUT7 TI0 OUT8 # led1_r TI0 OUT9 TI0 OUT10 TI0 OUT11 # led1_g TI0 OUT12 TI0 OUT13 TI0 OUT14 # led1_b TI0 OUT15 TI1 OUT0 TI1 OUT1 # led2_r TI1 OUT2 TI1 OUT3 TI1 OUT4 # led2_g TI1 OUT5 TI1 OUT6 TI1 OUT7 # led2_b TI1 OUT8 TI1 OUT9 TI1 OUT10 # led3_r TI1 OUT11 TI1 OUT12 TI1 OUT13 # led3_g TI1 OUT14 TI1 OUT15 TI2 OUT0 # led3_b TI2 OUT1 TI2 OUT2 TI2 OUT3 # led4_r TI2 OUT4 TI2 OUT5 TI2 OUT6 # led4_g TI2 OUT7 TI2 OUT8 TI2 OUT9 # led4_b TI2 OUT10 TI2 OUT11 TI2 OUT12 class tlc5940_fifo(object): ft = None def __init__(self): self.ft = libftdi.ftdi() self.ft.write_data_set_chunksize(1) #self.ft.set_latency_timer(1) def close(self): self.ft.close() def senddata(self, command, bytearr=None): 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: # sending all at once doesn't seem to work right now. self.ft.write_data( [d]) return def reset(self): self.ft.purge_buffers() for i in range(24): tlc.senddata(0x80) return # Data ready to be clocked out MSB first. def setcolors( self, *ledrgb): #print ledrgb #assert len(ledrgb) == 5, "set5colors() requires a list of five tuples" # convert color intensities to fractions of 4095. #ledrgb = [ (int(r*4095), int(g*4095), int(b*4095)) # for (r, g, b) in ledrgb] # build output list of intensities out_values = [] for (i,rgb) in enumerate(ledrgb): for col in rgb: # 3 outputs are used for each channel out_values += 3*[int(col*4095)] # pad to 48 outputs out_values += (48-len(out_values)) * [0] # ports should be ordered greatest to least out_values.reverse() # 72-byte array rf = 72*[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 # test with 24 bytes #self.senddata(0x02, rf[-24:]) self.senddata(0x02, rf) return def set4colors(self, rgb_fl, rgb_fr, rgb_rr, rgb_rl): """RGB values, as tuples of floats, to control light intensity""" # lights connected to ports OUT15-OUT4, in order of R,G,B port_hex_values = [] # 9 ports for i in rgb_fl + rgb_fr + rgb_rr + rgb_rl: port_hex_values.append( int(i * 4095)) #print [hex(a) for a in port_hex_values] # 7 values (for 15 total) for i in [4095]*7: port_hex_values.append( 4095) # bits in order 15.H, 15.L, 14.H, ..., 0.H, 0.L all_bits = long() for (i,val) in enumerate(port_hex_values): # 4-bit blocks for j in range(2,-1,-1): subbyte = val & (0xF << j*4) # reverse subbytes #subbyte = (subbyte & 0xF0 >> 4) subbyte& all_bits = all_bits | (subbyte << i*12) #print i,j, hex(subbyte), hex(val), hex(all_bits) # bytes in order 0.L, 0.H, 1.L, ..., 15.L, 15.H # ready for transmission byte_arr = [] for i in range(0,24): byte_arr.append((all_bits >> (i*4*2)) & 0xFF) # HACK # reverse sub bytes that are shared for i in range(1,24,3): byte_arr[i] = byte_arr[i] >> 4 | (byte_arr[i] & 0x0F) << 4 print [hex(a) for a in byte_arr] #print len(byte_arr) self.senddata( 0x00, byte_arr) return def test0(): tlc.senddata(0x00) tlc.senddata(0xFF) tlc.senddata(0xF0) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) tlc.senddata(0x00) def test2(on=0.15, off=0.0): while True: tlc.setcolors( (1,0,0), (0,1,0), (0,0,1), (1,0,0), (0,0,0)) time.sleep(on) tlc.setcolors( (0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0)) time.sleep(off) tlc.setcolors( (0,1,0), (0,0,1), (0,1,0), (0,1,0), (0,0,0)) time.sleep(on) tlc.setcolors( (0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0)) time.sleep(off) tlc.setcolors( (0,0,1), (1,0,0), (0,0,1), (0,0,1), (0,0,0)) time.sleep(on) tlc.setcolors( (0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0)) time.sleep(off) tlc.setcolors( (0,1,0), (0,1,0), (0,1,1), (1,0,0), (0,0,0)) time.sleep(on) tlc.setcolors( (0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0)) time.sleep(off) tlc.setcolors( (0,0,1), (0,0,1), (0,0,1), (0,0,1), (0,0,0)) time.sleep(on) tlc.setcolors( (0,0,0), (0,0,0), (0,0,0), (0,0,0), (0,0,0)) time.sleep(off) def test3(on=0.05): r = 1.0 b = 0.0 up = True while True: tlc.setcolors( (1,1,1), (r, 0, 1-b), (0, r, b), (0, 1-r, 1-b)) time.sleep(on) if up: r = r - 0.001 b = b + 0.001 if r <= 0: up=False else: r = r + 0.001 b = b - 0.001 if b <= 0: up=True def test_circle(delay=0.02, angle_step=0.1, saturation=255, value=255): angle = 0.0 color_array = [None]*4 for led in range(4): color_array[led] = kdeui.KColor() while True: angle = (angle + angle_step ) % 360 rgb_array = [] for led in range(4): hue = (angle + led * 90) % 360 color_array[led].setHsv( hue, saturation, value) rgb_array.append( [float(c)/255 for c in color_array[led].getRgb()]) tlc.setcolors( *rgb_array) time.sleep( delay) def test1(): tlc.senddata(0x00) for i in range(24): tlc.senddata(0x00) if __name__ == "__main__": tlc = tlc5940_fifo() dot_full = [0xFF]*12 gs_full = [0xFF]*24 gs_off = [0x00]*24 #tlc.senddata( 0x00, gs_full) #tlc.senddata( 0x01,dot_full) #tlc.set4colors( (1,1,1), (1,1,1), (1,1,1), (1,1,1)) #tlc.set4colors( (1,0,0), (0,0,0), (0,0,0), (0,0,0))