diff --git a/libsigrokdecode4DSL/decoders/example/pd.py b/libsigrokdecode4DSL/decoders/example/pd.py index d193c301..c84ec240 100644 --- a/libsigrokdecode4DSL/decoders/example/pd.py +++ b/libsigrokdecode4DSL/decoders/example/pd.py @@ -20,148 +20,181 @@ ## ## 开发脚本的前提条件是必须掌握python语言 -## 非windows用户,想要打印出信息,用self.printlog(string),并在控制台下运行DSView。但是最终需要注释掉,因为影响性能。 ## 更复杂的协议请查考(0-i2c、0-spi、 0-uart、1-i2c、1-spi、1-uart) -## 底层模块提供的属性有: -## 1. samplenum 数据样品位置 -## 2. matched 本次查找调用wait匹配的信息,返回一个uint64类型数值,表示0到63个通道的匹配信息 -## The prerequisite for developing scripts is to master Python language ## text block fill color table: ## [#EF2929,#F66A32,#FCAE3E,#FBCA47,#FCE94F,#CDF040,#8AE234,#4EDC44,#55D795,#64D1D2 ## ,#729FCF,#D476C4,#9D79B9,#AD7FA8,#C2629B,#D7476F] -## 导出核心模块类 +# 导出核心模块类,c代码实现的类 import sigrokdecode as srd -## 本协议模块类 +# 协议模块类 class Decoder(srd.Decoder): - ## 必须的 + # 这里定义类的一些全局变量,有一些是底层框架要求必须要写的,其它提根据需要 + # 自己加,注意缩进,不清楚请查看python手册 + + # 说明需要安装的python版本 api_version = 3 - ## 协议标识,必须唯一 - ## The protocol ID, which must be unique + # 协议标识,必须唯一,这里我们用"example"给协议命名 id = 'example' - ## 协议名称, 不一定要求跟标识一致 - ## The protocol name, it not necessarily consistent with ID - name = 'example' + # 协议名称, 不一定要求跟标识一致 + name = 'Example' - ## 协议长名称 - ## Long name - longname = 'example-devel' + # 协议长名称 + longname = 'example-lala' - ## 简介内容 - ## Descript text - desc = 'This is an example of protocol development' + # 简介内容 + desc = 'This is an example of protocol' - ## 开源协议 + # 开源协议 license = 'gplv2+' - ## 接收的输入的数据源名 - ## Ten input data source name + # 接收的输入的数据源名,如果是多层协议一起工作,可使用上一个协议的输出名 inputs = ['logic'] - ## 输出的数据类别名,可作为下层协议的输入数据源名 - ## The output data source name + # 输出的数据源名,多层协议模式下,可作为下层协议的输入数据源名 outputs = ['test'] - ## 适用范围标签 + # 适用范围标签 tags = ['Embedded/industrial'] - ## 必须要绑定的通道定义,将在界面上可见 - ## id:通道标识, 任意命名 - ## type:类型,根据需要设置一个值, -1:COMMON,0:SCLK,1:SDATA,2:ADATA - ## name:标签名 - ## desc:该通道的说明 + # 必须要绑定的通道定义,将在界面上可见 + # id:通道标识, 任意命名 + # type:类型,根据需要设置一个值, -1:COMMON,0:SCLK,1:SDATA,2:ADATA + # name:标签名 + # desc:该通道的说明 + # 注意元组的最后的逗号不能少 channels = ( {'id': 'c1', type:0, 'name': 'c1', 'desc': 'chan1-input'}, ) - ## 可选通道,其它跟上面的一样 + # 可选通道,其它跟上面的一样 optional_channels = ( - {'id': 'c2', type:0, 'name': 'c2', 'desc': 'chan2-input'}, + {'id': 'c2', type:0, 'name': 'c2', 'desc': 'chan2-input'}, ) - ## 提供给用户通过界面设置的参数,根据业务需要来定义 + # 提供给用户通过界面设置的参数,根据业务需要来定义 + # 通过self.options[id]取值,id就是各个项的id值,比如下面的"wordsize" options = ( - {'id': 'bit-len', 'desc': 'match bit length', 'default': 16, 'values': (8,16)}, - {'id': 'mode', 'desc': 'work mode', 'default': 'up','values': ('up','low')}, + # 这种参数是一个下拉列表 + {'id': 'debug_bits', 'desc': 'Print each bit', 'default': 'no', + 'values': ('yes', 'no')}, + + # 这是一个输入框 + {'id': 'wordsize', 'desc': 'Data wordsize (# bus cycles)', 'default': 0}, ) - ## 解析结果项定义 - ## annotations里的每一项可以有2到3个属性,当有3个属性时,第一个表示类型 - ## 类型对应0-16个颜色,当类型范围在200-299时,将绘制边沿箭头 + # 解析结果项定义 + # annotations里的每一项可以有2到3个属性,当有3个属性时,第一个表示类型 + # 类型对应0-16个颜色,当类型范围在200-299时,将绘制边沿箭头 annotations = ( - ('1', 'test-data1', 'example test data1'), - ('2', 'test-data2', 'example test data2'), - ('222', 'test-data3', 'example test data3'), + ('1', 'data1', 'test data1'), + ('2', 'data2', 'test data2'), + ('222', 'data3', 'test data3'), ) - ## 解析结果的行定义 + # 解析结果行定义 annotation_rows = ( - ('lab1', 'the lab1', (0,)), #可输出第1个定义的annotations类型 - ('lab2', 'the lab2', (1,2)), #可输出第1个和第2个定义的annotations类型 + # (0,)表示可输出第1个定义的annotations类型 + ('lab1', 'row1', (0,)), + + # (1,2)表示可输出第1个和第2个定义的annotations类型 + ('lab2', 'row2', (1,2)), ) - ## 构造函数,自动被调用 + # 构造函数,自动被调用 def __init__(self): + # 这里调用一个类成员函数,完成一些参数的初始化 self.reset() - ## 在这里做一些重置和定义私有变量工作 + # 重置函数,在这里做一些重置和定义类私有变量工作 def reset(self): + # 定义一个私有变量count self.count = 0 - ## 脚本开始运行时,会自动调用 - ## 注册一些解析结果类型 - ## 有: OUTPUT_ANN,OUTPUT_PYTHON,OUTPUT_BINARY,OUTPUT_META + # 开始执行解码任务时,由c底层代码自动调用一次 + # 这里,完成一些解码结果项annotation类型的注册 + # 类型有: OUTPUT_ANN,OUTPUT_PYTHON,OUTPUT_BINARY,OUTPUT_META + # self.register函数是c底层类提供的 def start(self): self.out_ann = self.register(srd.OUTPUT_ANN) - #self.out_python = self.register(srd.OUTPUT_PYTHON) - ## 定义一个输出函数 - ## a,b为采样起点和终点, value为要输出的数值 - def put_row1(self, a, b, value): - # '@%02X', 前边加@是告诉底层模块这是一个数值数据,显示格式可转化为hex/oct/bin/acii/dec - # {$}是占位符,内容由数值部分填充 - # @特殊符号和{$}占位符的特性,只有DSView版本在1.2.0以上才支持 - # []描述输出内容,第一个元素表示annotation序号,annotation的输出在哪一行由annotation_rows集合定决定 - self.put(a, b, self.out_ann, [0, ['r1:{$}', '@%02X' % value]]) - - def put_row2(self, a, b, value): - self.put(a, b, self.out_ann, [2, ['r2:{$}', '@%02X' % value]]) - + # 定义一个输出函数 + # a,b为采样位置的起点和终点 + # ann为annotations定义的项序号 + # data是一个列表,列表里有1到3个字符串,它们将显示到屏幕 + # annotation输出到哪一行由annotation_rows决定 + # self.out_ann就是上面注册的消息类型了 + # self.put是c底层类提供的函数 + def put_ann(self, a, b, ann, data): + self.put(a, b, self.out_ann, [ann, data]) - ## 触发解析工作 + # 解码函数,解码任务开始时由c底层代码调用 + # 这里不断循环等待所有采样数据被处理完成 + # 下面的未例代码是想以一对向上边沿和向下边沿,输出它们的样品位置差值, + # 同时奇数次显示第二行,偶数次显示在第一行,我们只要指定了annotations里定义的序号 + # 软件会自动根据annotation_rows的设置,决定显示在哪一行 def decode(self): + # 次数计数 times = 0 - lst_dex = self.samplenum + + # 向上边沿样品位置 + rising_sample = 0 + + # 条件参数列表 flag_arr = [{0:'r'}, {0:'f'}] + + # wait参数的条件序号 flag_dex = 0 + # 不断循环,处理完所有数据 while True: - # 从原始数据中按条件匹配数据,用于接受返回值的元组里的变量个数由通道数决定 - # 如果可选通道未绑定真实通道,则返回255,比如这里的b变成255 - # wait()不带条件,表示进行所有匹配 - #(a,b) = self.wait() - - (a,b) = self.wait(flag_arr[flag_dex]) + # 边沿条件 + edge = flag_arr[flag_dex] + + # 取一个条件,调用wait函数,找到符合条件的数据 + # (a,b)是一个元组,里边的变量数一定要跟channel数一致 + (a,b) = self.wait(edge) + # 条件在向上边沿和向下边沿中切换 + # 初始是向上边沿,取到样品位置后,切换成下向边沿 if flag_dex == 0: flag_dex = 1 - lst_dex = self.samplenum + + # 保存向上边沿采样位置 + rising_sample = self.samplenum else: flag_dex = 0 + + # 打印次数计数加1 times += 1 - if times % 2 == 0: - self.put_row1(lst_dex, self.samplenum, self.samplenum - lst_dex) - else: - self.put_row2(lst_dex, self.samplenum, self.samplenum - lst_dex) - #self.put_row3(lst_dex, self.samplenum, 0) + + # 向下边沿采样位置 + falling_sample = self.samplenum + + # 向下边沿和向上边沿采样位置差 + v = falling_sample - rising_sample + + # 转换成16进制的字符串 + s = '%02X' % v + + # 对times求余得值在0和1中变换,对应annotation的序号 + ann = times % 2 + self.put_ann(rising_sample, falling_sample, ann, [s]) - # wait({0:'f'}), 0表示通道序号(从0开始),'f'表示查找下边沿 - # wait()可传多个条件,与条件:{0:'f',1:'r'}, 或条件:[{0:'f'},{1:'r'}] - # h:高电平,l:低电平,r:上边沿,f:下边沿,e:上沿或下沿, n:要么0,要么1 - # (a,b) = self.wait([{0:'f'}]) - + # self.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里的通道数决定,包括可选通道 + # optional_channels 。例如:channels和optional_channels共定义了4个通道, + # 则变成(a,b,c,d) = self.wait(),共四个变量 + + # 底层模块提供的属性: + # 1. self.samplenum 当前wait()调用匹配结束的采样点位置 + # 2. self.matched 本次调用wait()后所有通道的匹配结果信息,是一个uint64类型数值, + # 表示0到63个通道的匹配信息,通过位运算来获取具体信息。 \ No newline at end of file