当前位置: 首页 > news >正文

[GN] sigrokdecode 模块

系列文章目录

sigrokdecode 模块学习指南 — 准备阶段
通讯协议 - Uart
sigrokdecode 模块



前言

libsigrokdecode 为我们提供了一个 sigrokdecode 模块。它包含以下三种数据 :

  • sigrokdecode.Decoder 类
  • 5个常量
  • 解码成功, 返回三个特殊变量: samplenum 数值 、 matched 元组 、pinvalues 元组

sigrokdecode.Decoder 类

是很重要的一个类, 所有的协议解码器都是基于这个类而创建。

四个方法

它还为我们提供了以下四种方法 (函数) :

  • put(startsample, endsample, output_id, data)

    此函数用于将解码后的数据提供给底层库, 例如注释, 或者叠加协议时底层协议(例如: spi )传输给上层协议(例如: spi flash)的数据

    • startsample 指定解码数据/注释的起始位置
    • endsample 指定解码数据/注释的结束位置
    • output_id 是由 register() 函数返回的输出标识符: OUTPUT_ANN/OUTPUT_PYTHON/OUTPUT_BINARY/OUTPUT_META
    • data 参数的内容取决于输出类型 ( output_id ), 关于具体的数据类型, 请参考下面 5个常量 小节内容
  • register(output_type)

    此函数用于注册解码器输出数据的类型, 该函数会返回一个标识符, 然后可以将其用作 put() 函数的 output_id 参数。

    • output_type:OUTPUT_ANN/OUTPUT_PYTHON/OUTPUT_BINARY/OUTPUT_META
  • wait(conds)

    此函数由解码器调用, 参数 conds 传入查询条件, 底层 C 库会在采样数据中找到指定的条件, 才会将控制权返回给解码器。这是一个阻塞调用, 只有找到指定条件时, 才会返回。

    • 等待直到 conds 中的一个或多个条件匹配, 才会返回
    • self.samplenum 设置为匹配样本的当前位置 (绝对位置)
    • 根据匹配的条件设置 self.matched
    • 返回一个元组, 其中包含匹配样本的当前引脚值
  • has_channel(idx)

    此函数会根据输入的通道编号 idx 判断当前的可选通道是否存在, 存在返回 True, 否则返回 False

    • idx 可选通道的ID

register(output_type) 返回 output_id 用作 put() 函数。【output_type有四个类型——OUTPUT_ANN;OUTPUT_PYTHON;OUTPUT_BINARY;OUTPUT_META】

put(startsample, endsample, output_id, data) data取决于输出类型output_id

wait(conds) 函数

conds 中可以提供多个条件, 支持逻辑或和逻辑与判断。 条件可以是 列表[] 表示 或逻辑, 如果是 字典{} 表示 与逻辑

conds 条件

看过前文我们知道 wait(conds) 函数 需要一个 conds 条件 参数, 那我们如何写这个条件呢?

单个条件始终是 Python 中的 字典dict, 其中可以包含零个或多个键/值对。键 (和值) 可以是不同的类型。

libsigrokdecode 为我们提供了6种 引脚状态条件 定义, 其他值都会导致出错。

  • 'l' : 低引脚值 (逻辑 0)
  • 'h' : 高引脚值 (逻辑 1)
  • 'r' : 上升沿
  • 'f' : 下降沿
  • 'e' : 任一边缘 (上升或下降)
  • 's' : 稳定状态, 与’e’相反。也就是说, 没有边沿, 当前和前一个引脚值都为低 (或都为高)
# 等待 pin 2/3/4 为低且 pin 16 有任何边沿
pins = self.wait({2: 'l', 3: 'l', 4: 'l', 16: 'e'})

# 等待 引脚 9 的上升沿          或
# 引脚 27 上的高状态 (逻辑 1)   或
# 样本超过 1000 个样本数
pins = self.wait([{9: 'r'}, {27: 'h'}, {'skip': 1000}])
跳过条件

在解码器中是一种很常见的条件, 它不会关心引脚电平。 当解码器想要跳过一定数量的样本时, 可以使用这个条件。

跳过条件 可以通过条件 字典 中的特殊键 'skip' 来完成

# 跳过接下来的 100 个样本
pins = self.wait({'skip': 100})

# 跳过接下来的 20ms 样本
pins = self.wait({'skip': 20 * (1000 / self.samplerate)})

# 跳过半个位宽的样本 (例如 UART)
self.halfbitwidth = int((self.samplerate / self.options['baudrate']) / 2.0)
pins = self.wait({'skip': self.halfbitwidth})

5个常量

前面在讲到 register(output_type) 函数时提到过这个输入参数 output_type, 下面我们就来介绍一下这个参数值。

libsigrokdecode 是一个功能很完善的协议解码库, 为了解决解码器处理不同数据的问题, 定义了以下四种数据类型 :

  • OUTPUT_ANN 用于注册注释数据输出的常量, 用于输出解码后的注释字符串数据。
  • OUTPUT_PYTHON 用于注册 Python 数据输出的常量。 这个会在协议叠加的时候用到, Python 输出数据作为输入数据传递给堆叠到当前解码器上的上层解码器。
  • OUTPUT_BINARY 用于注册二进制数据输出的常量。 未指定输出数据的格式, 由解码器选择一种 (或多种) 合适的格式。例如: UART 解码器输出它解码的原始字节, I²S 解码器输出 WAV 格式的音频, 但对于解码显示协议的解码器, 输出也可以是图像 (JPG、PNG 等) 文件, 或许多其他格式之一。
  • OUTPUT_META 用于注册自定义数据输出的常量。 可以参考 SPI 解码器源码。

OUTPUT_ANN:

数据参数是一个包含两项的 Python 列表。第一项是注释索引 (由解码器 annotations 中的项顺序确定) , 第二项是注释字符串列表。字符串应该是相同注释文本的更长和更短版本 (按长度排序, 最长的在前) , 前端可以使用它们根据缩放级别显示不同的注释文本。

# 输出的数据跨越 10 到 20 个样本
# 类型为 OUTPUT_ANN, 注释索引为 4, 注释字符串列表为 “Start”、“St”、“S”
self.put(10, 20, self.out_ann, [4, ['Start', 'St', 'S']])

# 输出的数据跨越 10 到 20 个样本
# 类型为 OUTPUT_ANN, 注释索引为 4, 注释字符串列表只是“CRC” (该列表仅包含一项)
self.put(10, 20, self.out_ann, [4, ['CRC']])

OUTPUT_PYTHON

数据参数是将传递给叠加解码器的 Python 对象数据, 格式和内容完全取决于解码器。

# 发出的数据跨越 10 到 20 个样本
# 类型为 OUTPUT_PYTHON, 数据内容本身完全取决于相应的解码器, 记录在其pd.py文件中
self.put(10, 20, self.out_python, ['PACKET', ['Foo', 19.7, [1, 2, 3], ('bar', 'baz')]])

OUTPUT_BINARY

数据参数是一个包含两项的 Python 列表。第一项是二进制格式的索引 (由解码器 binary 中项目的顺序确定) , 第二项是 Python 字节对象

# 发出的数据跨越 10 到 20 个样本
# 类型为 OUTPUT_BINARY, 二进制格式的索引为 4, 发出的字节为 0xfe、0x55、0xaa
self.put(10, 20, self.out_binary, [4, b'\xfe\x55\xaa'])

OUTPUT_META:

数据参数是特定类型的 Python 对象, 在各自的 register() 函数中定义

# 发出的数据跨越 10 到 20 个样本
# 属于 OUTPUT_META 类型, 在这种情况下, 数据本身是一个浮点数。
self.put(10, 20, self.out_meta, 15.7)

# 发出的数据跨越 10 到 20 个样本
# 属于 OUTPUT_META 类型, 在这种情况下, 数据本身是一个整数。
self.put(10, 20, self.out_meta, 42)

samplenum / matched / pinvalues

wait(conds) 函数时候提到过三个数据 : samplenum , matched , pinvalues , 这个三个数据只有在该函数 conds 条件中的一个或多个条件匹配成功时才会正确返回。

samplenum

在解码器中为只读属性, 只能由 libsigrokdecode 底层设置。 当条件匹配成功时, self.wait 函数会返回当前样本解析的绝对位置(样本从0开始), 解码器可以通过访问该变量知道样本当前解析位置。

这里以 uart 解码器举例作为说明, 源码如下 :

# 根据 samplenum 计算当前输出注释在样本中的起始位置和结束位置
s, halfbit = self.startsample[rxtx], self.bit_width / 2.0
self.put(s - floor(halfbit), self.samplenum + ceil(halfbit), self.out_ann, data)

matched

self.wait(conds) 函数有多个条件匹配成功返回时, 解码器只知道 至少有一个条件匹配成功, 然而在大多数情况下, 它还需要知道哪些条件匹配(或不匹配)。 这就是该变量的作用, self.matched 可以为解码器提供条件是否匹配成功的信息, 它是一个 boolean (True / False) 类型的元组, 对于每一个条件, 都可以从相应的值中确定条件是否匹配成功。

# 等待 引脚 9 的上升沿          或
# 引脚 27 上的高状态 (逻辑 1)   或
# 样本数超过 1000 个
pins = self.wait([{9: 'r'}, {27: 'h'}, {'skip': 1000}])

if self.matched == (True, True, False):
    # 前两个条件在同一时间/样本匹配。
    # 引脚 9 包含上升沿, 引脚 27 为高电平。
elif self.matched == (True, False, False):
    # 9脚上升沿, 27脚不高。

pinvalues

self.wait 始终会返回一个值, 一个包含此特定解码器所有通道的引脚状态 (0/1 表示低/高) 的元组。 元组中的条目列表与解码器的 channelsoptional_channels 元组的索引/排序相匹配。

# 示例解码器:UART。可选通道:RX、TX
rx, tx = self.wait(...)

相关文章:

  • 【Java面试系列】Spring Boot中自动配置原理与自定义Starter开发实践详解 - 3-5年Java开发必备知识
  • Python第七章10:异常、模块、包的综合案例
  • 【组件封装-优化】vue+element plus:二次封装select组件,实现下拉列表有分页、自定义是否可搜索的一系列功能
  • Apache Airflow开源程序是一个以编程方式编写、计划和监控工作流程的平台
  • 苹果内购支付 Java 接口
  • 蓝桥杯:日期统计
  • 基于STM32、HAL库的CH224K 快充协议芯片简介及驱动程序设计
  • AI平台如何实现推理?数算岛是一个开源的AI平台(主要用于管理和调度分布式AI训练和推理任务。)
  • 【Java设计模式】第7章 建造者模式讲解
  • class与构造函数
  • Podman配置
  • AI在未来会不会代替人工???
  • Redis中AOF的实现方式和AOF重写
  • 运动规划实战案例 | 基于可视图的路径规划算法(附ROS C++/Python仿真)
  • 动态列表的数据渲染、新增、编辑等功能开发及数据处理
  • MySQL安装与基础配置(Windows版以及linux版)
  • RISCV GCC 4 后端优化
  • 国产数据库 YanshanDB 和 达梦数据库 的选型
  • PHP MySQL 创建数据库
  • 4S店汽车维修保养管理系统 (源码+lw+部署文档+讲解),源码可白嫖!
  • 帮做3d模型的网站/百度热搜广告位
  • 营销型企业网站群策略/上海网络营销seo
  • 网站建设规范方法/网站建设网络营销
  • 网站挂载/信息流广告投放平台
  • 利于seo的网站设计/新手做销售怎么开发客户
  • 奇艺广州网站建设熊掌号/网上培训机构