diff --git a/ds1307fixed/__init__.py b/ds1307fixed/__init__.py index d722a49..3643cb6 100644 --- a/ds1307fixed/__init__.py +++ b/ds1307fixed/__init__.py @@ -20,7 +20,10 @@ ''' This decoder stacks on top of the 'i2c' PD and decodes the Dallas DS1307 -real-time clock (RTC) specific registers and commands. +real-time clock (RTC) specific registers and commands. This is a fixed version of this decoder capable of decoding +communication that starts with reading from registers without needing to specify the address of the register where the +reading starts. In this version, the decoder is also capable of visualizing that only some registers +were read from/written to. ''' from .pd import Decoder diff --git a/ds1307fixed/pd.py b/ds1307fixed/pd.py index 8556d67..e1cc9d9 100644 --- a/ds1307fixed/pd.py +++ b/ds1307fixed/pd.py @@ -187,6 +187,7 @@ def handle_reg_0x3f(self, b): # RAM (bytes 0x08-0x3f) self.putd(7, 0, [Ann.REG_RAM, ['RAM', 'R']]) self.putd(7, 0, [Ann.BIT_RAM, ['SRAM: 0x%02X' % b, '0x%02X' % b]]) + # Túto metódu som pridal vrámci TODO: možnosť zobrazovania len časti čítaných/zapisovaných údajov def get_stored_values(self): output = "" if self.seconds != -1: @@ -215,6 +216,7 @@ def reset_stored_values(self): self.years = -1 def output_datetime(self, cls, rw): + # Tu som pridal TODO: možnosť zobrazovania len časti čítaných/zapisovaných údajov if (self.days == -1 or self.date == -1 or self.months == -1 or self.years == -1 or self.hours == -1 or self.minutes == -1 or self.seconds == -1): d = self.get_stored_values() @@ -265,14 +267,15 @@ def decode(self, ss, es, data): self.ss_block = ss elif self.state == 'GET SLAVE ADDR': # Wait for an address read/write operation. - if cmd != 'ADDRESS WRITE' and cmd != 'ADDRESS READ': + if cmd != 'ADDRESS WRITE' and cmd != 'ADDRESS READ': # aby bolo možné dekódovanie nového typu komunikácie popísanej v reporte, musí tu byť možnosť hned na začiatku komunikacie dekódovať ADDRESS READ return if not self.is_correct_chip(databyte): self.state = 'IDLE' return - if cmd == 'ADDRESS WRITE': + # Tu som pridal možnosť, aby dekóder zistil a rozlíšil, či bude komunikácia typu Figure 5. Data Read zo špecifikácie v reporte. Zvyšné 2 boli už predtým rozlíšené na inom mieste v kóde. + if cmd == 'ADDRESS WRITE': # ak sme dekódovali ADDRESS WRITE, nasledovať bude čítanie adresy registra, kde sa začne čítanie self.state = 'GET REG ADDR' - elif cmd == 'ADDRESS READ': + elif cmd == 'ADDRESS READ': # ak sme dekódovali ADDRESS READ, tak bude rovno nasledovať čítanie z registrov self.state = 'READ RTC REGS' elif self.state == 'GET REG ADDR': # Wait for a data write (master selects the slave register). @@ -282,7 +285,7 @@ def decode(self, ss, es, data): self.state = 'WRITE RTC REGS' elif self.state == 'WRITE RTC REGS': # If we see a Repeated Start here, it's an RTC read. - if cmd == 'START REPEAT': + if cmd == 'START REPEAT': # tu sa rozlišuje, či bude komunikácia pokračovať ako Figure 6. Data Read zo špecifikácie v reporte (to som ale ja nepridával) self.state = 'GET SLAVE READ ADDR' return # Otherwise: Get data bytes until a STOP condition occurs. diff --git a/extractor_i2c/pd.py b/extractor_i2c/pd.py index 1daea39..b46b6d9 100644 --- a/extractor_i2c/pd.py +++ b/extractor_i2c/pd.py @@ -26,7 +26,6 @@ : - 'ADDRESS - 'DATA' - - 'PACKET END' (: 0) is the data or address byte associated with the 'ADDRESS' or 'DATA' command. @@ -86,14 +85,9 @@ def decode(self, ss, es, data): # State machine. if cmd == 'START' or cmd == 'START REPEAT': self.state = 'ACTIVE' - # START REPEAT means an end of a packet - if cmd == 'START REPEAT': - self.putp(['PACKET END', 0, 0]) return elif cmd == 'STOP': self.state = 'INACTIVE' - # STOP means an end of a packet - self.putp(['PACKET END', 0, 0]) return if self.state == 'ACTIVE': diff --git a/extractor_spi/pd.py b/extractor_spi/pd.py index 0aae15f..99acc9b 100644 --- a/extractor_spi/pd.py +++ b/extractor_spi/pd.py @@ -25,7 +25,6 @@ : - 'DATA' - - 'PACKET END' (: 0) is the data byte associated with the 'DATA' command. diff --git a/extractor_uart/pd.py b/extractor_uart/pd.py index 0e955f6..c4cd19e 100644 --- a/extractor_uart/pd.py +++ b/extractor_uart/pd.py @@ -26,7 +26,6 @@ : - 'ADDRESS - 'DATA' - - 'PACKET END' (: 0) is the data value associated with the 'DATA' command. @@ -76,8 +75,6 @@ def decode(self, ss, es, data): self.state = 'ACTIVE' elif cmd == 'STOPBIT': self.state = 'INACTIVE' - # STOPBIT means end of a packet - self.putp(['PACKET END', 0, rxtx]) elif cmd == 'DATA': - # Send just value of received data packet without individual bits + # Send just the value of the received data packet without the individual bits self.send_data_value(data_value_and_bits[0], rxtx) diff --git a/packeter/pd.py b/packeter/pd.py index 5dfab3b..f6826b9 100644 --- a/packeter/pd.py +++ b/packeter/pd.py @@ -73,7 +73,7 @@ def reset(self): self.state = ['NEUTRAL', 'NEUTRAL'] self.current_row = 0 self.stored_values = [[], []] - self.separation_sequence_pointer = [0, 0] + self.separation_sequence_pointer_set = [{0}, {0}] def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) @@ -96,25 +96,29 @@ def output_stored_values(self, t): self.put(self.ss[0], self.es[0], self.out_ann, [Ann.DATA, ['Data: ' + self.get_output(), 'Da', 'D']]) elif self.current_row == 1: self.put(self.ss[1], self.es[1], self.out_ann, [Ann.DATA2, ['Data: ' + self.get_output(), 'Da', 'D']]) - elif t == 'ADDR': + elif t == 'ADDRESS': if self.current_row == 0: self.put(self.ss[0], self.es[0], self.out_ann, [Ann.ADDRESS, ['Address: ' + self.get_output(), 'Add', 'A']]) elif self.current_row == 1: self.put(self.ss[1], self.es[1], self.out_ann, [Ann.ADDRESS2, ['Address: ' + self.get_output(), 'Add', 'A']]) - # Resets the current state, stored values and separation sequence pointer for the current row + # Resets the current state, stored values and separation sequence pointers for the current row self.state[self.current_row] = 'NEUTRAL' self.stored_values[self.current_row] = [] - self.separation_sequence_pointer[self.current_row] = 0 + self.separation_sequence_pointer_set[self.current_row] = {0} def have_to_output(self): # Returns True if the options indicate that a new packet should be started and the previous one finished return self.options['max-packet-length'] == len(self.stored_values[self.current_row]) or self.is_separated_by_sequence() def is_separated_by_sequence(self): - # Returns True if the sequence separation is active and the pointer indicates the need of separation - return (self.options['use-separator-sequence'] == 'yes' and - 0 < len(self.separation_sequence) <= self.separation_sequence_pointer[self.current_row]) + # Returns True if the sequence separation is active and one of the pointers indicates a need for separation + if self.options['use-separator-sequence'] == 'no' or len(self.separation_sequence) == 0: + return False + for p in self.separation_sequence_pointer_set[self.current_row]: + if p >= len(self.separation_sequence): + return True + return False def move_separation_sequence_pointer(self, value): # If the sequence separation is active @@ -124,12 +128,13 @@ def move_separation_sequence_pointer(self, value): value = bcd2int(value) # ...and this value is starting a separation sequence or following an already - # started separation sequence, move the separation sequence pointer potentially causing separation - if str(hex(value).replace("0x", "")) == self.separation_sequence[self.separation_sequence_pointer[self.current_row]]: - self.separation_sequence_pointer[self.current_row] += 1 - # ...otherwise reset separation sequence pointer - else: - self.separation_sequence_pointer[self.current_row] = 0 + # started separation sequence, move the separation sequence pointers, which might + # potentially cause separation + new_set = {0} + for p in self.separation_sequence_pointer_set[self.current_row]: + if str(hex(value).replace("0x", "")) == self.separation_sequence[p]: + new_set.add(p+1) + self.separation_sequence_pointer_set[self.current_row] = new_set def get_output(self): # If the options say so, the separation sequence characters should be excluded from the output @@ -139,41 +144,35 @@ def get_output(self): # Get the output from the values stored in the current row according to output and input binary format options output = '' - if self.options['output-format'] == 'dec': - for b in self.stored_values[self.current_row]: - if self.options['input-binary-format'] == 'BCD': - b = bcd2int(b) - output = output + ' ' + str(b) - elif self.options['output-format'] == 'bin': - for b in self.stored_values[self.current_row]: - if self.options['input-binary-format'] == 'BCD': - b = bcd2int(b) - output = output + ' ' + str(bin(b).replace("0b", "")) - elif self.options['output-format'] == 'ASCII': - for b in self.stored_values[self.current_row]: - if self.options['input-binary-format'] == 'BCD': - b = bcd2int(b) - - # If the output format is ASCII, visualize only characters with codes from 32 up to 126 + for b in self.stored_values[self.current_row]: + if self.options['input-binary-format'] == 'BCD': + b = bcd2int(b) + + if self.options['output-format'] == 'dec': + b = str(b) + elif self.options['output-format'] == 'bin': + b = str(bin(b).replace("0b", "")) + elif self.options['output-format'] == 'hex': + b = hex(b) + elif self.options['output-format'] == 'ASCII': + # If the output format is ASCII, visualize only characters with codes from range 33 to 126 # and use special symbols for the other codes - if b == 10: - b = "\u240a" + if 33 <= b <= 126: + b = chr(b) elif b == 13: b = "\u240d" elif b == 32: b = "\u2423" elif b == 9: b = "\u21e5" - elif 126 >= b >= 32: - b = chr(b) + elif b == 10: + b = "\u240a" else: b = "\ufffd" - output = output + b - elif self.options['output-format'] == 'hex': - for b in self.stored_values[self.current_row]: - if self.options['input-binary-format'] == 'BCD': - b = bcd2int(b) - output = output + ' ' + hex(b) + + if output != "" and self.options['output-format'] != 'ASCII': + b = " " + b + output = output + b return output # Any addition to stored values should be done via this method @@ -192,33 +191,19 @@ def decode(self, ss, es, data): if self.state[self.current_row] == 'NEUTRAL': self.ss[self.current_row] = ss - if cmd == 'DATA': - # If has not finished collecting an ADDRESS packet yet, finish it now - if self.state[self.current_row] == 'RECEIVING ADDRESS': - self.output_stored_values('ADDR') + if cmd == 'DATA' or cmd == 'ADDRESS': + # If the type of the next packet on this row changes, + # finish packing the previous packet and send it to the output + if (self.state[self.current_row] == 'DATA' and cmd == 'ADDRESS') \ + or (self.state[self.current_row] == 'ADDRESS' and cmd == 'DATA'): + self.output_stored_values(self.state[self.current_row]) self.ss[self.current_row] = ss - # On this row we are receiving DATA packets now - self.state[self.current_row] = 'RECEIVING DATA' - # Set the end of the current packet on this row for now + # On this row we are receiving packets of type corresponding to the cmd + self.state[self.current_row] = cmd + # Set the end of the current packet to be the end of the whole packet collected until now self.es[self.current_row] = es - self.add_to_stored_values(data_value) # Send all data values stored in this row until now if it is necessary and clear the buffer - self.manage_stored_values('DATA') - elif cmd == 'ADDRESS': - # If has not finished collecting a DATA packet yet, finish it now - if self.state[self.current_row] == 'RECEIVING DATA': - self.output_stored_values('DATA') - self.ss[self.current_row] = ss - - # On this row we are receiving ADDRESS packets now - self.state[self.current_row] = 'RECEIVING ADDRESS' - # Set the end of the current packet on this row for now - self.es[self.current_row] = es - - self.add_to_stored_values(data_value) - - # Send all address values stored in this row until now if it is necessary and clear the buffer - self.manage_stored_values('ADDR') + self.manage_stored_values(cmd)