Protocol decoder HOWTO

From sigrok
Revision as of 02:53, 26 January 2012 by Uwe Hermann (talk | contribs) (Protocol decoder HOWTO)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

This page serves as a quick-start guide for people who want to write their own sigrok protocol decoders (PDs).

It is not intended to replace the Protocol Decoder API page, but rather to give a short overview/tutorial and some tips.

Introduction

TODO.

Files

  • __init_.py
  • <decodername>.py
  • ...

Protocol decoder skeleton

This is a minimalistic framework/example for a sigrok protocol decoder (license header, comments, and some other parts omitted):

 import sigrokdecode as srd
 
 '''
 <Module-level docstring, accessible by frontends via the libsigrokdecode API>
 '''
 
 class Decoder(srd.Decoder):
     api_version = 1
     id = 'i2c'
     name = 'I2C'
     longname = 'Inter-Integrated Circuit'
     desc = '<Short, one-line description>'
     longdesc = '<Long, multi-line description>'
     license = 'gplv2+'
     inputs = ['logic']
     outputs = ['i2c']
     probes = [
         {'id': 'scl', 'name': 'SCL', 'desc': 'Serial clock line'},
         {'id': 'sda', 'name': 'SDA', 'desc': 'Serial data line'},
     ]
     optional_probes = []
     options = {
         'addressing': ['Slave address size (in bits)', 7],
     }
     annotations = [
         ['ASCII', 'Annotations in ASCII format'],
     ]
 
     def __init__(self, **kwargs):
         self.state = 'IDLE'
 
     def start(self, metadata):
         self.samplerate = metadata['samplerate']
         self.out_proto = self.add(srd.OUTPUT_PROTO, 'i2c')
         self.out_ann = self.add(srd.OUTPUT_ANN, 'i2c')
 
     def report(self):
         # ...
 
     def decode(self, ss, es, data):
         for samplenum, (scl, sda) in data:
             # ...

Random notes, tips and tricks

  • You should only use raise in a protocol decoder to raise exceptions in cases which are a clear bug in the protocol decoder.
  • A simple and fast way to calculate a parity (i.e., count the number of 1 bits) over a number (0x55 in this example) is: ones = bin(0x55).count('1').
  • A simple function to convert a BCD number (max. 8 bits) to an integer is: def bcd2int(b): return (b & 0x0f) + ((b >> 4) * 10).
  • A nice way to construct method names according to (e.g.) protocol commands is: fn = getattr(self, 'handle_cmd_0x%02x' % cmd); fn(arg1, arg2, ...).