This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DLPC900: Problems with writing my own software in Python

Part Number: DLPC900

Hi,

I'm trying to write my own software in Python for controlling the DLPC900. For this purpose, I am using the hidapi library in python. So far I was able to make it work only the stop sequence and start sequence commands (the latter only in pre-stored pattern mode), while if I want to load other images it doesn't work. I'm using a code based on the work of another user (https://e2e.ti.com/support/dlp/f/94/t/540992?I-released-a-small-python-interface-for-the-lightcrafter-6500), the main difference is that I am using hidap library, and not libusb (I used libusb and it worked fine, but sometimes the connection with the board was lost, so I preferred to switch library).

I would like to know if anyone have already controlled the board with the hidapi library in python, so that I can find out what's wrong with the code.

Here my code:

import hid
import time
import numpy
import os

class DmdDeviceHID:
    
    def __init__(self):
        
        hid.enumerate()
        self.device = hid.device()

        self.device.open(0x0451, 0xc900)
        print(self.device.get_manufacturer_string())
        print(self.device.get_product_string())
        print(self.device.get_serial_number_string())
#         self.ans = []

    def command(self,mode,sequencebyte,com1,com2,data=None):
        buffer = []

        flagstring=''
        if mode=='r':
            flagstring+='1'
        else:
            flagstring+='0'        
        flagstring+='0000000'
        buffer.append(0x00)
        buffer.append(bitstobytes(flagstring)[0])
        buffer.append(sequencebyte)
        temp=bitstobytes(convlen(len(data)+2,16))
        buffer.append(temp[0])
        buffer.append(temp[1])
        buffer.append(com2) 
        buffer.append(com1)

        if len(buffer)+len(data)<=65: #65 = max number of sent bytes 
        
            for i in data:
                buffer.append(i)

            for i in range(65-len(buffer)):
                buffer.append(0x00)


            self.device.write(buffer)

        else:
            for i in range(65-len(buffer)):
                buffer.append(data[i])

            self.device.write(buffer)

            buffer = [0x00]

            j=0
            while j<len(data)-58:
                buffer.append(data[j+58])
                j=j+1
                if j%65==0:
                    self.device.write(buffer)

                    buffer = [0x00]

            if j%65!=0:

                while j%65!=0:
                    buffer.append(0x00)
                    j=j+1
                    
                self.device.write(buffer)               
                

    def checkforerrors(self):
        self.command('r',0x22,0x01,0x00,[])
#         if self.ans[6]!=0:
#             print (self.ans[6])    

## function printing all of the dlp answer

#     def readreply(self):
#         for i in self.ans:
#             print (hex(i))

## functions for idle mode activation

    def idle_on(self):
        self.command('w',0x00,0x02,0x01,[int('00000001',2)])
#         self.checkforerrors()

    def idle_off(self):
        self.command('w',0x00,0x02,0x01,[int('00000000',2)])
#         self.checkforerrors()

## functions for power management

    def standby(self):
        self.command('w',0x00,0x02,0x00,[int('00000001',2)])
#         self.checkforerrors()

    def wakeup(self):
        self.command('w',0x00,0x02,0x00,[int('00000000',2)])
#         self.checkforerrors()

    def reset(self):
        self.command('w',0x00,0x02,0x00,[int('00000010',2)])
#         self.checkforerrors()

## test write and read operations, as reported in the dlpc900 programmer's guide

    def testread(self):
        self.command('r',0xff,0x11,0x00,[])
#         self.readreply()

    def testwrite(self):
        self.command('w',0x22,0x11,0x00,[0xff,0x01,0xff,0x01,0xff,0x01])
#         self.checkforerrors()

## some self explaining functions

    def changemode(self,mode):
        self.command('w',0x00,0x1a,0x1b,[mode])
#         self.checkforerrors()

    def startsequence(self):
        self.command('w',0x00,0x1a,0x24,[2])
#         self.checkforerrors()

    def pausesequence(self):
        self.command('w',0x00,0x1a,0x24,[1])
#         self.checkforerrors()

    def stopsequence(self):
        self.command('w',0x00,0x1a,0x24,[0])
#         self.checkforerrors()


    def configurelut(self,imgnum,repeatnum):
        img=convlen(imgnum,11)
        repeat=convlen(repeatnum,32)

        string=repeat+'00000'+img

        im_bytes=bitstobytes(string)
        
        self.command('w',0x00,0x1a,0x31,im_bytes)
#         self.checkforerrors()
        
    def definepattern(self,index,exposure,bitdepth,color,triggerin,darktime, triggerout,patind,bitpos):
        
        payload=[]
        index=convlen(index,16)
        index=bitstobytes(index)
        for i in index:
            payload.append(i)

        exposure=convlen(exposure,24) #24 or 32?
        exposure=bitstobytes(exposure)
        for i in exposure:
            payload.append(i)
            
        optionsbyte=''
        #optionsbyte+='0'*8 #I put this line. I dont know if it's right. see the manual
        optionsbyte+='1'
        bitdepth=convlen(bitdepth-1,3)
        optionsbyte=bitdepth+optionsbyte
        optionsbyte=color+optionsbyte
        if triggerin:
            optionsbyte='1'+optionsbyte
        else:
            optionsbyte='0'+optionsbyte

        payload.append(bitstobytes(optionsbyte)[0])

        darktime=convlen(darktime,24)
        darktime=bitstobytes(darktime)
        for i in darktime:
            payload.append(i)

        triggerout=convlen(not triggerout,8)
        triggerout=bitstobytes(triggerout)
        for i in triggerout:
            payload.append(i)

        patind=convlen(patind,11)
        bitpos=convlen(bitpos,5)
        lastbits=bitpos+patind
        lastbits=bitstobytes(lastbits)
        for i in lastbits:
            payload.append(i)


        self.command('w',0x00,0x1a,0x34,payload)
#         self.checkforerrors()
        
    def setbmp(self,index,size):
        payload=[]

        index=convlen(index,5)
        index='0'*11+index
        index=bitstobytes(index)
        for i in index:
            payload.append(i) 


        total=convlen(size,32)
        total=bitstobytes(total)
        for i in total:
            payload.append(i)         
        
        self.command('w',0x00,0x1a,0x2a,payload)

#         self.checkforerrors()
    def bmpload(self,image,size):

        t=time.clock()

        packnum=int(size//504)+1

        counter=0

        for i in range(packnum):
            
            if i %100==0:
                print (i,packnum)
                
            payload=[]
            
            if i<packnum-1:
                leng=convlen(504,16)
                bits=504
            else:
                leng=convlen(size%504,16)
                bits=size%504
                
            leng=bitstobytes(leng)
            
            for j in range(2):
                payload.append(leng[j])
                
            for j in range(bits):
                payload.append(image[counter])
                counter+=1
                
            self.command('w',0x11,0x1a,0x2b,payload) #0x11 is for a response, IDK if we need it
            

#             self.checkforerrors()
            
        print("Time for loading: ", time.clock()-t)

    def defsequence(self,images,exp,ti,dt,to,rep):

        self.stopsequence()

        arr=[]

        for i in images:
            arr.append(i)


        num=len(arr)

        encodedimages=[]
        sizes=[]
        t=time.clock()
        
        self.configurelut(num,rep)
        
        for i in range(int((num-1)//24)+1):
            print ('merging...')
            if i<(int((num-1)//24)):
                imagedata=mergeimages(arr[i*24:(i+1)*24])
            else:
                imagedata=mergeimages(arr[i*24:])
            

            print('encoding...')
            
            imagedata,size=new_encode(imagedata)
            

            encodedimages.append(imagedata)
            sizes.append(size)

            if i<(int((num-1)//24)):
                for j in range(i*24,(i+1)*24):
                    self.definepattern(j,exp[j],1,'111',ti[j],dt[j],to[j],i,j-i*24)
            else:
                for j in range(i*24,num):
                    self.definepattern(j,exp[j],1,'111',ti[j],dt[j],to[j],i,j-i*24)
        
        print ("Time for merging and encoding: ", time.clock()-t)
        

        for i in range(int((num-1)//24)+1): #for i in range(len(encodedimages)) should work?
            self.setbmp(int((num-1)//24)-i,sizes[int((num-1)//24)-i])
            print ('uploading...')
            self.bmpload(encodedimages[int((num-1)//24)-i],sizes[int((num-1)//24)-i])
            
        print ("Total time: ", time.clock()-t)


def convlen(a,l):
    """
    This function converts a number "a" into a bit string of
    length "l".
    """
    b=bin(a)[2:]
    padding=l-len(b)
    b='0'*padding+b

    return b

def bitstobytes(a):
    """
    This function converts a bit string into a given nuymber of bytes
    """
    bytelist=[]
    
    if len(a)%8!=0: #if length is not a multiple of 8, make it a multiple.
        padding=8-len(a)%8
        a='0'*padding+a
        
    for i in range(int(len(a)//8)): #put the bit in an array of byte
        bytelist.append(int(a[8*i:8*(i+1)],2))

    bytelist.reverse() #reverse the list

    return bytelist

def mergeimages(images):
    """
    function that encodes a 8 bit numpy array matrix as a enhanced run length encoded string of bits
    """
    mergedimage=numpy.zeros((1080,1920,3),dtype='uint8') #put this as numpy.uint8?

    for i in range(len(images)):
        
        if i<8:
            mergedimage[:,:,2]=mergedimage[:,:,2]+images[i]*(2**i) #with the multiplication, the 8 bit pixel contains the info abopu all the 8 images (if we are in binary...)

        if i>7 and i<16:
            mergedimage[:,:,1]=mergedimage[:,:,1]+images[i]*(2**(i-8))

        if i>15 and i<24: #maybe 24 because in RGB you have 8*3
            mergedimage[:,:,0]=mergedimage[:,:,0]+images[i]*(2**(i-16))
            
    return mergedimage

def new_encode(image):


## header creation
    bytecount=48    
    bitstring=[]

    bitstring.append(0x53)
    bitstring.append(0x70)
    bitstring.append(0x6c)
    bitstring.append(0x64)
    
    width=convlen(1920,16)
    width=bitstobytes(width)
    for i in width:
        bitstring.append(i)

    height=convlen(1080,16)
    height=bitstobytes(height)
    for i in height:
        bitstring.append(i)


    total=convlen(0,32)
    total=bitstobytes(total)
    for i in total:
        bitstring.append(i)        

    for i in range(8):
        bitstring.append(0xff)

    for i in range(4):    ## black curtain
        bitstring.append(0x00)

    bitstring.append(0x00)

    bitstring.append(0x02) ## enhanced rle

    bitstring.append(0x01)

    for i in range(21):
        bitstring.append(0x00)

    n=0
    i=0
    j=0

    while i <1080:

        while j <1920:

            if i>0:
                if numpy.all(image[i,j,:]==image[i-1,j,:]):
                    while j<1920 and numpy.all(image[i,j,:]==image[i-1,j,:]):
                        n=n+1
                        j=j+1
                        
    
                    bitstring.append(0x00)
                    bitstring.append(0x01)
                    bytecount+=2
                    
                    if n>=128:
                        byte1=(n & 0x7f)|0x80
                        byte2=(n >> 7)
                        bitstring.append(byte1)
                        bitstring.append(byte2)
                        bytecount+=2
                        
                    else:
                        bitstring.append(n)
                        bytecount+=1
                    n=0

            
                else:
                    if j < 1919: #1919 since I compare j and j+1 pixel
                        if numpy.all(image[i,j,:]==image[i,j+1,:]):
                            n=n+1
                    
                            while j<1919 and numpy.all(image[i,j,:]==image[i,j+1,:]):
                                n=n+1
                                j=j+1
                            if n>=128:
                                byte1=(n & 0x7f)|0x80
                                byte2=(n >> 7)
                                bitstring.append(byte1)
                                bitstring.append(byte2)
                                bytecount+=2
                                
                            else:
                                bitstring.append(n)
                                bytecount+=1
        
                            bitstring.append(image[i,j-1,0])
                            bitstring.append(image[i,j-1,1])
                            bitstring.append(image[i,j-1,2])
                            bytecount+=3
                            
                            j=j+1
                            n=0
                        elif j > 1917 or numpy.all(image[i,j+1,:]==image[i,j+2,:]) or numpy.all(image[i,j+1,:]==image[i-1,j+1,:]):
                            bitstring.append(0x01)
                            bytecount+=1
                            bitstring.append(image[i,j,0])
                            bitstring.append(image[i,j,1])
                            bitstring.append(image[i,j,2])
                            bytecount+=3
                            
                            j=j+1
                            n=0
                        else:
                            bitstring.append(0x00)
                            bytecount+=1
    
                            toappend=[]
    
                            while j<1919 and numpy.any(image[i,j,:]!=image[i,j+1,:]):

                                """
                                I've moved the j<1919 condition as first condition since sometimes it
                                tries to read image array at wrong index.
                                """
                                n=n+1
                                toappend.append(image[i,j,0])
                                toappend.append(image[i,j,1])
                                toappend.append(image[i,j,2])
                                j=j+1
                                
                            if n>=128:
                                byte1=(n & 0x7f)|0x80
                                byte2=(n >> 7)
                                bitstring.append(byte1)
                                bitstring.append(byte2)
                                bytecount+=2
    
                            else:
                                bitstring.append(n)
                                bytecount+=1
    
    
                            for k in toappend:
                                bitstring.append(k)
                                bytecount+=1
                            #j=j+1
                            n=0                           
                    elif j == 1919:
                        
                        bitstring.append(0x01)
                        bytecount+=1
                        bitstring.append(image[i,j,0])
                        bitstring.append(image[i,j,1])
                        bitstring.append(image[i,j,2])
                        bytecount+=3
                        
                        j=j+1
                        n=0
            else:
                
                if j < 1919: #1919 since I compare j and j+1 pixel
                
                    if numpy.all(image[i,j,:]==image[i,j+1,:]):
                        n=n+1
                
                        while j<1919 and numpy.all(image[i,j,:]==image[i,j+1,:]):
                            n=n+1
                            j=j+1
                        if n>=128:
                            byte1=(n & 0x7f)|0x80
                            byte2=(n >> 7)
                            bitstring.append(byte1)
                            bitstring.append(byte2)
                            bytecount+=2
                            
                        else:
                            bitstring.append(n)
                            bytecount+=1
    
                        bitstring.append(image[i,j-1,0])
                        bitstring.append(image[i,j-1,1])
                        bitstring.append(image[i,j-1,2])
                        bytecount+=3
                        
                        j=j+1
                        n=0
                    elif j > 1917 or numpy.all(image[i,j+1,:]==image[i,j+2,:]) or numpy.all(image[i,j+1,:]==image[i-1,j+1,:]):
                        bitstring.append(0x01)
                        bytecount+=1
                        bitstring.append(image[i,j,0])
                        bitstring.append(image[i,j,1])
                        bitstring.append(image[i,j,2])
                        bytecount+=3
                        
                        j=j+1
                        n=0
                    else:
                        bitstring.append(0x00)
                        bytecount+=1

                        toappend=[]

                        while j<1919 and numpy.any(image[i,j,:]!=image[i,j+1,:]):

                            """
                            I've moved the j<1919 condition as first condition since sometimes it
                            tries to read image array at wrong index.
                            """
                            n=n+1
                            toappend.append(image[i,j,0])
                            toappend.append(image[i,j,1])
                            toappend.append(image[i,j,2])
                            j=j+1
                            
                        if n>=128:
                            byte1=(n & 0x7f)|0x80
                            byte2=(n >> 7)
                            bitstring.append(byte1)
                            bitstring.append(byte2)
                            bytecount+=2

                        else:
                            bitstring.append(n)
                            bytecount+=1


                        for k in toappend:
                            bitstring.append(k)
                            bytecount+=1
                        #j=j+1
                        n=0                           
                elif j == 1919:
                    
                    bitstring.append(0x01)
                    bytecount+=1
                    bitstring.append(image[i,j,0])
                    bitstring.append(image[i,j,1])
                    bitstring.append(image[i,j,2])
                    bytecount+=3
                    
                    j=j+1
                    n=0
    
        j=0
        i=i+1
        bitstring.append(0x00)
        bitstring.append(0x00)
        bytecount+=2
    bitstring.append(0x00)
    bitstring.append(0x01)
    bitstring.append(0x00)
    bytecount+=3


    while (bytecount)%4!=0:
        bitstring.append(0x00)
        bytecount+=1        

    size=bytecount

    print (size)

    total=convlen(size,32)
    total=bitstobytes(total)
    for i in range(len(total)):
        bitstring[i+8]=total[i]    
    
    for i in bitstring:
        print(i)
    return bitstring, bytecount

    


if __name__ == "__main__":
    
    hiddev = DmdDeviceHID()

    import PIL.Image

    try:
        images=[]
         
        directory_in_str = "X:\\DMD\\Patterns\\DMD_patterns\\bin_sinusoidal_pattern\\"
        directory = os.fsencode(directory_in_str)
        i = 0
        for file in sorted(os.listdir(directory)):
            filename = os.fsdecode(file)
            if filename.endswith("320.png"):

                arr = numpy.asarray(PIL.Image.open(directory_in_str+filename), dtype = numpy.bool)
                images.append(arr)
                i += 1
            if i > 1:
                break
     
        hiddev.changemode(3)
        
        exposure=[1000000]*len(images)
        dark_time=[0]*len(images)
        trigger_in=[False]*len(images)
        trigger_out=[True]*len(images)
        
        hiddev.defsequence(images,exposure,trigger_in,dark_time,trigger_out, 60)
        
        hiddev.startsequence()
        work = "y"
        while work != "n":
            work = input()
    finally:
        hiddev.stopsequence()
        print("stopped")

Thank you,

Michele

  • Hi Michele,

    Which particular command is not working. Do you read status to check command fail or success?

    -ykc
  • Hi,

    I am not able to read any data from the device since, when I use the read command of the library, the software freezes, so for the moment I simply put under the carpet the reading part of the software, trying to work on the writing part. Is it mandatory to read after write?

    Thank you,

    EDIT: for the reading I think it's just a problem with the flag string, so now I am going to change the code for reading from the device. When I do it, what I have to check in the error string?


    Michele

  • import pywinusb.hid as hid
    import time
    from ctypes import *
    
    gl_resp_rcvd = False
    gl_resp_buf = []
    dict_disp_mode = {'VIDEO': 0,
                      'PRE_STORE': 1,
                      'VIDEO_PAT': 2,
                      'PAT_FLY': 3}
    
    dict_start = {'STOP': 0,
                    'PAUSE': 1,
                    'START': 2}
    
    dict_power = {'NORMAL': 0,
                    'STANDBY': 1,
                    'SW_RESET': 2}
    
    dict_abs_idx = {'CMD_PARAM': 7,
                    'RD_PAYLOAD':5}
    dict_rw = { 'WR': 0,
               'RD': 1}
    
    dict_reply = { 'NO_REPLY': 0,
                'YES_REPLY': 1}
    
    dict_nack = { 'ACK': 0,
                'NACK': 1}
    
    dict_dest = { 'PROJCTRL': 0,
                 'RFC': 1,
                 'DBG_MSG': 2}
    
    
    class HDR_BITS(LittleEndianStructure):
        _fields_ = [("dest", c_ubyte, 3),
                    ("reserved", c_ubyte, 2),
                    ("nack", c_ubyte, 1),
                    ("reply", c_ubyte, 1),
                    ("rw", c_ubyte, 1)]
    
    class HDR_FLAGS(Union):
        _fields_ = [("bits", HDR_BITS),
                    ("val", c_ubyte)]
    
    class HDR(Structure):
        _pack_ = 1
        _fields_ = [("report_id", c_ubyte),
                    ("flags", HDR_FLAGS),
                    ("seq", c_ubyte),
                    ("length", c_ushort)]
    
    class CMD_DATA(Union):
        _fields_ = [("cmd", c_ushort),
                    ("data", c_ubyte * 512)]
    
    class UF_USHORT(LittleEndianStructure):
        _fields_ = [("val", c_ushort)]
    
    class HID_MSG(Structure):
        _pack_ = 1
        _fields_ = [("head", HDR),
                    ("text", CMD_DATA)]
    
    dict_cmd_pos = {
        "I2C_CMD" : 0,
        "USBCMD" : 1,
        "LEN" : 2,
        "VAR_LEN" : 3,
    }
    
    dict_cmdlist ={
        "SOURCE_SEL":               (0x00, 0x1A00, 0x01, 0 ),
        "PIXEL_FORMAT":             (0x02, 0x1A02, 0x01, 0 ),
        "CLK_SEL":                  (0x03, 0x1A03, 0x01, 0 ),
        "CHANNEL_SWAP":             (0x04, 0x1A37, 0x01, 0 ),
        "FPD_MODE":                 (0x05, 0x1A04, 0x01, 0 ),
        "POWER_CONTROL":            (0x07, 0x0200, 0x01, 0 ),
        "FLIP_LONG":                (0x08, 0x1008, 0x01, 0 ),
        "FLIP_SHORT":               (0x09, 0x1009, 0x01, 0 ),
        "TPG_SEL":                  (0x0A, 0x1203, 0x01, 0 ),
        "PWM_INVERT":               (0x0B, 0x1A05, 0x01, 0 ),
        "LED_ENABLE":               (0x10, 0x1A07, 0x01, 0 ),
        "GET_VERSION":              (0x11, 0x0205, 0x00, 0 ),
        "SW_RESET":                 (0x13, 0x0802, 0x01, 0 ),
        "DMD_PARK":                 (0x14, 0x0609, 0x01, 0 ),
        "STATUS_HW":                (0x20, 0x1A0A, 0x00, 0 ),
        "STATUS_SYS":               (0x21, 0x1A0B, 0x00, 0 ),
        "STATUS_MAIN":              (0x22, 0x1A0C, 0x00, 0 ),
        "PWM_ENABLE":               (0x40, 0x1A10, 0x01, 0 ),
        "PWM_SETUP":                (0x41, 0x1A11, 0x06, 0 ),
        "PWM_CAPTURE_CONFIG":       (0x43, 0x1A12, 0x05, 0 ),
        "GPIO_CONFIG":              (0x44, 0x1A38, 0x02, 0 ),
        "LED_CURRENT":              (0x4B, 0x0B01, 0x03, 0 ),
        "DISP_CONFIG":              (0x7E, 0x1000, 0x10, 0 ),
        "DISP_MODE":                (0x69, 0x1A1B, 0x01, 0 ),
        "TRIG_OUT1_CTL":            (0x6A, 0x1A1D, 0x05, 0 ),
        "TRIG_OUT2_CTL":            (0x6B, 0x1A1E, 0x05, 0 ),
        "RED_LED_ENABLE_DLY":       (0x6C, 0x1A1F, 0x04, 0 ),
        "GREEN_LED_ENABLE_DLY":     (0x6D, 0x1A20, 0x04, 0 ),
        "BLUE_LED_ENABLE_DLY":      (0x6E, 0x1A21, 0x04, 0 ),
        "PAT_START_STOP":           (0x65, 0x1A24, 0x01, 0 ),
        "TRIG_IN1_CTL":             (0x79, 0x1A35, 0x03, 0 ),
        "TRIG_IN2_CTL":             (0x7A, 0x1A36, 0x01, 0 ),
        "INVERT_DATA":              (0x74, 0x1A30, 0x01, 0 ),
        "PAT_CONFIG":               (0x75, 0x1A31, 0x06, 0 ),
        "MBOX_ADDRESS":             (0x76, 0x1A32, 0x02, 0 ),
        "MBOX_CONTROL":             (0x77, 0x1A33, 0x01, 0 ),
        "MBOX_DATA":                (0x78, 0x1A34, 0x0C, 0 ),
        "SPLASH_LOAD":              (0x7F, 0x1A39, 0x01, 0 ),
        "GPCLK_CONFIG":             (0x48, 0x0807, 0x03, 0 ),
        "TPG_COLOR":                (0x1A, 0x1204, 0x0C, 0 ),
        "PWM_CAPTURE_READ":         (0x4E, 0x1A13, 0x05, 0 ),
        "I2C_PASSTHRU":             (0x4F, 0x1A4F, 0x05, 2 ),
        "PATMEM_LOAD_INIT_MASTER":  (0x2A, 0x1A2A, 0x06, 0 ),
        "PATMEM_LOAD_DATA_MASTER":  (0x2B, 0x1A2B, 0x00, 2 ),
        "PATMEM_LOAD_INIT_SLAVE":   (0x2C, 0x1A2C, 0x06, 0 ),
        "PATMEM_LOAD_DATA_SLAVE":   (0x2D, 0x1A2D, 0x00, 2 ),
        "BATCHFILE_NAME":           (0x3A, 0x1A14, 0x01, 0 ),
        "BATCHFILE_EXECUTE":        (0x3B, 0x1A15, 0x01, 0 ),
        "DELAY":                    (0x3C, 0x1A16, 0x04, 0 ),
        "DEBUG":                    (0x00, 0x1A5B, 0x05, 0 ),
        "I2C_CONFIG":               (0x45, 0x1A4E, 0x05, 0 ),
        "CURTAIN_COLOR":            (0x06, 0x1100, 0x06, 0 ),
        "VIDEO_CONT_SEL":           (0x0C, 0x1A01, 0x01, 0 ),
        "READ_ERROR_CODE":          (0x32, 0x0100, 0x01, 0 ),
        "READ_ERROR_MSG":           (0x33, 0x0101, 0x80, 0 ),
        "READ_FRMW_VERSION":        (0x12, 0x0206, 0x21, 0 ),
        "DMD_BLOCKS":               (0x60, 0x1A40, 0x02, 0 ),
        "DMD_IDLE":                 (0x0D, 0x0201, 0x01, 0 ),
        "LED_PULSE_WIDTH":          (0x62, 0x1A41, 0x02, 0 ),
        "MIN_EXPOSURE":             (0x63, 0x1A42, 0x02, 0 ),
        "BL_STATUS":                (0x01, 0x0000, 0x00, 0 ),
        "BL_SPL_MODE":              (0x23, 0x0023, 0x01, 0 ),
        "BL_GET_FLASH_PRESENT":     (0x0B, 0x0015, 0x01, 0 ),
        "BL_GET_MANID":             (0x0C, 0x0015, 0x01, 0 ),
        "BL_GET_DEVID":             (0x0D, 0x0015, 0x01, 0 ),
        "BL_GET_CHKSUM":            (0x00, 0x0015, 0x01, 0 ),
        "BL_SET_SECTADDR":          (0x29, 0x0029, 0x04, 0 ),
        "BL_SECT_ERASE":            (0x28, 0x0028, 0x00, 0 ),
        "BL_SET_DNLDSIZE":          (0x2C, 0x002C, 0x04, 0 ),
        "BL_DNLD_DATA":             (0x25, 0x0025, 0x00, 0 ),
        "BL_FLASH_TYPE":            (0x2F, 0x002F, 0x01, 0 ),
        "BL_CALC_CHKSUM":           (0x26, 0x0026, 0x00, 0 ),
        "BL_PROG_MODE":             (0x30, 0x0030, 0x01, 0 ),
        "BL_MASTER_SLAVE":          (0x31, 0x0031, 0x01, 0 ),
        "BL_SET_SECTADDR_4BYTE":    (0x32, 0x0032, 0x04, 0 ),
        "BL_SET_DNLDSIZE_4BYTE":    (0x33, 0x0033, 0x04, 0)
    }
    
    list_mbox_data_4 = [
    [0x00, 0x00, 0x40, 0x42, 0x0F, 0x17, 0x40, 0x42, 0x0F, 0x00, 0x00, 0x00],
    [0x01, 0x00, 0x40, 0x42, 0x0F, 0x17, 0x40, 0x42, 0x0F, 0x00, 0x00, 0x20],
    [0x02, 0x00, 0x40, 0x42, 0x0F, 0x17, 0x40, 0x42, 0x0F, 0x00, 0x00, 0x40],
    [0x03, 0x00, 0x40, 0x42, 0x0F, 0x17, 0x40, 0x42, 0x0F, 0x00, 0x00, 0x60],
    ]
    
    list_pat_cfg_4 = [0x04, 0x00, 0x00, 0x00, 0x00, 0x00]
    
    list_mbox_data = [
    [0x00, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x00, 0x00],
    [0x01, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x00, 0x20],
    [0x02, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x00, 0x40],
    [0x03, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x00, 0x60],
    [0x04, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x00, 0x80],
    [0x05, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x00, 0xA0],
    [0x06, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x01, 0x00],
    [0x07, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x01, 0x20],
    [0x08, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x01, 0x40],
    [0x09, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x01, 0x60],
    [0x0A, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x01, 0x80],
    [0x0B, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x01, 0xA0],
    [0x0C, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x02, 0x00],
    [0x0D, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x02, 0x20],
    [0x0E, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x02, 0x40],
    [0x0F, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x02, 0x60],
    [0x10, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x02, 0x80],
    [0x11, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x02, 0xA0],
    [0x12, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x03, 0x00],
    [0x13, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x03, 0x20],
    [0x14, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x03, 0x40],
    [0x15, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x03, 0x60],
    [0x16, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x03, 0x80],
    [0x17, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x03, 0xA0],
    [0x18, 0x00, 0x40, 0x42, 0x0F, 0x27, 0x20, 0xA1, 0x07, 0x00, 0x04, 0x00]
    ]
    
    list_pat_cfg = [0x19, 0x00, 0x00, 0x00, 0x00, 0x00]
    
    seq_number = 0
    def prep_write_cmd(cmd, param=None, reply="YES_REPLY", dest="PROJCTRL"):
        if cmd in dict_cmdlist:
            hid_msg = HID_MSG()
            hid_msg.head.flags.bits.rw = dict_rw["WR"]
            hid_msg.head.flags.bits.reply = dict_reply[reply]
            hid_msg.head.flags.bits.dest = dict_dest[dest]
            global seq_number
            temp = c_ubyte(seq_number)
            hid_msg.head.seq = temp
            seq_number = temp.value
            seq_number += 1
            hid_msg.text.cmd = dict_cmdlist[cmd][dict_cmd_pos["USBCMD"]]
            hid_msg.head.length = dict_cmdlist[cmd][dict_cmd_pos["LEN"]] + 2
            if param is not None:
                hid_msg.text.data = param
            return hid_msg
        else:
            raise ValueError("Unknown command")
    
    def prep_read_cmd(cmd, param=None, reply="YES_REPLY", dest="PROJCTRL"):
        if cmd in dict_cmdlist:
            hid_msg = HID_MSG()
            hid_msg.head.flags.bits.rw = dict_rw["RD"]
            hid_msg.head.flags.bits.reply = dict_reply[reply]
            hid_msg.head.flags.bits.dest = dict_dest[dest]
            global seq_number
            temp = c_ubyte(seq_number)
            hid_msg.head.seq = temp
            seq_number = temp.value
            seq_number += 1
            hid_msg.text.cmd = dict_cmdlist[cmd][dict_cmd_pos["USBCMD"]]
            hid_msg.head.length = 2
    
            if param is not None:
                hid_msg.text.data[2] = c_ubyte(param);
                hid_msg.head.length = 3;
                return hid_msg
    
            if cmd == "BL_GET_FLASH_PRESENT":
                hid_msg.text.data[2] = 0x0B;
                hid_msg.head.length = 3;
            elif cmd == "BL_GET_MANID":
                hid_msg.text.data[2] = 0x0C;
                hid_msg.head.length = 3;
            elif cmd == "BL_GET_DEVID":
                hid_msg.text.data[2] = 0x0D;
                hid_msg.head.length = 3;
            elif cmd == "BL_GET_CHKSUM":
                hid_msg.text.data[2] = 0x00;
                hid_msg.head.length = 3;
    
            return hid_msg
        else:
            raise ValueError("Unknown command")
    
    def get_devices(vid, pid):
        return hid.HidDeviceFilter(vendor_id = vid,
                                   product_id = pid).get_devices()
    
    # Returns a dictionary parent, hid items
    def get_devices_by_parent(vid, pid):
        return hid.HidDeviceFilter(vendor_id = vid,
                                   product_id = pid).get_devices_by_parent()
    
    def read_values(target_usage):
        """read feature report values"""
        # browse all devices
        all_devices = hid.HidDeviceFilter(vendor_id = target_vendor_id, product_id = target_product_id).get_devices()
    
        if not all_devices:
            print("Can't find any TI HID device connected")
        else:
            # search for our target usage
            usage_found = False
            for device in all_devices:
                try:
                    device.open()
                    # browse feature reports
                    for report in device.find_feature_reports():
                        if target_usage in report:
                            # we found our usage
                            report.get()
                            # print result
                            print("The value:", list(report[target_usage]))
                            print("All the report: {0}".format(report.get_raw_data()))
                            usage_found = True
                finally:
                    device.close()
            if not usage_found:
                print("The target device was found, but the requested usage does not exist!\n")
        #
    
    def sample_handler(data):
        global gl_resp_buf
        gl_resp_buf = bytearray(byte for byte in data)
        global gl_resp_rcvd
        gl_resp_rcvd = True
        #  print_resp(bytearray(byte for byte in data))
    
    def check_prep():
        hid_msg = prep_write_cmd("STATUS_MAIN")
        buffer = bytearray(hid_msg)
        print_buffer(buffer)
    
    def print_raw_buf(buffer):
        for byte in buffer:
            print(hex(byte) + " ", end='')
        print()
    
    def key_fvalue(dictn, value):
        return list(dictn.keys())[list(dictn.values()).index(value)]
    
    def print_s(input):
        print(str(input), end= ' ')
    
    def get_cmd_name(buffer):
        cmd = UF_USHORT.from_buffer(buffer[5:7])
        for name, values in dict_cmdlist.items():
            if values[1] == cmd.val:
                return name
        raise ValueError(" Command name not found " + str(hex(cmd.val)))
    
    
    def print_buf(buffer, name):
        actual_name = name
        flags = HDR_FLAGS()
        flags.val = buffer[1]
        if name == "Cmd":
            name = " " +  get_cmd_name(buffer) + " "
        else:
            name = " "
        print_s(actual_name + "-> " + str(buffer[2]) + name)
        print_s(key_fvalue(dict_rw, flags.bits.rw))
        print_s(key_fvalue(dict_reply, flags.bits.reply))
        print_s(key_fvalue(dict_nack, flags.bits.nack))
        print_s(key_fvalue(dict_dest, flags.bits.dest))
        head = HDR.from_buffer(buffer)
        print(str(head.length) + "b")
        if actual_name == "Cmd":
            end_idx = head.length + 7 - 2
            if end_idx != 7:
                print_s("   ")
                print_raw_buf(buffer[7:end_idx])
        else:
            print_s("   ")
            end_idx = 5 + head.length
            print_raw_buf(buffer[5:end_idx])
    
    def print_resp(buffer):
        print_buf(buffer, "Res")
        print()
    
    def print_cmd(buffer):
        print_buf(buffer, "Cmd")
    
    def send_cmd(report, buffer, print_buf=True, wait_infinite=True):
        #  print(len(buffer))
        #  print_raw_buf(buffer)
        if print_buf:
            print_cmd(buffer)
        global gl_resp_rcvd
        gl_resp_rcvd = False
        report.send(buffer)
    
        if wait_infinite:
            while gl_resp_rcvd is not True:
                pass
        else:
            start_time = time.time()
            while gl_resp_rcvd is not True and time.time() - start_time < 5:
                pass
    
        if gl_resp_rcvd:
            if print_buf:
                print_resp(gl_resp_buf)
            flags = HDR_FLAGS()
            flags.val = gl_resp_buf[1]
            result = key_fvalue(dict_nack, flags.bits.nack)
            if result == "ACK":
                return True
            else:
                return False
        else:
            return False
    
    
    def set_disp_mode(report, param="PAT_FLY"):
        hid_msg = prep_write_cmd("DISP_MODE")
        buffer = bytearray(hid_msg)[0:65]
        buffer[dict_abs_idx['CMD_PARAM']]= dict_disp_mode[param]
        return send_cmd(report, buffer)
    
    def set_start_stop(report, param="START"):
        hid_msg = prep_write_cmd("PAT_START_STOP")
        buffer = bytearray(hid_msg)[0:65]
        buffer[dict_abs_idx['CMD_PARAM']]= dict_start[param]
        return send_cmd(report, buffer)
    
    def set_power(report, param="NORMAL"):
        hid_msg = prep_write_cmd("POWER_CONTROL")
        buffer = bytearray(hid_msg)[0:65]
        buffer[dict_abs_idx['CMD_PARAM']]= dict_power[param]
        #  buffer[2] = 0x1e
        #  print_raw_buf(buffer)
        return send_cmd(report, buffer)
    
    def read_power(report):
        hid_msg = prep_read_cmd("POWER_CONTROL")
        buffer = bytearray(hid_msg)[0:65]
        #  buffer[dict_abs_idx['CMD_PARAM']]= dict_power[param]
        if send_cmd(report, buffer):
            global gl_resp_buf
            val = gl_resp_buf[dict_abs_idx["RD_PAYLOAD"]]
            if val == 0:
                return "NORMAL"
            elif val == 1:
                return "STANDBY"
            else:
                return "SW_RESET"
        else:
            raise RuntimeError("Read power failed")
    
    def set_lut(report, count=0):
        param_idx = dict_abs_idx['CMD_PARAM']
        if count == 0:
            cmds_count = len(list_mbox_data)
        else:
            cmds_count = count
        for i in range(0, cmds_count):
            hid_msg = prep_write_cmd("MBOX_DATA")
            buffer = bytearray(hid_msg)[0:65]
            buffer[param_idx:param_idx + 12]= list_mbox_data[i][0:12]
            send_cmd(report, buffer, print_buf=False)
    
    # Max image count for now is 255
    def set_pat_config(report, count=0, repeat=False):
        if count == 0:
            cmds_count = len(list_mbox_data)
        else:
            cmds_count = count
    
        param_idx = dict_abs_idx['CMD_PARAM']
        hid_msg = prep_write_cmd("PAT_CONFIG")
        buffer = bytearray(hid_msg)[0:65]
        buffer[param_idx:param_idx + 6]= list_pat_cfg[0:6]
        buffer[param_idx] = cmds_count
        if repeat:
            buffer[param_idx + 2] = 0
        else:
            buffer[param_idx + 2] = cmds_count
        send_cmd(report, buffer)
    
    reorder_list = [0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
                      0x18, 0x00, 0x17, 0x00, 0x16, 0x00,
                      0x15, 0x00, 0x14, 0x00, 0x13, 0x00, 0x12, 0x00,
                      0x11, 0x00, 0x10, 0x00, 0x0f, 0x00, 0x0e, 0x00,
                      0x0d, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x0a, 0x00,
                      0x09, 0x00, 0x08, 0x00, 0x07, 0x00, 0x06, 0x00,
                      0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00,
                      0x01, 0x00, 0x00, 0x00]
    def set_reorder(report, tc_count=0):
        r_list = reorder_list
        if tc_count == 0:
            payload_len = len(reorder_list)
        else:
            payload_len = 6 + 2 * tc_count
            r_list[0] = tc_count
            r_list[6: payload_len -6] = reorder_list[6 + (25 - tc_count)*2:]
    
        param_idx = dict_abs_idx['CMD_PARAM']
        hid_msg = prep_write_cmd("MBOX_ADDRESS")
        hid_msg.head.length = 2 + payload_len
        buffer = bytearray(hid_msg)[0:65]
        buffer[param_idx:param_idx + payload_len] = r_list[0:payload_len]
        send_cmd(report, buffer)
    
    
    # tc_81 Test sequence reorder command
    def tc_81(report, tc_count=25):
    
        set_start_stop(report, param="STOP")
        set_disp_mode(report, param="PRE_STORE")
        set_lut(report, count=tc_count)
        set_pat_config(report, count=tc_count)
        set_start_stop(report, param="START")
        time.sleep(tc_count + tc_count/2 + 2)
        set_start_stop(report, param="STOP")
        time.sleep(5)
        set_reorder(report, tc_count)
        set_start_stop(report, param="START")
        time.sleep(tc_count + tc_count/2 + 2)
    
    
    
    # tc_116 Issue normal mode when already in normal mode cause standby
    def tc_116(report):
        tc_count = 0
    
        set_disp_mode(report, param="PRE_STORE")
        set_lut(report, count=tc_count)
        set_pat_config(report, count=tc_count)
    
        if read_power(report) == "STANDBY":
            set_power(report, param="STANDBY")
            time.sleep(0.3)
        else:
            # Here normal commnad should be ignored if already in normal mode
            set_power(report, param="NORMAL")
            time.sleep(0.3)
    
            set_start_stop(report, param="START")
            if tc_count == 0:
                time.sleep(0.35*len(list_mbox_data))
            else:
                time.sleep(0.35*tc_count)
    
    
    
    # tc_119 Hang after normal/standby cycles
    # Load base image with patterns only from settings.txt file
    def tc_119(report, tc_count=1, iter_count=500):
        if read_power(report) == "STANDBY":
            set_power(report, param="NORMAL")
            time.sleep(5)
    
        for i in range(1, iter_count):
            print("Iteration: " + str(i))
            if read_power(report) == "STANDBY":
                set_power(report, param="NORMAL")
                time.sleep(0.3)
    
            set_disp_mode(report, param="PRE_STORE")
            set_lut(report, count=tc_count)
            set_pat_config(report, count=tc_count)
    
            set_start_stop(report, param="START")
            if tc_count == 0:
                time.sleep(0.35*len(list_mbox_data))
            else:
                time.sleep(0.35*tc_count)
            set_power(report, param="STANDBY")
    
    # tc_debug Gui not working but composer working
    # Problem with interface
    def tc_debug(report):
            set_power(report, param="NORMAL")
            time.sleep(0.3)
    
    if __name__ == '__main__':
        ti_devs = get_devices(0x0451, 0xc900)
        if not ti_devs:
            print("Could not find dlpc900 device")
        print("No of devices found: " + str(len(ti_devs)))
        #  print("Devices:")
        #  print(ti_devs[0])
        #  print(ti_devs[1])
        device = ti_devs[0]
        for dev in ti_devs:
            if dev.product_name == "DLPC900":
                device = dev
        try:
            device.open()
            #  print(device)
            #  print(dir(device))
            print("Dev Opened: " + device.product_name)
            device.set_raw_data_handler(sample_handler)
            report = device.find_output_reports()
            #  print("Reports:")
            #  print(report)
            #  print(device.is_plugged())
    
            #  tc_119(report[0])
            #  tc_116(report[0])
            #  tc_debug(report[0])
            tc_81(report[0])
    
        except Exception as e:
            print(e)
            print("IO Exception occured")
        finally:
            device.close()
    
    
    
    

    Please check programmer's guide for details on error codes.

    I am attaching some sample code which I used long time back to test some commands. It was working fine.

  • Hi,

    Thank you very much (again), I have used your code (with some adjustments), and it works.

    Thank you very much,

    Michele