From e0b156d42eb2e1df29c1b02003a18e3becd1d4eb Mon Sep 17 00:00:00 2001 From: dylantubular <69211169+dylantubular@users.noreply.github.com> Date: Thu, 23 Nov 2023 10:21:30 -0600 Subject: [PATCH 1/2] adding support for SET_I2C_ADDRESS --- src/tfmpi2c/__init__.py | 63 +++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/src/tfmpi2c/__init__.py b/src/tfmpi2c/__init__.py index e1324c9..62e5e99 100644 --- a/src/tfmpi2c/__init__.py +++ b/src/tfmpi2c/__init__.py @@ -250,7 +250,7 @@ def getData(): # # Create a proper command byte array, send the command, # get a response, and return the status -def sendCommand( cmnd, param): +def sendCommand(cmnd, param=None): ''' Send command and get reply data''' # - - - - - - - - - - - - - - - - - - - - - - - - - @@ -267,16 +267,25 @@ def sendCommand( cmnd, param): # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # From 32bit 'cmnd' integer, create a four byte array of: # reply length, command length, command number and a one byte parameter - cmndData = bytearray( cmnd.to_bytes( TFMP_COMMAND_MAX, byteorder = 'little')) + cmndData = bytearray(cmnd.to_bytes(TFMP_COMMAND_MAX, byteorder = 'little')) # - replyLen = cmndData[ 0] # Save the first byte as reply length. - cmndLen = cmndData[ 1] # Save the second byte as command length. - cmndData[ 0] = 0x5A # Set the first byte to the HEADER code. + replyLen = cmndData[0] # Save the first byte as reply length. + cmndLen = cmndData[1] # Save the second byte as command length. + cmndData[0] = 0x5A # Set the first byte to the HEADER code. # - if( cmnd == SET_FRAME_RATE): # If the command is Set FrameRate... - cmndData[3:2] = param.to_bytes( 2, byteorder = 'little') # add the 2 byte FrameRate parameter. - elif( cmnd == SET_BAUD_RATE): # If the command is Set BaudRate... - cmndData[3:3] = param.to_bytes( 3, byteorder = 'little') # add the 3 byte BaudRate parameter. + + # check that param is not none if the cmd expects input + if cmnd in [SET_BAUD_RATE, SET_FRAME_RATE, SET_I2C_ADDRESS] and not param: + # NOTE: this is terrible as it doesn't provide any hint as to why it failed. This library + # could use a refactor to be more object oriented in the future, at that time fix this! + return False + + if cmnd == SET_FRAME_RATE: # If the command is Set FrameRate... + cmndData[3:2] = param.to_bytes(2, byteorder = 'little') # add the 2 byte FrameRate parameter. + elif cmnd == SET_BAUD_RATE: # If the command is Set BaudRate... + cmndData[3:3] = param.to_bytes(3, byteorder = 'little') # add the 3 byte BaudRate parameter. + elif cmnd == SET_I2C_ADDRESS: + cmndData[3:1] = param.to_bytes(1, byteorder = 'little') # add the 3 byte BaudRate parameter. # cmndData = cmndData[0:cmndLen] # re-establish length of command data array # @@ -285,23 +294,23 @@ def sendCommand( cmnd, param): # necessary, but the value is irrelevant.) chkSum = 0 # Add together all bytes but the last. - for i in range( cmndLen -1): - chkSum += cmndData[ i] + for i in range(cmndLen - 1): + chkSum += cmndData[i] # and save it as the last byte of command data. - cmndData[ cmndLen -1] = ( chkSum & 0xFF) + cmndData[cmndLen -1] = (chkSum & 0xFF) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - # - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Step 2 - Send the command data array to the device # - - - - - - - - - - - - - - - - - - - - - - - - - - - - cmndList = list(cmndData) - bus = SMBus( port) - bus.write_i2c_block_data( addr, 0, cmndList) + bus = SMBus(port) + bus.write_i2c_block_data(addr, 0, cmndList) bus.close() # # If the command does not expect a reply, then we're # finished here. Go home. - if( replyLen == 0): + if(replyLen == 0): return True # + + + + + + + + + + + + + + + + + + + + + + + + + @@ -311,8 +320,8 @@ def sendCommand( cmnd, param): # Give device a chance to fill its registers time.sleep(0.002) # Read block of data into declared list 'reply' - bus = SMBus( port) - reply = bus.read_i2c_block_data( addr, 0, replyLen) + bus = SMBus(port) + reply = bus.read_i2c_block_data(addr, 0, replyLen) bus.close() ''' @@ -329,26 +338,26 @@ def sendCommand( cmnd, param): # Declare and clear the 'chkSum' variable chkSum = 0 # Add together all bytes but the last. - for i in range( replyLen -1): - chkSum += reply[ i] + for i in range(replyLen - 1): + chkSum += reply[i] # If the low order byte does not equal the last byte... - if( ( chkSum & 0xff) != reply[ replyLen - 1]): + if((chkSum & 0xff) != reply[replyLen - 1]): status = TFMP_CHECKSUM # ...then set error return False # and return 'False.' # - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Step 5 - Interpret different command responses. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if( cmnd == OBTAIN_FIRMWARE_VERSION): + if(cmnd == OBTAIN_FIRMWARE_VERSION): version =\ - str( reply[ 5]) + '.' +\ - str( reply[ 4]) + '.' +\ - str( reply[ 3]) + str(reply[5]) + '.' +\ + str(reply[4]) + '.' +\ + str(reply[3]) else: - if( cmnd == SYSTEM_RESET or + if(cmnd == SYSTEM_RESET or cmnd == RESTORE_FACTORY_SETTINGS or - cmnd == SAVE_SETTINGS ): - if( reply[ 3] == 1): # If PASS/FAIL byte non-zero + cmnd == SAVE_SETTINGS): + if(reply[3] == 1): # If PASS/FAIL byte non-zero status = TFMP_FAIL # then set status to 'FAIL' return False # and return 'False'. From 25e9e9faf592d168807c015a789d3fcafb64fc7f Mon Sep 17 00:00:00 2001 From: dylantubular <69211169+dylantubular@users.noreply.github.com> Date: Fri, 24 Nov 2023 00:48:28 +0000 Subject: [PATCH 2/2] Fixing error state and some cleanup --- src/tfmpi2c/__init__.py | 71 +++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/src/tfmpi2c/__init__.py b/src/tfmpi2c/__init__.py index 62e5e99..4bd2e7c 100644 --- a/src/tfmpi2c/__init__.py +++ b/src/tfmpi2c/__init__.py @@ -95,6 +95,9 @@ def begin( portNumber, devAddress): TFMP_FLOOD = 12 # Ambient Light saturation TFMP_MEASURE = 13 +# Local Error Codes, starting at 50 to separate from the system codes above +TFMP_NOPARAM = 50 # Required param missing from sendCommand call + '''- - - - - - TFMini Plus data formats - - - - - - - - - Data Frame format: Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7 Byte8 @@ -250,7 +253,7 @@ def getData(): # # Create a proper command byte array, send the command, # get a response, and return the status -def sendCommand(cmnd, param=None): +def sendCommand( cmnd, param=None): ''' Send command and get reply data''' # - - - - - - - - - - - - - - - - - - - - - - - - - @@ -267,50 +270,49 @@ def sendCommand(cmnd, param=None): # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # From 32bit 'cmnd' integer, create a four byte array of: # reply length, command length, command number and a one byte parameter - cmndData = bytearray(cmnd.to_bytes(TFMP_COMMAND_MAX, byteorder = 'little')) + cmndData = bytearray( cmnd.to_bytes( TFMP_COMMAND_MAX, byteorder = 'little')) # - replyLen = cmndData[0] # Save the first byte as reply length. - cmndLen = cmndData[1] # Save the second byte as command length. - cmndData[0] = 0x5A # Set the first byte to the HEADER code. + replyLen = cmndData[ 0] # Save the first byte as reply length. + cmndLen = cmndData[ 1] # Save the second byte as command length. + cmndData[ 0] = 0x5A # Set the first byte to the HEADER code. # # check that param is not none if the cmd expects input - if cmnd in [SET_BAUD_RATE, SET_FRAME_RATE, SET_I2C_ADDRESS] and not param: - # NOTE: this is terrible as it doesn't provide any hint as to why it failed. This library - # could use a refactor to be more object oriented in the future, at that time fix this! + if cmnd in [ SET_BAUD_RATE, SET_FRAME_RATE, SET_I2C_ADDRESS] and not param: + status = TFMP_NOPARAM return False - if cmnd == SET_FRAME_RATE: # If the command is Set FrameRate... - cmndData[3:2] = param.to_bytes(2, byteorder = 'little') # add the 2 byte FrameRate parameter. - elif cmnd == SET_BAUD_RATE: # If the command is Set BaudRate... - cmndData[3:3] = param.to_bytes(3, byteorder = 'little') # add the 3 byte BaudRate parameter. - elif cmnd == SET_I2C_ADDRESS: - cmndData[3:1] = param.to_bytes(1, byteorder = 'little') # add the 3 byte BaudRate parameter. + if( cmnd == SET_FRAME_RATE): # If the command is Set FrameRate... + cmndData[ 3:2] = param.to_bytes( 2, byteorder = 'little') # add the 2 byte FrameRate parameter. + elif( cmnd == SET_BAUD_RATE): # If the command is Set BaudRate... + cmndData[ 3:3] = param.to_bytes( 3, byteorder = 'little') # add the 3 byte BaudRate parameter. + elif( cmnd == SET_I2C_ADDRESS): + cmndData[ 3:1] = param.to_bytes( 1, byteorder = 'little') # add the 3 byte BaudRate parameter. # - cmndData = cmndData[0:cmndLen] # re-establish length of command data array + cmndData = cmndData[ 0:cmndLen] # re-establish length of command data array # # Create a checksum for the last byte of the array # (Tests indicate the presence of the byte is # necessary, but the value is irrelevant.) chkSum = 0 # Add together all bytes but the last. - for i in range(cmndLen - 1): - chkSum += cmndData[i] + for i in range( cmndLen -1): + chkSum += cmndData[ i] # and save it as the last byte of command data. - cmndData[cmndLen -1] = (chkSum & 0xFF) + cmndData[ cmndLen -1] = ( chkSum & 0xFF) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - # - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Step 2 - Send the command data array to the device # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cmndList = list(cmndData) - bus = SMBus(port) - bus.write_i2c_block_data(addr, 0, cmndList) + cmndList = list( cmndData) + bus = SMBus( port) + bus.write_i2c_block_data( addr, 0, cmndList) bus.close() # # If the command does not expect a reply, then we're # finished here. Go home. - if(replyLen == 0): + if( replyLen == 0): return True # + + + + + + + + + + + + + + + + + + + + + + + + + @@ -318,10 +320,10 @@ def sendCommand(cmnd, param=None): # Step 3 - Get command reply data back from the device. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Give device a chance to fill its registers - time.sleep(0.002) + time.sleep( 0.002) # Read block of data into declared list 'reply' - bus = SMBus(port) - reply = bus.read_i2c_block_data(addr, 0, replyLen) + bus = SMBus( port) + reply = bus.read_i2c_block_data( addr, 0, replyLen) bus.close() ''' @@ -338,26 +340,26 @@ def sendCommand(cmnd, param=None): # Declare and clear the 'chkSum' variable chkSum = 0 # Add together all bytes but the last. - for i in range(replyLen - 1): - chkSum += reply[i] + for i in range( replyLen -1): + chkSum += reply[ i] # If the low order byte does not equal the last byte... - if((chkSum & 0xff) != reply[replyLen - 1]): + if(( chkSum & 0xff) != reply[ replyLen -1]): status = TFMP_CHECKSUM # ...then set error return False # and return 'False.' # - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Step 5 - Interpret different command responses. # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if(cmnd == OBTAIN_FIRMWARE_VERSION): + if( cmnd == OBTAIN_FIRMWARE_VERSION): version =\ - str(reply[5]) + '.' +\ - str(reply[4]) + '.' +\ - str(reply[3]) + str( reply[ 5]) + '.' +\ + str( reply[ 4]) + '.' +\ + str( reply[ 3]) else: - if(cmnd == SYSTEM_RESET or + if( cmnd == SYSTEM_RESET or cmnd == RESTORE_FACTORY_SETTINGS or cmnd == SAVE_SETTINGS): - if(reply[3] == 1): # If PASS/FAIL byte non-zero + if( reply[ 3] == 1): # If PASS/FAIL byte non-zero status = TFMP_FAIL # then set status to 'FAIL' return False # and return 'False'. @@ -392,6 +394,7 @@ def printStatus(): elif( status == TFMP_WEAK): print( "Signal weak", end= '') elif( status == TFMP_STRONG): print( "Signal saturation", end= '') elif( status == TFMP_FLOOD): print( "Ambient light saturation", end= '') + elif( status == TFMP_NOPARAM): print( "Required parameter missing", end= '') else: print( "OTHER", end= '') print() #