##
'''
-1-Wire protocol decoder.
+1-Wire protocol decoder (link layer).
-The 1-Wire protocol enables bidirectional communication over a single wire (and
-ground) between a single master and one or multiple slaves. The protocol is
-layered.
-- Link layer (reset, presence detection, reading/writing bits)
-- Network layer (skip/search/match device ROM addresses)
-- Transport layer (transport data between 1-Wire master and device)
+The 1-Wire protocol enables bidirectional communication over a single wire
+(and ground) between a single master and one or multiple slaves. The protocol
+is layered:
-Link layer
+ - Link layer (reset, presence detection, reading/writing bits)
+ - Network layer (skip/search/match device ROM addresses)
+ - Transport layer (transport data between 1-Wire master and device)
+
+Link layer protocol details:
Sample rate:
-A high enough sample rate is required to properly detect all the elements of
-the protocol. A lower sample rate can be used if the master does not use
-overdrive communication speed. The next minimal values should be used:
-- overdrive available: 2MHz minimum, 5MHz suggested
-- overdrive not available: 400kHz minimum, 1MHz suggested
+A sufficiently high samplerate is required to properly detect all the elements
+of the protocol. A lower samplerate can be used if the master does not use
+overdrive communication speed. The following minimal values should be used:
+
+ - overdrive available: 2MHz minimum, 5MHz suggested
+ - overdrive not available: 400kHz minimum, 1MHz suggested
Probes:
1-Wire requires a single signal, but some master implementations might have a
-separate signal use to deliver power to the bus during temperature conversion
-as an example. This power signal is currently not parsed.
-- owr (1-Wire bus)
-- pwr (1-Wire power)
+separate signal used to deliver power to the bus during temperature conversion
+as an example. This power signal is currently not used.
+
+ - owr (1-Wire signal line)
+ - pwr (optional, dedicated power supply pin)
Options:
-1-Wire is an asynchronous protocol, so the decoder must know the sample rate.
-The timing for sampling bits, presence and reset is calculated by the decoder,
+1-Wire is an asynchronous protocol, so the decoder must know the samplerate.
+The timing for sampling bits, presence, and reset is calculated by the decoder,
but in case the user wishes to use different values, it is possible to
-configure the next timing values (number of sample rate periods):
-- overdrive (if active the decoder will be prepared for overdrive)
-- cnt_normal_bit (time for normal mode sample bit)
-- cnt_normal_slot (time for normal mode data slot)
-- cnt_normal_presence (time for normal mode sample presence)
-- cnt_normal_reset (time for normal mode reset)
-- cnt_overdrive_bit (time for overdrive mode sample bit)
-- cnt_overdrive_slot (time for overdrive mode data slot)
-- cnt_overdrive_presence (time for overdrive mode sample presence)
-- cnt_overdrive_reset (time for overdrive mode reset)
-This options should be configured only on very rare cases and the user should
+configure the following timing values (number of samplerate periods):
+
+ - overdrive (if active the decoder will be prepared for overdrive)
+ - cnt_normal_bit (time for normal mode sample bit)
+ - cnt_normal_slot (time for normal mode data slot)
+ - cnt_normal_presence (time for normal mode sample presence)
+ - cnt_normal_reset (time for normal mode reset)
+ - cnt_overdrive_bit (time for overdrive mode sample bit)
+ - cnt_overdrive_slot (time for overdrive mode data slot)
+ - cnt_overdrive_presence (time for overdrive mode sample presence)
+ - cnt_overdrive_reset (time for overdrive mode reset)
+
+These options should be configured only on very rare cases and the user should
read the decoder source code to understand them correctly.
+Protocol output format:
+TODO.
+
Annotations:
-Link layer annotations show the next events:
-- NOTE/WARNING/ERROR
- Possible sample rate related timing issues are reported.
-- RESET/PRESENCE True/False
- The event is marked from the signal negative edge to the end of the reset
- high period. It is also reported if there are any devices attached to the
- bus.
-- BIT 0/1
- The event is marked from the signal negative edge to the end of the data
- slot. The value of each received bit is also provided.
+
+Link layer annotations show the following events:
+
+ - NOTE/WARNING/ERROR
+ Possible samplerate related timing issues are reported.
+ - Reset/presence true/false
+ The event is marked from the signal negative edge to the end of the reset
+ high period. It's also reported if there are any devices attached to the bus.
+ - Bit 0/1
+ The event is marked from the signal negative edge to the end of the data
+ slot. The value of each received bit is also provided.
TODO:
-- check for protocol correctness, if events are timed inside prescribed limits
-- maybe add support for interrupts, check if this feature is deprecated
+- Check for protocol correctness, if events are timed inside prescribed limits.
+- Maybe add support for interrupts, check if this feature is deprecated.
'''
-from .onewire_link import *
+from .onewire_link import *
+
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
-# 1-Wire link layer protocol decoder
+# 1-Wire protocol decoder (link layer)
import sigrokdecode as srd
api_version = 1
id = 'onewire_link'
name = '1-Wire link layer'
- longname = '1-Wire serial communication bus'
+ longname = '1-Wire serial communication bus (link layer)'
desc = 'Bidirectional, half-duplex, asynchronous serial bus.'
license = 'gplv2+'
inputs = ['logic']
{'id': 'pwr', 'name': 'PWR', 'desc': '1-Wire power'},
]
options = {
- 'overdrive' : ['Overdrive', 1],
- 'cnt_normal_bit' : ['Time (in samplerate periods) for normal mode sample bit' , 0],
- 'cnt_normal_slot' : ['Time (in samplerate periods) for normal mode data slot' , 0],
- 'cnt_normal_presence' : ['Time (in samplerate periods) for normal mode sample presence', 0],
- 'cnt_normal_reset' : ['Time (in samplerate periods) for normal mode reset' , 0],
- 'cnt_overdrive_bit' : ['Time (in samplerate periods) for overdrive mode sample bit' , 0],
- 'cnt_overdrive_slot' : ['Time (in samplerate periods) for overdrive mode data slot' , 0],
- 'cnt_overdrive_presence': ['Time (in samplerate periods) for overdrive mode sample presence', 0],
- 'cnt_overdrive_reset' : ['Time (in samplerate periods) for overdrive mode reset' , 0],
+ 'overdrive': ['Overdrive', 1],
+ # Time options (specified in number of samplerate periods):
+ 'cnt_normal_bit': ['Normal mode sample bit time', 0],
+ 'cnt_normal_slot': ['Normal mode data slot time', 0],
+ 'cnt_normal_presence': ['Normal mode sample presence time', 0],
+ 'cnt_normal_reset': ['Normal mode reset time', 0],
+ 'cnt_overdrive_bit': ['Overdrive mode sample bit time', 0],
+ 'cnt_overdrive_slot': ['Overdrive mode data slot time', 0],
+ 'cnt_overdrive_presence': ['Overdrive mode sample presence time', 0],
+ 'cnt_overdrive_reset': ['Overdrive mode reset time', 0],
}
annotations = [
['Link', 'Link layer events (reset, presence, bit slots)'],
]
def __init__(self, **kwargs):
- # Common variables
self.samplenum = 0
# Link layer variables
- self.state = 'WAIT FOR FALLING EDGE'
+ self.state = 'WAIT FOR FALLING EDGE'
self.present = 0
- self.bit = 0
+ self.bit = 0
self.bit_cnt = 0
self.command = 0
self.overdrive = 0
# Event timing variables
- self.fall = 0
- self.rise = 0
+ self.fall = 0
+ self.rise = 0
def start(self, metadata):
self.out_proto = self.add(srd.OUTPUT_PROTO, 'onewire_link')
- self.out_ann = self.add(srd.OUTPUT_ANN , 'onewire_link')
+ self.out_ann = self.add(srd.OUTPUT_ANN, 'onewire_link')
- # check if samplerate is appropriate
self.samplerate = metadata['samplerate']
- if (self.options['overdrive']):
+
+ # Check if samplerate is appropriate.
+ if self.options['overdrive']:
self.put(0, 0, self.out_ann, [0,
- ['NOTE: Sample rate checks assume overdrive mode.']])
- if (self.samplerate < 2000000):
+ ['NOTE: Sample rate checks assume overdrive mode.']])
+ if self.samplerate < 2000000:
self.put(0, 0, self.out_ann, [0,
- ['ERROR: Sampling rate is too low must be above 2MHz for proper overdrive mode decoding.']])
- elif (self.samplerate < 5000000):
+ ['ERROR: Sampling rate is too low. Must be above 2MHz ' +
+ 'for proper overdrive mode decoding.']])
+ elif self.samplerate < 5000000:
self.put(0, 0, self.out_ann, [0,
- ['WARNING: Sampling rate is suggested to be above 5MHz for proper overdrive mode decoding.']])
+ ['WARNING: Sampling rate is suggested to be above 5MHz ' +
+ 'for proper overdrive mode decoding.']])
else:
self.put(0, 0, self.out_ann, [0,
- ['NOTE: Sample rate checks assume normal mode only.']])
- if (self.samplerate < 400000):
+ ['NOTE: Sample rate checks assume normal mode only.']])
+ if self.samplerate < 400000:
self.put(0, 0, self.out_ann, [0,
- ['ERROR: Sampling rate is too low must be above 400kHz for proper normal mode decoding.']])
+ ['ERROR: Sampling rate is too low. Must be above ' +
+ '400kHz for proper normal mode decoding.']])
elif (self.samplerate < 1000000):
self.put(0, 0, self.out_ann, [0,
- ['WARNING: Sampling rate is suggested to be above 1MHz for proper normal mode decoding.']])
+ ['WARNING: Sampling rate is suggested to be above ' +
+ '1MHz for proper normal mode decoding.']])
- # The default 1-Wire time base is 30us, this is used to calculate sampling times.
- if (self.options['cnt_normal_bit']):
+ # The default 1-Wire time base is 30us. This is used to calculate
+ # sampling times.
+ samplerate = float(self.samplerate)
+ if self.options['cnt_normal_bit']:
self.cnt_normal_bit = self.options['cnt_normal_bit']
else:
- self.cnt_normal_bit = int(float(self.samplerate) * 0.000015) - 1 # 15ns
- if (self.options['cnt_normal_slot']):
+ self.cnt_normal_bit = int(samplerate * 0.000015) - 1 # 15ns
+ if self.options['cnt_normal_slot']:
self.cnt_normal_slot = self.options['cnt_normal_slot']
else:
- self.cnt_normal_slot = int(float(self.samplerate) * 0.000060) - 1 # 60ns
- if (self.options['cnt_normal_presence']):
+ self.cnt_normal_slot = int(samplerate * 0.000060) - 1 # 60ns
+ if self.options['cnt_normal_presence']:
self.cnt_normal_presence = self.options['cnt_normal_presence']
else:
- self.cnt_normal_presence = int(float(self.samplerate) * 0.000075) - 1 # 75ns
- if (self.options['cnt_normal_reset']):
+ self.cnt_normal_presence = int(samplerate * 0.000075) - 1 # 75ns
+ if self.options['cnt_normal_reset']:
self.cnt_normal_reset = self.options['cnt_normal_reset']
else:
- self.cnt_normal_reset = int(float(self.samplerate) * 0.000480) - 1 # 480ns
- if (self.options['cnt_overdrive_bit']):
+ self.cnt_normal_reset = int(samplerate * 0.000480) - 1 # 480ns
+ if self.options['cnt_overdrive_bit']:
self.cnt_overdrive_bit = self.options['cnt_overdrive_bit']
else:
- self.cnt_overdrive_bit = int(float(self.samplerate) * 0.000002) - 1 # 2ns
- if (self.options['cnt_overdrive_slot']):
+ self.cnt_overdrive_bit = int(samplerate * 0.000002) - 1 # 2ns
+ if self.options['cnt_overdrive_slot']:
self.cnt_overdrive_slot = self.options['cnt_overdrive_slot']
else:
- self.cnt_overdrive_slot = int(float(self.samplerate) * 0.0000073) - 1 # 6ns+1.3ns
- if (self.options['cnt_overdrive_presence']):
+ self.cnt_overdrive_slot = int(samplerate * 0.0000073) - 1 # 6ns+1.3ns
+ if self.options['cnt_overdrive_presence']:
self.cnt_overdrive_presence = self.options['cnt_overdrive_presence']
else:
- self.cnt_overdrive_presence = int(float(self.samplerate) * 0.000010) - 1 # 10ns
- if (self.options['cnt_overdrive_reset']):
+ self.cnt_overdrive_presence = int(samplerate * 0.000010) - 1 # 10ns
+ if self.options['cnt_overdrive_reset']:
self.cnt_overdrive_reset = self.options['cnt_overdrive_reset']
else:
- self.cnt_overdrive_reset = int(float(self.samplerate) * 0.000048) - 1 # 48ns
+ self.cnt_overdrive_reset = int(samplerate * 0.000048) - 1 # 48ns
- # organize values into lists
- self.cnt_bit = [self.cnt_normal_bit , self.cnt_overdrive_bit ]
+ # Organize values into lists.
+ self.cnt_bit = [self.cnt_normal_bit, self.cnt_overdrive_bit]
self.cnt_presence = [self.cnt_normal_presence, self.cnt_overdrive_presence]
- self.cnt_reset = [self.cnt_normal_reset , self.cnt_overdrive_reset ]
- self.cnt_slot = [self.cnt_normal_slot , self.cnt_overdrive_slot ]
-
- # Check if sample times are in the allowed range
- time_min = float(self.cnt_normal_bit ) / self.samplerate
- time_max = float(self.cnt_normal_bit+1) / self.samplerate
- if ( (time_min < 0.000005) or (time_max > 0.000015) ) :
- self.put(0, 0, self.out_ann, [0,
- ['WARNING: The normal mode data sample time interval (%2.1fus-%2.1fus) should be inside (5.0us, 15.0us).'
- % (time_min*1000000, time_max*1000000)]])
- time_min = float(self.cnt_normal_presence ) / self.samplerate
- time_max = float(self.cnt_normal_presence+1) / self.samplerate
- if ( (time_min < 0.0000681) or (time_max > 0.000075) ) :
- self.put(0, 0, self.out_ann, [0,
- ['WARNING: The normal mode presence sample time interval (%2.1fus-%2.1fus) should be inside (68.1us, 75.0us).'
- % (time_min*1000000, time_max*1000000)]])
- time_min = float(self.cnt_overdrive_bit ) / self.samplerate
- time_max = float(self.cnt_overdrive_bit+1) / self.samplerate
- if ( (time_min < 0.000001) or (time_max > 0.000002) ) :
- self.put(0, 0, self.out_ann, [0,
- ['WARNING: The overdrive mode data sample time interval (%2.1fus-%2.1fus) should be inside (1.0us, 2.0us).'
- % (time_min*1000000, time_max*1000000)]])
- time_min = float(self.cnt_overdrive_presence ) / self.samplerate
- time_max = float(self.cnt_overdrive_presence+1) / self.samplerate
- if ( (time_min < 0.0000073) or (time_max > 0.000010) ) :
- self.put(0, 0, self.out_ann, [0,
- ['WARNING: The overdrive mode presence sample time interval (%2.1fus-%2.1fus) should be inside (7.3us, 10.0us).'
- % (time_min*1000000, time_max*1000000)]])
+ self.cnt_reset = [self.cnt_normal_reset, self.cnt_overdrive_reset]
+ self.cnt_slot = [self.cnt_normal_slot, self.cnt_overdrive_slot]
+
+ # Check if sample times are in the allowed range.
+
+ time_min = float(self.cnt_normal_bit) / self.samplerate
+ time_max = float(self.cnt_normal_bit + 1) / self.samplerate
+ if (time_min < 0.000005) or (time_max > 0.000015):
+ self.put(0, 0, self.out_ann, [0,
+ ['WARNING: The normal mode data sample time interval ' +
+ '(%2.1fus-%2.1fus) should be inside (5.0us, 15.0us).'
+ % (time_min * 1000000, time_max * 1000000)]])
+
+ time_min = float(self.cnt_normal_presence) / self.samplerate
+ time_max = float(self.cnt_normal_presence + 1) / self.samplerate
+ if (time_min < 0.0000681) or (time_max > 0.000075):
+ self.put(0, 0, self.out_ann, [0,
+ ['WARNING: The normal mode presence sample time interval ' +
+ '(%2.1fus-%2.1fus) should be inside (68.1us, 75.0us).'
+ % (time_min * 1000000, time_max * 1000000)]])
+
+ time_min = float(self.cnt_overdrive_bit) / self.samplerate
+ time_max = float(self.cnt_overdrive_bit + 1) / self.samplerate
+ if (time_min < 0.000001) or (time_max > 0.000002):
+ self.put(0, 0, self.out_ann, [0,
+ ['WARNING: The overdrive mode data sample time interval ' +
+ '(%2.1fus-%2.1fus) should be inside (1.0us, 2.0us).'
+ % (time_min * 1000000, time_max * 1000000)]])
+
+ time_min = float(self.cnt_overdrive_presence) / self.samplerate
+ time_max = float(self.cnt_overdrive_presence + 1) / self.samplerate
+ if (time_min < 0.0000073) or (time_max > 0.000010):
+ self.put(0, 0, self.out_ann, [0,
+ ['WARNING: The overdrive mode presence sample time interval ' +
+ '(%2.1fus-%2.1fus) should be inside (7.3us, 10.0us).'
+ % (time_min*1000000, time_max*1000000)]])
def report(self):
pass
def decode(self, ss, es, data):
for (self.samplenum, (owr, pwr)) in data:
-
# State machine.
if self.state == 'WAIT FOR FALLING EDGE':
# The start of a cycle is a falling edge.
- if (owr == 0):
+ if owr == 0:
# Save the sample number for the falling edge.
self.fall = self.samplenum
- # Go to waiting for sample time
+ # Go to waiting for sample time.
self.state = 'WAIT FOR DATA SAMPLE'
elif self.state == 'WAIT FOR DATA SAMPLE':
- # Sample data bit
- if (self.samplenum - self.fall == self.cnt_bit[self.overdrive]):
- self.bit = owr
+ # Sample data bit.
+ t = self.samplenum - self.fall
+ if t == self.cnt_bit[self.overdrive]:
+ self.bit = owr
self.state = 'WAIT FOR DATA SLOT END'
elif self.state == 'WAIT FOR DATA SLOT END':
- # A data slot ends in a recovery period, otherwise, this is probably a reset
- if (self.samplenum - self.fall == self.cnt_slot[self.overdrive]):
- if (owr):
- self.put(self.fall, self.samplenum, self.out_ann, [0, ['BIT: %01x' % self.bit]])
- self.put(self.fall, self.samplenum, self.out_proto, ['BIT', self.bit])
- # Checking the first command to see if overdrive mode should be entered
- if (self.bit_cnt <= 8):
- self.command = self.command | (self.bit << self.bit_cnt)
- elif (self.bit_cnt == 8):
- if (self.command in [0x3c, 0x69]):
- self.put(self.fall, self.cnt_bit[self.overdrive], self.out_ann, [0, ['ENTER OVERDRIVE MODE']])
- # Incrementing the bit counter
+ # A data slot ends in a recovery period, otherwise, this is
+ # probably a reset.
+ t = self.samplenum - self.fall
+ if t == self.cnt_slot[self.overdrive]:
+ if owr:
+ self.put(self.fall, self.samplenum, self.out_ann,
+ [0, ['BIT: %01x' % self.bit]])
+ self.put(self.fall, self.samplenum, self.out_proto,
+ ['BIT', self.bit])
+
+ # Checking the first command to see if overdrive mode
+ # should be entered.
+ if self.bit_cnt <= 8:
+ self.command |= (self.bit << self.bit_cnt)
+ elif self.bit_cnt == 8 and self.command in [0x3c, 0x69]:
+ self.put(self.fall, self.cnt_bit[self.overdrive],
+ self.out_ann,
+ [0, ['ENTER OVERDRIVE MODE']])
+ # Increment the bit counter.
self.bit_cnt += 1
- # Wait for next slot
+ # Wait for next slot.
self.state = 'WAIT FOR FALLING EDGE'
else:
- # This seems to be a reset slot, wait for its end
+ # This seems to be a reset slot, wait for its end.
self.state = 'WAIT FOR RISING EDGE'
elif self.state == 'WAIT FOR RISING EDGE':
# The end of a cycle is a rising edge.
- if (owr):
- # Check if this was a reset cycle
- if (self.samplenum - self.fall > self.cnt_normal_reset):
+ if owr:
+ # Check if this was a reset cycle.
+ t = self.samplenum - self.fall
+ if t > self.cnt_normal_reset:
# Save the sample number for the falling edge.
self.rise = self.samplenum
- self.state = "WAIT FOR PRESENCE DETECT"
- # Exit overdrive mode
- if (self.overdrive):
- self.put(self.fall, self.cnt_bit[self.overdrive], self.out_ann, [0, ['EXIT OVERDRIVE MODE']])
+ self.state = 'WAIT FOR PRESENCE DETECT'
+ # Exit overdrive mode.
+ if self.overdrive:
+ self.put(self.fall, self.cnt_bit[self.overdrive],
+ self.out_ann, [0, ['EXIT OVERDRIVE MODE']])
self.overdrive = 0
- # Clear command bit counter and data register
+ # Clear command bit counter and data register.
self.bit_cnt = 0
self.command = 0
- elif ((self.samplenum - self.fall > self.cnt_overdrive_reset) and (self.overdrive)):
+ elif (t > self.cnt_overdrive_reset) and self.overdrive:
# Save the sample number for the falling edge.
self.rise = self.samplenum
self.state = "WAIT FOR PRESENCE DETECT"
# Otherwise this is assumed to be a data bit.
- else :
+ else:
self.state = "WAIT FOR FALLING EDGE"
elif self.state == 'WAIT FOR PRESENCE DETECT':
- # Sample presence status
- if (self.samplenum - self.rise == self.cnt_presence[self.overdrive]):
+ # Sample presence status.
+ t = self.samplenum - self.rise
+ if t == self.cnt_presence[self.overdrive]:
self.present = owr
self.state = 'WAIT FOR RESET SLOT END'
elif self.state == 'WAIT FOR RESET SLOT END':
# A reset slot ends in a long recovery period
- if (self.samplenum - self.rise == self.cnt_reset[self.overdrive]):
- if (owr):
- self.put(self.fall, self.samplenum, self.out_ann, [0, ['RESET/PRESENCE: %s' % ('False' if self.present else 'True')]])
- self.put(self.fall, self.samplenum, self.out_proto, ['RESET/PRESENCE', not self.present])
- # Wait for next slot
+ t = self.samplenum - self.rise
+ if t == self.cnt_reset[self.overdrive]:
+ if owr:
+ self.put(self.fall, self.samplenum, self.out_ann,
+ [0, ['RESET/PRESENCE: %s'
+ % ('False' if self.present else 'True')]])
+ self.put(self.fall, self.samplenum, self.out_proto,
+ ['RESET/PRESENCE', not self.present])
+ # Wait for next slot.
self.state = 'WAIT FOR FALLING EDGE'
else:
- # This seems to be a reset slot, wait for its end
+ # This seems to be a reset slot, wait for its end.
self.state = 'WAIT FOR RISING EDGE'
else:
- raise Exception('Invalid state: %d' % self.state)
+ raise Exception('Invalid state: %s' % self.state)