File format:protocoldata

From sigrok
Revision as of 09:47, 30 July 2023 by Gsi (talk | contribs) (mention data values separation on text lines)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
protocoldata
Name Generate logic traces from protocol's data values
Status supported
Source code (in) protocoldata.c
Source code (out)
Common extension(s) .sr-protocol, .protocol, .bin
MIME type
ASCII format yes

The Protocol data values format can be either binary or text formatted, while the text incarnation is more versatile and useful, easier to read by humans and as easy to generate by external applications. This file format is exclusive to sigrok, its syntax was made up to import UART bytes that were taken from a serial port monitor, then extended to demonstrate its versatility.

The protocoldata input module accepts a sequence of data values as input, optionally interleaved with control instructions, and (re-)creates the waveforms of several logic channels. This makes externally provided data accessible to sigrok decoders even though the capture was not taken by sigrok means and does not come in one of the other supported input formats that sigrok can import.

Several serial protocols are implemented within the input module (currently these are: UART, SPI, and I2C). Adding more protocol handlers is straight forward. The text language is rather expressive and easy to extend, it is assumed that existing infrastructure lends itself well to other protocols that stress different features (controlling select lines, additional ack slots, multiple quanta in a bit slot, phases of differing width, bit stuffing, optional inversion and adjustable signal polarity, etc etc).

Format

File content overview, alternative input formats

The file content can take different forms of varying flexibility:

  • File content can be binary. Every byte is one data value. A given protocol handler will create "protocol frames" from these data values, the meaning of which depends on the specific protocol. In the UART case one byte corresponds to one UART frame. Other protocols could support the concept of "frames" which span multiple bytes, which necessitates control over a select line or other frame marker, which is beyond the scope of binary input which exclusively carries data values.
  • An optional leading magic string can start an input file. Which allows for automatic detection of the file format, and obsoletes the necessity that users specify the format upon import. It's understood that specifying input module options does require the specification of an input module which the options shall get applied to.
  • An optional header section can follow the magic file format detection string. The header section is surrounded by start and end markers for reliable detection. Lines within the header section can carry input module options. User specified options take precedence over file content.
  • Data values follow the (optional) file format detection string and the (optional) header section. In other words a file can exclusively consist of data values, or optionally can provide more details to self describe its content and support automatic loading without any user specs.
  • As an alternative to binary input, data values can also be in text format. A header item in the file content, or a user provided option, can switch to the text format for the data section of the file content. Protocol handlers can also prefer one format over the other. Some protocols (many? most?) require instructions beyond data values to become useful.
  • Text input supports the concept of comment lines. These start at a comment marker, and span to the end of the text line. Comments get discarded upon reception, non-comment lines carry data values in text format. The current implementation does not support mixing data values and comments on the same text line.
  • The text format reader and protocol handlers support the concept of pseudo comments. These affect and control the interpretation of following text input, and the creation of waveforms for logic traces as data values are seen.

Common concepts, protocol agnostic keywords

See the --show output for a list of input module options. These correspond to the header section items below.

The string literal for the file format detection is rather long, to reduce the probability of false matches. If your binary input happens to start with this very sequence, consider adding an arbitrary byte before or within these first few bytes, to avoid the erroneous detection which would "consume" the leading text and would not interpret it as data values.

 # -- sigrok protocol data values file --

The header section start and end markers are similarly long to again reduce the probability of false detection. The header section MUST immediately follow the file format detection string, and precedes the data section of the file content.

 # -- sigrok protocol data header start --
 ... header lines go here, carrying input module options ...
 # -- sigrok protocol data header end --

Comment lines in the header section are ignored. Non-comment lines in the header section carry input module options. Each option occupies a separate line. All of them are optional. Empty lines get ignored.

Supported header line keywords are:

 samplerate=<number>
 bitrate=<number>
 protocol=<string>
 frameformat=<string>
 textinput=<bool>

  • samplerate= takes an integer number, and configures the samplerate of the generated logic traces waveform
  • bitrate= takes an integer number, and specifies the protocol's bitrate
  • protocol= takes a string value, which selects the protocol handler to have the waveform generated
  • frameformat= takes a string value, its interpretation depends on the selected protocol, multiple details can be space or comma separated
  • textinput= takes a boolean value, false translates to binary input, true translates to text formatted input data

The data section which follows the optional header is either a sequence of bytes (binary input) where every byte is one data value. Or a sequence of text lines which carry data values in text form (non-comments), or comments, or pseudo comments.

Data values in text form support different presentations as seen in programming languages: decimal by default, binary if selected by the '0b' prefix, octal if preceded by a '0' digit, hexadecimal when prefixed with '0x'. Pseudo comments can configure the default base, the conversion base can be changed any number of times within the data section. The radix= value is always interpreted as a decimal number.

A text line can carry any number of data values. Values on a text line can be space or comma or semicolon separated. Values can occupy up to 32 bits. The interpretation of data values is at the protocol handler's discretion. Some of them can be taken as the number of values to follow (to form a frame in the specific protocol's context), some can select alternative frame formats (think CAN A and B), some can be taken as addresses instead of payload data, etc. In other words, not all data values in the input file need to show up in verbatim form in the generated waveform.

 # decimal values
 32 33 34 35
 # other radices, explicit prefix
 0b10101010 0377 0xaffe
 # default base aka radix
 # textinput: radix=16
 20 21 22 23
 # explicit prefix and default radix also works
 # textinput: radix=16
 0x30 0x31 0x32 0x33
 # comma separation simplifies data exchange with other applications
 1, 2, 3,

Pseudo comments are prefixed to either apply them to the text input reader ('textinput:' prefix) or the protocol handler (protocol name and a colon as prefix). One or more whitespace separated words follow, one pseudo comment line can carry multiple instructions.

 # textinput: <instruction>...
 # <protocol name>: <instruction>...

The text input reader instructions apply universally to all input files regardless of the selected protocol. Supported instructions are:

 # textinput: radix=<number>

  • radix= specifies the base for the text to number conversion. The argument is always taken as a decimal number.

UART protocol specific keywords

The UART protocol handler supports these frame format specs in the header section:

 frameformat=<format detail>...
 frameformat=8e2,inverted

Supported frame format keywords:

  • 8n1 et al, specifies the number of data bits, parity type, and number of stop bits
  • inverted inverts the polarity of the RX/TX signal

UART protocol specific pseudo comments take the form:

 # uart: <instruction>...
 # uart: idle
 # uart: break

Supported pseudo comment instructions:

  • idle inserts a period of idle level (length of a UART frame)
  • break sends the BREAK signal (low RX/TX signal for the length of a UART frame)

SPI protocol specific keywords

The SPI protocol handler supports these frame format specs in the header section:

 frameformat=<format detail>...
 frameformat=cs-low,bits=8,mode=0,msb-first

Supported frame format keywords:

  • cs-low, cs-high specify the polarity of the chip select signal
  • bits=<number> selects the number of data bits, the current implementation exclusively supports bytes with 8 bits
  • mode=<number>, cpol=<number>, cpha=<number> specifies the SPI mode (a number in the 0..3 range), or controls CPHA and CPOL (numbers 0 or 1)
  • msb-first, lsb-first specifies the bit order within a byte

SPI protocol specific pseudo comments take the form:

 # spi: <instruction>...
 # spi: mosi-only miso-only mosi-then-miso miso-then-mosi
 # spi: mosi-fixed=<number> miso-fixed=<number>
 # spi: cs-assert cs-release
 # spi: cs-auto-next=<number>
 # spi: idle

Supported pseudo comment instructions:

  • mosi-only, miso-only, mosi-then-miso, miso-then-mosi control how many data values are required to form one byte time and their order in the input stream
  • mosi-fixed=, miso-fixed= accept a value (in the currently effective base) and assume a fixed value for the specified part of the byte time, requiring only the variable value to be in the input stream
  • cs-assert, cs-release explicitly control the chip select signal, usually data values are between those opening and closing markers
  • cs-auto-next= automatically controls the chip select signal, assumes a period spanning the specified number of byte times; the number argument (the byte times count) is interpreted with a zero radix, which means it's decimal by default unless prefixed for other number formats, in other words the currently effective radix for data values text conversion does not apply here
  • idle generates a waveform the length of a byte time, with clocks but not data when chip select is active, or without clock outside of active select

I2C protocol specific keywords

The I2C protocol handler supports these frame format specs in the header section:

 frameformat=<format detail>...
 frameformat=addr-7bit
 frameformat=addr-10bit

Supported frame format keywords:

  • addr-7bit, addr-10bit specifies whether slave addresses are of the 7bit or 10bit kind

I2C protocol specific pseudo comments take the form:

 # i2c: <instruction>...
 # i2c: start repeat-start stop
 # i2c: addr-write=<addr> addr-read=<addr>
 # i2c: ack-next ack-next=<count>

Supported pseudo comment instructions:

  • start, repeat-start, stop generate waveforms that communicate the respective condition, start and repeated start are identical from the implementation point of view, but their keywords serve as documentation in pseudo comments
  • addr-write=, addr-read= generate bytes on the wire which carry the user perspective's slave address including the read/write control bit, these instructions consume exactly one ack count regardless of address format; the slave address is interpreted with a zero radix, which means it is decimal by default unless prefixed for other number formats, the currently effective data values conversion radix does not apply here
  • ack-next, ack-next= arrange for the next number of bytes to have ACK active (dominant), after that count's expiration bytes will be NAKed (recessive), ack-next without a count is a convenience to mean the counter value is 1; the number argument is interpreted with a zero radix, which means that it is decimal by default unless prefixed for other number formats, the currently effective data values conversion radix does not apply here

Example file content, example invocations

general invocation

 $ sigrok-cli -I protocoldata --show
 ID: protocoldata
 Name: Protocol data
 Description: Generate logic traces from protocol's data values
 Options:
   samplerate: Samplerate of generated logic traces (default 0)
   bitrate: Bitrate used in protocol's communication (default 0)
   protocol: The type of protocol to generate waveforms for (default ' ', possible values 'uart', 'spi', 'i2c')
   frameformat: Textual description of the protocol's frame format (default ' ')
   textinput: Input is not data bytes, but text formatted values (default 'from-file', possible values 'from-file', 'raw-bytes', 'text-format')

binary format, UART protocol

 $ echo "Hello UART" | sigrok-cli -I protocoldata -i - --show
 Samplerate: 1000000
 Channels: 1
 - rxtx: logic
 Logic unitsize: 1
 Logic sample count: 1360

 $ echo "Hello UART" | sigrok-cli -I protocoldata -i - -P uart:format=ascii -A uart=rx-data
 uart-1: H
 uart-1: e
 uart-1: l
 uart-1: l
 uart-1: o
 uart-1:  
 uart-1: U
 uart-1: A
 uart-1: R
 uart-1: T
 uart-1: [0A]

text format, UART protocol

 $ cat proto-uart-futaba.txt
 # -- sigrok protocol data values file --
 # -- sigrok protocol data header start --
 # synthetic data for SBUS decoder development
 
 protocol=uart
 bitrate=100000
 frameformat=8e2,inverted
 textinput=yes
 
 # -- sigrok protocol data header end --
 
 # SBUS Futaba packet layout: header, 16x 11bit dense, flags, footer (then idle)
 0b00001111
 # textinput: radix=16
 40 a6 28 fa 78 05 19 ee c2 92 70  58 62 09 a9 f1 ca 44 90 d1 07 19
 # textinput: radix=0
 0b00000010
 0
 # uart: idle idle idle
 
 # SBUS Futaba packet layout: header, 16x 11bit dense, flags, footer (then idle)
 0b00001111
 # textinput: radix=16
 58 62 09 a9 f1 ca 44 90 d1 07 19  40 a6 28 fa 78 05 19 ee c2 92 70
 # textinput: radix=0
 0b00000001
 0
 # uart: idle idle idle

 $ sigrok-cli -i proto-uart-futaba.txt  \
   -P uart:invert_rx=yes:baudrate=100000:parity=even,sbus_futaba -A sbus_futaba  \
   --protocol-decoder-ann-class
 sbus_futaba-1: header: 0x0f
 sbus_futaba-1: proportional: 1600
 sbus_futaba-1: proportional: 1300
 sbus_futaba-1: proportional: 1000
 sbus_futaba-1: proportional: 700
 sbus_futaba-1: proportional: 400
 sbus_futaba-1: proportional: 1500
 sbus_futaba-1: proportional: 1200
 sbus_futaba-1: proportional: 900
 sbus_futaba-1: proportional: 600
 sbus_futaba-1: proportional: 300
 sbus_futaba-1: proportional: 1700
 sbus_futaba-1: proportional: 1400
 sbus_futaba-1: proportional: 1100
 sbus_futaba-1: proportional: 800
 sbus_futaba-1: proportional: 500
 sbus_futaba-1: proportional: 200
 sbus_futaba-1: digital: 0
 sbus_futaba-1: digital: 1
 sbus_futaba-1: framelost: 0
 sbus_futaba-1: failsafe: 0
 sbus_futaba-1: footer: 0x00
 sbus_futaba-1: header: 0x0f
 sbus_futaba-1: proportional: 600
 sbus_futaba-1: proportional: 300
 sbus_futaba-1: proportional: 1700
 sbus_futaba-1: proportional: 1400
 sbus_futaba-1: proportional: 1100
 sbus_futaba-1: proportional: 800
 sbus_futaba-1: proportional: 500
 sbus_futaba-1: proportional: 200
 sbus_futaba-1: proportional: 1600
 sbus_futaba-1: proportional: 1300
 sbus_futaba-1: proportional: 1000
 sbus_futaba-1: proportional: 700
 sbus_futaba-1: proportional: 400
 sbus_futaba-1: proportional: 1500
 sbus_futaba-1: proportional: 1200
 sbus_futaba-1: proportional: 900
 sbus_futaba-1: digital: 1
 sbus_futaba-1: digital: 0
 sbus_futaba-1: framelost: 0
 sbus_futaba-1: failsafe: 0
 sbus_futaba-1: footer: 0x00

 $ pulseview -i proto-uart-futaba.txt &

UART example screenshot

text format, SPI protocol

 $ cat proto-spi-example.txt
 # -- sigrok protocol data values file --
 # -- sigrok protocol data header start --
 
 protocol=spi
 textinput=yes
 
 # -- sigrok protocol data header end --
 # textinput: radix=16
 
 # spi: cs-assert
 de be  ad ef
 # spi: cs-release
 
 # spi: cs-auto-next=3
 de be  ad ef  00 ff
 
 # spi: mosi-only miso-fixed=aa
 # spi: cs-assert
 01 02 03 04
 # spi: idle
 # spi: cs-release
 
 # spi: idle
 
 # spi: miso-only mosi-fixed=55
 # spi: cs-assert
 # spi: idle
 21 22 23 24
 # spi: cs-release
 
 # spi: mosi-then-miso
 # spi: cs-assert
 05 35  06 36  07 37  08 38
 # spi: cs-release

 $ sigrok-cli -i proto-spi-example.txt  \
   -P spi:clk=sck:miso=miso:mosi=mosi:cs=cs -A spi=mosi-transfers:miso-transfers  \
   --protocol-decoder-ann-class
 spi-1: miso-transfer: BE EF
 spi-1: mosi-transfer: DE AD
 spi-1: miso-transfer: BE EF FF
 spi-1: mosi-transfer: DE AD 00
 spi-1: miso-transfer: AA AA AA AA 00
 spi-1: mosi-transfer: 01 02 03 04 00
 spi-1: miso-transfer: 00 21 22 23 24
 spi-1: mosi-transfer: 00 55 55 55 55
 spi-1: miso-transfer: 35 36 37 38
 spi-1: mosi-transfer: 05 06 07 08

 $ pulseview -i proto-spi-example.txt &

SPI example screenshot

text format, I2C protocol

 $ cat proto-i2c-example.txt
 # -- sigrok protocol data values file --
 # -- sigrok protocol data header start --
 
 protocol=i2c
 frameformat=addr-10bit
 
 # -- sigrok protocol data header end --
 # textinput: radix=16
 
 # EEPROM write, addr 0x52, mem addr 0x30, bytes 01 02 03 04
 # i2c: start ack-next addr-write=0x52 ack-next=5
 30  01 02 03 04
 # i2c: stop
 
 # EEPROM read, addr 0x51, mem addr 0x20, bytes 05 06 07 08
 # i2c: start ack-next addr-write=0x51 ack-next
 20
 # i2c: repeat-start ack-next addr-read=0x51 ack-next=3
 05 06 07 08
 # i2c: stop

 $ sigrok-cli -i proto-i2c-example.txt \ 
   -P i2c:scl=scl:sda=sda -A i2c=addr-data \
   --protocol-decoder-ann-class  \
 i2c-1: start: Start
 i2c-1: address-write: Address write: 78
 i2c-1: address-write: Write
 i2c-1: ack: ACK
 i2c-1: address-write: Address write: 52
 i2c-1: ack: ACK
 i2c-1: data-write: Data write: 30
 i2c-1: ack: ACK
 i2c-1: data-write: Data write: 01
 i2c-1: ack: ACK
 i2c-1: data-write: Data write: 02
 i2c-1: ack: ACK
 i2c-1: data-write: Data write: 03
 i2c-1: ack: ACK
 i2c-1: data-write: Data write: 04
 i2c-1: ack: ACK
 i2c-1: stop: Stop
 i2c-1: start: Start
 i2c-1: address-write: Address write: 78
 i2c-1: address-write: Write
 i2c-1: ack: ACK
 i2c-1: address-write: Address write: 51
 i2c-1: ack: ACK
 i2c-1: data-write: Data write: 20
 i2c-1: ack: ACK
 i2c-1: repeat-start: Start repeat
 i2c-1: address-read: Address read: 78
 i2c-1: address-read: Read
 i2c-1: ack: ACK
 i2c-1: address-read: Address read: 51
 i2c-1: ack: ACK
 i2c-1: data-read: Data read: 05
 i2c-1: ack: ACK
 i2c-1: data-read: Data read: 06
 i2c-1: ack: ACK
 i2c-1: data-read: Data read: 07
 i2c-1: ack: ACK
 i2c-1: data-read: Data read: 08
 i2c-1: nack: NACK
 i2c-1: stop: Stop

 $ pulseview -i proto-i2c-example.txt &

I2C example screenshot