+ # Annotations.
+ if self.have_miso:
+ self.putw([0, ['%02X' % self.misodata]])
+ if self.have_mosi:
+ self.putw([1, ['%02X' % self.mosidata]])
+
+ # Meta bitrate.
+ elapsed = 1 / float(self.samplerate) * (self.samplenum - self.startsample + 1)
+ bitrate = int(1 / elapsed * self.options['wordsize'])
+ self.put(self.startsample, self.samplenum, self.out_bitrate, bitrate)
+
+ if self.have_cs and self.cs_was_deasserted_during_data_word:
+ self.putw([4, ['CS# was deasserted during this data word!']])
+
+ self.reset_decoder_state()
+
+ def find_clk_edge(self, miso, mosi, clk, cs):
+ if self.have_cs and self.oldcs != cs:
+ # Send all CS# pin value changes.
+ self.put(self.samplenum, self.samplenum, self.out_python,
+ ['CS-CHANGE', self.oldcs, cs])
+ self.oldcs = cs
+ # Reset decoder state when CS# changes (and the CS# pin is used).
+ self.reset_decoder_state()
+
+ # Ignore sample if the clock pin hasn't changed.
+ if clk == self.oldclk:
+ return
+
+ self.oldclk = clk
+
+ # Sample data on rising/falling clock edge (depends on mode).
+ mode = spi_mode[self.options['cpol'], self.options['cpha']]
+ if mode == 0 and clk == 0: # Sample on rising clock edge
+ return
+ elif mode == 1 and clk == 1: # Sample on falling clock edge
+ return
+ elif mode == 2 and clk == 1: # Sample on falling clock edge
+ return
+ elif mode == 3 and clk == 0: # Sample on rising clock edge
+ return
+
+ # Found the correct clock edge, now get the SPI bit(s).
+ self.handle_bit(miso, mosi, clk, cs)
+
+ def decode(self, ss, es, data):
+ if self.samplerate is None:
+ raise Exception("Cannot decode without samplerate.")
+ # Either MISO or MOSI can be omitted (but not both). CS# is optional.
+ for (self.samplenum, pins) in data:
+
+ # Ignore identical samples early on (for performance reasons).
+ if self.oldpins == pins:
+ continue
+ self.oldpins, (clk, miso, mosi, cs) = pins, pins
+ self.have_miso = (miso in (0, 1))
+ self.have_mosi = (mosi in (0, 1))
+ self.have_cs = (cs in (0, 1))
+
+ # State machine.
+ if self.state == 'IDLE':
+ self.find_clk_edge(miso, mosi, clk, cs)
+ else:
+ raise Exception('Invalid state: %s' % self.state)