在DSView安装目录下,有一个decoders文件夹,里面有许多目录是以各种协议名称命名的。每个目录下有至少2个扩展名为.py的文件,这些都是python代码文件。在linux系统下,decoders目录位于”/usr/local/share/libsigrokdecode4DSL”下。
DSView通过底层python解释器执行python代码,对逻辑分析仪的数据进行解析,按各种算法得出需要的结果。每个协议目录下必须存在两个文件:
python语言是一个解释执行的语言。在官方网站下载并安装好python,就可以进行开发了。
新建一个文本文件,里边输入一行文字:
print('Hello,world!')
保存为 test.py,然后在命令行里输入
python test.py
将会输出“Hello,world!”
这里的python入门只是为了帮助一些读者能够顺利阅读部分协议代码,它所讲的python知识还不够全面和深入,需要读者自行通过其它方式获得python资料,以便提升自己的python编程能力。
from .pd import Decoder
以下是解码协议代码框架,写在pd.py文件里。所有协议的代码核心部分是一样的。
下面从c模块继承一个类:
import sigrokdecode as srd class Decoder(srd.Decoder): api_version = 3 ##协议标识,必须唯一 id = 'bala' ##协议名称, 不一定要求跟标识一致 name = 'bala' ##协议长名称 longname = 'bala protocal' ##简介内容 desc = 'This is an example' ##开源协议 license = 'gplv2+' #第一句是导出c底层的模块 #第二句是定义一个类,继承自c底层的类
inputs = ['logic'] #接收的输入的数据源,默认是是逻辑分析仪数据 #在多层协议模式下,可使用上层协议的输出名
outputs = ['bala'] #输出的数据源名,在多层协议模式下, #其它协议可以使用这个输出名指定数据输入来源
tags = ['Embedded/industrial'] #协议的适用范围标签
channels = ( {'id': 'c1', type:0, 'name': 'c1', 'desc': 'chan1-input'}, ) #必须要绑定的通道 #id:通道标识, 任意命名 #'type':类型,有: -1:COMMON,0:SCLK,1:SDATA,2:ADATA #name:标签名 #desc:该通道的说明
optional_channels = ( {'id': 'c2', type:0, 'name': 'c2', 'desc': 'chan2-input'}, ) #可选通道,其它跟上面的一样
options = ( {'id': 'debug_bits','desc': 'Print each bit', 'default': 'no', 'values': ('yes', 'no')}, {'id': 'wordsize', 'desc': 'Data wordsize', 'default': 0}, ) #提供给用户通过界面设置的参数 #根据业务需要来定义 #通过'self.options[id]'取值,id就是各个项的id值, #比如下面的'wordsize' #上面第一项是下拉框,第二项是输入框
annotations = ( ('1', 'data1', 'test1'), ('2', 'data2', 'test2'), ('222', 'data3', 'test3'), ) #解析结果项定义 #annotations里每一项可以有2到3个属性, #当有3个属性时,第一个表示类型 #类型对应0-16个颜色,当类型范围 #在200-299时,将绘制边沿箭头
annotation_rows = ( ('lab1', 'row1', (0,)), ('lab2', 'row2', (1,2)), ) #解析结果行定义 #(0,)表示可输出第1个定义的annotations类型 #(1,2)表示可输出第2个和第3个定义的annotations类型
def __init__(self): self.reset() #这里调用reset函数,完成一些变量的初始化 #构造函数,自动被调用, #这里调用reset函数完成一个变量的初始化
def reset(self): self.count = 0 #初始化函数,这里定义类的私有变量
def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) #这里注册消息类型 #开始执行解码任务时,由c底层代码自动调用一次 #这里,完成一些解码结果项annotation类型的注册 #有: OUTPUT_ANN、OUTPUT_PYTHON、 #OUTPUT_BINARY、OUTPUT_META #register函数是c底层类提供的
def put_ann(self,a,b,ann,data): self.put(a, b, self.out_ann, [ann, data]) #输出内容 #a,b为采样位置的起点和终点 #ann为annotations定义的项序号 #data是一个列表,列表里有1到3个字符串,它们将显示到屏幕 #annotation输出到哪一行由annotation_rows决定 #self.out_ann就是上面注册的消息类型了 #self.put是c底层类提供的函数
def decode(self): while True: (a,b)=self.wait({0:'r'}) #一直调用,直到所有数据处理完 #解码任务开始时由c底层代码调用 #这里不断循环等待所有采样数据被处理完成 #wait函数参数详解: #wait函数可带参数,也可以不带参数, #不带参数时将返回每个采样数据 #参数'{0:'r'}', 0表示匹配channels第1 #项绑定的通道,r表示查找向上边沿 #wait函数可传多个条件, #与条件:{0:'f',1:'r'}, #或条件:[{0:'f'},{1:'r'}] #h:高电平,l:低电平,r:向上边沿, #f:向下边沿, #e:向上沿或向下沿, #n:要么0,要么1 #wait函数前的变量(a,b),数量由定义 #的channels里的通道数决定,包括可选通道 #例如:共定义了4个通道, #则变成(a,b,c,d) = self.wait()
#c底层提供了两个属性: self.samplenum #当前wait()调用匹配结束的采样点位置 self.matched #是一个uint64类型数值, #表示0到63个通道的匹配信息, #通过位运算来获取具体信息。
到这里,解码协议代码框架模板结束。
在上面代码框架的基础上,我们接下来实现一个简单的例子。具体是,通过解码某一通道的数据,从一个向上边沿开始到向下边沿结束,输出采样点差值信息。奇数次输出放在第二行,偶数次输出放在第一行。具体编码和说明如下:
def decode(self): times = 0 rising_sample = 0 flag_arr = [{0:'r'}, {0:'f'}] flag_dex = 0 while True: edge = flag_arr[flag_dex] (a,b) = self.wait(edge) if flag_dex == 0: flag_dex = 1 rising_sample = self.samplenum else: flag_dex = 0 times += 1 falling_sample = self.samplenum v = falling_sample - rising_sample s = '%02X' % v ann = times % 2 self.put_ann(rising_sample, falling_sample, ann, [s]) #times用于输出次数计数,偶数次输出到第一行,奇数次输出到第二行 #ann = times % 2 对次数变量求余,其值在0和1中变换,调用put_ann时指定了annotation的序号 #再根据序号由annotation_rows决定输出在哪一行 #边沿条件就两种:向上和向下,调用wait函数时,在这两个边沿条件中切换 #首次是取向上边沿,然后再换成向下边沿 #每次调用wait后,通过self.samplenum取采样位置 #求出两次的样品位置差后,转换成16进制的字符串,通过类函数put_ann输出
通过c代码和python代码的互操作,将采样数据交给python分析。经过一系列的处理,最终生成解码结果,用于显示以及供给上层协议作为分析的数据来源。解码模块的核心主要由以下部分组成:
import sigrokdecode as srd
python可访问的Decoder基类的方法有:
python调用方式:
self.out_ann=self.register(srd.OUTPUT_ANN) self.out_py=self.register(srd.OUTPUT_PYTHON)
put方法
输出数据到屏幕或上层协议,python调用方式:
self.put(a,b,self.out_ann,[0,['abc']])
其中,a、b为采样点区间值,self.out_ann为注册的消息类型,[0,[‘abc’]], 0为消息类型序号,参考之前的内容;[‘abc’]为消息内容了
wait方法
获得上一次分析位置后的采样数据,可通过参数指定边沿查找条件。
调用方式: self.wait()
可指定参数,如:{0,’r’}表示第1个绑定的通道满足向上边沿的数据;{1,’f’}表示第2个绑定通道足向下边沿的数据。其它条件标志还有:h、l、e、n。
可通过多个条件组成并和或的条件。并条件如:{0:’f’,1:’r’},或条件如:[{0:’f’},{1:’r’}]
self.has_channel(0)
0是通道序号。
import sigrokdecode as srd class Decoder(srd.Decoder):
子类Decoder的方法有:
self.name = 'abc'
self.out_ann = self.register(srd.OUTPUT_ANN) self.out_py = self.register(srd.OUTPUT_PYTHON)
while True: (a,b) = self.wait()
(a,b)元组里的变量数跟声明的chnnaels里声明的通道数一致,包括可选的通道上。
解码任务执行流程:
在DSView版本1.2.0以上,更新以下功能:
self.put(s, e, self.out_ann, [1,['%02X' % value])
put函数将数据输出c底层,并在屏幕上显示。其中,value为要显示的数据。在输出到时需要转换为16进制的字符串。当需要让数据支持在多种格式间转换时,代码修改如下:
self.put(s, e, self.out_ann, [1,['@' + '%02X' % value])
它是通过在数据部分前加@符号,告诉c底层这一部分内空是数据部分,如:
'@66FB'
如果存在前缀文字,需要将格式部分和数据部分开,如:
['Data:{$}','D:{$}', '@66FB']
{$}是占位符,系统将数据部分格式化后替换掉占位符,就会变成:Data:66FB
全部0条评论
快来发表一下你的评论吧 !