<jupyter_start><jupyter_text>Decoding I2C Transactions using Trace Analyzer---  Aim* This notebook shows how to use the trace analyzer to capture and analyze the run-time patterns on digital I/O pins. It requires the use of Pmod TMP2 sensor. With minor changes to the notebook script, other I2C sensors can also be tested. References* [Pmod TMP2](https://store.digilentinc.com/pmod-tmp2-temperature-sensor/)     Revision History* Initial Release---  Load _base_ OverlayThe trace analyzer for all the interfaces are exposed from the base overlay.<jupyter_code>from pynq.overlays.base import BaseOverlay

overlay = BaseOverlay('base.bit')
trace_analyzer = overlay.trace_pmod0<jupyter_output><empty_output><jupyter_text>![](./images/trace_analyzer_block.png)   Fig 1. Trace Analyzer Block Diagram  Setup the trace analyzerThe I2C controller on PMODA interface runs at 100KHz, it is recommended to oversample the transactions (capturing more than 2 samples per logic level). Hence here we set the sampling frequency to 400KHz.Since we are intrested in one temperature read transaction to capture, which will last for about 360 samples, we set number of samples to 400.<jupyter_code>trace_analyzer.setup(frequency_mhz=0.4, num_analyzer_samples=400)<jupyter_output><empty_output><jupyter_text>Make Physical Connections     Insert the PMOD TMP2 sensor into the PMODA connector.  Instantiate the I2C-based PMOD_TMP2 sensor<jupyter_code>from pynq.lib.pmod import Pmod_TMP2

sensor = Pmod_TMP2(overlay.PMODA)<jupyter_output><empty_output><jupyter_text>Run the trace analyzerStart the run the trace analyzer, followed by the sensor reading the temperature values in degree C.<jupyter_code>trace_analyzer.run()
reading = sensor.read()
trace_analyzer.stop()

print('Temperature is {} degree C.'.format(reading))<jupyter_output>Temperature is 29.1 degree C.<jupyter_text>After the trace analyzer has been stopped, we can call `analyze()` method to prepare all the captured samples into lanes of data. We can ignore the returned values for now because we want to see the sigrok decoded transactions as well.<jupyter_code>_ = trace_analyzer.analyze()<jupyter_output><empty_output><jupyter_text>Analyzing and decodingThe next following cells utilize the sigrok decoders. The decoders are slightly modified, so decoded transactions can be aligned with the captured samples.The next cell sets the protocol and the signal probes.Fore more information, please read https://sigrok.org/wiki/Sigrok-cli<jupyter_code>trace_analyzer.set_protocol(protocol='i2c', 
                            probes={'SCL': 'D2', 'SDA': 'D3'})<jupyter_output><empty_output><jupyter_text>Sigrok can also show the information about a specified protocol.<jupyter_code>trace_analyzer.show_protocol()<jupyter_output>ID: i2c
Name: I²C
Long name: Inter-Integrated Circuit
Description: Two-wire, multi-master, serial bus.
License: gplv2+
Annotation classes:
- start: Start condition
- repeat-start: Repeat start condition
- stop: Stop condition
- ack: ACK
- nack: NACK
- bit: Data/address bit
- address-read: Address read
- address-write: Address write
- data-read: Data read
- data-write: Data write
- warnings: Human-readable warnings
Annotation rows:
- bits (Bits): 5 
- addr-data (Address/Data): 0 1 2 3 4 6 7 8 9 
- warnings (Warnings): 10 
Required channels:
- scl (SCL): Serial clock line
- sda (SDA): Serial data line
Optional channels:
None.
Options:
- address_format: Displayed slave address format ('shifted', 'unshifted', default 'shifted')
Documentation:
I²C (Inter-Integrated Circuit) is a bidirectional, multi-master
bus using two signals (SCL = serial clock line, SDA = serial data line).<jupyter_text>After the protocol and probes have been set, we can call the `decode()` method. The path to the saved samples, the starting and ending sample numbers, and the path to the decoded file have to be specified. **Note: It is recommended not to set too large a number for samples to decode.** A very large number of decoded samples may lead to very slow rendering of the waveform display, possibly hanging the system. In this example, we only decode 1000 samples. In general, it is okay to decode less than 4000 samples at a time. Users can decode more than 4000 samples, but displaying the waveforms will become very slow.If users want to check various parts of the entire trace of samples, users can set the starting and ending positions repeatedly and rerun this cell.<jupyter_code>start_position, stop_position = 1, 400
waveform_lanes = trace_analyzer.decode('pmod_i2c_trace.csv', 
                                       start_position, stop_position,
                                       'pmod_i2c_trace.pd')<jupyter_output><empty_output><jupyter_text>Waveform displayLet's polish the waveform for better display. We will add footer and header to the waveform dictionary.For more information: http://wavedrom.com/tutorial.html<jupyter_code>waveform_dict = {'signal': waveform_lanes,
                 'foot': {'tock': start_position},
                 'head': {'text': ['tspan', {'class': 'info h3'}, 
                                   'Pmod I2C Transactions']}}<jupyter_output><empty_output><jupyter_text>The next cell will display the waveform. Users can use scrollbar to check the I2C transactions. The Pmod TMP2 sensor has the I2C base address 0x4B.The next cell will take a few seconds to render the waveform.<jupyter_code>from pynq.lib.logictools.waveform import draw_wavedrom

draw_wavedrom(waveform_dict)
from pprint import pprint

pprint(trace_analyzer.get_transactions())<jupyter_output>[{'begin': 82, 'command': 'Start', 'end': 82},
 {'begin': 86, 'command': 'Address read: 4B', 'end': 115},
 {'begin': 119, 'command': 'ACK', 'end': 123},
 {'begin': 123, 'command': 'Data read: 0E', 'end': 156},
 {'begin': 156, 'command': 'ACK', 'end': 160},
 {'begin': 160, 'command': 'Data read: 90', 'end': 193},
 {'begin': 193, 'command': 'NACK', 'end': 197},
 {'begin': 199, 'command': 'Stop', 'end': 199},
 {'begin': 200, 'command': 'Start', 'end': 200},
 {'begin': 204, 'command': 'Address read: 4B', 'end': 233},
 {'begin': 237, 'command': 'ACK', 'end': 241},
 {'begin': 241, 'command': 'Data read: 0E', 'end': 274},
 {'begin': 274, 'command': 'ACK', 'end': 278},
 {'begin': 278, 'command': 'Data read: 90', 'end': 311},
 {'begin': 311, 'command': 'NACK', 'end': 315},
 {'begin': 317, 'command': 'Stop', 'end': 317}]<jupyter_text>Cleaning upUsers can reset the trace analyzer; this will clear all the saved files (`*.csv`, `*.pd`, etc.).If users want to use a different setup, `reset()` method also has to be called.<jupyter_code>trace_analyzer.reset()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.1071858087793145, 'fraction_numerical': 0.02660853878532772, 'mean_word_length': 4.887610619469027, 'pattern_counts': {'":': 0, '<': 42, '<?xml version=': 0, '>': 42, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '11', 'dir': 'jupyter-structured-clean-dedup', 'id': '146738', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2157, 'n_tokens_neox': 1953, 'n_words': 758, 'path': 'Pynq-ZU/base/notebooks/utils/trace_analyzer_i2c.ipynb', 'repo_name': 'cathalmccabe/PYNQ-ZU', 'size': '6652'}