Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update CEC decoder: Improve collision detection and add ARC opcodes #85

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions decoders/cec/pd.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2018 Jorge Solla Rubiales <[email protected]>
## Copyright (c) 2022 Marcin Mikula <[email protected]>
##
## 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
Expand Down Expand Up @@ -94,6 +95,9 @@ def reset(self):
self.fall_start = None
self.fall_end = None
self.rise = None
self.prev_fall_start = None
self.prev_fall_end = None
self.prev_rise = None
self.reset_frame_vars()

def reset_frame_vars(self):
Expand All @@ -112,7 +116,7 @@ def metadata(self, key, value):
self.samplerate = value
self.precalculate()

def handle_frame(self, is_nack):
def handle_frame(self, is_nack, is_incomplete = 0):
if self.fall_start is None or self.fall_end is None:
return

Expand Down Expand Up @@ -148,8 +152,11 @@ def handle_frame(self, is_nack):
if i == 1:
string += ' | OPC: PING' if self.eom else ' | OPC: NONE. Aborted cmd'

# Add extra information (ack of the command from the destination)
string += ' | R: NACK' if is_nack else ' | R: ACK'
if is_incomplete:
string += ' | INCOMPLETE'
else:
# Add extra information (ack of the command from the destination)
string += ' | R: NACK' if is_nack else ' | R: ACK'

self.put(self.frame_start, self.frame_end, self.out_ann, [8, [string]])

Expand All @@ -167,33 +174,41 @@ def process(self):
# VALIDATION: Invalid pulse
if pulse == Pulse.INVALID:
self.stat = Stat.WAIT_START
self.put(self.fall_start, self.fall_end, self.out_ann, [9, ['Invalid pulse: Wrong timing']])
string = 'ERROR: Invalid pulse: Wrong timing (' + str(zero_time) + ')'
self.put(self.fall_start, self.fall_end, self.out_ann, [9, [string]])
return

# VALIDATION: If waiting for start, discard everything else
if self.stat == Stat.WAIT_START and pulse != Pulse.START:
self.put(self.fall_start, self.fall_end, self.out_ann, [9, ['Expected START: BIT found']])
self.put(self.fall_start, self.fall_end, self.out_ann, [9, ['ERROR: Expected START: BIT found']])
return

# VALIDATION: If waiting for ACK or EOM, only BIT pulses (0/1) are expected
if (self.stat == Stat.WAIT_ACK or self.stat == Stat.WAIT_EOM) and pulse == Pulse.START:
self.put(self.fall_start, self.fall_end, self.out_ann, [9, ['Expected BIT: START received)']])
self.put(self.fall_start, self.fall_end, self.out_ann, [9, ['ERROR: Expected BIT: START received)']])
self.stat = Stat.WAIT_START

# VALIDATION: ACK bit pulse remains high till the next frame (if any): Validate only min time of the low period
if self.stat == Stat.WAIT_ACK and pulse != Pulse.START:
if total_time < timing[pulse]['total']['min']:
pulse = Pulse.INVALID
self.put(self.fall_start, self.fall_end, self.out_ann, [9, ['ACK pulse below minimun time']])
self.put(self.fall_start, self.fall_end, self.out_ann, [9, ['ERROR: ACK pulse below minimun time']])
self.stat = Stat.WAIT_START
return

# VALIDATION / PING FRAME DETECTION: Initiator doesn't sets the EOM = 1 but stops sending when ack doesn't arrive
if self.stat == Stat.GET_BITS and pulse == Pulse.START:
# Make sure we received a complete byte to consider it a valid ping
if self.bit_count == 0:
self.handle_frame(self.is_nack)
if self.frame_start is None or self.frame_end is None:
zero_time = ((self.prev_rise - self.prev_fall_start) / self.samplerate) * 1000.0
total_time = ((self.prev_fall_end - self.prev_fall_start) / self.samplerate) * 1000.0
string = 'ERROR: Unexpected pulse (' + str(zero_time) + '/' + str(total_time) + ')'
self.put(self.prev_fall_start, self.prev_fall_end, self.out_ann, [9, [string]])
else:
self.handle_frame(self.is_nack)
else:
self.handle_frame(self.is_nack, 1)
self.put(self.frame_start, self.samplenum, self.out_ann, [9, ['ERROR: Incomplete byte received']])

# Set wait start so we receive next frame
Expand All @@ -202,7 +217,8 @@ def process(self):
# VALIDATION: Check timing of the BIT (0/1) pulse in any other case (not waiting for ACK)
if self.stat != Stat.WAIT_ACK and pulse != Pulse.START:
if total_time < timing[pulse]['total']['min'] or total_time > timing[pulse]['total']['max']:
self.put(self.fall_start, self.fall_end, self.out_ann, [9, ['Bit pulse exceeds total pulse timespan']])
string = 'ERROR: Bit pulse exceeds total pulse timespan (' + str(total_time) +')'
self.put(self.fall_start, self.fall_end, self.out_ann, [9, [string]])
pulse = Pulse.INVALID
self.stat = Stat.WAIT_START
return
Expand Down Expand Up @@ -292,13 +308,16 @@ def decode(self):

while True:
self.wait({0: 'r'})
self.prev_rise = self.rise
self.rise = self.samplenum

if self.stat == Stat.WAIT_ACK:
self.wait([{0: 'f'}, {'skip': self.max_ack_len_samples}])
else:
self.wait([{0: 'f'}])

self.prev_fall_start = self.fall_start
self.prev_fall_end = self.fall_end
self.fall_start = self.fall_end
self.fall_end = self.samplenum
self.process()
Expand Down
8 changes: 8 additions & 0 deletions decoders/cec/protocoldata.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2018 Jorge Solla Rubiales <[email protected]>
## Copyright (c) 2022 Marcin Mikula <[email protected]>
##
## 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
Expand Down Expand Up @@ -99,6 +100,13 @@
0x70: 'SYSTEM_AUDIO_MODE_REQUEST',
0x7E: 'SYSTEM_AUDIO_MODE_STATUS',
0x9A: 'SET_AUDIO_RATE',
0xC0: 'INITIATE_ARC',
0xC1: 'REPORT_ARC_INITIATED',
0xC2: 'REPORT_ARC_TERMINATED',
0xC3: 'REQUEST_ARC_INITIATION',
0xC4: 'REQUEST_ARC_TERMINATION',
0xC5: 'TERMINATE_ARC',
0xF8: 'CDC_MESSAGE',
}

def resolve_logical_address(id_, is_initiator):
Expand Down