2626import subprocess
2727import sys
2828import time
29+ import struct
2930
3031import ftdi1 as ftdi
3132
@@ -254,6 +255,18 @@ def _mpsse_sync(self, max_retries=10):
254255 if tries >= max_retries :
255256 raise RuntimeError ('Could not synchronize with FT232H!' )
256257
258+ def mpsse_clock (self , clock_hz , three_phase = False ):
259+ # Compute divisor for requested clock.
260+ # Use equation from section 3.8.1 of:
261+ # http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
262+ # Note equation is using 60mhz master clock instead of 12mhz.
263+ divisor = int (math .ceil ((30000000.0 - float (clock_hz ))/ float (clock_hz ))) & 0xFFFF
264+ if three_phase :
265+ divisor = int (divisor * (2.0 / 3.0 ))
266+ logger .debug ('Setting clockspeed with divisor value {0}' .format (divisor ))
267+ # return command to set divisor from low and high byte values.
268+ return bytearray ((0x86 , divisor & 0xFF , (divisor >> 8 ) & 0xFF ))
269+
257270 def mpsse_set_clock (self , clock_hz , adaptive = False , three_phase = False ):
258271 """Set the clock speed of the MPSSE engine. Can be any value from 450hz
259272 to 30mhz and will pick that speed or the closest speed below it.
@@ -273,16 +286,8 @@ def mpsse_set_clock(self, clock_hz, adaptive=False, three_phase=False):
273286 self ._write ('\x8C ' )
274287 else :
275288 self ._write ('\x8D ' )
276- # Compute divisor for requested clock.
277- # Use equation from section 3.8.1 of:
278- # http://www.ftdichip.com/Support/Documents/AppNotes/AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf
279- # Note equation is using 60mhz master clock instead of 12mhz.
280- divisor = int (math .ceil ((30000000.0 - float (clock_hz ))/ float (clock_hz ))) & 0xFFFF
281- if three_phase :
282- divisor = int (divisor * (2.0 / 3.0 ))
283- logger .debug ('Setting clockspeed with divisor value {0}' .format (divisor ))
284- # Send command to set divisor from low and high byte values.
285- self ._write (str (bytearray ((0x86 , divisor & 0xFF , (divisor >> 8 ) & 0xFF ))))
289+ clock_command = self .mpsse_clock (clock_hz , three_phase )
290+ self ._write (str (clock_command ))
286291
287292 def mpsse_read_gpio (self ):
288293 """Read both GPIO bus states and return a 16 bit value with their state.
@@ -815,3 +820,336 @@ def readS16BE(self, register):
815820 """Read a signed 16-bit value from the specified register, in big
816821 endian byte order."""
817822 return self .readS16 (register , little_endian = False )
823+
824+ class OneWireDevice (object ):
825+
826+ def __init__ (self , ft232h , pin , overdrive = False ):
827+ self ._pin = pin
828+ self ._ft232h = ft232h
829+ self ._buffer = False
830+ self ._output = None
831+
832+ # setup the clock and get delay timing commands
833+ self ._ft232h .mpsse_set_clock (30000000 , False , False )
834+ self .enable_overdrive (overdrive )
835+
836+ # Two ways to delay. dump a byte to tms, or pulse the clock for n
837+ # bits. A 1 bit pulse seems to take the same as time as a 8bit
838+ # dump to TMS? Default is to pulse the clock.
839+ self ._tms_dump = '\x4a \x01 \xff ' # Dump 8 bits to TMS
840+ self ._pb = '\x8e \x01 ' # Pulse clock (1 bits)
841+ self ._delay = self ._pb
842+
843+ # MPSSE Command to read GPIO
844+ self ._read_gpio = '\x81 \x83 '
845+
846+ # Set up our GPIO mask for 1-Wire, and leave it high
847+ self .set_pin (pin , GPIO .OUT , GPIO .HIGH )
848+
849+
850+ # Return the MPSSE command required to set the clock to a given frequency
851+ # for the provided delay
852+ def _get_delay_cmd (self , seconds ):
853+ if seconds == 0 :
854+ clock_hz = 30000000.0
855+ else :
856+ clock_hz = ( 1.00 / seconds ) * 2
857+ return self ._ft232h .mpsse_clock (clock_hz , False )
858+
859+ # Calculate the delay clocks for 1Wire timings
860+ def enable_overdrive (self , overdrive ):
861+ if overdrive :
862+ logger .debug ('1Wire: Overdrive is enabled' )
863+ # overdrive speeds
864+ self ._overdrive = True
865+ self ._clock_A = self ._get_delay_cmd (0.0000010 )
866+ self ._clock_B = self ._get_delay_cmd (0.0000075 )
867+ self ._clock_C = self ._get_delay_cmd (0.0000075 )
868+ self ._clock_D = self ._get_delay_cmd (0.0000025 )
869+ self ._clock_E = self ._get_delay_cmd (0.0000010 )
870+ self ._clock_F = self ._get_delay_cmd (0.0000070 )
871+ self ._clock_G = self ._get_delay_cmd (0.0000025 )
872+ self ._clock_H = self ._get_delay_cmd (0.0000700 )
873+ self ._clock_I = self ._get_delay_cmd (0.0000085 )
874+ self ._clock_J = self ._get_delay_cmd (0.0000400 )
875+ else :
876+ # standard clock speeds
877+ logger .debug ('1Wire: Overdrive is disabled' )
878+ self ._overdrive = False
879+ self ._clock_A = self ._get_delay_cmd (0.000006 )
880+ self ._clock_B = self ._get_delay_cmd (0.000064 )
881+ self ._clock_C = self ._get_delay_cmd (0.000060 )
882+ self ._clock_D = self ._get_delay_cmd (0.000010 )
883+ self ._clock_E = self ._get_delay_cmd (0.000009 )
884+ self ._clock_F = self ._get_delay_cmd (0.000055 )
885+ self ._clock_G = self ._get_delay_cmd (0.000000 )
886+ self ._clock_H = self ._get_delay_cmd (0.000480 )
887+ self ._clock_I = self ._get_delay_cmd (0.000070 )
888+ self ._clock_J = self ._get_delay_cmd (0.000410 )
889+
890+ # Buffer write commands and then send them to the MPSSE with a flush
891+ def enable_command_buffer (self ):
892+ if self ._buffer :
893+ raise Exception ("Buffering was already enabled!!" )
894+ self ._buffer = True
895+ self ._output = None
896+
897+ # flush buffered commands to the MPSSE
898+ def flush_command_buffer (self ):
899+ self ._buffer = False
900+ if self ._output is not None :
901+ self ._write (self ._output )
902+ self ._output = None
903+
904+ def _write (self , string ):
905+ if self ._buffer :
906+ if self ._output is None :
907+ self ._output = string
908+ else :
909+ self ._output += string
910+ return
911+ self ._ft232h ._write (string )
912+
913+ def _read (self , length , timeout = 5 ):
914+ return self ._ft232h ._poll_read (length , timeout )
915+
916+ # Set the GPIO to the state requested and update the self.low, self.high
917+ # values to take into account the changed pin.
918+ def set_pin (self , pin , mode , value ):
919+
920+ # Update pin state to that requested
921+ if pin is not self ._pin :
922+ self ._ft232h .setup (pin , mode )
923+ self ._ft232h .output (pin , value )
924+
925+ # Calculate the mask for the GPIO when 1-wire is low
926+ self ._ft232h .setup (self ._pin , GPIO .OUT )
927+ self ._ft232h .output (pin , GPIO .LOW )
928+ self ._low = self ._ft232h .mpsse_gpio ()
929+
930+ # Calculate the mask for the GPIO when 1-wire is high
931+ self ._ft232h .setup (self ._pin , GPIO .IN )
932+ self ._ft232h .output (pin , GPIO .HIGH )
933+ self ._high = self ._ft232h .mpsse_gpio ()
934+
935+ # Let the GPIO settle
936+ time .sleep (0.1 )
937+
938+ # Here begins the 1-wire stuff
939+
940+ # Send a 1-wire reset on the GPIO, This makes all slaves listen up for commands.
941+ # It also detects the presance of the slaves. If nothing responds, then no devices
942+ # are connected and we return false.
943+ def reset (self ):
944+
945+ logger .debug ("1Wire: Reset" )
946+ commands = self ._clock_H + self ._low + self ._delay + self ._high + self ._clock_I + \
947+ self ._delay + self ._read_gpio + self ._clock_J + self ._delay + \
948+ self ._read_gpio
949+
950+ self ._write (str (commands ))
951+ present = self ._read (4 )
952+
953+ if present == '\xff ' * 4 :
954+ if self ._overdrive :
955+ logger .debug ("1Wire: No Devices Present. Disabling Overdrive" )
956+ self .enable_overdrive (False )
957+ return self .reset ()
958+ else :
959+ logger .debug ("1Wire: No Devices Present" )
960+ return False
961+ else :
962+ logger .debug ("1Wire: Devices Present" )
963+ return True
964+
965+ # Write a bit to the 1-wire bus, either a 1 or a 0
966+ def write_bit (self , bit ):
967+ if bit :
968+ commands = self ._clock_A + self ._low + self ._delay + self ._high + \
969+ self ._clock_B + self ._delay
970+ else :
971+ commands = self ._clock_C + self ._low + self ._delay + self ._high + \
972+ self ._clock_D + self ._delay
973+
974+ self ._write (str (commands ))
975+
976+ def read_command (self , bits = 1 ):
977+ for i in range (bits ):
978+ commands = self ._clock_A + self ._low + self ._delay + self ._high + \
979+ self ._clock_E + self ._delay + self ._read_gpio + self ._clock_F + \
980+ self ._delay
981+ self ._write (str (commands ))
982+
983+ def read_response (self , bits = 1 ):
984+ states = []
985+ read = self ._read (2 * bits )
986+ for i in range (0 ,2 * bits ,2 ):
987+ bit = bytearray ([read [i ], read [i + 1 ]])
988+ states .append ( struct .unpack ("H" , str (bit ))[0 ] >> self ._pin & 01 )
989+ if bits == 1 :
990+ return states .pop ()
991+ return states
992+
993+ # Read a bit from the 1-wire bus.
994+ def read_bit (self ):
995+ self .read_command ()
996+ return self .read_response ()
997+
998+ # Use the write_bit function to write bytes out to the bus
999+ def write_byte (self , byte ):
1000+ manage_buffer = self ._buffer == False
1001+ if manage_buffer :
1002+ self .enable_command_buffer ()
1003+ for i in range (8 ):
1004+ self .write_bit (byte & 1 )
1005+ byte >>= 1
1006+ if manage_buffer :
1007+ self .flush_command_buffer ()
1008+
1009+ # write multiple bytes to the bus
1010+ def write_bytes (self , data ):
1011+ for byte in data :
1012+ self .write_byte (byte )
1013+
1014+ # Use the read_bit function to read bytes from the bus
1015+ def read_byte (self ):
1016+ byte = 0
1017+ manage_buffer = self ._buffer == False
1018+ if manage_buffer :
1019+ self .enable_command_buffer ()
1020+ self .read_command (8 )
1021+ if manage_buffer :
1022+ self .flush_command_buffer ()
1023+ bits = self .read_response (8 )
1024+ for i in range (8 ):
1025+ byte |= bits [i ] << i
1026+ return byte
1027+
1028+ # Read multiple bytes from the 1-wire bus
1029+ def read_bytes (self , count ):
1030+ data = bytearray (count )
1031+ for i in range (count ):
1032+ data [i ] = self .read_byte ()
1033+ return data
1034+
1035+ # read multiple bits from the 1-wire bus. Used for device discovery
1036+ def read_bits (self , count ):
1037+ bits = []
1038+ for i in range (count ):
1039+ bits .append ( self .read_bit () )
1040+ return bits
1041+
1042+ # There is only one device on the bus, so ask it to identify itself.
1043+ def rom_read (self ):
1044+ rom = bytearray (8 )
1045+ self .write_byte (0x33 )
1046+ for i in range (8 ):
1047+ rom [i ] = self .read_byte ()
1048+ return rom
1049+
1050+ # There is only one device on the bus so skip ROM matching.
1051+ def skip_rom (self ):
1052+ self .write_byte (0xcc )
1053+
1054+ # Target the ROM specified
1055+ def _match_rom (self , rom ):
1056+ if type (rom ) is str :
1057+ rom = self .string2bytes (rom )
1058+ self .write_byte (0x55 )
1059+ self .write_bytes (rom )
1060+
1061+ # Address the ROM if given, else perform a skip_rom()
1062+ def address_rom (self , rom ):
1063+ if rom is None :
1064+ self .skip_rom ()
1065+ else :
1066+ self ._match_rom (rom )
1067+
1068+ # Search for ROMs on the 1-wire bus
1069+ def search_roms (self ):
1070+ roms_found = []
1071+ partials = [ [] ]
1072+ logger .debug ("Search Start" )
1073+ while len (partials ) > 0 :
1074+ rom = partials .pop ()
1075+ roms_found .append ( self .bytes2string (self ._search (rom , partials )) )
1076+ logger .debug ("Search Complete" )
1077+ return roms_found
1078+
1079+ # When replaying the partial rom, flush the search out to the MPSSE every 10 bits
1080+ # improves performance.
1081+ def _search_flush_rom (self , count ):
1082+ self .flush_command_buffer ()
1083+ self .read_response (2 * count )
1084+ return 0
1085+
1086+ # Do the search for each partial ROM
1087+ def _search (self , rom = [], partials = []):
1088+
1089+ if self .reset () is False :
1090+ return
1091+
1092+ # Dump any partial rom to the MPSSE in 10bit chunks
1093+ self .enable_command_buffer ()
1094+ self .write_byte (0xf0 )
1095+ count = 0
1096+ for bit in rom :
1097+ if count == 10 :
1098+ count = self ._search_flush_rom (10 )
1099+ self .enable_command_buffer ()
1100+ count += 1
1101+ self .read_command (2 )
1102+ self .write_bit (bit )
1103+ self ._search_flush_rom (count )
1104+
1105+ # Continue the search from where we are.
1106+ for i in range (64 - len (rom )):
1107+ bits = self .read_bits (2 )
1108+ if bits [0 ] != bits [1 ]:
1109+ rom .append (bits [0 ])
1110+ self .write_bit (bits [0 ])
1111+ elif bits == [False , False ]:
1112+ np = list (rom )
1113+ np .append (True )
1114+ partials .append ( np )
1115+ rom .append (False )
1116+ self .write_bit (False )
1117+ else :
1118+ raise Exception ("Search Failed. Device Comms Interrupted" )
1119+
1120+ complete = bytearray (8 )
1121+ for i in range (8 ):
1122+ byte = 0
1123+ for o in range (8 ):
1124+ bit = rom [(i * 8 )+ o ]
1125+ byte |= bit << o
1126+ complete [i ] = byte
1127+
1128+ logger .debug ("Search Found: ROM {}" .format ( self .bytes2string (complete )))
1129+ if self .crc (complete ) is not 0x00 :
1130+ raise Exception ("CRC Check Failed" )
1131+ return complete
1132+
1133+ # Return an a string representation of the device ROM
1134+ def bytes2string (self , bytesarray ):
1135+ return ":" .join ("{:02x}" .format (c ) for c in bytesarray )
1136+
1137+ # Convert a hexadecimal string to bytes
1138+ def string2bytes (self , string ):
1139+ return bytearray (codecs .decode (string .replace (":" ,"" ),"hex" ))
1140+
1141+ # Calculate CRC, result should be 0x00
1142+ def crc (self , data ):
1143+ poly = 0x8c # x8,x5,x4,+ 1 inverse of 0x131 & 0xff
1144+ crc = 0x00
1145+ for byte in data :
1146+ for bit in range (8 ):
1147+ # When bit is on, shift and xor, else just shift
1148+ if ( byte ^ crc ) & 0x01 :
1149+ crc >>= 1
1150+ crc ^= poly
1151+ else :
1152+ crc >>= 1
1153+ byte >>= 1
1154+ return crc
1155+
0 commit comments