docs: 同步日常维护指南并补齐遗漏的板卡配置
This commit is contained in:
22
README.md
22
README.md
@@ -125,7 +125,27 @@ server {
|
|||||||
- **路径自动适配**:本项目已重构 `config.js`,部署时会自动识别 Linux 路径,无需手动修改 `config.json`。
|
- **路径自动适配**:本项目已重构 `config.js`,部署时会自动识别 Linux 路径,无需手动修改 `config.json`。
|
||||||
- **库文件全内置**:`arduino-libs` 已包含在 Git 仓库中,`git clone` 后即可直接编译带库的工程。
|
- **库文件全内置**:`arduino-libs` 已包含在 Git 仓库中,`git clone` 后即可直接编译带库的工程。
|
||||||
|
|
||||||
## 6. 常见问题排查
|
## 7. 日常维护与热更新
|
||||||
|
|
||||||
|
如果你在本地对代码进行了修改并不想重新执行全量部署,可以通过以下步骤快速同步:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 进入服务端目录
|
||||||
|
cd mixly3-server
|
||||||
|
|
||||||
|
# 1. 拉取最新代码 (包含核心逻辑修复或板卡库更新)
|
||||||
|
git pull
|
||||||
|
|
||||||
|
# 2. 重新构建生产代码 (非常重要:只要有 src 目录的改动就必须执行)
|
||||||
|
npm run build:prod
|
||||||
|
|
||||||
|
# 3. 重启服务
|
||||||
|
# 如果你是用 npm start 运行的,先 Ctrl+C 中断再运行即可。
|
||||||
|
# 如果你是用 pm2 管理的,执行:
|
||||||
|
pm2 reload mixly3
|
||||||
|
```
|
||||||
|
|
||||||
|
## 8. 常见问题排查
|
||||||
|
|
||||||
- **HTTPS 访问**:默认运行在 `https://你的IP:7100`。
|
- **HTTPS 访问**:默认运行在 `https://你的IP:7100`。
|
||||||
- **反向代理配置**:如果使用 Nginx 反代,请务必处理好的 WebSocket (Upgrade) 头,否则页面无法连接。
|
- **反向代理配置**:如果使用 Nginx 反代,请务必处理好的 WebSocket (Upgrade) 头,否则页面无法连接。
|
||||||
|
|||||||
463
mixly/CHANGELOG.md
Normal file
463
mixly/CHANGELOG.md
Normal file
@@ -0,0 +1,463 @@
|
|||||||
|
### 更新日志
|
||||||
|
|
||||||
|
#### 3.0 rc0 2024-08-25
|
||||||
|
|
||||||
|
- 修复 Arduino UNO和NANO的软件中断均无效,程序下载后测试无中断响应. [\#I8CLTQ](https://gitee.com/mixly2/mixly2.0_src/issues/I8CLTQ)
|
||||||
|
- 修复 Arduino UNO中调用红外发射功能,管脚号不正确. [\#I8EBUM](https://gitee.com/mixly2/mixly2.0_src/issues/I8EBUM)
|
||||||
|
- 修复 Python Robot中,超霸大师RFID错误. [\#I8JIUB](https://gitee.com/mixly2/mixly2.0_src/issues/I8JIUB)
|
||||||
|
- 修复 Python中的算法库有加载问题. [\#I8L6Z9](https://gitee.com/mixly2/mixly2.0_src/issues/I8L6Z9)
|
||||||
|
- 修复 Arduino ESP32C3中SD和SPIFFS说明相反. [\#I8MCAJ](https://gitee.com/mixly2/mixly2.0_src/issues/I8MCAJ)
|
||||||
|
- 修复 英文语言下Control-Delay模块时间单位缩写混沌. [\#I8MSB3](https://gitee.com/mixly2/mixly2.0_src/issues/I8MSB3)
|
||||||
|
- 修复 Arduino板卡下TFT屏-ST7796构建时出错. [\#I8QWPK](https://gitee.com/mixly2/mixly2.0_src/issues/I8QWPK)
|
||||||
|
- 修复 Arduino板卡下TFT屏中的显示文本有Bug. [\#I8ZQ24](https://gitee.com/mixly2/mixly2.0_src/issues/I8ZQ24)
|
||||||
|
- 修复 Python3程序运行错误,无错误提示. [\#IACRJ7](https://gitee.com/mixly2/mixly2.0_src/issues/IACRJ7)
|
||||||
|
- 更新 Arduino ESP32S3添加原理图. [\#I7X9LD](https://gitee.com/mixly2/mixly2.0_src/issues/I7X9LD)
|
||||||
|
- 更新 修改Arduino板卡中 `Serial.available() > 0` 为 `Serial.available()`. [\#I8BSZX](https://gitee.com/mixly2/mixly2.0_src/issues/I8BSZX)
|
||||||
|
- 更新 Arduino ESP32板卡中添加擦除flash功能. [\#IAE7AY](https://gitee.com/mixly2/mixly2.0_src/issues/IAE7AY)
|
||||||
|
- 更新 Electron更新到 `v31.2.1`,Blockly更新到 `v11.1.1`,Ace更新到 `v1.36.0`.
|
||||||
|
- 更新 Arduino和XPython板卡添加板卡文件管理功能.
|
||||||
|
- 重构 串口监视器和绘图器.
|
||||||
|
- 重构 使用ES6模块化重构所有默认板卡,扩展板卡构建时可通过 `npm install [板卡名]` 来安装默认板卡,以使用已有图形化模块.
|
||||||
|
- `@mixly/arduino`:[**v1.6.0**](https://www.npmjs.com/package/@mixly/arduino)
|
||||||
|
- `@mixly/arduino-avr`: [**v1.6.0**](https://www.npmjs.com/package/@mixly/arduino-avr)
|
||||||
|
- `@mixly/arduino-esp8266`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/arduino-esp8266)
|
||||||
|
- `@mixly/arduino-esp32`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/arduino-esp32)
|
||||||
|
- `@mixly/micropython`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython)
|
||||||
|
- `@mixly/micropython-esp32`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython-esp32)
|
||||||
|
- `@mixly/micropython-esp32c2`: [**v1.4.0**](https://www.npmjs.com/package/@mixly/micropython-esp32c2)
|
||||||
|
- `@mixly/micropython-esp32c3`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython-esp32c3)
|
||||||
|
- `@mixly/micropython-esp32s2`: [**v1.5.0**](https://www.npmjs.com/package/@mixly/micropython-esp32s2)
|
||||||
|
- `@mixly/micropython-esp32s3`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython-esp32s3)
|
||||||
|
- `@mixly/micropython-robot`: [**v1.2.0**](https://www.npmjs.com/package/@mixly/micropython-robot)
|
||||||
|
- `@mixly/micropython-k210-mixgoai`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython-k210-mixgoai)
|
||||||
|
- `@mixly/micropython-nrf51822-microbit`: [**v1.3.0**](https://www.npmjs.com/package/@mixly/micropython-nrf51822-microbit)
|
||||||
|
- `@mixly/micropython-nrf51822-mithoncc`: [**v1.2.0**](https://www.npmjs.com/package/@mixly/micropython-nrf51822-mithoncc)
|
||||||
|
- `@mixly/python`: [**v1.1.0**](https://www.npmjs.com/package/@mixly/python)
|
||||||
|
- `@mixly/python-mixpy`: [**v1.2.0**](https://www.npmjs.com/package/@mixly/python-mixpy)
|
||||||
|
- `@mixly/python-skulpt`: [**v1.2.0**](https://www.npmjs.com/package/@mixly/python-skulpt)
|
||||||
|
- `@mixly/python-skulpt-car`: [**v1.1.0**](https://www.npmjs.com/package/@mixly/python-skulpt-car)
|
||||||
|
- `@mixly/python-skulpt-mixtoy`: [**v1.1.0**](https://www.npmjs.com/package/@mixly/python-skulpt-mixtoy)
|
||||||
|
- 重构 使用第三板卡和第三方库模板重构云端板卡和云端库 (部分),持续进行中...
|
||||||
|
- `QDPK210 AIstart`:[**mixly-board-micropython-k210-aistart**](https://gitee.com/mixly2-package/mixly-board-micropython-k210-aistart)
|
||||||
|
- `Teaile AIBIT`:[**mixly-board-micropython-k210-aibit**](https://gitee.com/mixly2-package/mixly-board-micropython-k210-aibit)
|
||||||
|
- `Teaile ESP32`:[**mixly-board-micropython-esp32-acbit**](https://gitee.com/mixly2-package/mixly-board-micropython-esp32-acbit)
|
||||||
|
- `TCTM KZB01`:[**mixly-board-micropython-esp32-tctm**](https://gitee.com/mixly2-package/mixly-board-micropython-esp32-tctm)
|
||||||
|
- `Arduino UNO R4`:[**mixly-board-arduino-unor4**](https://gitee.com/mixly2-package/mixly-board-arduino-unor4)
|
||||||
|
- `Arduino RP2040`:[**mixly-board-arduino-rp2040**](https://gitee.com/mixly2-package/mixly-board-arduino-rp2040)
|
||||||
|
- `Nulllab LGT328P`:[**mixly-board-nulllab-avr**](https://gitee.com/mixly2-package/mixly-board-nulllab-avr)
|
||||||
|
- `Arduino STM32`:[**mixly-board-arduino-stm32**](https://gitee.com/mixly2-package/mixly-board-arduino-stm32)
|
||||||
|
- `Bemfa`:[**mixly-lib-bemfa**](https://gitee.com/mixly2-package/mixly-lib-bemfa)
|
||||||
|
- `YFRobot`:[**mixly-lib-yfrobot**](https://gitee.com/mixly2-package/mixly-lib-yfrobot)
|
||||||
|
- `FileSystem`:[**mixly-lib-arduino-fs**](https://gitee.com/mixly2-package/mixly-lib-arduino-fs)
|
||||||
|
- `BlockBuildTool`:[**mixly-lib-block-build-tool**](https://gitee.com/mixly2-package/mixly-lib-block-build-tool)
|
||||||
|
- 开发 一些新的扩展板卡正在开发中...
|
||||||
|
- `Arduino CH55X`:[**mixly-board-arduino-ch55x**](https://gitee.com/mixly2-package/mixly-board-arduino-ch55x)
|
||||||
|
- `C STC`:[**mixly-board-c-stcxx**](https://gitee.com/mixly2-package/mixly-board-c-stcxx)
|
||||||
|
- `Lua xt804`:[**mixly-board-lua-xt804**](https://gitee.com/mixly2-package/mixly-board-lua-xt804)
|
||||||
|
- `Web Python3`:[**mixly-board-web-python3**](https://gitee.com/mixly2-package/mixly-board-web-python3)
|
||||||
|
|
||||||
|
#### 2.0 rc4 2023-08-06
|
||||||
|
|
||||||
|
- 修复 Arduino ESP32C3 板载 WS2812 RGB灯编译出错. [\#I5P20N](https://gitee.com/mixly2/mixly2.0_src/issues/I5P20N)
|
||||||
|
- 修复 win7 32位 gcc版本不匹配. [#I5QOQO](https://gitee.com/mixly2/mixly2.0-win32-ia32/issues/I5QOQO)
|
||||||
|
- 修复 mac 下使用 Python ESP32-C3 初始化固件或上传时报错. [\#I5V5S3](https://gitee.com/mixly2/mixly2.0_src/issues/I5V5S3)
|
||||||
|
- 修复 Arduino AVR 板卡下 RGB 输入框和取色器 R、B 颜色反了. [\#I63AJJ](https://gitee.com/mixly2/mixly2.0_src/issues/I63AJJ)
|
||||||
|
- 修复 Arduino ESP32 板卡下当变量类型设置为布尔时上传错误. [\#I672R5](https://gitee.com/mixly2/mixly2.0_src/issues/I672R5)
|
||||||
|
- 修复 Arduino ESP32 硬件定时器导致系统不断重启. [\#I6B5WZ](https://gitee.com/mixly2/mixly2.0_src/issues/I6B5WZ)
|
||||||
|
- 修复 python3 语音技术运行报错. [\#I6B7AH](https://gitee.com/mixly2/mixly2.0-win32-x64/issues/I6B7AH)
|
||||||
|
- 修复 Arduino ESP32C3 下 串口图形块bug. [\#I6HUWN](https://gitee.com/mixly2/mixly2.0_src/issues/I6HUWN)
|
||||||
|
- 修复 代码区编辑代码后存本地,再打开后不会显示之前已编辑的代码. [\#I6JIM0](https://gitee.com/mixly2/mixly2.0_src/issues/I6JIM0)
|
||||||
|
- 修复 mac 下一键更新安装,Arduino编译提示 "bad CPU type in executable". [\#I6MNUY](https://gitee.com/mixly2/mixly2.0_src/issues/I6MNUY)
|
||||||
|
- 修复 mac Mixly2.0文本内容复制粘贴不了. [\#I6Z21S](https://gitee.com/mixly2/mixly2.0_src/issues/I6Z21S)
|
||||||
|
- 修复 windows Arduino ESP8266代码区无代码,无法编译. [\#I710YW](https://gitee.com/mixly2/mixly2.0_src/issues/I710YW)
|
||||||
|
- 更新 Arduino ESP32C3 GPIO添加11引脚. [\#I6X4L6](https://gitee.com/mixly2/mixly2.0_src/issues/I6X4L6)
|
||||||
|
- 更新 Blockly ( version: 10.0.2 )
|
||||||
|
- `Blockly.Blocks.xxx.HUE` → `Blockly.Msg['xxx_HUE']`
|
||||||
|
- `Blockly.xxx` → `Blockly.Msg['xxx']`
|
||||||
|
- `Blockly.Mutator` → `Blockly.icons.MutatorIcon`
|
||||||
|
- `generator.xxx` → `generator.forBlock['xxx']`
|
||||||
|
|
||||||
|
- 更新 XPython板卡和Arduino板卡
|
||||||
|
- 更新 板卡管理工具和库管理工具
|
||||||
|
- 更新 xpython板卡烧录所用python工具
|
||||||
|
- 更新 `导出PNG` 选项移动到 Blockly 工作区右键菜单
|
||||||
|
- 添加 右键菜单选项项 `添加注释`在 Blockly 工作区
|
||||||
|
- 添加 墨水屏模块在 Arduino 板卡. [\#I670FM](https://gitee.com/mixly2/mixly2.0_src/issues/I670FM)
|
||||||
|
- 添加 用户配置项
|
||||||
|
- 上传结束后自动打开串口. [\#I605PY](https://gitee.com/mixly2/mixly2.0_src/issues/I605PY)
|
||||||
|
- 主题调整为 "跟随系统"、"深色"、"浅色". [\#I692QN](https://gitee.com/mixly2/mixly2.0_src/issues/I692QN)
|
||||||
|
- 添加 消息栏在板卡页面
|
||||||
|
- 添加 配置项说明在配置板卡栏
|
||||||
|
- 添加 `此视图只读` 提示在状态栏和右侧代码预览区 ( `Enter`、`Del`、`Backspace` 触发 )
|
||||||
|
- 添加 新功能在Blockly
|
||||||
|
- 工作区高亮
|
||||||
|
- 工作区网格
|
||||||
|
- 工作区缩略图 ( `实验性` )
|
||||||
|
- 工作区多重选择 ( `实验性` - `Shift` + `鼠标左键` 触发 )
|
||||||
|
- 渲染器切换
|
||||||
|
|
||||||
|
#### 2.0 rc3 2022-08-10
|
||||||
|
|
||||||
|
- 修复自代码区切换至模块区颜色选择模块尺寸改变
|
||||||
|
- 修复串口操作导致窗口崩溃
|
||||||
|
- 修复Blockly解析xml字符串报错
|
||||||
|
- 修复Arduino下创建函数块右键生成函数块乱码
|
||||||
|
- 修复双击文件打开程序不显示
|
||||||
|
- 更新板卡管理工具和库管理工具
|
||||||
|
- 更新Electron ( version: 19.0.6 )
|
||||||
|
- 更新Ace、Ampy、Layui、fontello、skulpt、amWiki、fpJS
|
||||||
|
- 更新XPython板卡和Arduino板卡
|
||||||
|
- 更新Mixly板卡页面布局
|
||||||
|
- 更新配置Arduino板卡操作
|
||||||
|
- 串口输出框、代码框添加右键菜单
|
||||||
|
- 添加反馈、wiki、例程和图文转换按钮
|
||||||
|
- 添加Blockly工具箱查找和工作区查找
|
||||||
|
- 添加书包
|
||||||
|
- 添加Blockly.FieldGridDropdown、Blockly.FieldBitmap和Blockly.FieldSlider
|
||||||
|
|
||||||
|
#### 2.0 rc2 2022-03-19
|
||||||
|
|
||||||
|
- 修复ESP32数码管问题
|
||||||
|
- 修复在图像化模块的注释打开时弹层位置不在窗口中央的问题
|
||||||
|
- 修复导入本地第三方库错误
|
||||||
|
- 尝试修复有时使用Blockly.Xml.textToDom函数报错
|
||||||
|
- 尝试修复串口长时间使用时页面崩溃问题
|
||||||
|
- 更新板卡micropython_esp32_handbit
|
||||||
|
- 更新板卡circuitpython_esp32s2_mixgocar
|
||||||
|
- 更新板卡micropython_k210_mixgoai
|
||||||
|
- 更新板卡micropython_esp32_mixgo
|
||||||
|
- 更新板卡micropython_nrf51822_microbit
|
||||||
|
- 更新板卡micropython_nrf51822_mithoncc
|
||||||
|
- 更新esptool ( version: 3.2 )
|
||||||
|
- 更新Ampy
|
||||||
|
- 更新electron ( version: 17.1.2 )
|
||||||
|
- 添加板卡micropython_esp32_mixgope
|
||||||
|
- 添加板卡micropython_esp32c3_mixgocar
|
||||||
|
- 添加板卡micropython_esp32c3_mixgocc
|
||||||
|
- 添加python_skulpt_mixtoy
|
||||||
|
- 添加【其他固件】按钮在xPython页面
|
||||||
|
- 添加AI Thinker ESP32-CAM在Arduino ESP32
|
||||||
|
- 添加过渡动画在板卡index切换时
|
||||||
|
- 添加程序执行时间显示在python板卡状态栏
|
||||||
|
- 调整头部工具栏
|
||||||
|
- 调整各弹层在dark下的颜色
|
||||||
|
- 自动获取category标签的id属性,不需要在code.js中手动添加
|
||||||
|
- 移除Arduino STM32板卡,改为用户手动导入
|
||||||
|
- 移除Arduino ESP32C3板卡不能使用的blynk,板载资源与蓝牙块
|
||||||
|
|
||||||
|
#### 2.0 rc1 2021-11-07
|
||||||
|
|
||||||
|
- 修复导入云端库时的一些问题
|
||||||
|
- 修复库管理器对本地一些库无法进行管理的问题
|
||||||
|
- 修复Arduino类板卡软串口错误
|
||||||
|
- 修复python页面下生成代码存在很多空行的问题
|
||||||
|
- 修复Arduino类板卡编译时中文输出为乱码的问题
|
||||||
|
- 更新Arduino ESP32c3页面的串口配置和管脚定义
|
||||||
|
- 更新CircuitPython MixGoCE与MixGoCar的固件
|
||||||
|
- 更新MicroPython MixGoAI
|
||||||
|
- 增加通用旋转编码器图形化模块
|
||||||
|
- 增加ESP系列红外解码图形化模块
|
||||||
|
- 增加新板卡mPython
|
||||||
|
- 增加 "until" 及更新 "while" 图形化模块在xPython页面下
|
||||||
|
- 增加OTA图形化模块在Arduino ESP页面下
|
||||||
|
- 增加360°舵机和HCSR04超声波控制图形化模块在CricuitPython MixGoCE页面下
|
||||||
|
- 增加折叠块在MixGoCE&MixGoCar页面下
|
||||||
|
- 移除Arduino ESP页面下WIFI_AP&STA图形化模块 (变为云端导入)
|
||||||
|
|
||||||
|
#### 2.0 rc0 2021-09-30
|
||||||
|
|
||||||
|
- 修复导入第三方库后切换语言一些第三方库语言没有改变
|
||||||
|
- 修复CircuitPython MixGoCE界面下上传程序后状态栏不自动切换到串口输出
|
||||||
|
- 注释串口读取时对连续两个数据时间间隔需大于50ms的限制
|
||||||
|
- 更新CircuitPython MixGoCE与MixGoCar的固件
|
||||||
|
- Arduino下增加对于mixio的支持
|
||||||
|
- 添加Arduino ESP8266管脚映射图形化模块
|
||||||
|
- 更新Arduino和Python第三方库url
|
||||||
|
- 取消导入库和板卡时的编辑url按钮
|
||||||
|
- 板卡页面头部工具栏添加按钮点击效果
|
||||||
|
- 同步弹出打开、保存文件窗口改为异步弹出
|
||||||
|
- Arduino类板卡页面支持云端导入Arduino库文件和管理本地Arduino库文件
|
||||||
|
- Python类板卡页面支持云端导入py文件和管理本地py文件
|
||||||
|
|
||||||
|
#### 2.0 Beta14 2021-09-14
|
||||||
|
|
||||||
|
- 修复软件主题设为dark时从主页面到板卡页面会有短暂闪屏
|
||||||
|
- 修复Arduino类板卡下blynk分类下一些模块无法生成代码
|
||||||
|
- 修复Arduino ESP8266板卡下红外通信模块生成代码编译报错
|
||||||
|
- 修复Arduino ESP32板卡下使用ESP32 CAM相关模块编译报错
|
||||||
|
- 修复设置语言后刷新页面会变成默认语言的问题
|
||||||
|
- 修复Arduino类板卡下编译上传时报错信息会显示两次
|
||||||
|
- 修复串口工具读取数据时会剔除空行的问题
|
||||||
|
- 更新CircuitPython MixGoCE与MixGoCar的固件和相关图形化模块
|
||||||
|
- 更新electron版本到13.3.0
|
||||||
|
- 更新blockly版本到6.20210701.0
|
||||||
|
- 更换主页面背景图片
|
||||||
|
- 板卡页面更改语言后支持动态更新页面
|
||||||
|
- 板卡页面导入和删除第三方库后支持动态更新左侧工具箱
|
||||||
|
- 主页面导入和删除板卡后支持动态更新页面
|
||||||
|
- 完善软件对多国语言的支持
|
||||||
|
- Arduino类板卡编译和上传时支持同时编译所打开MIX、INO所在目录下的[*.h, *.hpp, *.c, *.cpp]文件
|
||||||
|
|
||||||
|
#### 2.0 Beta13 2021-08-26
|
||||||
|
|
||||||
|
- 修复Arduino AVR板卡下Blynk连接状态函数无法生成代码的问题
|
||||||
|
- 修复MicroPython MixGo AI板卡在串口工具打开时复位按钮无法使用的问题
|
||||||
|
- 修复microPython和CircuitPython下数学分类下某些模块生成代码上传报错的问题
|
||||||
|
- 修复打开和保存文件时默认路径有时不为sample文件夹的问题
|
||||||
|
- 修复py下if-else & try-except使用ctrl+z后报错的问题
|
||||||
|
- 修复初始化固件或上传程序后有时遮罩无法关闭的问题
|
||||||
|
- 修复串口读取数据时无法解码中文编码字符串的问题
|
||||||
|
- 调整板卡配置文件
|
||||||
|
- CircuitPython MixGo CE板卡下添加Mixly Key、获取cpu温度、NTP时间和SD卡操作图形化模块
|
||||||
|
- 更新CircuitPython MixGo CE板卡固件
|
||||||
|
- 更新状态栏,支持在状态栏中显示串口号
|
||||||
|
- 更新板卡页面头部工具栏
|
||||||
|
- Arduino板卡下支持导出和导入已编译的bin、hex文件
|
||||||
|
|
||||||
|
#### 2.0 Beta12 2021-08-14
|
||||||
|
|
||||||
|
- 修复Arduino页面下函数声明模块无法被禁用的问题
|
||||||
|
- 修复侧边代码框和代码编辑框字体大小不同步的问题
|
||||||
|
- 修复MixGo AI下有时程序卡住时无法再上传的的问题
|
||||||
|
- 修复串口接收数据为中文时有乱码问题
|
||||||
|
- 修复主页面下显示多行板卡时有时某几行板卡无法显示的问题
|
||||||
|
- 修复Microbit下舵机和蜂鸣器无法使用的问题
|
||||||
|
- 更新Mixgo CE 和 MixGo Car图形化模块及其固件
|
||||||
|
- 更新例程
|
||||||
|
- 支持双击文件在Mixly中打开(需要先关联MIX文件到Mixly)
|
||||||
|
- 串口监视器添加DTR和RTS设置
|
||||||
|
|
||||||
|
#### 2.0 Beta11 2021-08-06
|
||||||
|
|
||||||
|
- 修复Arduino ESP8266和ESP32板卡页面blynk模块编译报错问题
|
||||||
|
- 修复MixGoAI板卡使用kflash工具烧录时的报错问题
|
||||||
|
- 修复Arduino ESP8266和ESP32界面下使用本地导入库后无第三方模块的问题
|
||||||
|
- 修复主页面下显示的板卡在高分辨率屏幕上排列会出错的问题
|
||||||
|
- 修复串口在读取数据时如果没有换行符数据不会显示的问题
|
||||||
|
- Arduino ESP32S2板卡页面增加USB串口程序块
|
||||||
|
- Arduino ESP32S2和ESP32C3板卡页面添加GPIO图
|
||||||
|
- 更新Sample下例程版本为Mixly2.0
|
||||||
|
- 更新MixGo CE和MixGo Car下图形化模块和所用固件
|
||||||
|
- 添加py模块pgzero
|
||||||
|
- Arduino STM32支持使用Mixly烧录固件
|
||||||
|
|
||||||
|
#### 2021-08-01
|
||||||
|
|
||||||
|
- 修复保存文件后不显示保存路径的问题
|
||||||
|
- 修复当软件路径中含有空格时编译、烧录和上传操作会出错的问题
|
||||||
|
- 尝试修复导入Mxixly1.x所用第三方库有些分类无法显示的问题
|
||||||
|
- 更新MixGo CE和MixGo Car下图形化模块和所用固件
|
||||||
|
|
||||||
|
#### 2021-07-30
|
||||||
|
|
||||||
|
- 同步Mixly1.x下Arduino类图形化模块
|
||||||
|
- 添加新板卡Arduino ESP32S2和ESP32C3
|
||||||
|
|
||||||
|
#### 2021-07-29
|
||||||
|
|
||||||
|
- 添加主进程调试工具electron-dev-console
|
||||||
|
- 添加新板卡Arduino MixGo CE
|
||||||
|
|
||||||
|
#### 2021-07-28
|
||||||
|
|
||||||
|
- 修复Mac和Linux下通过VID、PID无法筛选串口的问题
|
||||||
|
- 修复Linux下通过盘符号获取路径出错的问题
|
||||||
|
|
||||||
|
#### 2021-07-27
|
||||||
|
|
||||||
|
- 修复在打开两个及以上窗口时启动速度变慢的问题
|
||||||
|
- 串口工具支持拖拽改变尺寸
|
||||||
|
- 添加本地快捷键
|
||||||
|
| Mixly2.0客户端界面操作 | 快捷键 |
|
||||||
|
| :--------------------: | :----: |
|
||||||
|
| 打开新页面 | Ctrl+N |
|
||||||
|
|
||||||
|
#### 2021-07-26
|
||||||
|
|
||||||
|
- 更新云端板卡TCTM KZB01
|
||||||
|
- 更新本地快捷键
|
||||||
|
| Mixly2.0客户端界面操作 | 快捷键 |
|
||||||
|
| :--------------------: | :----------: |
|
||||||
|
| 缩小页面 | Ctrl+Shift+- |
|
||||||
|
|
||||||
|
#### 2021-07-25
|
||||||
|
|
||||||
|
- 修复K210板卡使用ampy上传有时会失败的问题
|
||||||
|
- Mac系统下使用which python3命令获取已安装python3的路径
|
||||||
|
- 支持使用ampy递归上传文件
|
||||||
|
|
||||||
|
#### 2021-07-24
|
||||||
|
|
||||||
|
- 添加新板卡MixGo AI
|
||||||
|
- 更新云端板卡TCTM KZB01
|
||||||
|
- 添加本地快捷键
|
||||||
|
| Mixly2.0客户端界面操作 | 快捷键 |
|
||||||
|
| :--------------------: | :----: |
|
||||||
|
| 打开更新日志 | Ctrl+H |
|
||||||
|
|
||||||
|
#### 2021-07-22
|
||||||
|
|
||||||
|
- 添加新板卡MixGo Car
|
||||||
|
|
||||||
|
#### 2021-07-21
|
||||||
|
|
||||||
|
- 修复Arduino界面下LCD1602编译出错问题
|
||||||
|
- 修复Arduino界面OLED分类下模块下拉图片链接出错的问题
|
||||||
|
- 修复Arduino界面下模块SDA、SCL等管脚无法使用默认配置的问题
|
||||||
|
|
||||||
|
#### 2021-07-20
|
||||||
|
|
||||||
|
- 修复导入第三方库后在开发者模式下无法查看已导入第三方库js文件的问题
|
||||||
|
|
||||||
|
#### 2021-07-17
|
||||||
|
|
||||||
|
- 修复本地导入板卡和第三方库按钮不可用问题
|
||||||
|
|
||||||
|
#### 2021-07-16
|
||||||
|
|
||||||
|
- 修复Microbit和Mithon页面下【保存HEX】按钮文字不显示的问题
|
||||||
|
- 修复Win下ESP32板卡编译失败的问题
|
||||||
|
- 支持同时对多个同类型板卡进行固件烧录或程序上传操作
|
||||||
|
|
||||||
|
#### 2021-07-14
|
||||||
|
|
||||||
|
- 修复Arduino页面下缩小窗口时编译按钮不折叠的问题
|
||||||
|
- 串口绘图支持绘制多条折线
|
||||||
|
- 添加本地快捷键
|
||||||
|
| Mixly2.0客户端界面操作 | 快捷键 |
|
||||||
|
| :--------------------: | :----------: |
|
||||||
|
| 还原页面 | Ctrl+0 |
|
||||||
|
| 放大页面 | Ctrl+Shift+= |
|
||||||
|
| 缩小页面 | Ctrl+- |
|
||||||
|
|
||||||
|
#### 2021-07-10
|
||||||
|
|
||||||
|
- 添加云端板卡MicroPython_esp32_TCTM_KZB01
|
||||||
|
|
||||||
|
#### 2021-07-09
|
||||||
|
|
||||||
|
- 添加测试板卡MicroPython_K210_MaixDock
|
||||||
|
|
||||||
|
#### 2021-07-07
|
||||||
|
|
||||||
|
- 支持用户自定义arduinoCli和Python3的路径,当在默认路径下未检测到对应软件时,会使用自定义路径
|
||||||
|
|
||||||
|
#### 2021-07-05
|
||||||
|
|
||||||
|
- 添加K210固件烧录工具kflash
|
||||||
|
|
||||||
|
#### 2021-07-04
|
||||||
|
|
||||||
|
- 添加本地快捷键
|
||||||
|
| Mixly2.0客户端界面操作 | 快捷键 |
|
||||||
|
| :--------------------: | :----------: |
|
||||||
|
| 打开或关闭开发者工具 | Ctrl+Shift+I |
|
||||||
|
| 重载页面 | Ctrl+R |
|
||||||
|
| 最小化窗口 | Ctrl+M |
|
||||||
|
| 关闭窗口 | Ctrl+W |
|
||||||
|
- 修复在打开两个及以上窗口时会出现短暂白屏问题
|
||||||
|
|
||||||
|
#### 2021-07-01
|
||||||
|
|
||||||
|
- Mixly 网页端MixGo板卡使用WebSerial上传
|
||||||
|
- Mixly 网页端MixGo和MixGoCE板卡固件烧录采用WebSerial ESPTool
|
||||||
|
- 尝试修复MixGoCE上传结束后的灰屏问题
|
||||||
|
|
||||||
|
#### 2021-06-19
|
||||||
|
|
||||||
|
- 修复microbit界面TCS34725颜色传感器模块读取RGB数据出错的问题
|
||||||
|
- 配置文件支持添加多个盘符
|
||||||
|
- 状态栏支持通过快捷键设置字体大小、发送Ctrl+C和Ctrl+D、清空状态栏
|
||||||
|
| 状态栏操作 | 快捷键 |
|
||||||
|
| :--------: | :------------: |
|
||||||
|
| 增大字体 | Ctrl-=\|Ctrl-+ |
|
||||||
|
| 减小字体 | Ctrl+-\|Ctrl- |
|
||||||
|
| 发送Ctrl+C | Ctrl+Shift+C |
|
||||||
|
| 发送Ctrl+D | Ctrl+Shift+D |
|
||||||
|
| 清空状态栏 | Ctrl+E |
|
||||||
|
|
||||||
|
#### 2021-05-29
|
||||||
|
|
||||||
|
- 修复侧边代码框向左拖动时宽度无限制的问题
|
||||||
|
- 修复打开文件或在文本转图形时图形化模块无法居中的问题
|
||||||
|
- 修复打开文件后左侧分类树无法自动复位的问题
|
||||||
|
- 修复主题设为dark时进入板卡页面后主题依然为light的问题
|
||||||
|
|
||||||
|
#### 2021-05-13
|
||||||
|
|
||||||
|
- 修复打开mix文件显示“无效的xml”的问题
|
||||||
|
- 修复保存png文件后无法打开的问题
|
||||||
|
- 修复串口输出介于[-1,1]的数字会读取出错的问题
|
||||||
|
- 修复有多个串口时无法正常切换串口的问题
|
||||||
|
- 修复板卡页面主题设为dark后左侧分类树字体颜色为黑的问题
|
||||||
|
- 更新MixGo CE页面图形块及固件
|
||||||
|
|
||||||
|
#### 2021-05-09
|
||||||
|
|
||||||
|
- 修复主页面在改变窗口尺寸或屏幕分辨率后板卡会堆叠在一起的问题
|
||||||
|
- 修复板卡页面鼠标滚轮缩放速率过大的问题
|
||||||
|
- 使用node https替换request模块
|
||||||
|
|
||||||
|
#### 2021-04-19
|
||||||
|
|
||||||
|
- 修复Arduino界面终止编译/上传后状态栏仍会继续显示部分编译/上传信息
|
||||||
|
- 修复点击“打开”按钮时未选择文件则会清除当前文件路径的问题
|
||||||
|
- 修复打开文件显示invalid xml file!时会清除工作区和代码区程序的问题
|
||||||
|
- 修复打开文件后退出板卡页面再次进入会丢失文件路径的问题
|
||||||
|
- 修复从板卡页面退出轮播索引会自动设为0的问题
|
||||||
|
|
||||||
|
#### 2021-04-18
|
||||||
|
|
||||||
|
- 修复打开文件显示invalid xml file!时仍会显示文件路径的问题
|
||||||
|
- 修复打开文件显示invalid xml file!时代码区仍会显示部分代码的问题
|
||||||
|
- 修复状态栏和工作区在主题为dark时无效果的问题
|
||||||
|
- 修复代码区代码在退出页面后再次进入无法恢复的问题
|
||||||
|
- 修复设置语言后重启软件会变回默认语言的问题
|
||||||
|
- 修复Arduino界面板卡切换后工作区图形化模块管脚不会同步的问题
|
||||||
|
- 使用Arduino-CLI替换Arduino IDE,加快编译和上传速度,目前已添加AVR板卡
|
||||||
|
- MixGoCE 外接元件/传感器、物联网分类下模块添加文本转图形
|
||||||
|
|
||||||
|
#### 2021-04-16
|
||||||
|
|
||||||
|
- 修复重复打开相同文件时不会读取文件数据的问题
|
||||||
|
- 修复python界面input模块输入中文时输出乱码的问题
|
||||||
|
- 修复python和micropython界面在包含类与对象相关模块时会出错的问题
|
||||||
|
- 更新“保存”、“另存为”、“新建”、“打开”操作
|
||||||
|
- 更新串口可视化
|
||||||
|
- 串口和头部工具栏支持用户使用config.json来配置
|
||||||
|
- 缓存文件支持不同界面数据分开储存
|
||||||
|
|
||||||
|
#### 2021-04-12
|
||||||
|
|
||||||
|
- 更新“保存”、“另存为”按钮
|
||||||
|
- 修复MixGo按RST后无法上传的问题
|
||||||
|
- 串口加上关闭/打开按钮
|
||||||
|
|
||||||
|
#### 2021-04-08
|
||||||
|
|
||||||
|
- 修复板卡选择下拉框展开时展开框不居中的问题
|
||||||
|
- 修复释放头部工具栏中某个按钮后此按钮依旧为按下状态的问题
|
||||||
|
- 调整串口、状态框、编译、烧录、上传等相关函数
|
||||||
|
|
||||||
|
#### 2021-04-02
|
||||||
|
|
||||||
|
- 串口选择下拉框支持显示多行
|
||||||
|
- 修复非MixGOCE、microbit、mithon板卡的串口切换错误问题
|
||||||
|
- 初始化固件、上传支持记住上一次选择的串口或盘符号
|
||||||
|
- 板卡切换按钮设置为一直显示
|
||||||
|
|
||||||
|
#### 2021-03-21
|
||||||
|
|
||||||
|
- RGB灯带的逻辑修改为官网逻辑
|
||||||
|
- python编辑器自动缩进为4个空格
|
||||||
|
- 修复缩小窗口时文字重叠问题
|
||||||
|
- 去掉了初始化超声波图形模块
|
||||||
|
- 更新串口工具
|
||||||
|
- 修复串口短时间获取大量数据时卡死问题
|
||||||
|
- 支持在软件内动态添加板卡,支持直接在软件内删除板卡
|
||||||
|
- 暂时只添加了Arduino AVR板卡
|
||||||
|
- 添加MixGo板卡
|
||||||
|
- 添加导入库、管理库、切换板卡按钮,暂时不支持导入库、管理库、切换板卡操作
|
||||||
|
- 添加Shift+Ctrl+C和Shift+Ctrl+V操作
|
||||||
|
- MixGo上传采用python-shell调用ampy工具
|
||||||
|
- MixGo和MixGoCE烧录固件采用python-shell调用esptool工具
|
||||||
3
mixly/LICENSE
Normal file
3
mixly/LICENSE
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
本软件使用了Electron,Node.JS,Blockly,Skulpt,Arduino,Micropython,CircuitPython,ESP-IDF,Arduino-cli,Arduino-ESP32,,Arduino-ESP8266等一大堆开源软件,用户在使用是必须遵守上述开源软件各种的License,除此以外,除非与上述协议冲突,否则,任何使用本代码的用户和组织在修改后必须保留Mixly这一软件名称及作者信息,但可以使用Mixly4XXX这样的名字,XXX就是使用者自己的名字。
|
||||||
|
|
||||||
|
This software uses a large number of open source software such as Electron, Node.JS, Blockly, Skulpt, Arduino, Micropython,CircuitPython, ESP-IDF, Arduino-cli, Arduino-ESP32, Arduino-ESP8266, etc. The user must comply with the above open source software's Licenses, in addition, Unless it conflicts with the above Licenses, any user or organization using this code must retain the name of the Software and author information after modification, but may use a name such as Mixly4XXX, which is the user's own name.
|
||||||
BIN
mixly/boards/HDK/MixGo CC-V3.2.pdf
Normal file
BIN
mixly/boards/HDK/MixGo CC-V3.2.pdf
Normal file
Binary file not shown.
BIN
mixly/boards/HDK/MixGo CE-V3.7.pdf
Normal file
BIN
mixly/boards/HDK/MixGo CE-V3.7.pdf
Normal file
Binary file not shown.
BIN
mixly/boards/HDK/MixGo ME-V2.3.pdf
Normal file
BIN
mixly/boards/HDK/MixGo ME-V2.3.pdf
Normal file
Binary file not shown.
BIN
mixly/boards/HDK/MixGo Nova-V2.6.pdf
Normal file
BIN
mixly/boards/HDK/MixGo Nova-V2.6.pdf
Normal file
Binary file not shown.
BIN
mixly/boards/HDK/MixGo_MINI-V1.7.pdf
Normal file
BIN
mixly/boards/HDK/MixGo_MINI-V1.7.pdf
Normal file
Binary file not shown.
BIN
mixly/boards/default/micropython/build/HZK12.bin
Normal file
BIN
mixly/boards/default/micropython/build/HZK12.bin
Normal file
Binary file not shown.
BIN
mixly/boards/default/micropython/build/HZK16.bin
Normal file
BIN
mixly/boards/default/micropython/build/HZK16.bin
Normal file
Binary file not shown.
BIN
mixly/boards/default/micropython/build/HZK16_GBK.bin
Normal file
BIN
mixly/boards/default/micropython/build/HZK16_GBK.bin
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
602
mixly/boards/default/micropython/build/lib/adafruit_miniqr.py
Normal file
602
mixly/boards/default/micropython/build/lib/adafruit_miniqr.py
Normal file
@@ -0,0 +1,602 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2009 Kazuhiko Arase
|
||||||
|
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
# Ported from the Javascript library by Sam Curren
|
||||||
|
# QRCode for Javascript
|
||||||
|
# http://d-project.googlecode.com/svn/trunk/misc/qrcode/js/qrcode.js
|
||||||
|
#
|
||||||
|
# Minimized for CircuitPython by ladyada for adafruit industries
|
||||||
|
#
|
||||||
|
# The word "QR Code" is registered trademark of
|
||||||
|
# DENSO WAVE INCORPORATED
|
||||||
|
# http://www.denso-wave.com/qrcode/faqpatent-e.html
|
||||||
|
"""
|
||||||
|
`adafruit_miniqr`
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
A non-hardware dependant miniature QR generator library. All native Python!
|
||||||
|
|
||||||
|
* Author(s): ladyada
|
||||||
|
|
||||||
|
Implementation Notes
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
**Hardware:**
|
||||||
|
|
||||||
|
* Any!
|
||||||
|
|
||||||
|
**Software and Dependencies:**
|
||||||
|
|
||||||
|
* Python 3
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# imports
|
||||||
|
import math
|
||||||
|
|
||||||
|
try:
|
||||||
|
from typing import Dict, List, Optional, Tuple
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
__version__ = "0.0.0+auto.0"
|
||||||
|
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_miniQR.git"
|
||||||
|
|
||||||
|
# Consts!
|
||||||
|
M = 0
|
||||||
|
L = 1
|
||||||
|
H = 2
|
||||||
|
Q = 3
|
||||||
|
|
||||||
|
_MODE_8BIT_BYTE = 1 << 2
|
||||||
|
_PAD0 = 0xEC
|
||||||
|
_PAD1 = 0x11
|
||||||
|
|
||||||
|
# Optimized polynomial helpers
|
||||||
|
|
||||||
|
|
||||||
|
def _glog(n: int) -> int:
|
||||||
|
"""Lookup log(n) from pre-calculated byte table"""
|
||||||
|
if n < 1:
|
||||||
|
raise ValueError("glog(" + n + ")")
|
||||||
|
return LOG_TABLE[n]
|
||||||
|
|
||||||
|
|
||||||
|
def _gexp(n: int) -> int:
|
||||||
|
"""Lookup exp(n) from pre-calculated byte table"""
|
||||||
|
while n < 0:
|
||||||
|
n += 255
|
||||||
|
while n >= 256:
|
||||||
|
n -= 255
|
||||||
|
return EXP_TABLE[n]
|
||||||
|
|
||||||
|
|
||||||
|
EXP_TABLE = b"\x01\x02\x04\x08\x10 @\x80\x1d:t\xe8\xcd\x87\x13&L\x98-Z\xb4u\xea\xc9\x8f\x03\x06\x0c\x180`\xc0\x9d'N\x9c%J\x945j\xd4\xb5w\xee\xc1\x9f#F\x8c\x05\n\x14(P\xa0]\xbai\xd2\xb9o\xde\xa1_\xbea\xc2\x99/^\xbce\xca\x89\x0f\x1e<x\xf0\xfd\xe7\xd3\xbbk\xd6\xb1\x7f\xfe\xe1\xdf\xa3[\xb6q\xe2\xd9\xafC\x86\x11\"D\x88\r\x1a4h\xd0\xbdg\xce\x81\x1f>|\xf8\xed\xc7\x93;v\xec\xc5\x973f\xcc\x85\x17.\\\xb8m\xda\xa9O\x9e!B\x84\x15*T\xa8M\x9a)R\xa4U\xaaI\x929r\xe4\xd5\xb7s\xe6\xd1\xbfc\xc6\x91?~\xfc\xe5\xd7\xb3{\xf6\xf1\xff\xe3\xdb\xabK\x961b\xc4\x957n\xdc\xa5W\xaeA\x82\x192d\xc8\x8d\x07\x0e\x1c8p\xe0\xdd\xa7S\xa6Q\xa2Y\xb2y\xf2\xf9\xef\xc3\x9b+V\xacE\x8a\t\x12$H\x90=z\xf4\xf5\xf7\xf3\xfb\xeb\xcb\x8b\x0b\x16,X\xb0}\xfa\xe9\xcf\x83\x1b6l\xd8\xadG\x8e\x01" # noqa: E501
|
||||||
|
|
||||||
|
LOG_TABLE = b"\x00\x00\x01\x19\x022\x1a\xc6\x03\xdf3\xee\x1bh\xc7K\x04d\xe0\x0e4\x8d\xef\x81\x1c\xc1i\xf8\xc8\x08Lq\x05\x8ae/\xe1$\x0f!5\x93\x8e\xda\xf0\x12\x82E\x1d\xb5\xc2}j'\xf9\xb9\xc9\x9a\txM\xe4r\xa6\x06\xbf\x8bbf\xdd0\xfd\xe2\x98%\xb3\x10\x91\"\x886\xd0\x94\xce\x8f\x96\xdb\xbd\xf1\xd2\x13\\\x838F@\x1eB\xb6\xa3\xc3H~nk:(T\xfa\x85\xba=\xca^\x9b\x9f\n\x15y+N\xd4\xe5\xacs\xf3\xa7W\x07p\xc0\xf7\x8c\x80c\rgJ\xde\xed1\xc5\xfe\x18\xe3\xa5\x99w&\xb8\xb4|\x11D\x92\xd9# \x89.7?\xd1[\x95\xbc\xcf\xcd\x90\x87\x97\xb2\xdc\xfc\xbea\xf2V\xd3\xab\x14*]\x9e\x84<9SGmA\xa2\x1f-C\xd8\xb7{\xa4v\xc4\x17I\xec\x7f\x0co\xf6l\xa1;R)\x9dU\xaa\xfb`\x86\xb1\xbb\xcc>Z\xcbY_\xb0\x9c\xa9\xa0Q\x0b\xf5\x16\xebzu,\xd7O\xae\xd5\xe9\xe6\xe7\xad\xe8t\xd6\xf4\xea\xa8PX\xaf" # noqa: E501
|
||||||
|
|
||||||
|
|
||||||
|
class QRCode:
|
||||||
|
"""The generator class for QR code matrices"""
|
||||||
|
|
||||||
|
def __init__(self, *, qr_type: Optional[int] = None, error_correct: int = L):
|
||||||
|
"""Initialize an empty QR code. You can define the `qr_type` (size)
|
||||||
|
of the code matrix, or have the libary auto-select the smallest
|
||||||
|
match. Default `error_correct` is type L (7%), but you can select M,
|
||||||
|
Q or H."""
|
||||||
|
self.type = qr_type
|
||||||
|
self.ECC = error_correct
|
||||||
|
self.matrix = None
|
||||||
|
self.module_count = 0
|
||||||
|
self.data_cache = None
|
||||||
|
self.data_list = []
|
||||||
|
|
||||||
|
def add_data(self, data: bytes) -> None:
|
||||||
|
"""Add more data to the QR code, must be bytestring stype"""
|
||||||
|
self.data_list.append(data)
|
||||||
|
datalen = sum(len(x) for x in self.data_list)
|
||||||
|
if not self.type:
|
||||||
|
for qr_type in range(1, 10):
|
||||||
|
rs_blocks = _get_rs_blocks(qr_type, self.ECC)
|
||||||
|
total_data_count = 0
|
||||||
|
for block in rs_blocks:
|
||||||
|
total_data_count += block["data"]
|
||||||
|
if total_data_count > datalen:
|
||||||
|
self.type = qr_type
|
||||||
|
break
|
||||||
|
self.data_cache = None
|
||||||
|
|
||||||
|
def make(self, *, test: bool = False, mask_pattern: int = 0) -> None:
|
||||||
|
"""Perform the actual generation of the QR matrix. To keep things
|
||||||
|
small and speedy we don't generate all 8 mask patterns and pick
|
||||||
|
the best. Instead, please pass in a desired mask_pattern, the
|
||||||
|
default mask is 0."""
|
||||||
|
self.module_count = self.type * 4 + 17
|
||||||
|
self.matrix = QRBitMatrix(self.module_count, self.module_count)
|
||||||
|
|
||||||
|
self._setup_position_probe_pattern(0, 0)
|
||||||
|
self._setup_position_probe_pattern(self.module_count - 7, 0)
|
||||||
|
self._setup_position_probe_pattern(0, self.module_count - 7)
|
||||||
|
self._setup_position_adjust_pattern()
|
||||||
|
self._setup_timing_pattern()
|
||||||
|
self._setup_type_info(test, mask_pattern)
|
||||||
|
|
||||||
|
if self.type >= 7:
|
||||||
|
self._setup_type_number(test)
|
||||||
|
|
||||||
|
if self.data_cache is None:
|
||||||
|
self.data_cache = QRCode._create_data(self.type, self.ECC, self.data_list)
|
||||||
|
self._map_data(self.data_cache, mask_pattern)
|
||||||
|
|
||||||
|
def _setup_position_probe_pattern(self, row: int, col: int) -> None:
|
||||||
|
"""Add the positition probe data pixels to the matrix"""
|
||||||
|
for r in range(-1, 8):
|
||||||
|
if row + r <= -1 or self.module_count <= row + r:
|
||||||
|
continue
|
||||||
|
for c in range(-1, 8):
|
||||||
|
if col + c <= -1 or self.module_count <= col + c:
|
||||||
|
continue
|
||||||
|
test = (
|
||||||
|
(0 <= r <= 6 and (c in (0, 6)))
|
||||||
|
or (0 <= c <= 6 and (r in (0, 6)))
|
||||||
|
or (2 <= r <= 4 and 2 <= c <= 4)
|
||||||
|
)
|
||||||
|
self.matrix[row + r, col + c] = test
|
||||||
|
|
||||||
|
def _setup_timing_pattern(self) -> None:
|
||||||
|
"""Add the timing data pixels to the matrix"""
|
||||||
|
for r in range(8, self.module_count - 8):
|
||||||
|
if self.matrix[r, 6] is not None:
|
||||||
|
continue
|
||||||
|
self.matrix[r, 6] = r % 2 == 0
|
||||||
|
|
||||||
|
for c in range(8, self.module_count - 8):
|
||||||
|
if self.matrix[6, c] is not None:
|
||||||
|
continue
|
||||||
|
self.matrix[6, c] = c % 2 == 0
|
||||||
|
|
||||||
|
def _setup_position_adjust_pattern(self) -> None:
|
||||||
|
"""Add the position adjust data pixels to the matrix"""
|
||||||
|
pos = QRUtil.get_pattern_position(self.type)
|
||||||
|
|
||||||
|
for row in pos:
|
||||||
|
for col in pos:
|
||||||
|
if self.matrix[row, col] is not None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
for r in range(-2, 3):
|
||||||
|
for c in range(-2, 3):
|
||||||
|
test = abs(r) == 2 or abs(c) == 2 or (r == 0 and c == 0)
|
||||||
|
self.matrix[row + r, col + c] = test
|
||||||
|
|
||||||
|
def _setup_type_number(self, test: bool) -> None:
|
||||||
|
"""Add the type number pixels to the matrix"""
|
||||||
|
bits = QRUtil.get_BCH_type_number(self.type)
|
||||||
|
|
||||||
|
for i in range(18):
|
||||||
|
mod = not test and ((bits >> i) & 1) == 1
|
||||||
|
self.matrix[i // 3, i % 3 + self.module_count - 8 - 3] = mod
|
||||||
|
|
||||||
|
for i in range(18):
|
||||||
|
mod = not test and ((bits >> i) & 1) == 1
|
||||||
|
self.matrix[i % 3 + self.module_count - 8 - 3, i // 3] = mod
|
||||||
|
|
||||||
|
def _setup_type_info(self, test: bool, mask_pattern: int) -> None:
|
||||||
|
"""Add the type info pixels to the matrix"""
|
||||||
|
data = (self.ECC << 3) | mask_pattern
|
||||||
|
bits = QRUtil.get_BCH_type_info(data)
|
||||||
|
|
||||||
|
# // vertical
|
||||||
|
for i in range(15):
|
||||||
|
mod = not test and ((bits >> i) & 1) == 1
|
||||||
|
if i < 6:
|
||||||
|
self.matrix[i, 8] = mod
|
||||||
|
elif i < 8:
|
||||||
|
self.matrix[i + 1, 8] = mod
|
||||||
|
else:
|
||||||
|
self.matrix[self.module_count - 15 + i, 8] = mod
|
||||||
|
|
||||||
|
# // horizontal
|
||||||
|
for i in range(15):
|
||||||
|
mod = not test and ((bits >> i) & 1) == 1
|
||||||
|
if i < 8:
|
||||||
|
self.matrix[8, self.module_count - i - 1] = mod
|
||||||
|
elif i < 9:
|
||||||
|
self.matrix[8, 15 - i - 1 + 1] = mod
|
||||||
|
else:
|
||||||
|
self.matrix[8, 15 - i - 1] = mod
|
||||||
|
|
||||||
|
# // fixed module
|
||||||
|
self.matrix[self.module_count - 8, 8] = not test
|
||||||
|
|
||||||
|
def _map_data(self, data: bytes, mask_pattern: int) -> None:
|
||||||
|
"""Map the data onto the QR code"""
|
||||||
|
inc = -1
|
||||||
|
row = self.module_count - 1
|
||||||
|
bit_idx = 7
|
||||||
|
byte_idx = 0
|
||||||
|
|
||||||
|
for col in range(self.module_count - 1, 0, -2):
|
||||||
|
if col == 6:
|
||||||
|
col -= 1 # noqa: PLW2901 loop variable overwritten
|
||||||
|
|
||||||
|
while True:
|
||||||
|
for c in range(2):
|
||||||
|
if self.matrix[row, col - c] is None:
|
||||||
|
dark = False
|
||||||
|
if byte_idx < len(data):
|
||||||
|
dark = ((data[byte_idx] >> bit_idx) & 1) == 1
|
||||||
|
mask = QRUtil.get_mask(mask_pattern, row, col - c)
|
||||||
|
if mask:
|
||||||
|
dark = not dark
|
||||||
|
self.matrix[row, col - c] = dark
|
||||||
|
bit_idx -= 1
|
||||||
|
if bit_idx == -1:
|
||||||
|
byte_idx += 1
|
||||||
|
bit_idx = 7
|
||||||
|
row += inc
|
||||||
|
if row < 0 or self.module_count <= row:
|
||||||
|
row -= inc
|
||||||
|
inc = -inc
|
||||||
|
break
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _create_data(qr_type: int, ecc: int, data_list: list) -> bytes:
|
||||||
|
"""Check and format data into bit buffer"""
|
||||||
|
rs_blocks = _get_rs_blocks(qr_type, ecc)
|
||||||
|
|
||||||
|
buffer = QRBitBuffer()
|
||||||
|
|
||||||
|
for data in data_list:
|
||||||
|
if isinstance(data, str):
|
||||||
|
data = str.encode(data) # noqa: PLW2901 loop variable overwritten
|
||||||
|
buffer.put(_MODE_8BIT_BYTE, 4)
|
||||||
|
buffer.put(len(data), 8)
|
||||||
|
for byte in data:
|
||||||
|
buffer.put(byte, 8)
|
||||||
|
|
||||||
|
# // calc num max data.
|
||||||
|
total_data_count = 0
|
||||||
|
for block in rs_blocks:
|
||||||
|
total_data_count += block["data"]
|
||||||
|
|
||||||
|
if buffer.get_length_bits() > total_data_count * 8:
|
||||||
|
raise RuntimeError(
|
||||||
|
"Code length overflow: %d > %d" % (buffer.get_length_bits(), total_data_count * 8)
|
||||||
|
)
|
||||||
|
|
||||||
|
# // end code
|
||||||
|
if buffer.get_length_bits() + 4 <= total_data_count * 8:
|
||||||
|
buffer.put(0, 4)
|
||||||
|
|
||||||
|
# // padding
|
||||||
|
while buffer.get_length_bits() % 8 != 0:
|
||||||
|
buffer.put_bit(False)
|
||||||
|
|
||||||
|
# // padding
|
||||||
|
while True:
|
||||||
|
if buffer.get_length_bits() >= total_data_count * 8:
|
||||||
|
break
|
||||||
|
buffer.put(_PAD0, 8)
|
||||||
|
if buffer.get_length_bits() >= total_data_count * 8:
|
||||||
|
break
|
||||||
|
buffer.put(_PAD1, 8)
|
||||||
|
|
||||||
|
return QRCode._create_bytes(buffer, rs_blocks)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _create_bytes(buffer: bytes, rs_blocks: List[Dict]) -> bytes: # noqa: PLR0912 Too many branches
|
||||||
|
"""Perform error calculation math on bit buffer"""
|
||||||
|
|
||||||
|
offset = 0
|
||||||
|
max_dc_count = 0
|
||||||
|
max_ec_count = 0
|
||||||
|
|
||||||
|
dcdata = [0] * len(rs_blocks)
|
||||||
|
ecdata = [0] * len(rs_blocks)
|
||||||
|
|
||||||
|
for r, block in enumerate(rs_blocks):
|
||||||
|
dc_count = block["data"]
|
||||||
|
ec_count = block["total"] - dc_count
|
||||||
|
|
||||||
|
max_dc_count = max(max_dc_count, dc_count)
|
||||||
|
max_ec_count = max(max_ec_count, ec_count)
|
||||||
|
|
||||||
|
dcdata[r] = [0] * dc_count
|
||||||
|
|
||||||
|
for i in range(len(dcdata[r])):
|
||||||
|
dcdata[r][i] = 0xFF & buffer.buffer[i + offset]
|
||||||
|
offset += dc_count
|
||||||
|
|
||||||
|
rs_poly = QRUtil.get_error_correct_polynomial(ec_count)
|
||||||
|
mod_poly = QRPolynomial(dcdata[r], rs_poly.get_length() - 1)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if mod_poly.get_length() - rs_poly.get_length() < 0:
|
||||||
|
break
|
||||||
|
ratio = _glog(mod_poly.get(0)) - _glog(rs_poly.get(0))
|
||||||
|
num = [0 for x in range(mod_poly.get_length())]
|
||||||
|
for i in range(mod_poly.get_length()):
|
||||||
|
num[i] = mod_poly.get(i)
|
||||||
|
for i in range(rs_poly.get_length()):
|
||||||
|
num[i] ^= _gexp(_glog(rs_poly.get(i)) + ratio)
|
||||||
|
mod_poly = QRPolynomial(num, 0)
|
||||||
|
|
||||||
|
ecdata[r] = [0 for x in range(rs_poly.get_length() - 1)]
|
||||||
|
for i in range(len(ecdata[r])):
|
||||||
|
mod_index = i + mod_poly.get_length() - len(ecdata[r])
|
||||||
|
if mod_index >= 0:
|
||||||
|
ecdata[r][i] = mod_poly.get(mod_index)
|
||||||
|
else:
|
||||||
|
ecdata[r][i] = 0
|
||||||
|
|
||||||
|
total_code_count = 0
|
||||||
|
for block in rs_blocks:
|
||||||
|
total_code_count += block["total"]
|
||||||
|
|
||||||
|
data = [None] * total_code_count
|
||||||
|
index = 0
|
||||||
|
|
||||||
|
for i in range(max_dc_count):
|
||||||
|
for r in range(len(rs_blocks)):
|
||||||
|
if i < len(dcdata[r]):
|
||||||
|
data[index] = dcdata[r][i]
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
for i in range(max_ec_count):
|
||||||
|
for r in range(len(rs_blocks)):
|
||||||
|
if i < len(ecdata[r]):
|
||||||
|
data[index] = ecdata[r][i]
|
||||||
|
index += 1
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
class QRUtil:
|
||||||
|
"""A selection of bit manipulation tools for QR generation and BCH encoding"""
|
||||||
|
|
||||||
|
PATTERN_POSITION_TABLE = [
|
||||||
|
b"",
|
||||||
|
b"\x06\x12",
|
||||||
|
b"\x06\x16",
|
||||||
|
b"\x06\x1a",
|
||||||
|
b"\x06\x1e",
|
||||||
|
b'\x06"',
|
||||||
|
b"\x06\x16&",
|
||||||
|
b"\x06\x18*",
|
||||||
|
b"\x06\x1a.",
|
||||||
|
b"\x06\x1c2",
|
||||||
|
]
|
||||||
|
|
||||||
|
G15 = 0b10100110111
|
||||||
|
G18 = 0b1111100100101
|
||||||
|
G15_MASK = 0b101010000010010
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_BCH_type_info(data: int) -> int:
|
||||||
|
"""Encode with G15 BCH mask"""
|
||||||
|
d = data << 10
|
||||||
|
while QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G15) >= 0:
|
||||||
|
d ^= QRUtil.G15 << (QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G15))
|
||||||
|
|
||||||
|
return ((data << 10) | d) ^ QRUtil.G15_MASK
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_BCH_type_number(data: int) -> int:
|
||||||
|
"""Encode with G18 BCH mask"""
|
||||||
|
d = data << 12
|
||||||
|
while QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G18) >= 0:
|
||||||
|
d ^= QRUtil.G18 << (QRUtil.get_BCH_digit(d) - QRUtil.get_BCH_digit(QRUtil.G18))
|
||||||
|
return (data << 12) | d
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_BCH_digit(data: int) -> int:
|
||||||
|
"""Count digits in data"""
|
||||||
|
digit = 0
|
||||||
|
while data != 0:
|
||||||
|
digit += 1
|
||||||
|
data >>= 1
|
||||||
|
return digit
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_pattern_position(qr_type: int) -> bytes:
|
||||||
|
"""The mask pattern position array for this QR type"""
|
||||||
|
return QRUtil.PATTERN_POSITION_TABLE[qr_type - 1]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_mask(mask: int, i: int, j: int) -> int: # noqa: PLR0911 Too many return statements
|
||||||
|
"""Perform matching calculation on two vals for given pattern mask"""
|
||||||
|
if mask == 0:
|
||||||
|
return (i + j) % 2 == 0
|
||||||
|
if mask == 1:
|
||||||
|
return i % 2 == 0
|
||||||
|
if mask == 2:
|
||||||
|
return j % 3 == 0
|
||||||
|
if mask == 3:
|
||||||
|
return (i + j) % 3 == 0
|
||||||
|
if mask == 4:
|
||||||
|
return (math.floor(i / 2) + math.floor(j / 3)) % 2 == 0
|
||||||
|
if mask == 5:
|
||||||
|
return (i * j) % 2 + (i * j) % 3 == 0
|
||||||
|
if mask == 6:
|
||||||
|
return ((i * j) % 2 + (i * j) % 3) % 2 == 0
|
||||||
|
if mask == 7:
|
||||||
|
return ((i * j) % 3 + (i + j) % 2) % 2 == 0
|
||||||
|
raise ValueError("Bad mask pattern:" + mask)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_error_correct_polynomial(ecc_length: int) -> "QRPolynomial":
|
||||||
|
"""Generate a ecc polynomial"""
|
||||||
|
poly = QRPolynomial([1], 0)
|
||||||
|
for i in range(ecc_length):
|
||||||
|
poly = poly.multiply(QRPolynomial([1, _gexp(i)], 0))
|
||||||
|
return poly
|
||||||
|
|
||||||
|
|
||||||
|
class QRPolynomial:
|
||||||
|
"""Structure for creating and manipulating error code polynomials"""
|
||||||
|
|
||||||
|
def __init__(self, num: int, shift: int):
|
||||||
|
"""Create a QR polynomial"""
|
||||||
|
if not num:
|
||||||
|
raise ValueError(num.length + "/" + shift)
|
||||||
|
offset = 0
|
||||||
|
while offset < len(num) and num[offset] == 0:
|
||||||
|
offset += 1
|
||||||
|
self.num = [0 for x in range(len(num) - offset + shift)]
|
||||||
|
for i in range(len(num) - offset):
|
||||||
|
self.num[i] = num[i + offset]
|
||||||
|
|
||||||
|
def get(self, index: int) -> int:
|
||||||
|
"""The exponent at the index location"""
|
||||||
|
return self.num[index]
|
||||||
|
|
||||||
|
def get_length(self) -> int:
|
||||||
|
"""Length of the poly"""
|
||||||
|
return len(self.num)
|
||||||
|
|
||||||
|
def multiply(self, other_polynomial: "QRPolynomial") -> "QRPolynomial":
|
||||||
|
"""Multiply two polynomials, returns a new one"""
|
||||||
|
num = [0 for x in range(self.get_length() + other_polynomial.get_length() - 1)]
|
||||||
|
|
||||||
|
for i in range(self.get_length()):
|
||||||
|
for j in range(other_polynomial.get_length()):
|
||||||
|
num[i + j] ^= _gexp(_glog(self.get(i)) + _glog(other_polynomial.get(j)))
|
||||||
|
|
||||||
|
return QRPolynomial(num, 0)
|
||||||
|
|
||||||
|
|
||||||
|
_QRRS_BLOCK_TABLE = (
|
||||||
|
b"\x01\x1a\x10",
|
||||||
|
b"\x01\x1a\x13",
|
||||||
|
b"\x01\x1a\t",
|
||||||
|
b"\x01\x1a\r",
|
||||||
|
b"\x01,\x1c",
|
||||||
|
b'\x01,"',
|
||||||
|
b"\x01,\x10",
|
||||||
|
b"\x01,\x16",
|
||||||
|
b"\x01F,",
|
||||||
|
b"\x01F7",
|
||||||
|
b"\x02#\r",
|
||||||
|
b"\x02#\x11",
|
||||||
|
b"\x022 ",
|
||||||
|
b"\x01dP",
|
||||||
|
b"\x04\x19\t",
|
||||||
|
b"\x022\x18",
|
||||||
|
b"\x02C+",
|
||||||
|
b"\x01\x86l",
|
||||||
|
b'\x02!\x0b\x02"\x0c',
|
||||||
|
b'\x02!\x0f\x02"\x10',
|
||||||
|
b"\x04+\x1b",
|
||||||
|
b"\x02VD",
|
||||||
|
b"\x04+\x0f",
|
||||||
|
b"\x04+\x13",
|
||||||
|
b"\x041\x1f",
|
||||||
|
b"\x02bN",
|
||||||
|
b"\x04'\r\x01(\x0e",
|
||||||
|
b"\x02 \x0e\x04!\x0f",
|
||||||
|
b"\x02<&\x02='",
|
||||||
|
b"\x02ya",
|
||||||
|
b"\x04(\x0e\x02)\x0f",
|
||||||
|
b"\x04(\x12\x02)\x13",
|
||||||
|
b"\x03:$\x02;%",
|
||||||
|
b"\x02\x92t",
|
||||||
|
b"\x04$\x0c\x04%\r",
|
||||||
|
b"\x04$\x10\x04%\x11",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_rs_blocks(qr_type: int, ecc: int) -> List[Dict]:
|
||||||
|
rs_block = _QRRS_BLOCK_TABLE[(qr_type - 1) * 4 + ecc]
|
||||||
|
|
||||||
|
length = len(rs_block) // 3
|
||||||
|
blocks = []
|
||||||
|
for i in range(length):
|
||||||
|
count = rs_block[i * 3 + 0]
|
||||||
|
total = rs_block[i * 3 + 1]
|
||||||
|
data = rs_block[i * 3 + 2]
|
||||||
|
block = {"total": total, "data": data}
|
||||||
|
for _ in range(count):
|
||||||
|
blocks.append(block)
|
||||||
|
return blocks
|
||||||
|
|
||||||
|
|
||||||
|
class QRBitMatrix:
|
||||||
|
"""A bit-packed storage class for matrices"""
|
||||||
|
|
||||||
|
def __init__(self, width: int, height: int):
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
if width > 60:
|
||||||
|
raise ValueError("Max 60 bits wide:", width)
|
||||||
|
self.buffer = [0] * self.height * 2
|
||||||
|
self.used = [0] * self.height * 2
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
b = ""
|
||||||
|
for y in range(self.height):
|
||||||
|
for x in range(self.width):
|
||||||
|
if self[x, y]:
|
||||||
|
b += "X"
|
||||||
|
else:
|
||||||
|
b += "."
|
||||||
|
b += "\n"
|
||||||
|
return b
|
||||||
|
|
||||||
|
def __getitem__(self, key: Tuple[int, int]) -> int:
|
||||||
|
x, y = key
|
||||||
|
if y > self.width:
|
||||||
|
raise ValueError()
|
||||||
|
i = 2 * x + (y // 30)
|
||||||
|
j = y % 30
|
||||||
|
if not self.used[i] & (1 << j):
|
||||||
|
return None
|
||||||
|
return self.buffer[i] & (1 << j)
|
||||||
|
|
||||||
|
def __setitem__(self, key: Tuple[int, int], value: int) -> None:
|
||||||
|
x, y = key
|
||||||
|
if y > self.width:
|
||||||
|
raise ValueError()
|
||||||
|
i = 2 * x + (y // 30)
|
||||||
|
j = y % 30
|
||||||
|
if value:
|
||||||
|
self.buffer[i] |= 1 << j
|
||||||
|
else:
|
||||||
|
self.buffer[i] &= ~(1 << j)
|
||||||
|
self.used[i] |= 1 << j # buffer item was set
|
||||||
|
|
||||||
|
|
||||||
|
class QRBitBuffer:
|
||||||
|
"""Storage class for a length of individual bits"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.buffer = []
|
||||||
|
self.length = 0
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return ".".join([str(n) for n in self.buffer])
|
||||||
|
|
||||||
|
def get(self, index: int) -> int:
|
||||||
|
"""The bit value at a location"""
|
||||||
|
i = index // 8
|
||||||
|
return self.buffer[i] & (1 << (7 - index % 8))
|
||||||
|
|
||||||
|
def put(self, num: int, length: int) -> None:
|
||||||
|
"""Add a number of bits from a single integer value"""
|
||||||
|
for i in range(length):
|
||||||
|
self.put_bit(num & (1 << (length - i - 1)))
|
||||||
|
|
||||||
|
def get_length_bits(self) -> int:
|
||||||
|
"""Size of bit buffer"""
|
||||||
|
return self.length
|
||||||
|
|
||||||
|
def put_bit(self, bit: int) -> None:
|
||||||
|
"""Insert one bit at the end of the bit buffer"""
|
||||||
|
i = self.length // 8
|
||||||
|
if len(self.buffer) <= i:
|
||||||
|
self.buffer.append(0)
|
||||||
|
if bit:
|
||||||
|
self.buffer[i] |= 0x80 >> (self.length % 8)
|
||||||
|
self.length += 1
|
||||||
52
mixly/boards/default/micropython/build/lib/adxl345.py
Normal file
52
mixly/boards/default/micropython/build/lib/adxl345.py
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ADXL345
|
||||||
|
import time
|
||||||
|
import ustruct
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
DATA_FORMAT = const(0x31)
|
||||||
|
BW_RATE = const(0x2c)
|
||||||
|
POWER_CTL = const(0x2d)
|
||||||
|
INT_ENABLE = const(0x2E)
|
||||||
|
OFSX = const(0x1e)
|
||||||
|
OFSY = const(0x1f)
|
||||||
|
OFSZ = const(0x20)
|
||||||
|
|
||||||
|
class ADXL345:
|
||||||
|
def __init__(self, i2c, address=0X53):
|
||||||
|
self._device = i2c
|
||||||
|
self._address = address
|
||||||
|
if self._rreg(0x0) != 0xe5:
|
||||||
|
raise AttributeError("Cannot find a ADXL345")
|
||||||
|
|
||||||
|
self._wreg(DATA_FORMAT,0x2B) #16g量程
|
||||||
|
self._wreg(BW_RATE,0x0A) #数据输出速度为100Hz
|
||||||
|
self._wreg(INT_ENABLE,0x00) #不使用中断
|
||||||
|
|
||||||
|
self._wreg(OFSX,0x00)
|
||||||
|
self._wreg(OFSY,0x00)
|
||||||
|
self._wreg(OFSZ,0x00)
|
||||||
|
self._wreg(POWER_CTL,0x08) #链接使能,测量模式
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
def readXYZ(self):
|
||||||
|
x, = ustruct.unpack('<h', self._rreg(0x32,2))
|
||||||
|
y, = ustruct.unpack('<h', self._rreg(0x34,2))
|
||||||
|
z, = ustruct.unpack('<h', self._rreg(0x36,2))
|
||||||
|
return (x/256,y/256,z/256)
|
||||||
|
|
||||||
|
def readX(self):
|
||||||
|
return self.readXYZ()[0]
|
||||||
|
|
||||||
|
def readY(self):
|
||||||
|
return self.readXYZ()[1]
|
||||||
|
|
||||||
|
def readZ(self):
|
||||||
|
return self.readXYZ()[2]
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg,nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
97
mixly/boards/default/micropython/build/lib/ags10.py
Normal file
97
mixly/boards/default/micropython/build/lib/ags10.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
"""
|
||||||
|
AGS10
|
||||||
|
|
||||||
|
Micropython library for the AGS10(TVOC)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_AGS10_ADC = const(0x00)
|
||||||
|
_AGS10_CAL = const(0x01)
|
||||||
|
_AGS10_RES = const(0x20)
|
||||||
|
_AGS10_ADD = const(0x21)
|
||||||
|
|
||||||
|
class AGS10:
|
||||||
|
def __init__(self, i2c_bus, address=0x1A, delay=1000):
|
||||||
|
self._i2c = i2c_bus
|
||||||
|
self._addr = address
|
||||||
|
self._voc = 0
|
||||||
|
self._delay = delay
|
||||||
|
self._star = 0
|
||||||
|
self.ready = 0
|
||||||
|
|
||||||
|
def _crc8(self, buf, is_byte=False):
|
||||||
|
'''Perform CRC check on the data'''
|
||||||
|
crc = 0xff
|
||||||
|
for byte in buf:
|
||||||
|
crc ^= byte
|
||||||
|
for _ in range(8):
|
||||||
|
if crc & 0x80:
|
||||||
|
crc = (crc << 1) ^ 0x31
|
||||||
|
else:
|
||||||
|
crc = crc << 1
|
||||||
|
return crc.to_bytes(1, 'little') if is_byte else crc & 0xff
|
||||||
|
|
||||||
|
def _wreg(self, reg, buf):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._i2c.writeto_mem(self._addr, reg, buf)
|
||||||
|
time.sleep_ms(20)
|
||||||
|
|
||||||
|
def _rreg(self, reg, nbytes=5):
|
||||||
|
'''Read memory address'''
|
||||||
|
_buf = self._i2c.readfrom_mem(self._addr, reg, nbytes)
|
||||||
|
time.sleep_ms(20)
|
||||||
|
return _buf[:4] if self._crc8(_buf[:4]) == _buf[4] else None
|
||||||
|
|
||||||
|
def address(self, addr=None):
|
||||||
|
_scan = self._i2c.scan()
|
||||||
|
if addr is None:
|
||||||
|
if self._addr in _scan:
|
||||||
|
return self._addr
|
||||||
|
elif len(_scan) == 1:
|
||||||
|
self._addr = _scan[0]
|
||||||
|
return self._addr
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
if self.address():
|
||||||
|
if 8<= addr <=119:
|
||||||
|
_buf = bytes([addr, (~ addr) & 0xff] * 2)
|
||||||
|
self._wreg(_AGS10_ADD, _buf + self._crc8(_buf, True))
|
||||||
|
if addr in self._i2c.scan():
|
||||||
|
self._addr = addr
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
raise ValueError("Not within the valid range of 8-119")
|
||||||
|
|
||||||
|
def calibration(self, zero=1):
|
||||||
|
'''0: Factory restoration 1:Sensor resistance'''
|
||||||
|
_buf = b'\x00\x0c'
|
||||||
|
_buf += b'\x00\x00' if zero else b'\xff\xff'
|
||||||
|
self._wreg(_AGS10_ADD, _buf + self._crc8(_buf, True))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def getdata(self):
|
||||||
|
if time.ticks_diff(time.ticks_ms(), self._star) >= self._delay:
|
||||||
|
self._star = time.ticks_ms()
|
||||||
|
_buf = self._rreg(_AGS10_ADC)
|
||||||
|
self._voc = int.from_bytes(_buf[1:4], 'big')
|
||||||
|
self.ready = not (_buf[0] & 0x01)
|
||||||
|
return self._voc / 1000
|
||||||
|
|
||||||
|
def read(self, hcho_mw=30.033 , co2_mv=0.853, co2_base=400):
|
||||||
|
'''unit ppm'''
|
||||||
|
self.getdata
|
||||||
|
_voc = self._voc / 1000 #ppm
|
||||||
|
return round( _voc, 2), round( _voc / hcho_mw, 2), co2_base + round( _voc / co2_mv, 2)
|
||||||
|
|
||||||
|
def tvoc(self):
|
||||||
|
return self.read()[0]
|
||||||
|
|
||||||
|
def hcho(self, tvoc_mw=30.053):
|
||||||
|
return self.read(hcho_mw=hcho_mw)[1]
|
||||||
|
|
||||||
|
def eco2(self, co2_mv=0.853):
|
||||||
|
return self.read(co2_mv=co2_mv)[2]
|
||||||
88
mixly/boards/default/micropython/build/lib/ahtx0.py
Normal file
88
mixly/boards/default/micropython/build/lib/ahtx0.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
"""
|
||||||
|
AHT21
|
||||||
|
|
||||||
|
Micropython library for the AHT21(temperature,humidity)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Changed from circuitpython to micropython 20220211
|
||||||
|
#Format unified 20220623
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import utime
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
AHTX0_I2CADDR_DEFAULT = const(0x38) # Default I2C address
|
||||||
|
AHTX0_CMD_INITIALIZE = const(0xE1) # Initialization command
|
||||||
|
AHTX0_CMD_TRIGGER = const(0xAC) # Trigger reading command
|
||||||
|
AHTX0_CMD_SOFTRESET = const(0xBA) # Soft reset command
|
||||||
|
AHTX0_STATUS_BUSY = const(0x80) # Status bit for busy
|
||||||
|
AHTX0_STATUS_CALIBRATED = const(0x08) # Status bit for calibrated
|
||||||
|
|
||||||
|
class AHTx0:
|
||||||
|
"""Interface library for AHT10/AHT20 temperature+humidity sensors"""
|
||||||
|
def __init__(self, i2c, address=AHTX0_I2CADDR_DEFAULT):
|
||||||
|
utime.sleep_ms(20) # 20ms delay to wake up
|
||||||
|
self._i2c = i2c
|
||||||
|
self._address = address
|
||||||
|
self._buf = bytearray(6)
|
||||||
|
self.reset()
|
||||||
|
if not self.initialize():
|
||||||
|
raise AttributeError("Cannot find a AHTx0")
|
||||||
|
self._temp = None
|
||||||
|
self._humidity = None
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Perform a soft-reset of the AHT"""
|
||||||
|
self._buf[0] = AHTX0_CMD_SOFTRESET
|
||||||
|
self._i2c.writeto(self._address, self._buf[0:1])
|
||||||
|
utime.sleep_ms(20) # 20ms delay to wake up
|
||||||
|
|
||||||
|
def initialize(self):
|
||||||
|
"""Ask the sensor to self-initialize. Returns True on success, False otherwise"""
|
||||||
|
self._buf[0] = AHTX0_CMD_INITIALIZE
|
||||||
|
self._buf[1] = 0x08
|
||||||
|
self._buf[2] = 0x00
|
||||||
|
self._i2c.writeto(self._address, self._buf[0:3])
|
||||||
|
self._wait_for_idle()
|
||||||
|
if not self.status() & AHTX0_STATUS_CALIBRATED:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def status(self):
|
||||||
|
"""The status byte initially returned from the sensor, see datasheet for details"""
|
||||||
|
self._read_to_buffer()
|
||||||
|
return self._buf[0]
|
||||||
|
|
||||||
|
def _read_to_buffer(self):
|
||||||
|
self._i2c.readfrom_into(self._address, self._buf)
|
||||||
|
|
||||||
|
def _trigger_measurement(self):
|
||||||
|
"""Internal function for triggering the AHT to read temp/humidity"""
|
||||||
|
self._buf[0] = AHTX0_CMD_TRIGGER
|
||||||
|
self._buf[1] = 0x33
|
||||||
|
self._buf[2] = 0x00
|
||||||
|
self._i2c.writeto(self._address, self._buf[0:3])
|
||||||
|
|
||||||
|
def _wait_for_idle(self):
|
||||||
|
while self.status() & AHTX0_STATUS_BUSY:
|
||||||
|
utime.sleep_ms(5)
|
||||||
|
|
||||||
|
def _perform_measurement(self):
|
||||||
|
self._trigger_measurement()
|
||||||
|
self._wait_for_idle()
|
||||||
|
self._read_to_buffer()
|
||||||
|
|
||||||
|
def humidity(self):
|
||||||
|
"""The measured relative humidity in percent."""
|
||||||
|
self._perform_measurement()
|
||||||
|
self._humidity = (self._buf[1] << 12) | (self._buf[2] << 4) | (self._buf[3] >> 4)
|
||||||
|
self._humidity = (self._humidity * 100) / 0x100000
|
||||||
|
return self._humidity
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
"""The measured temperature in degrees Celcius."""
|
||||||
|
self._perform_measurement()
|
||||||
|
self._temp = ((self._buf[3] & 0xF) << 16) | (self._buf[4] << 8) | self._buf[5]
|
||||||
|
self._temp = ((self._temp * 200.0) / 0x100000) - 50
|
||||||
|
return self._temp
|
||||||
59
mixly/boards/default/micropython/build/lib/ap3216c.py
Normal file
59
mixly/boards/default/micropython/build/lib/ap3216c.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
"""
|
||||||
|
AP3216C
|
||||||
|
|
||||||
|
MicroPython library for the AP3216C(ALS,PS,IRS)
|
||||||
|
=======================================================
|
||||||
|
#Preliminary composition 20240630
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
AP3216_ADD = const(0x1E)
|
||||||
|
AP_SYS_CMD = const(0x00)
|
||||||
|
AP_DAT = const(0x0A)
|
||||||
|
AP_ALS_CMD = const(0x10)
|
||||||
|
AP_PS_CMD = const(0x20)
|
||||||
|
AP_PS_LED = const(0x21)
|
||||||
|
Resolution = 0.35
|
||||||
|
|
||||||
|
class AP3216C:
|
||||||
|
def __init__(self, i2c_bus, addr=AP3216_ADD):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
self._wreg(AP_SYS_CMD, 0x04) # SW reset
|
||||||
|
time.sleep_ms(100)
|
||||||
|
self._wreg(AP_SYS_CMD, 0x03) # 011: ALS and PS+IR functions active
|
||||||
|
self._wreg(AP_ALS_CMD, 0x00) # Range 1: 0 ~ 20661 Lux. Resolution = 0.35 lux/count.
|
||||||
|
self._wreg(AP_PS_CMD, 0x09) # PS gain:10
|
||||||
|
self._wreg(AP_PS_LED, 0x23) # PS LED pulse:10
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg, nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def getdata(self):
|
||||||
|
'''处理获取数据'''
|
||||||
|
#buf = self._rreg(AP_DAT, 6)
|
||||||
|
ir = (self._rreg(AP_DAT + 0) & 0x03) | self._rreg(AP_DAT + 1) << 2
|
||||||
|
als= (self._rreg(AP_DAT + 2) | self._rreg(AP_DAT + 3) << 8) * Resolution
|
||||||
|
ps = (self._rreg(AP_DAT + 4) & 0x0F) | (self._rreg(AP_DAT + 5) & 0x3F) << 4
|
||||||
|
return round(als, 2), ir, ps
|
||||||
|
|
||||||
|
def als_vis(self):
|
||||||
|
'''可见光Lux'''
|
||||||
|
return self.getdata[0]
|
||||||
|
|
||||||
|
def als_ir(self):
|
||||||
|
'''红外Lux'''
|
||||||
|
return self.getdata[1]
|
||||||
|
|
||||||
|
def ps_nl(self):
|
||||||
|
'''接近距离'''
|
||||||
|
return self.getdata[2]
|
||||||
294
mixly/boards/default/micropython/build/lib/apds9960.py
Normal file
294
mixly/boards/default/micropython/build/lib/apds9960.py
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
"""
|
||||||
|
APDS9960`
|
||||||
|
|
||||||
|
MicroPython library for the APDS9960(Supports gesture, proximity, and color detection)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20220224
|
||||||
|
#base on https://github.com/adafruit/Adafruit_CircuitPython_BusDevice 20220623
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_DEVICE_ID = const(0xAB)
|
||||||
|
_APDS9960_ENABLE = const(0x80)
|
||||||
|
_APDS9960_ATIME = const(0x81)
|
||||||
|
_APDS9960_PILT = const(0x89)
|
||||||
|
_APDS9960_PIHT = const(0x8B)
|
||||||
|
_APDS9960_PERS = const(0x8C)
|
||||||
|
_APDS9960_CONTROL = const(0x8F)
|
||||||
|
_APDS9960_ID = const(0x92)
|
||||||
|
_APDS9960_STATUS = const(0x93)
|
||||||
|
_APDS9960_CDATAL = const(0x94)
|
||||||
|
_APDS9960_PDATA = const(0x9C)
|
||||||
|
_APDS9960_GPENTH = const(0xA0)
|
||||||
|
_APDS9960_GEXTH = const(0xA1)
|
||||||
|
_APDS9960_GCONF1 = const(0xA2)
|
||||||
|
_APDS9960_GCONF2 = const(0xA3)
|
||||||
|
_APDS9960_GPULSE = const(0xA6)
|
||||||
|
_APDS9960_GCONF4 = const(0xAB)
|
||||||
|
_APDS9960_GFLVL = const(0xAE)
|
||||||
|
_APDS9960_GSTATUS = const(0xAF)
|
||||||
|
_APDS9960_AICLEAR = const(0xE7)
|
||||||
|
_APDS9960_GFIFO_U = const(0xFC)
|
||||||
|
_BIT_MASK_ENABLE_EN = const(0x01)
|
||||||
|
_BIT_MASK_ENABLE_COLOR = const(0x02)
|
||||||
|
_BIT_MASK_ENABLE_PROX = const(0x04)
|
||||||
|
_BIT_MASK_ENABLE_PROX_INT = const(0x20)
|
||||||
|
_BIT_MASK_ENABLE_GESTURE = const(0x40)
|
||||||
|
_BIT_MASK_STATUS_AVALID = const(0x01)
|
||||||
|
_BIT_MASK_STATUS_GINT = const(0x04)
|
||||||
|
_BIT_MASK_GSTATUS_GFOV = const(0x02)
|
||||||
|
_BIT_MASK_GCONF4_GFIFO_CLR = const(0x04)
|
||||||
|
_BIT_POS_PERS_PPERS = const(4)
|
||||||
|
_BIT_MASK_PERS_PPERS = const(0xF0)
|
||||||
|
_BIT_POS_CONTROL_AGAIN = const(0)
|
||||||
|
_BIT_MASK_CONTROL_AGAIN = const(3)
|
||||||
|
_BIT_POS_CONTROL_PGAIN = const(2)
|
||||||
|
_BIT_MASK_CONTROL_PGAIN = const(0x0C)
|
||||||
|
_BIT_POS_GCONF2_GGAIN = const(5)
|
||||||
|
_BIT_MASK_GCONF2_GGAIN = const(0x60)
|
||||||
|
|
||||||
|
class APDS9960:
|
||||||
|
def __init__(self, i2c, address=0x39):
|
||||||
|
self._device = i2c
|
||||||
|
self._address = address
|
||||||
|
self._select = [True,True,True]
|
||||||
|
|
||||||
|
if self._rreg(_APDS9960_ID) != _DEVICE_ID:
|
||||||
|
raise AttributeError("Cannot find a APDS9960")
|
||||||
|
|
||||||
|
self.enable(True) # Re-enable sensor and wait 10ms for the power on delay to finish
|
||||||
|
time.sleep(0.010)
|
||||||
|
self._wreg(_APDS9960_GPENTH, 0x05) # Enter gesture engine at >= 5 proximity counts
|
||||||
|
self._wreg(_APDS9960_GEXTH, 0x1E) # Exit gesture engine if all counts drop below 30
|
||||||
|
self._wreg(_APDS9960_GCONF1, 0x82) # GEXPERS: 2 (4 cycles), GEXMSK: 0 (default) GFIFOTH: 2 (8 datasets)
|
||||||
|
self._wreg(_APDS9960_GCONF2, 0x41) # GGAIN: 2 (4x), GLDRIVE: 100 mA (default), GWTIME: 1 (2.8ms)
|
||||||
|
self._wreg(_APDS9960_GPULSE, 0x85) # GPULSE: 5 (6 pulses), GPLEN: 2 (16 us)
|
||||||
|
self.color_integration_time(256) # ATIME: 256 (712ms color integration time, max count of 65535)
|
||||||
|
|
||||||
|
# method for reading and writing to I2C
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _writecmdonly(self, val):
|
||||||
|
"""Writes a command and 0 bytes of data to the I2C device"""
|
||||||
|
self._device.writeto(self._address,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg,nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _get_bit(self, reg, mask):
|
||||||
|
"""Gets a single bit value from the I2C device's register"""
|
||||||
|
return bool(self._rreg(reg) & mask)
|
||||||
|
|
||||||
|
def _set_bit(self, reg, mask, value):
|
||||||
|
"""Sets a single bit value in the I2C device's register"""
|
||||||
|
buf=self._rreg(reg)
|
||||||
|
buf= buf | mask if value else buf & ~mask
|
||||||
|
self._wreg(reg,buf)
|
||||||
|
|
||||||
|
def _set_bits(self, reg, pos, mask, value):
|
||||||
|
"""Sets a multi-bit value in the I2C device's register"""
|
||||||
|
buf=self._rreg(reg)
|
||||||
|
buf = (buf & ~mask) | (value << pos)
|
||||||
|
self._wreg(reg,buf)
|
||||||
|
|
||||||
|
def _color_data16(self, reg):
|
||||||
|
"""Sends a command and reads 2 bytes of data from the I2C device"""
|
||||||
|
buf = self._rreg(reg,2)
|
||||||
|
return buf[1] << 8 | buf[0]
|
||||||
|
|
||||||
|
def enable(self, value):
|
||||||
|
"""sensor is enabled"""
|
||||||
|
self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_EN, value)
|
||||||
|
|
||||||
|
def enable_proximity(self, value):
|
||||||
|
"""sensor's proximity engine is enabled."""
|
||||||
|
self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_PROX, value)
|
||||||
|
|
||||||
|
def proximity_gain(self, value):
|
||||||
|
"""""Proximity sensor gain value"""
|
||||||
|
# proximity_gain" "Gain Multiplier" "Note"
|
||||||
|
# 0, "1x", "Power-on Default"
|
||||||
|
# 1, "2x", ""
|
||||||
|
# 2, "4x", ""
|
||||||
|
# 3, "8x", ""
|
||||||
|
self._set_bits(_APDS9960_CONTROL, _BIT_POS_CONTROL_PGAIN, _BIT_MASK_CONTROL_PGAIN, value)
|
||||||
|
|
||||||
|
def enable_gesture(self, value):
|
||||||
|
"""sensor's gesture engine is enabled"""
|
||||||
|
self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_GESTURE, value)
|
||||||
|
|
||||||
|
def gesture_gain(self, value):
|
||||||
|
"""Gesture mode gain value"""
|
||||||
|
# "gesture_gain" "Gain Multiplier" "Note"
|
||||||
|
# 0, "1x", "Power-on Default"
|
||||||
|
# 1, "2x", ""
|
||||||
|
# 2, "4x", "Driver Default"
|
||||||
|
# 3, "8x", ""
|
||||||
|
self._set_bits(_APDS9960_GCONF2, _BIT_POS_GCONF2_GGAIN, _BIT_MASK_GCONF2_GGAIN, value)
|
||||||
|
|
||||||
|
def enable_color(self, value):
|
||||||
|
"""sensor's color/light engine is enabled"""
|
||||||
|
self._set_bit(_APDS9960_ENABLE, _BIT_MASK_ENABLE_COLOR, value)
|
||||||
|
|
||||||
|
def color_gain(self, value):
|
||||||
|
"""Color/light sensor gain value"""
|
||||||
|
# "color_gain" "Gain Multiplier" "Note"
|
||||||
|
# 0, "1x", "Power-on Default"
|
||||||
|
# 1, "4x", "Driver Default"
|
||||||
|
# 2, "16x", ""
|
||||||
|
# 3, "64x", ""
|
||||||
|
self._set_bits(_APDS9960_CONTROL, _BIT_POS_CONTROL_AGAIN, _BIT_MASK_CONTROL_AGAIN, value)
|
||||||
|
|
||||||
|
def color_integration_time(self, value):
|
||||||
|
"""Color/light sensor gain"""
|
||||||
|
# "color_integration_time" "Time" "Max Count" "Note"
|
||||||
|
# 1, "2.78 ms", 1025, "Power-on Default"
|
||||||
|
# 10, "27.8 ms", 10241, ""
|
||||||
|
# 37, "103 ms", 37889, ""
|
||||||
|
# 72, "200 ms", 65535, ""
|
||||||
|
# 256, "712 ms", 65535, "Driver Default"
|
||||||
|
self._wreg(_APDS9960_ATIME, 256 - value)
|
||||||
|
|
||||||
|
## PROXIMITY
|
||||||
|
def proximity(self,gain=2):
|
||||||
|
"""Proximity sensor data"""
|
||||||
|
if self._select[0]:
|
||||||
|
self._select=[False,True,True]
|
||||||
|
self.enable_proximity(True)
|
||||||
|
self.enable_gesture(False)
|
||||||
|
self.enable_color(False)
|
||||||
|
self.proximity_gain(gain)
|
||||||
|
|
||||||
|
return self._rreg(_APDS9960_PDATA)
|
||||||
|
|
||||||
|
## GESTURE
|
||||||
|
def gesture(self,gain=3):
|
||||||
|
"""Gesture sensor data"""
|
||||||
|
# If FIFOs have overflowed we're already way too late, so clear those FIFOs and wait
|
||||||
|
if self._select[1]:
|
||||||
|
self._select=[True,False,True]
|
||||||
|
self.enable_proximity(True)
|
||||||
|
self.enable_gesture(True)
|
||||||
|
self.enable_color(False)
|
||||||
|
self.gesture_gain(gain)
|
||||||
|
|
||||||
|
if self._get_bit(_APDS9960_GSTATUS, _BIT_MASK_GSTATUS_GFOV):
|
||||||
|
self._set_bit(_APDS9960_GCONF4, _BIT_MASK_GCONF4_GFIFO_CLR, True)
|
||||||
|
wait_cycles = 0
|
||||||
|
while ( not self._get_bit(_APDS9960_STATUS, _BIT_MASK_STATUS_GINT) and wait_cycles <= 30 ):
|
||||||
|
time.sleep(0.003)
|
||||||
|
wait_cycles += 1
|
||||||
|
|
||||||
|
frame = []
|
||||||
|
datasets_available = self._rreg(_APDS9960_GFLVL)
|
||||||
|
if (self._get_bit(_APDS9960_STATUS, _BIT_MASK_STATUS_GINT) and datasets_available > 0 ):
|
||||||
|
|
||||||
|
buffer = bytearray(128)
|
||||||
|
buffer_dataset = bytearray(4)
|
||||||
|
while True:
|
||||||
|
dataset_count = self._rreg(_APDS9960_GFLVL)
|
||||||
|
if dataset_count == 0:
|
||||||
|
break
|
||||||
|
buffer=self._rreg(_APDS9960_GFIFO_U,min(128, 1 + (dataset_count * 4)))
|
||||||
|
# Unpack data stream into more usable U/D/L/R datasets for analysis
|
||||||
|
idx = 0
|
||||||
|
for i in range(dataset_count):
|
||||||
|
idx = i * 4
|
||||||
|
buffer_dataset[0] = buffer[idx]
|
||||||
|
buffer_dataset[1] = buffer[idx + 1]
|
||||||
|
buffer_dataset[2] = buffer[idx + 2]
|
||||||
|
buffer_dataset[3] = buffer[idx + 3]
|
||||||
|
|
||||||
|
if ((not all(val == 255 for val in buffer_dataset))
|
||||||
|
and (not all(val == 0 for val in buffer_dataset))
|
||||||
|
and (all(val >= 30 for val in buffer_dataset))
|
||||||
|
):
|
||||||
|
if len(frame) < 2:
|
||||||
|
frame.append(tuple(buffer_dataset))
|
||||||
|
else:
|
||||||
|
frame[1] = tuple(buffer_dataset)
|
||||||
|
time.sleep(0.03)
|
||||||
|
if len(frame) < 2:
|
||||||
|
return None
|
||||||
|
# Determine our up/down and left/right ratios along with our first/last deltas
|
||||||
|
f_r_ud = ((frame[0][0] - frame[0][1]) * 100) // (frame[0][0] + frame[0][1])
|
||||||
|
f_r_lr = ((frame[0][2] - frame[0][3]) * 100) // (frame[0][2] + frame[0][3])
|
||||||
|
l_r_ud = ((frame[1][0] - frame[1][1]) * 100) // (frame[1][0] + frame[1][1])
|
||||||
|
l_r_lr = ((frame[1][2] - frame[1][3]) * 100) // (frame[1][2] + frame[1][3])
|
||||||
|
delta_ud = l_r_ud - f_r_ud
|
||||||
|
delta_lr = l_r_lr - f_r_lr
|
||||||
|
# Make our first guess at what gesture we saw, if any
|
||||||
|
state_ud = 0
|
||||||
|
state_lr = 0
|
||||||
|
if delta_ud >= 30:
|
||||||
|
state_ud = 1
|
||||||
|
elif delta_ud <= -30:
|
||||||
|
state_ud = -1
|
||||||
|
|
||||||
|
if delta_lr >= 30:
|
||||||
|
state_lr = 1
|
||||||
|
elif delta_lr <= -30:
|
||||||
|
state_lr = -1
|
||||||
|
# Make our final decision based on our first guess and, if required, the delta data
|
||||||
|
gesture_found = 0
|
||||||
|
# Easy cases
|
||||||
|
if state_ud == -1 and state_lr == 0:
|
||||||
|
gesture_found = 1
|
||||||
|
elif state_ud == 1 and state_lr == 0:
|
||||||
|
gesture_found = 2
|
||||||
|
elif state_ud == 0 and state_lr == -1:
|
||||||
|
gesture_found = 3
|
||||||
|
elif state_ud == 0 and state_lr == 1:
|
||||||
|
gesture_found = 4
|
||||||
|
# Not so easy cases
|
||||||
|
if gesture_found == 0:
|
||||||
|
if state_ud == -1 and state_lr == 1:
|
||||||
|
if abs(delta_ud) > abs(delta_lr):
|
||||||
|
gesture_found = 1
|
||||||
|
else:
|
||||||
|
gesture_found = 4
|
||||||
|
elif state_ud == 1 and state_lr == -1:
|
||||||
|
if abs(delta_ud) > abs(delta_lr):
|
||||||
|
gesture_found = 2
|
||||||
|
else:
|
||||||
|
gesture_found = 3
|
||||||
|
elif state_ud == -1 and state_lr == -1:
|
||||||
|
if abs(delta_ud) > abs(delta_lr):
|
||||||
|
gesture_found = 1
|
||||||
|
else:
|
||||||
|
gesture_found = 3
|
||||||
|
elif state_ud == 1 and state_lr == 1:
|
||||||
|
if abs(delta_ud) > abs(delta_lr):
|
||||||
|
gesture_found = 2
|
||||||
|
else:
|
||||||
|
gesture_found = 3
|
||||||
|
|
||||||
|
dir_lookup = [None,"left", "right", "down", "up"]
|
||||||
|
return dir_lookup[gesture_found]
|
||||||
|
|
||||||
|
## COLOR
|
||||||
|
def color(self,gain=1):
|
||||||
|
"""Tuple containing red, green, blue, and clear light intensity values"""
|
||||||
|
if self._select[2]:
|
||||||
|
self._select=[True,True,False]
|
||||||
|
self.enable_proximity(False)
|
||||||
|
self.enable_gesture(False)
|
||||||
|
self.enable_color(True)
|
||||||
|
self.color_gain(gain)
|
||||||
|
|
||||||
|
while not self._get_bit(_APDS9960_STATUS, _BIT_MASK_STATUS_AVALID):
|
||||||
|
time.sleep(0.005) #"""Color data ready flag"""
|
||||||
|
return (
|
||||||
|
self._color_data16(_APDS9960_CDATAL + 2),
|
||||||
|
self._color_data16(_APDS9960_CDATAL + 4),
|
||||||
|
self._color_data16(_APDS9960_CDATAL + 6),
|
||||||
|
self._color_data16(_APDS9960_CDATAL),
|
||||||
|
)
|
||||||
114
mixly/boards/default/micropython/build/lib/baidu_speech.py
Normal file
114
mixly/boards/default/micropython/build/lib/baidu_speech.py
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
"""
|
||||||
|
Baidu ASR API
|
||||||
|
|
||||||
|
MicroPython library for Baidu ASR API
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20230223
|
||||||
|
#https://ai.baidu.com/ai-doc/SPEECH/Ek39uxgre
|
||||||
|
#https://ai.baidu.com/unit/home#/home
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json,gc
|
||||||
|
import urequests,array
|
||||||
|
from ubinascii import hexlify
|
||||||
|
from machine import Timer,unique_id
|
||||||
|
|
||||||
|
'''Set constant'''
|
||||||
|
_framerate=8000
|
||||||
|
_unique_id=hexlify(unique_id()).decode()
|
||||||
|
|
||||||
|
def urequests_api(method, url, **kw):
|
||||||
|
'''Request data'''
|
||||||
|
try:
|
||||||
|
return json.loads(urequests.request(method, url, **kw).text)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("API request failed or WiFi is not connected",e)
|
||||||
|
|
||||||
|
def fetch_token(API_Key,Secret_Key):
|
||||||
|
"""Get access_token"""
|
||||||
|
url='http://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id={}&client_secret={}'.format(API_Key,Secret_Key)
|
||||||
|
results=urequests_api("GET",url)
|
||||||
|
if "error_description" in results.keys():
|
||||||
|
raise ValueError(results["error_description"])
|
||||||
|
if "access_token" in results.keys():
|
||||||
|
return results["access_token"]
|
||||||
|
|
||||||
|
class Recorder:
|
||||||
|
def __init__(self, adc,timer=2):
|
||||||
|
self._timer=Timer(timer)
|
||||||
|
self._mic=adc
|
||||||
|
|
||||||
|
def _timer_callback(self,timer):
|
||||||
|
'''Timer callback read microphone'''
|
||||||
|
try:
|
||||||
|
_mic=self._mic.read_u16()-32768
|
||||||
|
self._pcm_buffer.append(_mic &0xFF)
|
||||||
|
self._pcm_buffer.append(_mic >>8)
|
||||||
|
self._record_time-=1
|
||||||
|
except:
|
||||||
|
print("Warning: MemoryError!")
|
||||||
|
self._pcm_buffer=bytearray()
|
||||||
|
gc.collect()
|
||||||
|
self._record_time=0
|
||||||
|
|
||||||
|
def record(self,record_time=1):
|
||||||
|
"""Call timer to record audio"""
|
||||||
|
self._pcm_buffer=bytearray()
|
||||||
|
gc.collect()
|
||||||
|
self._record_time=record_time*_framerate
|
||||||
|
self._timer.init(freq =_framerate, mode = Timer.PERIODIC, callback = self._timer_callback)
|
||||||
|
while True:
|
||||||
|
if self._record_time <= 0:
|
||||||
|
self._timer.deinit()
|
||||||
|
gc.collect()
|
||||||
|
return self._pcm_buffer
|
||||||
|
|
||||||
|
class ASR(Recorder):
|
||||||
|
def __init__(self, adc, API_Key, Secret_Key, timer=2):
|
||||||
|
self._token=fetch_token(API_Key,Secret_Key)
|
||||||
|
super().__init__(adc,timer)
|
||||||
|
|
||||||
|
def recognize(self,record_time=1,dev_pid=1537):
|
||||||
|
"""Access API to get voice results"""
|
||||||
|
pcm_buffer=self.record(record_time)
|
||||||
|
if max(pcm_buffer)>=250:
|
||||||
|
url='http://vop.baidu.com/server_api?dev_pid={}&cuid={}&token={}'.format(dev_pid,_unique_id,self._token)
|
||||||
|
headers = {'Content-Type': 'audio/pcm; rate={}'.format(_framerate)}
|
||||||
|
results=urequests_api("POST",url,data=pcm_buffer,headers=headers)
|
||||||
|
if results["err_no"] != 0:
|
||||||
|
raise ValueError(results["err_msg"],results["err_no"])
|
||||||
|
elif results["err_msg"] == "success.":
|
||||||
|
gc.collect()
|
||||||
|
return results["result"][0]
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
class UNIT:
|
||||||
|
def __init__(self, API_Key, Secret_Key):
|
||||||
|
self._token=fetch_token(API_Key,Secret_Key)
|
||||||
|
self._session_id=""
|
||||||
|
|
||||||
|
def chatbot(self,chatbot_id,query):
|
||||||
|
"""Access API to intelligent dialog"""
|
||||||
|
if len(query) > 0:
|
||||||
|
url='https://aip.baidubce.com/rpc/2.0/unit/service/v3/chat?access_token={}'.format(self._token)
|
||||||
|
data={"log_id":"log"+_unique_id,
|
||||||
|
"version":"3.0",
|
||||||
|
"service_id":chatbot_id,
|
||||||
|
"session_id":self._session_id,
|
||||||
|
"request":{"query":query,"terminal_id":_unique_id}}
|
||||||
|
headers = {"content-type": "application/json"}
|
||||||
|
results=urequests_api("POST",url,data=json.dumps(data).encode(),headers=headers)
|
||||||
|
if results["error_code"] != 0:
|
||||||
|
raise ValueError(results["error_msg"],results["error_code"])
|
||||||
|
elif results["error_msg"] == "success":
|
||||||
|
self._session_id=results["result"]['session_id']
|
||||||
|
gc.collect()
|
||||||
|
return results["result"]['responses'][0]['actions'][0]['say']
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
gc.collect()
|
||||||
480
mixly/boards/default/micropython/build/lib/base64.py
Normal file
480
mixly/boards/default/micropython/build/lib/base64.py
Normal file
@@ -0,0 +1,480 @@
|
|||||||
|
#! /usr/bin/env python3
|
||||||
|
|
||||||
|
"""RFC 3548: Base16, Base32, Base64 Data Encodings"""
|
||||||
|
|
||||||
|
# Modified 04-Oct-1995 by Jack Jansen to use binascii module
|
||||||
|
# Modified 30-Dec-2003 by Barry Warsaw to add full RFC 3548 support
|
||||||
|
# Modified 22-May-2007 by Guido van Rossum to use bytes everywhere
|
||||||
|
|
||||||
|
import re
|
||||||
|
import struct
|
||||||
|
import binascii
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
# Legacy interface exports traditional RFC 1521 Base64 encodings
|
||||||
|
"encode",
|
||||||
|
"decode",
|
||||||
|
"encodebytes",
|
||||||
|
"decodebytes",
|
||||||
|
# Generalized interface for other encodings
|
||||||
|
"b64encode",
|
||||||
|
"b64decode",
|
||||||
|
"b32encode",
|
||||||
|
"b32decode",
|
||||||
|
"b16encode",
|
||||||
|
"b16decode",
|
||||||
|
# Standard Base64 encoding
|
||||||
|
"standard_b64encode",
|
||||||
|
"standard_b64decode",
|
||||||
|
# Some common Base64 alternatives. As referenced by RFC 3458, see thread
|
||||||
|
# starting at:
|
||||||
|
#
|
||||||
|
# http://zgp.org/pipermail/p2p-hackers/2001-September/000316.html
|
||||||
|
"urlsafe_b64encode",
|
||||||
|
"urlsafe_b64decode",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
bytes_types = (bytes, bytearray) # Types acceptable as binary data
|
||||||
|
|
||||||
|
|
||||||
|
def _bytes_from_decode_data(s):
|
||||||
|
if isinstance(s, str):
|
||||||
|
try:
|
||||||
|
return s.encode("ascii")
|
||||||
|
# except UnicodeEncodeError:
|
||||||
|
except:
|
||||||
|
raise ValueError("string argument should contain only ASCII characters")
|
||||||
|
elif isinstance(s, bytes_types):
|
||||||
|
return s
|
||||||
|
else:
|
||||||
|
raise TypeError("argument should be bytes or ASCII string, not %s" % s.__class__.__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def _maketrans(f, t):
|
||||||
|
"""Re-implement bytes.maketrans() as there is no such function in micropython"""
|
||||||
|
if len(f) != len(t):
|
||||||
|
raise ValueError("maketrans arguments must have same length")
|
||||||
|
translation_table = dict(zip(f, t))
|
||||||
|
return translation_table
|
||||||
|
|
||||||
|
|
||||||
|
def _translate(input_bytes, trans_table):
|
||||||
|
"""Re-implement bytes.translate() as there is no such function in micropython"""
|
||||||
|
result = bytearray()
|
||||||
|
|
||||||
|
for byte in input_bytes:
|
||||||
|
translated_byte = trans_table.get(byte, byte)
|
||||||
|
result.append(translated_byte)
|
||||||
|
|
||||||
|
return bytes(result)
|
||||||
|
|
||||||
|
|
||||||
|
# Base64 encoding/decoding uses binascii
|
||||||
|
|
||||||
|
|
||||||
|
def b64encode(s, altchars=None):
|
||||||
|
"""Encode a byte string using Base64.
|
||||||
|
|
||||||
|
s is the byte string to encode. Optional altchars must be a byte
|
||||||
|
string of length 2 which specifies an alternative alphabet for the
|
||||||
|
'+' and '/' characters. This allows an application to
|
||||||
|
e.g. generate url or filesystem safe Base64 strings.
|
||||||
|
|
||||||
|
The encoded byte string is returned.
|
||||||
|
"""
|
||||||
|
if not isinstance(s, bytes_types):
|
||||||
|
raise TypeError("expected bytes, not %s" % s.__class__.__name__)
|
||||||
|
# Strip off the trailing newline
|
||||||
|
encoded = binascii.b2a_base64(s)[:-1]
|
||||||
|
if altchars is not None:
|
||||||
|
if not isinstance(altchars, bytes_types):
|
||||||
|
raise TypeError("expected bytes, not %s" % altchars.__class__.__name__)
|
||||||
|
assert len(altchars) == 2, repr(altchars)
|
||||||
|
encoded = _translate(encoded, _maketrans(b"+/", altchars))
|
||||||
|
return encoded
|
||||||
|
|
||||||
|
|
||||||
|
def b64decode(s, altchars=None, validate=False):
|
||||||
|
"""Decode a Base64 encoded byte string.
|
||||||
|
|
||||||
|
s is the byte string to decode. Optional altchars must be a
|
||||||
|
string of length 2 which specifies the alternative alphabet used
|
||||||
|
instead of the '+' and '/' characters.
|
||||||
|
|
||||||
|
The decoded string is returned. A binascii.Error is raised if s is
|
||||||
|
incorrectly padded.
|
||||||
|
|
||||||
|
If validate is False (the default), non-base64-alphabet characters are
|
||||||
|
discarded prior to the padding check. If validate is True,
|
||||||
|
non-base64-alphabet characters in the input result in a binascii.Error.
|
||||||
|
"""
|
||||||
|
s = _bytes_from_decode_data(s)
|
||||||
|
if altchars is not None:
|
||||||
|
altchars = _bytes_from_decode_data(altchars)
|
||||||
|
assert len(altchars) == 2, repr(altchars)
|
||||||
|
s = _translate(s, _maketrans(altchars, b"+/"))
|
||||||
|
if validate and not re.match(b"^[A-Za-z0-9+/]*=*$", s):
|
||||||
|
raise binascii.Error("Non-base64 digit found")
|
||||||
|
return binascii.a2b_base64(s)
|
||||||
|
|
||||||
|
|
||||||
|
def standard_b64encode(s):
|
||||||
|
"""Encode a byte string using the standard Base64 alphabet.
|
||||||
|
|
||||||
|
s is the byte string to encode. The encoded byte string is returned.
|
||||||
|
"""
|
||||||
|
return b64encode(s)
|
||||||
|
|
||||||
|
|
||||||
|
def standard_b64decode(s):
|
||||||
|
"""Decode a byte string encoded with the standard Base64 alphabet.
|
||||||
|
|
||||||
|
s is the byte string to decode. The decoded byte string is
|
||||||
|
returned. binascii.Error is raised if the input is incorrectly
|
||||||
|
padded or if there are non-alphabet characters present in the
|
||||||
|
input.
|
||||||
|
"""
|
||||||
|
return b64decode(s)
|
||||||
|
|
||||||
|
|
||||||
|
# _urlsafe_encode_translation = _maketrans(b'+/', b'-_')
|
||||||
|
# _urlsafe_decode_translation = _maketrans(b'-_', b'+/')
|
||||||
|
|
||||||
|
|
||||||
|
def urlsafe_b64encode(s):
|
||||||
|
"""Encode a byte string using a url-safe Base64 alphabet.
|
||||||
|
|
||||||
|
s is the byte string to encode. The encoded byte string is
|
||||||
|
returned. The alphabet uses '-' instead of '+' and '_' instead of
|
||||||
|
'/'.
|
||||||
|
"""
|
||||||
|
# return b64encode(s).translate(_urlsafe_encode_translation)
|
||||||
|
return b64encode(s, b"-_").rstrip(b"\n")
|
||||||
|
|
||||||
|
|
||||||
|
def urlsafe_b64decode(s):
|
||||||
|
"""Decode a byte string encoded with the standard Base64 alphabet.
|
||||||
|
|
||||||
|
s is the byte string to decode. The decoded byte string is
|
||||||
|
returned. binascii.Error is raised if the input is incorrectly
|
||||||
|
padded or if there are non-alphabet characters present in the
|
||||||
|
input.
|
||||||
|
|
||||||
|
The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
||||||
|
"""
|
||||||
|
# s = _bytes_from_decode_data(s)
|
||||||
|
# s = s.translate(_urlsafe_decode_translation)
|
||||||
|
# return b64decode(s)
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
# Base32 encoding/decoding must be done in Python
|
||||||
|
_b32alphabet = {
|
||||||
|
0: b"A",
|
||||||
|
9: b"J",
|
||||||
|
18: b"S",
|
||||||
|
27: b"3",
|
||||||
|
1: b"B",
|
||||||
|
10: b"K",
|
||||||
|
19: b"T",
|
||||||
|
28: b"4",
|
||||||
|
2: b"C",
|
||||||
|
11: b"L",
|
||||||
|
20: b"U",
|
||||||
|
29: b"5",
|
||||||
|
3: b"D",
|
||||||
|
12: b"M",
|
||||||
|
21: b"V",
|
||||||
|
30: b"6",
|
||||||
|
4: b"E",
|
||||||
|
13: b"N",
|
||||||
|
22: b"W",
|
||||||
|
31: b"7",
|
||||||
|
5: b"F",
|
||||||
|
14: b"O",
|
||||||
|
23: b"X",
|
||||||
|
6: b"G",
|
||||||
|
15: b"P",
|
||||||
|
24: b"Y",
|
||||||
|
7: b"H",
|
||||||
|
16: b"Q",
|
||||||
|
25: b"Z",
|
||||||
|
8: b"I",
|
||||||
|
17: b"R",
|
||||||
|
26: b"2",
|
||||||
|
}
|
||||||
|
|
||||||
|
_b32tab = [v[0] for k, v in sorted(_b32alphabet.items())]
|
||||||
|
_b32rev = dict([(v[0], k) for k, v in _b32alphabet.items()])
|
||||||
|
|
||||||
|
|
||||||
|
def b32encode(s):
|
||||||
|
"""Encode a byte string using Base32.
|
||||||
|
|
||||||
|
s is the byte string to encode. The encoded byte string is returned.
|
||||||
|
"""
|
||||||
|
if not isinstance(s, bytes_types):
|
||||||
|
raise TypeError("expected bytes, not %s" % s.__class__.__name__)
|
||||||
|
quanta, leftover = divmod(len(s), 5)
|
||||||
|
# Pad the last quantum with zero bits if necessary
|
||||||
|
if leftover:
|
||||||
|
s = s + bytes(5 - leftover) # Don't use += !
|
||||||
|
quanta += 1
|
||||||
|
encoded = bytearray()
|
||||||
|
for i in range(quanta):
|
||||||
|
# c1 and c2 are 16 bits wide, c3 is 8 bits wide. The intent of this
|
||||||
|
# code is to process the 40 bits in units of 5 bits. So we take the 1
|
||||||
|
# leftover bit of c1 and tack it onto c2. Then we take the 2 leftover
|
||||||
|
# bits of c2 and tack them onto c3. The shifts and masks are intended
|
||||||
|
# to give us values of exactly 5 bits in width.
|
||||||
|
c1, c2, c3 = struct.unpack("!HHB", s[i * 5 : (i + 1) * 5])
|
||||||
|
c2 += (c1 & 1) << 16 # 17 bits wide
|
||||||
|
c3 += (c2 & 3) << 8 # 10 bits wide
|
||||||
|
encoded += bytes(
|
||||||
|
[
|
||||||
|
_b32tab[c1 >> 11], # bits 1 - 5
|
||||||
|
_b32tab[(c1 >> 6) & 0x1F], # bits 6 - 10
|
||||||
|
_b32tab[(c1 >> 1) & 0x1F], # bits 11 - 15
|
||||||
|
_b32tab[c2 >> 12], # bits 16 - 20 (1 - 5)
|
||||||
|
_b32tab[(c2 >> 7) & 0x1F], # bits 21 - 25 (6 - 10)
|
||||||
|
_b32tab[(c2 >> 2) & 0x1F], # bits 26 - 30 (11 - 15)
|
||||||
|
_b32tab[c3 >> 5], # bits 31 - 35 (1 - 5)
|
||||||
|
_b32tab[c3 & 0x1F], # bits 36 - 40 (1 - 5)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
# Adjust for any leftover partial quanta
|
||||||
|
if leftover == 1:
|
||||||
|
encoded = encoded[:-6] + b"======"
|
||||||
|
elif leftover == 2:
|
||||||
|
encoded = encoded[:-4] + b"===="
|
||||||
|
elif leftover == 3:
|
||||||
|
encoded = encoded[:-3] + b"==="
|
||||||
|
elif leftover == 4:
|
||||||
|
encoded = encoded[:-1] + b"="
|
||||||
|
return bytes(encoded)
|
||||||
|
|
||||||
|
|
||||||
|
def b32decode(s, casefold=False, map01=None):
|
||||||
|
"""Decode a Base32 encoded byte string.
|
||||||
|
|
||||||
|
s is the byte string to decode. Optional casefold is a flag
|
||||||
|
specifying whether a lowercase alphabet is acceptable as input.
|
||||||
|
For security purposes, the default is False.
|
||||||
|
|
||||||
|
RFC 3548 allows for optional mapping of the digit 0 (zero) to the
|
||||||
|
letter O (oh), and for optional mapping of the digit 1 (one) to
|
||||||
|
either the letter I (eye) or letter L (el). The optional argument
|
||||||
|
map01 when not None, specifies which letter the digit 1 should be
|
||||||
|
mapped to (when map01 is not None, the digit 0 is always mapped to
|
||||||
|
the letter O). For security purposes the default is None, so that
|
||||||
|
0 and 1 are not allowed in the input.
|
||||||
|
|
||||||
|
The decoded byte string is returned. binascii.Error is raised if
|
||||||
|
the input is incorrectly padded or if there are non-alphabet
|
||||||
|
characters present in the input.
|
||||||
|
"""
|
||||||
|
s = _bytes_from_decode_data(s)
|
||||||
|
quanta, leftover = divmod(len(s), 8)
|
||||||
|
if leftover:
|
||||||
|
raise binascii.Error("Incorrect padding")
|
||||||
|
# Handle section 2.4 zero and one mapping. The flag map01 will be either
|
||||||
|
# False, or the character to map the digit 1 (one) to. It should be
|
||||||
|
# either L (el) or I (eye).
|
||||||
|
if map01 is not None:
|
||||||
|
map01 = _bytes_from_decode_data(map01)
|
||||||
|
assert len(map01) == 1, repr(map01)
|
||||||
|
s = _translate(s, _maketrans(b"01", b"O" + map01))
|
||||||
|
if casefold:
|
||||||
|
s = s.upper()
|
||||||
|
# Strip off pad characters from the right. We need to count the pad
|
||||||
|
# characters because this will tell us how many null bytes to remove from
|
||||||
|
# the end of the decoded string.
|
||||||
|
padchars = s.find(b"=")
|
||||||
|
if padchars > 0:
|
||||||
|
padchars = len(s) - padchars
|
||||||
|
s = s[:-padchars]
|
||||||
|
else:
|
||||||
|
padchars = 0
|
||||||
|
|
||||||
|
# Now decode the full quanta
|
||||||
|
parts = []
|
||||||
|
acc = 0
|
||||||
|
shift = 35
|
||||||
|
for c in s:
|
||||||
|
val = _b32rev.get(c)
|
||||||
|
if val is None:
|
||||||
|
raise binascii.Error("Non-base32 digit found")
|
||||||
|
acc += _b32rev[c] << shift
|
||||||
|
shift -= 5
|
||||||
|
if shift < 0:
|
||||||
|
parts.append(binascii.unhexlify(bytes("%010x" % acc, "ascii")))
|
||||||
|
acc = 0
|
||||||
|
shift = 35
|
||||||
|
# Process the last, partial quanta
|
||||||
|
last = binascii.unhexlify(bytes("%010x" % acc, "ascii"))
|
||||||
|
if padchars == 0:
|
||||||
|
last = b"" # No characters
|
||||||
|
elif padchars == 1:
|
||||||
|
last = last[:-1]
|
||||||
|
elif padchars == 3:
|
||||||
|
last = last[:-2]
|
||||||
|
elif padchars == 4:
|
||||||
|
last = last[:-3]
|
||||||
|
elif padchars == 6:
|
||||||
|
last = last[:-4]
|
||||||
|
else:
|
||||||
|
raise binascii.Error("Incorrect padding")
|
||||||
|
parts.append(last)
|
||||||
|
return b"".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
# RFC 3548, Base 16 Alphabet specifies uppercase, but hexlify() returns
|
||||||
|
# lowercase. The RFC also recommends against accepting input case
|
||||||
|
# insensitively.
|
||||||
|
def b16encode(s):
|
||||||
|
"""Encode a byte string using Base16.
|
||||||
|
|
||||||
|
s is the byte string to encode. The encoded byte string is returned.
|
||||||
|
"""
|
||||||
|
if not isinstance(s, bytes_types):
|
||||||
|
raise TypeError("expected bytes, not %s" % s.__class__.__name__)
|
||||||
|
return binascii.hexlify(s).upper()
|
||||||
|
|
||||||
|
|
||||||
|
def b16decode(s, casefold=False):
|
||||||
|
"""Decode a Base16 encoded byte string.
|
||||||
|
|
||||||
|
s is the byte string to decode. Optional casefold is a flag
|
||||||
|
specifying whether a lowercase alphabet is acceptable as input.
|
||||||
|
For security purposes, the default is False.
|
||||||
|
|
||||||
|
The decoded byte string is returned. binascii.Error is raised if
|
||||||
|
s were incorrectly padded or if there are non-alphabet characters
|
||||||
|
present in the string.
|
||||||
|
"""
|
||||||
|
s = _bytes_from_decode_data(s)
|
||||||
|
if casefold:
|
||||||
|
s = s.upper()
|
||||||
|
if re.search(b"[^0-9A-F]", s):
|
||||||
|
raise binascii.Error("Non-base16 digit found")
|
||||||
|
return binascii.unhexlify(s)
|
||||||
|
|
||||||
|
|
||||||
|
# Legacy interface. This code could be cleaned up since I don't believe
|
||||||
|
# binascii has any line length limitations. It just doesn't seem worth it
|
||||||
|
# though. The files should be opened in binary mode.
|
||||||
|
|
||||||
|
MAXLINESIZE = 76 # Excluding the CRLF
|
||||||
|
MAXBINSIZE = (MAXLINESIZE // 4) * 3
|
||||||
|
|
||||||
|
|
||||||
|
def encode(input, output):
|
||||||
|
"""Encode a file; input and output are binary files."""
|
||||||
|
while True:
|
||||||
|
s = input.read(MAXBINSIZE)
|
||||||
|
if not s:
|
||||||
|
break
|
||||||
|
while len(s) < MAXBINSIZE:
|
||||||
|
ns = input.read(MAXBINSIZE - len(s))
|
||||||
|
if not ns:
|
||||||
|
break
|
||||||
|
s += ns
|
||||||
|
line = binascii.b2a_base64(s)
|
||||||
|
output.write(line)
|
||||||
|
|
||||||
|
|
||||||
|
def decode(input, output):
|
||||||
|
"""Decode a file; input and output are binary files."""
|
||||||
|
while True:
|
||||||
|
line = input.readline()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
s = binascii.a2b_base64(line)
|
||||||
|
output.write(s)
|
||||||
|
|
||||||
|
|
||||||
|
def encodebytes(s):
|
||||||
|
"""Encode a bytestring into a bytestring containing multiple lines
|
||||||
|
of base-64 data."""
|
||||||
|
if not isinstance(s, bytes_types):
|
||||||
|
raise TypeError("expected bytes, not %s" % s.__class__.__name__)
|
||||||
|
pieces = []
|
||||||
|
for i in range(0, len(s), MAXBINSIZE):
|
||||||
|
chunk = s[i : i + MAXBINSIZE]
|
||||||
|
pieces.append(binascii.b2a_base64(chunk))
|
||||||
|
return b"".join(pieces)
|
||||||
|
|
||||||
|
|
||||||
|
def encodestring(s):
|
||||||
|
"""Legacy alias of encodebytes()."""
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn("encodestring() is a deprecated alias, use encodebytes()", DeprecationWarning, 2)
|
||||||
|
return encodebytes(s)
|
||||||
|
|
||||||
|
|
||||||
|
def decodebytes(s):
|
||||||
|
"""Decode a bytestring of base-64 data into a bytestring."""
|
||||||
|
if not isinstance(s, bytes_types):
|
||||||
|
raise TypeError("expected bytes, not %s" % s.__class__.__name__)
|
||||||
|
return binascii.a2b_base64(s)
|
||||||
|
|
||||||
|
|
||||||
|
def decodestring(s):
|
||||||
|
"""Legacy alias of decodebytes()."""
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
warnings.warn("decodestring() is a deprecated alias, use decodebytes()", DeprecationWarning, 2)
|
||||||
|
return decodebytes(s)
|
||||||
|
|
||||||
|
|
||||||
|
# Usable as a script...
|
||||||
|
def main():
|
||||||
|
"""Small main program"""
|
||||||
|
import sys, getopt
|
||||||
|
|
||||||
|
try:
|
||||||
|
opts, args = getopt.getopt(sys.argv[1:], "deut")
|
||||||
|
except getopt.error as msg:
|
||||||
|
sys.stdout = sys.stderr
|
||||||
|
print(msg)
|
||||||
|
print(
|
||||||
|
"""usage: %s [-d|-e|-u|-t] [file|-]
|
||||||
|
-d, -u: decode
|
||||||
|
-e: encode (default)
|
||||||
|
-t: encode and decode string 'Aladdin:open sesame'"""
|
||||||
|
% sys.argv[0]
|
||||||
|
)
|
||||||
|
sys.exit(2)
|
||||||
|
func = encode
|
||||||
|
for o, a in opts:
|
||||||
|
if o == "-e":
|
||||||
|
func = encode
|
||||||
|
if o == "-d":
|
||||||
|
func = decode
|
||||||
|
if o == "-u":
|
||||||
|
func = decode
|
||||||
|
if o == "-t":
|
||||||
|
test()
|
||||||
|
return
|
||||||
|
if args and args[0] != "-":
|
||||||
|
with open(args[0], "rb") as f:
|
||||||
|
func(f, sys.stdout.buffer)
|
||||||
|
else:
|
||||||
|
func(sys.stdin.buffer, sys.stdout.buffer)
|
||||||
|
|
||||||
|
|
||||||
|
def test():
|
||||||
|
s0 = b"Aladdin:open sesame"
|
||||||
|
print(repr(s0))
|
||||||
|
s1 = encodebytes(s0)
|
||||||
|
print(repr(s1))
|
||||||
|
s2 = decodebytes(s1)
|
||||||
|
print(repr(s2))
|
||||||
|
assert s0 == s2
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
# Helpers for generating BLE advertising payloads.
|
||||||
|
|
||||||
|
from micropython import const
|
||||||
|
import struct
|
||||||
|
import bluetooth
|
||||||
|
|
||||||
|
# Advertising payloads are repeated packets of the following form:
|
||||||
|
# 1 byte data length (N + 1)
|
||||||
|
# 1 byte type (see constants below)
|
||||||
|
# N bytes type-specific data
|
||||||
|
|
||||||
|
_ADV_TYPE_FLAGS = const(0x01)
|
||||||
|
_ADV_TYPE_NAME = const(0x09)
|
||||||
|
_ADV_TYPE_UUID16_COMPLETE = const(0x3)
|
||||||
|
_ADV_TYPE_UUID32_COMPLETE = const(0x5)
|
||||||
|
_ADV_TYPE_UUID128_COMPLETE = const(0x7)
|
||||||
|
_ADV_TYPE_UUID16_MORE = const(0x2)
|
||||||
|
_ADV_TYPE_UUID32_MORE = const(0x4)
|
||||||
|
_ADV_TYPE_UUID128_MORE = const(0x6)
|
||||||
|
_ADV_TYPE_APPEARANCE = const(0x19)
|
||||||
|
|
||||||
|
|
||||||
|
# Generate a payload to be passed to gap_advertise(adv_data=...).
|
||||||
|
def advertising_payload(limited_disc=False, br_edr=False, name=None, services=None, appearance=0):
|
||||||
|
payload = bytearray()
|
||||||
|
|
||||||
|
def _append(adv_type, value):
|
||||||
|
nonlocal payload
|
||||||
|
payload += struct.pack("BB", len(value) + 1, adv_type) + value
|
||||||
|
|
||||||
|
_append(
|
||||||
|
_ADV_TYPE_FLAGS,
|
||||||
|
struct.pack("B", (0x01 if limited_disc else 0x02) + (0x18 if br_edr else 0x04)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if name:
|
||||||
|
_append(_ADV_TYPE_NAME, name.encode())
|
||||||
|
|
||||||
|
if services:
|
||||||
|
for uuid in services:
|
||||||
|
b = bytes(uuid)
|
||||||
|
if len(b) == 2:
|
||||||
|
_append(_ADV_TYPE_UUID16_COMPLETE, b)
|
||||||
|
elif len(b) == 4:
|
||||||
|
_append(_ADV_TYPE_UUID32_COMPLETE, b)
|
||||||
|
elif len(b) == 16:
|
||||||
|
_append(_ADV_TYPE_UUID128_COMPLETE, b)
|
||||||
|
|
||||||
|
# See org.bluetooth.characteristic.gap.appearance.xml
|
||||||
|
if appearance:
|
||||||
|
_append(_ADV_TYPE_APPEARANCE, struct.pack("<h", appearance))
|
||||||
|
|
||||||
|
return payload
|
||||||
|
|
||||||
|
|
||||||
|
def decode_field(payload, adv_type):
|
||||||
|
i = 0
|
||||||
|
result = []
|
||||||
|
while i + 1 < len(payload):
|
||||||
|
if payload[i + 1] == adv_type:
|
||||||
|
result.append(payload[i + 2 : i + payload[i] + 1])
|
||||||
|
i += 1 + payload[i]
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def decode_name(payload):
|
||||||
|
n = decode_field(payload, _ADV_TYPE_NAME)
|
||||||
|
return str(n[0], "utf-8") if n else ""
|
||||||
|
|
||||||
|
|
||||||
|
def decode_services(payload):
|
||||||
|
services = []
|
||||||
|
for u in decode_field(payload, _ADV_TYPE_UUID16_COMPLETE):
|
||||||
|
services.append(bluetooth.UUID(struct.unpack("<h", u)[0]))
|
||||||
|
for u in decode_field(payload, _ADV_TYPE_UUID32_COMPLETE):
|
||||||
|
services.append(bluetooth.UUID(struct.unpack("<d", u)[0]))
|
||||||
|
for u in decode_field(payload, _ADV_TYPE_UUID128_COMPLETE):
|
||||||
|
services.append(bluetooth.UUID(u))
|
||||||
|
return services
|
||||||
217
mixly/boards/default/micropython/build/lib/ble_central.py
Normal file
217
mixly/boards/default/micropython/build/lib/ble_central.py
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
"""
|
||||||
|
Bluetooth-Central
|
||||||
|
|
||||||
|
Micropython library for the Bluetooth-Central
|
||||||
|
=======================================================
|
||||||
|
#Preliminary composition 20221018
|
||||||
|
#https://github.com/micropython/micropython/tree/master/examples/bluetooth
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time,gc
|
||||||
|
import bluetooth
|
||||||
|
from micropython import const
|
||||||
|
from ubinascii import hexlify,unhexlify
|
||||||
|
from ble_advertising import decode_services, decode_name
|
||||||
|
|
||||||
|
_IRQ_CENTRAL_CONNECT = const(1)
|
||||||
|
_IRQ_CENTRAL_DISCONNECT = const(2)
|
||||||
|
_IRQ_GATTS_WRITE = const(3)
|
||||||
|
_IRQ_GATTS_READ_REQUEST = const(4)
|
||||||
|
_IRQ_SCAN_RESULT = const(5)
|
||||||
|
_IRQ_SCAN_DONE = const(6)
|
||||||
|
_IRQ_PERIPHERAL_CONNECT = const(7)
|
||||||
|
_IRQ_PERIPHERAL_DISCONNECT = const(8)
|
||||||
|
_IRQ_GATTC_SERVICE_RESULT = const(9)
|
||||||
|
_IRQ_GATTC_SERVICE_DONE = const(10)
|
||||||
|
_IRQ_GATTC_CHARACTERISTIC_RESULT = const(11)
|
||||||
|
_IRQ_GATTC_CHARACTERISTIC_DONE = const(12)
|
||||||
|
_IRQ_GATTC_DESCRIPTOR_RESULT = const(13)
|
||||||
|
_IRQ_GATTC_DESCRIPTOR_DONE = const(14)
|
||||||
|
_IRQ_GATTC_READ_RESULT = const(15)
|
||||||
|
_IRQ_GATTC_READ_DONE = const(16)
|
||||||
|
_IRQ_GATTC_WRITE_DONE = const(17)
|
||||||
|
_IRQ_GATTC_NOTIFY = const(18)
|
||||||
|
_IRQ_GATTC_INDICATE = const(19)
|
||||||
|
|
||||||
|
_ADV_IND = const(0x00)
|
||||||
|
_ADV_DIRECT_IND = const(0x01)
|
||||||
|
_ADV_SCAN_IND = const(0x02)
|
||||||
|
_ADV_NONCONN_IND = const(0x03)
|
||||||
|
|
||||||
|
_UART_SERVICE_UUID = bluetooth.UUID(0x1101)
|
||||||
|
_UART_RX_CHAR_UUID = bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E")
|
||||||
|
_UART_TX_CHAR_UUID = bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E")
|
||||||
|
|
||||||
|
|
||||||
|
class BLESimpleCentral:
|
||||||
|
def __init__(self):
|
||||||
|
self._ble = bluetooth.BLE()
|
||||||
|
self._scan_flg = True
|
||||||
|
self._ble.active(True)
|
||||||
|
self._ble.irq(self._irq)
|
||||||
|
self._reset()
|
||||||
|
self.scan()
|
||||||
|
|
||||||
|
def _reset(self):
|
||||||
|
# Cached name and address from a successful scan.
|
||||||
|
self._name = None
|
||||||
|
self._addr_type = None
|
||||||
|
self._addr = None
|
||||||
|
|
||||||
|
# Callbacks for completion of various operations.
|
||||||
|
# These reset back to None after being invoked.
|
||||||
|
self._conn_callback = None
|
||||||
|
self._read_callback = None
|
||||||
|
|
||||||
|
# Persistent callback for when new data is notified from the device.
|
||||||
|
self._notify_callback = None
|
||||||
|
self._write_data=None
|
||||||
|
|
||||||
|
# Connected device.
|
||||||
|
self._conn_handle = None
|
||||||
|
self._start_handle = None
|
||||||
|
self._end_handle = None
|
||||||
|
self._tx_handle = None
|
||||||
|
self._rx_handle = None
|
||||||
|
|
||||||
|
def _irq(self, event, data):
|
||||||
|
if event == _IRQ_SCAN_RESULT:
|
||||||
|
addr_type, addr, adv_type, rssi, adv_data = data
|
||||||
|
|
||||||
|
if adv_type in (_ADV_IND, _ADV_DIRECT_IND) and _UART_SERVICE_UUID in decode_services(adv_data):
|
||||||
|
# Found a potential device, remember it and stop scanning.
|
||||||
|
self._addr_type = addr_type
|
||||||
|
self._addr = bytes(addr) # Note: addr buffer is owned by caller so need to copy it.
|
||||||
|
self._name = decode_name(adv_data) or "?"
|
||||||
|
if self._addr in self._info[2]:
|
||||||
|
self._ble.gap_scan(None)
|
||||||
|
else:
|
||||||
|
self._info[0].append(self._name)
|
||||||
|
self._info[1].append(self._addr_type)
|
||||||
|
self._info[2].append(self._addr)
|
||||||
|
self._info[3].append(rssi)
|
||||||
|
|
||||||
|
elif event == _IRQ_SCAN_DONE:
|
||||||
|
self._scan_flg = False
|
||||||
|
|
||||||
|
elif event == _IRQ_PERIPHERAL_CONNECT:
|
||||||
|
# Connect successful.
|
||||||
|
conn_handle, addr_type, addr = data
|
||||||
|
if addr_type == self._addr_type and addr == self._addr:
|
||||||
|
self._conn_handle = conn_handle
|
||||||
|
self._ble.gattc_discover_services(self._conn_handle)
|
||||||
|
|
||||||
|
elif event == _IRQ_PERIPHERAL_DISCONNECT:
|
||||||
|
# Disconnect (either initiated by us or the remote end).
|
||||||
|
conn_handle, _, _ = data
|
||||||
|
if conn_handle == self._conn_handle:
|
||||||
|
# If it was initiated by us, it'll already be reset.
|
||||||
|
self._reset()
|
||||||
|
|
||||||
|
elif event == _IRQ_GATTC_SERVICE_RESULT:
|
||||||
|
# Connected device returned a service.
|
||||||
|
conn_handle, start_handle, end_handle, uuid = data
|
||||||
|
print("service", data)
|
||||||
|
if conn_handle == self._conn_handle and uuid == _UART_SERVICE_UUID:
|
||||||
|
self._start_handle, self._end_handle = start_handle, end_handle
|
||||||
|
|
||||||
|
elif event == _IRQ_GATTC_SERVICE_DONE:
|
||||||
|
# Service query complete.
|
||||||
|
if self._start_handle and self._end_handle:
|
||||||
|
self._ble.gattc_discover_characteristics(
|
||||||
|
self._conn_handle, self._start_handle, self._end_handle
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
print("Failed to find uart service.")
|
||||||
|
|
||||||
|
elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT:
|
||||||
|
# Connected device returned a characteristic.
|
||||||
|
conn_handle, def_handle, value_handle, properties, uuid = data
|
||||||
|
if conn_handle == self._conn_handle and uuid == _UART_RX_CHAR_UUID:
|
||||||
|
self._rx_handle = value_handle
|
||||||
|
if conn_handle == self._conn_handle and uuid == _UART_TX_CHAR_UUID:
|
||||||
|
self._tx_handle = value_handle
|
||||||
|
|
||||||
|
elif event == _IRQ_GATTC_CHARACTERISTIC_DONE:
|
||||||
|
# Characteristic query complete.
|
||||||
|
if self._tx_handle is not None and self._rx_handle is not None:
|
||||||
|
# We've finished connecting and discovering device, fire the connect callback.
|
||||||
|
if self._conn_callback:
|
||||||
|
self._conn_callback()
|
||||||
|
else:
|
||||||
|
print("Failed to find uart rx characteristic.")
|
||||||
|
|
||||||
|
elif event == _IRQ_GATTC_WRITE_DONE:
|
||||||
|
conn_handle, value_handle, status = data
|
||||||
|
print("TX complete")
|
||||||
|
|
||||||
|
elif event == _IRQ_GATTC_NOTIFY:
|
||||||
|
conn_handle, value_handle, notify_data = data
|
||||||
|
if conn_handle == self._conn_handle and value_handle == self._tx_handle:
|
||||||
|
try:
|
||||||
|
self._write_data=bytes(notify_data).decode().strip()
|
||||||
|
except:
|
||||||
|
self._write_data=bytes(notify_data)
|
||||||
|
if self._notify_callback:
|
||||||
|
self._notify_callback(self._write_data)
|
||||||
|
|
||||||
|
# Returns true if we've successfully connected and discovered characteristics.
|
||||||
|
def is_connected(self):
|
||||||
|
return (self._conn_handle is not None and self._tx_handle is not None and self._rx_handle is not None)
|
||||||
|
|
||||||
|
# Find a device advertising the environmental sensor service.
|
||||||
|
def scan(self):
|
||||||
|
self._info = [[],[],[],[]]
|
||||||
|
self._ble.gap_scan(10000, 30000, 30000)
|
||||||
|
while self._scan_flg:
|
||||||
|
time.sleep_ms(10)
|
||||||
|
self._scan_flg = True
|
||||||
|
info=[]
|
||||||
|
for i in range(len(self._info[0])):
|
||||||
|
info.append([self._info[0][i],self._info[1][i],hexlify(self._info[2][i]).decode(),self._info[3][i]])
|
||||||
|
return info
|
||||||
|
|
||||||
|
# Connect to the specified device (otherwise use cached address from a scan).
|
||||||
|
def connect(self, name=None,mac=None, callback=None):
|
||||||
|
if mac and unhexlify(mac) in self._info[2]:
|
||||||
|
index=self._info[2].index(unhexlify(mac))
|
||||||
|
self._addr_type=self._info[1][index]
|
||||||
|
self._addr=unhexlify(mac)
|
||||||
|
elif name and name in self._info[0]:
|
||||||
|
index=self._info[0].index(name)
|
||||||
|
self._addr_type=self._info[1][index]
|
||||||
|
self._addr=self._info[2][index]
|
||||||
|
else:
|
||||||
|
raise ValueError("The '{}' Bluetooth was not found, Please check device is working".format(mac if name is None else name))
|
||||||
|
self._conn_callback = callback
|
||||||
|
self._ble.gap_connect(self._addr_type, self._addr)
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Disconnect from current device.
|
||||||
|
def disconnect(self):
|
||||||
|
if not self._conn_handle:
|
||||||
|
return
|
||||||
|
self._ble.gap_disconnect(self._conn_handle)
|
||||||
|
self._reset()
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
# Send data over the UART
|
||||||
|
def send(self, v, response=False):
|
||||||
|
if not self.is_connected():
|
||||||
|
return
|
||||||
|
self._ble.gattc_write(self._conn_handle, self._rx_handle, v, 1 if response else 0)
|
||||||
|
|
||||||
|
# Set handler for when data is received over the UART.
|
||||||
|
def recv(self, callback= None):
|
||||||
|
if callback:
|
||||||
|
self._notify_callback = callback
|
||||||
|
else:
|
||||||
|
write_data=self._write_data
|
||||||
|
self._write_data=None
|
||||||
|
return write_data
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mac(self):
|
||||||
|
'''Get mac address'''
|
||||||
|
return hexlify(self._ble.config('mac')[1]).decode()
|
||||||
37
mixly/boards/default/micropython/build/lib/ble_handle.py
Normal file
37
mixly/boards/default/micropython/build/lib/ble_handle.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
"""
|
||||||
|
Bluetooth remote control handle
|
||||||
|
|
||||||
|
Micropython library for the Bluetooth remote control handle
|
||||||
|
=======================================================
|
||||||
|
#Preliminary composition 202200704
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ble_peripheral import BLESimplePeripheral
|
||||||
|
|
||||||
|
class Handle(BLESimplePeripheral):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(name="TUDAO_MASTER")
|
||||||
|
self._buffer=bytearray(14)
|
||||||
|
|
||||||
|
def _receive_cb(self, data):
|
||||||
|
if self._on_receive:
|
||||||
|
if data !=self._buffer:
|
||||||
|
self._buffer=data
|
||||||
|
key=self._deal(self._buffer)
|
||||||
|
self._on_receive(key[0],key[1],key[2],key[3])
|
||||||
|
|
||||||
|
def recv(self,callback):
|
||||||
|
self._on_receive = callback
|
||||||
|
if callback:
|
||||||
|
super().recv(self._receive_cb)
|
||||||
|
|
||||||
|
def _u2s(self,n):
|
||||||
|
return n if n < (1 << 7) else n - (1 << 8)
|
||||||
|
|
||||||
|
def _deal(self,data):
|
||||||
|
if data[0]== 0xff and data[1]== 0xfe and data[12]== 0xfd and data[13]== 0xfc:
|
||||||
|
return self._u2s(data[5]),self._u2s(data[6]),self._u2s(data[7]),self._u2s(data[8])
|
||||||
|
else:
|
||||||
|
return None,None,None,None
|
||||||
235
mixly/boards/default/micropython/build/lib/ble_hid.py
Normal file
235
mixly/boards/default/micropython/build/lib/ble_hid.py
Normal file
@@ -0,0 +1,235 @@
|
|||||||
|
"""
|
||||||
|
Bluetooth-HID
|
||||||
|
|
||||||
|
Micropython library for the Bluetooth-HID(Compliant with equipment)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import bluetooth
|
||||||
|
import struct, time
|
||||||
|
from micropython import const
|
||||||
|
from ubinascii import hexlify
|
||||||
|
from ble_advertising import advertising_payload
|
||||||
|
from bluetooth import UUID, FLAG_READ, FLAG_WRITE ,FLAG_NOTIFY, FLAG_WRITE_NO_RESPONSE
|
||||||
|
|
||||||
|
_IRQ_CENTRAL_CONNECT = const(1)
|
||||||
|
_IRQ_CENTRAL_DISCONNECT = const(2)
|
||||||
|
_IRQ_GATTS_WRITE = const(3)
|
||||||
|
_IRQ_MTU_EXCHANGED = const(21)
|
||||||
|
_IRQ_CONNECTION_UPDATE = const(27)
|
||||||
|
_IRQ_GET_SECRET = const(29)
|
||||||
|
_IRQ_SET_SECRET = const(30)
|
||||||
|
_IRQ_PASSKEY_ACTION = const(31)
|
||||||
|
_PASSKEY_ACTION_INPUT = const(2)
|
||||||
|
_PASSKEY_ACTION_DISP = const(3)
|
||||||
|
_PASSKEY_ACTION_NUMCMP = const(4)
|
||||||
|
|
||||||
|
#HID 鼠标、键盘、手柄设备报告描述符
|
||||||
|
_HID_INPUT_REPORT = const(b'\x05\x01\t\x02\xa1\x01\x85\x01\t\x01\xa1\x00\x05\t\x19\x01)\x03\x15\x00%\x01\x95\x03u\x01\x81\x02\x95\x01u\x05\x81\x03\x05\x01\t0\t1\t8\x15\x81%\x7fu\x08\x95\x03\x81\x06\xc0\xc0\x05\x01\t\x06\xa1\x01\x85\x02u\x01\x95\x08\x05\x07\x19\xe0)\xe7\x15\x00%\x01\x81\x02\x95\x01u\x08\x81\x01\x95\x05u\x01\x05\x08\x19\x01)\x05\x91\x02\x95\x01u\x03\x91\x01\x95\x06u\x08\x15\x00%e\x05\x07\x19\x00)e\x81\x00\xc0\x05\x01\t\x04\xa1\x01\x85\x03\xa1\x00\t0\t1\x15\x81%\x7fu\x08\x95\x02\x81\x02\x05\t)\x08\x19\x01\x95\x08u\x01%\x01\x15\x00\x81\x02\xc0\xc0')
|
||||||
|
_KEYCODE = const(b'\x00\x00\x00\x00\x00\x00\x00\x00*+(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\x00,\x9e\xb4\xa0\xa1\xa2\xa44\xa6\xa7\xa5\xae6-78\'\x1e\x1f !"#$%&\xb33\xb6.\xb7\xb8\x9f\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d/10\xa3\xad5\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\xaf\xb1\xb0\xb5L')
|
||||||
|
|
||||||
|
_DIS = (UUID(0x180A), ( (UUID(0x2A24), FLAG_READ),
|
||||||
|
(UUID(0x2A25), FLAG_READ),
|
||||||
|
(UUID(0x2A26), FLAG_READ),
|
||||||
|
(UUID(0x2A27), FLAG_READ),
|
||||||
|
(UUID(0x2A28), FLAG_READ),
|
||||||
|
(UUID(0x2A29), FLAG_READ),
|
||||||
|
(UUID(0x2A50), FLAG_READ), ), )
|
||||||
|
|
||||||
|
_BAS = (UUID(0x180F), ( (UUID(0x2A19), FLAG_READ | FLAG_NOTIFY, ((UUID(0x2902), 0x03), (UUID(0x2904), 0x01),)), ), )
|
||||||
|
|
||||||
|
_HIDS = (UUID(0x1812), ((UUID(0x2A4A), FLAG_READ),
|
||||||
|
(UUID(0x2A4B), FLAG_READ),
|
||||||
|
(UUID(0x2A4C), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE),
|
||||||
|
(UUID(0x2A4D), FLAG_READ | FLAG_NOTIFY, ((UUID(0x2902), 0x03), (UUID(0x2908), 0x03),)), #鼠标
|
||||||
|
(UUID(0x2A4D), FLAG_READ | FLAG_NOTIFY, ((UUID(0x2902), 0x03), (UUID(0x2908), 0x03),)), #键盘发送
|
||||||
|
(UUID(0x2A4D), FLAG_READ | FLAG_WRITE, ((UUID(0x2902), 0x03), (UUID(0x2908), 0x03),)), #键盘状态
|
||||||
|
(UUID(0x2A4D), FLAG_READ | FLAG_NOTIFY, ((UUID(0x2902), 0x03), (UUID(0x2908), 0x03),)), #游戏手柄
|
||||||
|
(UUID(0x2A4E), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), ), )
|
||||||
|
|
||||||
|
class HID:
|
||||||
|
def __init__(self, name=None, passkey=1234, battery_level=100):
|
||||||
|
if (name is '') or (name is None):
|
||||||
|
name = "Mixgo_" + self.mac[-6:].upper()
|
||||||
|
print("HID Name:", name)
|
||||||
|
|
||||||
|
self._ble = bluetooth.BLE()
|
||||||
|
self._ble.active(True)
|
||||||
|
self._ble.irq(self._irq)
|
||||||
|
self._ble.config(gap_name=name)
|
||||||
|
self._ble.config(mtu=23)
|
||||||
|
self.device_state = False
|
||||||
|
self.conn_handle = None
|
||||||
|
self.passkey = passkey
|
||||||
|
self.battery_level = battery_level
|
||||||
|
self.report = b'\x00'
|
||||||
|
try:
|
||||||
|
import ble_hid_key
|
||||||
|
self.keys = ble_hid_key.keys
|
||||||
|
except:
|
||||||
|
self.keys = {}
|
||||||
|
|
||||||
|
handles = self._ble.gatts_register_services((_DIS, _BAS, _HIDS))
|
||||||
|
self._service_characteristics(handles)
|
||||||
|
self._payload = advertising_payload(name=name, services=[UUID(0x1812)], appearance=const(960))
|
||||||
|
self.advertise()
|
||||||
|
|
||||||
|
def _irq(self, event, data):
|
||||||
|
# Interrupt request callback function
|
||||||
|
if event == _IRQ_CENTRAL_CONNECT:
|
||||||
|
self.conn_handle, _, _ = data
|
||||||
|
print("HID connected:", self.conn_handle)
|
||||||
|
self.device_state = True
|
||||||
|
elif event == _IRQ_CENTRAL_DISCONNECT:
|
||||||
|
self.conn_handle = None
|
||||||
|
conn_handle, addr_type, addr = data
|
||||||
|
print("HID disconnected:", conn_handle)
|
||||||
|
self.advertise()
|
||||||
|
self.device_state = False
|
||||||
|
elif event == _IRQ_MTU_EXCHANGED:
|
||||||
|
conn_handle, mtu = data
|
||||||
|
self._ble.config(mtu=mtu)
|
||||||
|
print("MTU exchanged:", mtu)
|
||||||
|
elif event == _IRQ_CONNECTION_UPDATE:
|
||||||
|
self.conn_handle, _, _, _, _ = data
|
||||||
|
print("Connection update")
|
||||||
|
elif event == _IRQ_PASSKEY_ACTION:
|
||||||
|
conn_handle, action, passkey = data
|
||||||
|
print("Passkey action", conn_handle, action, passkey)
|
||||||
|
if action == _PASSKEY_ACTION_NUMCMP:
|
||||||
|
self._ble.gap_passkey(conn_handle, action, False)
|
||||||
|
elif action == _PASSKEY_ACTION_DISP:
|
||||||
|
print("Displaying passkey")
|
||||||
|
self._ble.gap_passkey(conn_handle, action, self.passkey)
|
||||||
|
elif action == _PASSKEY_ACTION_INPUT:
|
||||||
|
print("Prompting for passkey")
|
||||||
|
self._ble.gap_passkey(conn_handle, action, None)
|
||||||
|
else:
|
||||||
|
print("Unknown action")
|
||||||
|
elif event == _IRQ_GATTS_WRITE:
|
||||||
|
conn_handle, attr_handle = data
|
||||||
|
self.report = self._ble.gatts_read(attr_handle)
|
||||||
|
elif event == _IRQ_SET_SECRET:
|
||||||
|
sec_type, key, value = data
|
||||||
|
key = sec_type, bytes(key)
|
||||||
|
value = bytes(value) if value else None
|
||||||
|
#print("Set secret: ", key, value)
|
||||||
|
if value is None:
|
||||||
|
if key in self.keys:
|
||||||
|
del self.keys[key]
|
||||||
|
self._key_secrets(self.keys)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
self.keys[key] = value
|
||||||
|
self._key_secrets(self.keys)
|
||||||
|
return True
|
||||||
|
elif event == _IRQ_GET_SECRET:
|
||||||
|
sec_type, index, key = data
|
||||||
|
#print("Get secret: ", sec_type, index, bytes(key) if key else None)
|
||||||
|
if key is None:
|
||||||
|
i = 0
|
||||||
|
for (t, _key), value in self.keys.items():
|
||||||
|
if t == sec_type:
|
||||||
|
if i == index:
|
||||||
|
return value
|
||||||
|
i += 1
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
key = sec_type, bytes(key)
|
||||||
|
return self.keys.get(key, None)
|
||||||
|
# else:
|
||||||
|
# print("Unhandled IRQ event: ", event, data)
|
||||||
|
|
||||||
|
def _key_secrets(self, keys={}):
|
||||||
|
"""Save pairing key"""
|
||||||
|
with open("ble_hid_key.py", "w+") as s_f:
|
||||||
|
s_f.write("keys=" + str(keys) + "\n")
|
||||||
|
|
||||||
|
def _service_characteristics(self, handles):
|
||||||
|
"""Write BAS&service characteristics."""
|
||||||
|
(h_mod, h_ser, h_fwr, h_hwr, h_swr, h_man, h_pnp) = handles[0]
|
||||||
|
(self.h_bat, h_ccc, h_bfmt) = handles[1]
|
||||||
|
(h_info, h_hid, _, self.m_rep, _, h_d1, self.k_rep, _, h_d2, _, _, h_d3, self.j_rep, _, h_d4, h_proto) = handles[2]
|
||||||
|
# Write DIS characteristics.
|
||||||
|
self._ble.gatts_write(h_mod, b'1')
|
||||||
|
self._ble.gatts_write(h_ser, b'1')
|
||||||
|
self._ble.gatts_write(h_fwr, b'1')
|
||||||
|
self._ble.gatts_write(h_hwr, b'1')
|
||||||
|
self._ble.gatts_write(h_swr, b'1')
|
||||||
|
self._ble.gatts_write(h_man, b'Homebrew')
|
||||||
|
self._ble.gatts_write(h_pnp, b'\x01a\xfe\x01\x00#\x01')
|
||||||
|
# Write BAS characteristics.
|
||||||
|
self._ble.gatts_write(self.h_bat, struct.pack("<B", self.battery_level))
|
||||||
|
self._ble.gatts_write(h_bfmt, b'\x04\x00\xad\x27\x01\x00\x00')
|
||||||
|
self._ble.gatts_write(h_ccc, b'\x00\x00')
|
||||||
|
# Write service characteristics
|
||||||
|
self._ble.gatts_write(h_info, b"\x01\x01\x00\x02")
|
||||||
|
self._ble.gatts_write(h_hid, _HID_INPUT_REPORT)
|
||||||
|
self._ble.gatts_write(h_d1, b'\x01\x01')
|
||||||
|
self._ble.gatts_write(h_d2, b'\x02\x01')
|
||||||
|
self._ble.gatts_write(h_d3, b'\x02\x02')
|
||||||
|
self._ble.gatts_write(h_d4, b'\x03\x01')
|
||||||
|
self._ble.gatts_write(h_proto, b"\x01")
|
||||||
|
|
||||||
|
def is_connected(self):
|
||||||
|
'''蓝牙是否连接成功'''
|
||||||
|
return self.device_state
|
||||||
|
|
||||||
|
def advertise(self, interval_us=100000):
|
||||||
|
'''蓝牙广播'''
|
||||||
|
print("Starting advertising")
|
||||||
|
self._ble.gap_advertise(interval_us, adv_data=self._payload)
|
||||||
|
|
||||||
|
def battery_notify(self, level):
|
||||||
|
'''电池电量%'''
|
||||||
|
if self.is_connected():
|
||||||
|
self.battery_level = max(min(level, 100), 0)
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.h_bat, struct.pack("<B", self.battery_level))
|
||||||
|
|
||||||
|
def keyboard_state(self):
|
||||||
|
'''获取键盘 指示灯状态'''
|
||||||
|
return int.from_bytes(self.report, 'big')
|
||||||
|
|
||||||
|
def keyboard_notify(self, special=0, general=0, release=True):
|
||||||
|
'''键盘 特殊按键 + 常规组合按键*6'''
|
||||||
|
if self.is_connected():
|
||||||
|
_keys = bytearray(6)
|
||||||
|
if type(general) in (tuple, list):
|
||||||
|
for i in range(len(general)):
|
||||||
|
if i > 5: break
|
||||||
|
_keys[i] = general[i]
|
||||||
|
else:
|
||||||
|
_keys[0] = general
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.k_rep, bytes([special & 0xFF, 0]) + _keys)
|
||||||
|
if release:
|
||||||
|
time.sleep_ms(10)
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.k_rep, b'\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||||
|
|
||||||
|
def keyboard_str(self, string, delay=0):
|
||||||
|
'''键盘发送ASCLL码'''
|
||||||
|
for char in str(string):
|
||||||
|
char = max(min(ord(char), 127), 0)
|
||||||
|
self.keyboard_notify( 0x02 if _KEYCODE[char] >> 7 else 0x00, _KEYCODE[char] & 0x7F)
|
||||||
|
time.sleep_ms(20 + delay)
|
||||||
|
|
||||||
|
def mouse_notify(self, keys=0, move=(0, 0), wheel=0, release=True):
|
||||||
|
'''鼠标 按键*3 + 位移 + 滚轮'''
|
||||||
|
if self.is_connected():
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.m_rep, bytes([keys & 0x0F, move[0] & 0xFF, move[1] & 0xFF, wheel & 0xFF]))
|
||||||
|
if release:
|
||||||
|
time.sleep_ms(10)
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.m_rep, b'\x00\x00\x00\x00')
|
||||||
|
|
||||||
|
def Joystick_notify(self, keys=0, axes=(0, 0), release=False):
|
||||||
|
'''手柄 按键*8 + 摇杆'''
|
||||||
|
if self.is_connected():
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.j_rep, bytes([axes[0] & 0xFF, axes[1] & 0xFF, keys & 0xFF]))
|
||||||
|
if release:
|
||||||
|
time.sleep_ms(10)
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.j_rep, b'\x00\x00\x00')
|
||||||
|
@property
|
||||||
|
def mac(self):
|
||||||
|
'''Get mac address'''
|
||||||
|
return hexlify(self._ble.config('mac')[1]).decode()
|
||||||
218
mixly/boards/default/micropython/build/lib/ble_hid_keyboard.py
Normal file
218
mixly/boards/default/micropython/build/lib/ble_hid_keyboard.py
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
"""
|
||||||
|
Bluetooth-HID-Keyboard
|
||||||
|
|
||||||
|
Micropython library for the Bluetooth-HID-Keyboard
|
||||||
|
=======================================================
|
||||||
|
#https://github.com/Heerkog/MicroPythonBLEHID
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import bluetooth
|
||||||
|
import struct, time
|
||||||
|
from micropython import const
|
||||||
|
from ubinascii import hexlify
|
||||||
|
from ble_advertising import advertising_payload
|
||||||
|
from bluetooth import UUID, FLAG_READ, FLAG_WRITE ,FLAG_NOTIFY, FLAG_WRITE_NO_RESPONSE
|
||||||
|
|
||||||
|
_IRQ_CENTRAL_CONNECT = const(1)
|
||||||
|
_IRQ_CENTRAL_DISCONNECT = const(2)
|
||||||
|
_IRQ_GATTS_WRITE = const(3)
|
||||||
|
_IRQ_MTU_EXCHANGED = const(21)
|
||||||
|
_IRQ_CONNECTION_UPDATE = const(27)
|
||||||
|
_IRQ_GET_SECRET = const(29)
|
||||||
|
_IRQ_SET_SECRET = const(30)
|
||||||
|
_IRQ_PASSKEY_ACTION = const(31)
|
||||||
|
_PASSKEY_ACTION_INPUT = const(2)
|
||||||
|
_PASSKEY_ACTION_DISP = const(3)
|
||||||
|
_PASSKEY_ACTION_NUMCMP = const(4)
|
||||||
|
|
||||||
|
_HID_INPUT_REPORT = const(b'\x05\x01\t\x06\xa1\x01\x85\x01u\x01\x95\x08\x05\x07\x19\xe0)\xe7\x15\x00%\x01\x81\x02\x95\x01u\x08\x81\x01\x95\x05u\x01\x05\x08\x19\x01)\x05\x91\x02\x95\x01u\x03\x91\x01\x95\x06u\x08\x15\x00%e\x05\x07\x19\x00)e\x81\x00\xc0')
|
||||||
|
_KEYCODE = const(b'\x00\x00\x00\x00\x00\x00\x00\x00*+(\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\x00,\x9e\xb4\xa0\xa1\xa2\xa44\xa6\xa7\xa5\xae6-78\'\x1e\x1f !"#$%&\xb33\xb6.\xb7\xb8\x9f\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d/10\xa3\xad5\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\xaf\xb1\xb0\xb5L')
|
||||||
|
|
||||||
|
_DIS = (UUID(0x180A), ( (UUID(0x2A24), FLAG_READ),
|
||||||
|
(UUID(0x2A25), FLAG_READ),
|
||||||
|
(UUID(0x2A26), FLAG_READ),
|
||||||
|
(UUID(0x2A27), FLAG_READ),
|
||||||
|
(UUID(0x2A28), FLAG_READ),
|
||||||
|
(UUID(0x2A29), FLAG_READ),
|
||||||
|
(UUID(0x2A50), FLAG_READ), ), )
|
||||||
|
|
||||||
|
_BAS = (UUID(0x180F), ( (UUID(0x2A19), FLAG_READ | FLAG_NOTIFY, (
|
||||||
|
(UUID(0x2902), 0x01 | 0x02),
|
||||||
|
(UUID(0x2904), 0x01),)), ), )
|
||||||
|
|
||||||
|
_HIDS = (UUID(0x1812), ((UUID(0x2A4A), FLAG_READ),
|
||||||
|
(UUID(0x2A4B), FLAG_READ),
|
||||||
|
(UUID(0x2A4C), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE),
|
||||||
|
(UUID(0x2A4D), FLAG_READ | FLAG_NOTIFY, (
|
||||||
|
(UUID(0x2902), 0x01 | 0x02),
|
||||||
|
(UUID(0x2908), 0x01 | 0x02),)),
|
||||||
|
(UUID(0x2A4D), FLAG_READ | FLAG_WRITE, (
|
||||||
|
(UUID(0x2902), 0x01 | 0x02),
|
||||||
|
(UUID(0x2908), 0x01 | 0x02),)),
|
||||||
|
(UUID(0x2A4E), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), ), )
|
||||||
|
|
||||||
|
class Keyboard:
|
||||||
|
def __init__(self, name=None, passkey=1234, battery_level=100):
|
||||||
|
if (name is '') or (name is None):
|
||||||
|
name = "Mixgo_" + self.mac[-6:].upper()
|
||||||
|
print("Keyboard name:", name)
|
||||||
|
|
||||||
|
self._ble = bluetooth.BLE()
|
||||||
|
self._ble.active(True)
|
||||||
|
self._ble.irq(self._irq)
|
||||||
|
self._ble.config(gap_name=name)
|
||||||
|
self._ble.config(mtu=23)
|
||||||
|
self.device_state = False
|
||||||
|
self.conn_handle = None
|
||||||
|
self.passkey = passkey
|
||||||
|
self.battery_level = battery_level
|
||||||
|
self.report = b'\x00'
|
||||||
|
try:
|
||||||
|
import ble_hid_key
|
||||||
|
self.keys = ble_hid_key.keys
|
||||||
|
except:
|
||||||
|
self.keys = {}
|
||||||
|
|
||||||
|
handles = self._ble.gatts_register_services((_DIS, _BAS, _HIDS))
|
||||||
|
self._service_characteristics(handles)
|
||||||
|
self._payload = advertising_payload(name=name, services=[UUID(0x1812)], appearance=const(961))
|
||||||
|
self.advertise()
|
||||||
|
|
||||||
|
def _irq(self, event, data):
|
||||||
|
# Interrupt request callback function
|
||||||
|
if event == _IRQ_CENTRAL_CONNECT:
|
||||||
|
self.conn_handle, _, _ = data
|
||||||
|
print("Keyboard connected: ", self.conn_handle)
|
||||||
|
self.device_state = True
|
||||||
|
elif event == _IRQ_CENTRAL_DISCONNECT:
|
||||||
|
self.conn_handle = None
|
||||||
|
conn_handle, addr_type, addr = data
|
||||||
|
print("Keyboard disconnected: ", conn_handle)
|
||||||
|
self.advertise()
|
||||||
|
self.device_state = False
|
||||||
|
elif event == _IRQ_MTU_EXCHANGED:
|
||||||
|
conn_handle, mtu = data
|
||||||
|
self._ble.config(mtu=mtu)
|
||||||
|
print("MTU exchanged: ", mtu)
|
||||||
|
elif event == _IRQ_CONNECTION_UPDATE:
|
||||||
|
self.conn_handle, _, _, _, _ = data
|
||||||
|
print("Connection update")
|
||||||
|
elif event == _IRQ_PASSKEY_ACTION:
|
||||||
|
conn_handle, action, passkey = data
|
||||||
|
print("Passkey action", conn_handle, action, passkey)
|
||||||
|
if action == _PASSKEY_ACTION_NUMCMP:
|
||||||
|
self._ble.gap_passkey(conn_handle, action, False)
|
||||||
|
elif action == _PASSKEY_ACTION_DISP:
|
||||||
|
print("Displaying passkey")
|
||||||
|
self._ble.gap_passkey(conn_handle, action, self.passkey)
|
||||||
|
elif action == _PASSKEY_ACTION_INPUT:
|
||||||
|
print(" Prompting for passkey")
|
||||||
|
self._ble.gap_passkey(conn_handle, action, None)
|
||||||
|
else:
|
||||||
|
print("unknown action")
|
||||||
|
elif event == _IRQ_GATTS_WRITE:
|
||||||
|
conn_handle, attr_handle = data
|
||||||
|
self.report = self._ble.gatts_read(attr_handle)
|
||||||
|
elif event == _IRQ_SET_SECRET:
|
||||||
|
sec_type, key, value = data
|
||||||
|
key = sec_type, bytes(key)
|
||||||
|
value = bytes(value) if value else None
|
||||||
|
#print("Set secret: ", key, value)
|
||||||
|
if value is None:
|
||||||
|
if key in self.keys:
|
||||||
|
del self.keys[key]
|
||||||
|
self.key_secrets(self.keys)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
self.keys[key] = value
|
||||||
|
self.key_secrets(self.keys)
|
||||||
|
return True
|
||||||
|
elif event == _IRQ_GET_SECRET:
|
||||||
|
sec_type, index, key = data
|
||||||
|
#print("Get secret: ", sec_type, index, bytes(key) if key else None)
|
||||||
|
if key is None:
|
||||||
|
i = 0
|
||||||
|
for (t, _key), value in self.keys.items():
|
||||||
|
if t == sec_type:
|
||||||
|
if i == index:
|
||||||
|
return value
|
||||||
|
i += 1
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
key = sec_type, bytes(key)
|
||||||
|
return self.keys.get(key, None)
|
||||||
|
#else:
|
||||||
|
#print("Unhandled IRQ event: ", event, data)
|
||||||
|
|
||||||
|
def key_secrets(self, keys={}):
|
||||||
|
with open("ble_hid_key.py", "w+") as s_f:
|
||||||
|
s_f.write("keys=" + str(keys) + "\n")
|
||||||
|
|
||||||
|
def _service_characteristics(self, handles):
|
||||||
|
(h_mod, h_ser, h_fwr, h_hwr, h_swr, h_man, h_pnp) = handles[0]
|
||||||
|
(self.h_bat, h_ccc, h_bfmt,) = handles[1]
|
||||||
|
(h_info, h_hid, _, self.h_rep, _, h_d1, _, _, h_d2, h_proto) = handles[2]
|
||||||
|
|
||||||
|
# Write DIS characteristics.
|
||||||
|
self._ble.gatts_write(h_mod, b'1')
|
||||||
|
self._ble.gatts_write(h_ser, b'1')
|
||||||
|
self._ble.gatts_write(h_fwr, b'1')
|
||||||
|
self._ble.gatts_write(h_hwr, b'1')
|
||||||
|
self._ble.gatts_write(h_swr, b'1')
|
||||||
|
self._ble.gatts_write(h_man, b'Homebrew')
|
||||||
|
self._ble.gatts_write(h_pnp, struct.pack("<BHHH", 0x01, 0xFE61, 0x01, 0x0123))
|
||||||
|
# Write BAS characteristics.
|
||||||
|
self._ble.gatts_write(self.h_bat, struct.pack("<B", self.battery_level))
|
||||||
|
self._ble.gatts_write(h_bfmt, b'\x04\x00\xad\x27\x01\x00\x00')
|
||||||
|
self._ble.gatts_write(h_ccc, b'\x00\x00')
|
||||||
|
# Write service characteristics
|
||||||
|
self._ble.gatts_write(h_info, b"\x01\x01\x00\x02")
|
||||||
|
self._ble.gatts_write(h_hid, _HID_INPUT_REPORT)
|
||||||
|
self._ble.gatts_write(h_d1, b'\x01\x01')
|
||||||
|
self._ble.gatts_write(h_d2, b'\x01\x02')
|
||||||
|
self._ble.gatts_write(h_proto, b"\x01")
|
||||||
|
|
||||||
|
def state(self):
|
||||||
|
return int.from_bytes(self.report, 'big')
|
||||||
|
|
||||||
|
def is_connected(self):
|
||||||
|
return self.device_state
|
||||||
|
|
||||||
|
def advertise(self, interval_us=100000):
|
||||||
|
print("Starting advertising")
|
||||||
|
self._ble.gap_advertise(interval_us, adv_data=self._payload)
|
||||||
|
|
||||||
|
def notify_hid(self, special=0, general=0, release=True):
|
||||||
|
if self.is_connected():
|
||||||
|
_keys = bytearray(6)
|
||||||
|
if type(general) in (tuple, list):
|
||||||
|
for i in range(len(general)):
|
||||||
|
if i > 5: break
|
||||||
|
_keys[i] = general[i]
|
||||||
|
else:
|
||||||
|
_keys[0] = general
|
||||||
|
# Pack the mouse state as described by the input report
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.h_rep, bytes([special & 0xFF, 0]) + _keys)
|
||||||
|
if release:
|
||||||
|
time.sleep_ms(10)
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.h_rep, b'\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||||
|
|
||||||
|
def notify_battery(self, level):
|
||||||
|
if self.is_connected():
|
||||||
|
self.battery_level = max(min(level, 100), 0)
|
||||||
|
# Notifies the client by writing to the battery level handle.
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.h_bat, struct.pack("<B", self.battery_level))
|
||||||
|
|
||||||
|
def notify_str(self, string, delay=0):
|
||||||
|
for char in str(string):
|
||||||
|
char = max(min(ord(char), 127), 0)
|
||||||
|
self.notify_hid( 0x02 if _KEYCODE[char] >> 7 else 0x00, _KEYCODE[char] & 0x7F)
|
||||||
|
time.sleep_ms(20 + delay)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mac(self):
|
||||||
|
'''Get mac address'''
|
||||||
|
return hexlify(self._ble.config('mac')[1]).decode()
|
||||||
193
mixly/boards/default/micropython/build/lib/ble_hid_mouse.py
Normal file
193
mixly/boards/default/micropython/build/lib/ble_hid_mouse.py
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
"""
|
||||||
|
Bluetooth-HID-Mouse
|
||||||
|
|
||||||
|
Micropython library for the Bluetooth-HID-Mouse
|
||||||
|
=======================================================
|
||||||
|
#https://github.com/Heerkog/MicroPythonBLEHID
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import bluetooth
|
||||||
|
import struct, time
|
||||||
|
from micropython import const
|
||||||
|
from ubinascii import hexlify
|
||||||
|
from ble_advertising import advertising_payload
|
||||||
|
from bluetooth import UUID, FLAG_READ, FLAG_WRITE ,FLAG_NOTIFY, FLAG_WRITE_NO_RESPONSE
|
||||||
|
|
||||||
|
_IRQ_CENTRAL_CONNECT = const(1)
|
||||||
|
_IRQ_CENTRAL_DISCONNECT = const(2)
|
||||||
|
_IRQ_MTU_EXCHANGED = const(21)
|
||||||
|
_IRQ_CONNECTION_UPDATE = const(27)
|
||||||
|
_IRQ_GET_SECRET = const(29)
|
||||||
|
_IRQ_SET_SECRET = const(30)
|
||||||
|
_IRQ_PASSKEY_ACTION = const(31)
|
||||||
|
_PASSKEY_ACTION_INPUT = const(2)
|
||||||
|
_PASSKEY_ACTION_DISP = const(3)
|
||||||
|
_PASSKEY_ACTION_NUMCMP = const(4)
|
||||||
|
|
||||||
|
_HID_INPUT_REPORT = const(b'\x05\x01\t\x02\xa1\x01\x85\x01\t\x01\xa1\x00\x05\t\x19\x01)\x03\x15\x00%\x01\x95\x03u\x01\x81\x02\x95\x01u\x05\x81\x03\x05\x01\t0\t1\t8\x15\x81%\x7fu\x08\x95\x03\x81\x06\xc0\xc0')
|
||||||
|
|
||||||
|
_DIS = (UUID(0x180A), ( (UUID(0x2A24), FLAG_READ),
|
||||||
|
(UUID(0x2A25), FLAG_READ),
|
||||||
|
(UUID(0x2A26), FLAG_READ),
|
||||||
|
(UUID(0x2A27), FLAG_READ),
|
||||||
|
(UUID(0x2A28), FLAG_READ),
|
||||||
|
(UUID(0x2A29), FLAG_READ),
|
||||||
|
(UUID(0x2A50), FLAG_READ), ), )
|
||||||
|
|
||||||
|
_BAS = (UUID(0x180F), ( (UUID(0x2A19), FLAG_READ | FLAG_NOTIFY, (
|
||||||
|
(UUID(0x2902), 0x01 | 0x02),
|
||||||
|
(UUID(0x2904), 0x01),)), ), )
|
||||||
|
|
||||||
|
_HIDS = (UUID(0x1812), ((UUID(0x2A4A), FLAG_READ),
|
||||||
|
(UUID(0x2A4B), FLAG_READ),
|
||||||
|
(UUID(0x2A4C), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE),
|
||||||
|
(UUID(0x2A4D), FLAG_READ | FLAG_NOTIFY, (
|
||||||
|
(UUID(0x2902), 0x01 | 0x02),
|
||||||
|
(UUID(0x2908), 0x01 | 0x02), )),
|
||||||
|
(UUID(0x2A4E), FLAG_READ | FLAG_WRITE | FLAG_WRITE_NO_RESPONSE), ), )
|
||||||
|
|
||||||
|
class Mouse:
|
||||||
|
def __init__(self, name=None, passkey=1234, battery_level=100):
|
||||||
|
if (name is '') or (name is None):
|
||||||
|
name = "Mixgo_" + self.mac[-6:].upper()
|
||||||
|
print("Mouse name:", name)
|
||||||
|
|
||||||
|
self._ble = bluetooth.BLE()
|
||||||
|
self._ble.active(True)
|
||||||
|
self._ble.irq(self._irq)
|
||||||
|
self._ble.config(gap_name=name)
|
||||||
|
self._ble.config(mtu=23)
|
||||||
|
self.device_state = False
|
||||||
|
self.conn_handle = None
|
||||||
|
self.passkey = passkey
|
||||||
|
self.battery_level = battery_level
|
||||||
|
try:
|
||||||
|
import ble_hid_key
|
||||||
|
self.keys = ble_hid_key.keys
|
||||||
|
except:
|
||||||
|
self.keys = {}
|
||||||
|
|
||||||
|
handles = self._ble.gatts_register_services((_DIS, _BAS, _HIDS))
|
||||||
|
self._service_characteristics(handles)
|
||||||
|
self._payload = advertising_payload(name=name, services=[UUID(0x1812)], appearance=const(962))
|
||||||
|
self.advertise()
|
||||||
|
|
||||||
|
def _irq(self, event, data):
|
||||||
|
# Interrupt request callback function
|
||||||
|
if event == _IRQ_CENTRAL_CONNECT:
|
||||||
|
self.conn_handle, _, _ = data
|
||||||
|
print("Mouse connected: ", self.conn_handle)
|
||||||
|
self.device_state = True
|
||||||
|
elif event == _IRQ_CENTRAL_DISCONNECT:
|
||||||
|
self.conn_handle = None
|
||||||
|
conn_handle, addr_type, addr = data
|
||||||
|
print("Mouse disconnected: ", conn_handle)
|
||||||
|
self.advertise()
|
||||||
|
self.device_state = False
|
||||||
|
elif event == _IRQ_MTU_EXCHANGED:
|
||||||
|
conn_handle, mtu = data
|
||||||
|
self._ble.config(mtu=mtu)
|
||||||
|
print("MTU exchanged: ", mtu)
|
||||||
|
elif event == _IRQ_CONNECTION_UPDATE:
|
||||||
|
self.conn_handle, _, _, _, _ = data
|
||||||
|
print("Connection update")
|
||||||
|
elif event == _IRQ_PASSKEY_ACTION:
|
||||||
|
conn_handle, action, passkey = data
|
||||||
|
print("Passkey action", conn_handle, action, passkey)
|
||||||
|
if action == _PASSKEY_ACTION_NUMCMP:
|
||||||
|
self._ble.gap_passkey(conn_handle, action, False)
|
||||||
|
elif action == _PASSKEY_ACTION_DISP:
|
||||||
|
print("Displaying passkey")
|
||||||
|
self._ble.gap_passkey(conn_handle, action, self.passkey)
|
||||||
|
elif action == _PASSKEY_ACTION_INPUT:
|
||||||
|
print(" Prompting for passkey")
|
||||||
|
self._ble.gap_passkey(conn_handle, action, None)
|
||||||
|
else:
|
||||||
|
print("unknown action")
|
||||||
|
elif event == _IRQ_SET_SECRET:
|
||||||
|
sec_type, key, value = data
|
||||||
|
key = sec_type, bytes(key)
|
||||||
|
value = bytes(value) if value else None
|
||||||
|
#print("Set secret: ", key, value)
|
||||||
|
if value is None:
|
||||||
|
if key in self.keys:
|
||||||
|
del self.keys[key]
|
||||||
|
self.key_secrets(self.keys)
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
self.keys[key] = value
|
||||||
|
self.key_secrets(self.keys)
|
||||||
|
return True
|
||||||
|
elif event == _IRQ_GET_SECRET:
|
||||||
|
sec_type, index, key = data
|
||||||
|
#print("Get secret: ", sec_type, index, bytes(key) if key else None)
|
||||||
|
if key is None:
|
||||||
|
i = 0
|
||||||
|
for (t, _key), value in self.keys.items():
|
||||||
|
if t == sec_type:
|
||||||
|
if i == index:
|
||||||
|
return value
|
||||||
|
i += 1
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
key = sec_type, bytes(key)
|
||||||
|
return self.keys.get(key, None)
|
||||||
|
#else:
|
||||||
|
#print("Unhandled IRQ event: ", event, data)
|
||||||
|
|
||||||
|
def key_secrets(self, keys={}):
|
||||||
|
with open("ble_hid_key.py", "w+") as s_f:
|
||||||
|
s_f.write("keys=" + str(keys) + "\n")
|
||||||
|
|
||||||
|
def _service_characteristics(self, handles):
|
||||||
|
(h_mod, h_ser, h_fwr, h_hwr, h_swr, h_man, h_pnp) = handles[0]
|
||||||
|
(self.h_bat, h_ccc, h_bfmt,) = handles[1]
|
||||||
|
(h_info, h_hid, h_ctrl, self.h_rep, _, h_d1, h_proto) = handles[2]
|
||||||
|
|
||||||
|
# Write DIS characteristics.
|
||||||
|
self._ble.gatts_write(h_mod, b'1')
|
||||||
|
self._ble.gatts_write(h_ser, b'1')
|
||||||
|
self._ble.gatts_write(h_fwr, b'1')
|
||||||
|
self._ble.gatts_write(h_hwr, b'1')
|
||||||
|
self._ble.gatts_write(h_swr, b'1')
|
||||||
|
self._ble.gatts_write(h_man, b'Homebrew')
|
||||||
|
self._ble.gatts_write(h_pnp, struct.pack("<BHHH", 0x01, 0xFE61, 0x01, 0x0123))
|
||||||
|
# Write BAS characteristics.
|
||||||
|
self._ble.gatts_write(self.h_bat, struct.pack("<B", self.battery_level))
|
||||||
|
self._ble.gatts_write(h_bfmt, b'\x04\x00\xad\x27\x01\x00\x00')
|
||||||
|
self._ble.gatts_write(h_ccc, b'\x00\x00')
|
||||||
|
# Write service characteristics
|
||||||
|
self._ble.gatts_write(h_info, b"\x01\x01\x00\x02")
|
||||||
|
self._ble.gatts_write(h_hid, _HID_INPUT_REPORT)
|
||||||
|
self._ble.gatts_write(self.h_rep, b'\x00\x00\x00\x00')
|
||||||
|
self._ble.gatts_write(h_d1, b'\x01\x01')
|
||||||
|
self._ble.gatts_write(h_proto, b"\x01")
|
||||||
|
|
||||||
|
def is_connected(self):
|
||||||
|
return self.device_state
|
||||||
|
|
||||||
|
def advertise(self, interval_us=100000):
|
||||||
|
print("Starting advertising")
|
||||||
|
self._ble.gap_advertise(interval_us, adv_data=self._payload)
|
||||||
|
|
||||||
|
def notify_hid(self, keys=0, move=(0, 0), wheel=0, release=True):
|
||||||
|
if self.is_connected():
|
||||||
|
# Pack the mouse state as described by the input report
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.h_rep, bytes([keys & 0x0F, move[0] & 0xFF, move[1] & 0xFF, wheel & 0xFF]))
|
||||||
|
if release:
|
||||||
|
time.sleep_ms(10)
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.h_rep, b'\x00\x00\x00\x00')
|
||||||
|
|
||||||
|
def notify_battery(self, level):
|
||||||
|
if self.is_connected():
|
||||||
|
self.battery_level = max(min(level, 100), 0)
|
||||||
|
# Notifies the client by writing to the battery level handle.
|
||||||
|
self._ble.gatts_notify(self.conn_handle, self.h_bat, struct.pack("<B", self.battery_level))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mac(self):
|
||||||
|
'''Get mac address'''
|
||||||
|
return hexlify(self._ble.config('mac')[1]).decode()
|
||||||
91
mixly/boards/default/micropython/build/lib/ble_peripheral.py
Normal file
91
mixly/boards/default/micropython/build/lib/ble_peripheral.py
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
"""
|
||||||
|
Bluetooth-Peripheral
|
||||||
|
|
||||||
|
Micropython library for the Bluetooth-Peripheral
|
||||||
|
=======================================================
|
||||||
|
#Preliminary composition 20221018
|
||||||
|
#https://github.com/micropython/micropython/tree/master/examples/bluetooth
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bluetooth
|
||||||
|
from micropython import const
|
||||||
|
from ubinascii import hexlify
|
||||||
|
from ble_advertising import advertising_payload
|
||||||
|
|
||||||
|
_IRQ_CENTRAL_CONNECT = const(1)
|
||||||
|
_IRQ_CENTRAL_DISCONNECT = const(2)
|
||||||
|
_IRQ_GATTS_WRITE = const(3)
|
||||||
|
|
||||||
|
_FLAG_READ = const(0x0002)
|
||||||
|
_FLAG_WRITE_NO_RESPONSE = const(0x0004)
|
||||||
|
_FLAG_WRITE = const(0x0008)
|
||||||
|
_FLAG_NOTIFY = const(0x0010)
|
||||||
|
|
||||||
|
_UART_UUID = bluetooth.UUID(0x1101)
|
||||||
|
_UART_TX = (bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"),_FLAG_READ | _FLAG_NOTIFY,)
|
||||||
|
_UART_RX = (bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"),_FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE,)
|
||||||
|
_UART_SERVICE = (_UART_UUID,(_UART_TX, _UART_RX),)
|
||||||
|
|
||||||
|
class BLESimplePeripheral:
|
||||||
|
def __init__(self, name=None):
|
||||||
|
self._ble = bluetooth.BLE()
|
||||||
|
self._ble.active(True)
|
||||||
|
self._ble.irq(self._irq)
|
||||||
|
((self._handle_tx, self._handle_rx),) = self._ble.gatts_register_services((_UART_SERVICE,))
|
||||||
|
self._connections = set()
|
||||||
|
self._write_callback = None
|
||||||
|
self._write_data = None
|
||||||
|
if (name is '') or (name is None):
|
||||||
|
name = "Mixgo_" + self.mac[-6:].upper()
|
||||||
|
print("Bluetooth name:", name)
|
||||||
|
self._payload = advertising_payload(name=name, services=[_UART_UUID])
|
||||||
|
self._advertise()
|
||||||
|
|
||||||
|
def _irq(self, event, data):
|
||||||
|
# Track connections so we can send notifications.
|
||||||
|
if event == _IRQ_CENTRAL_CONNECT:
|
||||||
|
conn_handle, _, _ = data
|
||||||
|
print("New connection", conn_handle)
|
||||||
|
self._connections.add(conn_handle)
|
||||||
|
elif event == _IRQ_CENTRAL_DISCONNECT:
|
||||||
|
conn_handle, _, _ = data
|
||||||
|
print("Disconnected", conn_handle)
|
||||||
|
self._connections.remove(conn_handle)
|
||||||
|
# Start advertising again to allow a new connection.
|
||||||
|
self._advertise()
|
||||||
|
elif event == _IRQ_GATTS_WRITE:
|
||||||
|
conn_handle, value_handle = data
|
||||||
|
value = self._ble.gatts_read(value_handle)
|
||||||
|
if value_handle == self._handle_rx:
|
||||||
|
try:
|
||||||
|
self._write_data=value.decode().strip()
|
||||||
|
except:
|
||||||
|
self._write_data=value
|
||||||
|
if self._write_callback:
|
||||||
|
self._write_callback(self._write_data)
|
||||||
|
|
||||||
|
def send(self, data):
|
||||||
|
for conn_handle in self._connections:
|
||||||
|
self._ble.gatts_notify(conn_handle, self._handle_tx, data)
|
||||||
|
|
||||||
|
def is_connected(self):
|
||||||
|
return len(self._connections) > 0
|
||||||
|
|
||||||
|
def _advertise(self, interval_us=500000):
|
||||||
|
print("Starting advertising")
|
||||||
|
self._ble.gap_advertise(interval_us, adv_data=self._payload)
|
||||||
|
|
||||||
|
def recv(self, callback= None):
|
||||||
|
if callback:
|
||||||
|
self._write_callback = callback
|
||||||
|
else:
|
||||||
|
write_data=self._write_data
|
||||||
|
self._write_data=None
|
||||||
|
return write_data
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mac(self):
|
||||||
|
'''Get mac address'''
|
||||||
|
return hexlify(self._ble.config('mac')[1]).decode()
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
"""
|
||||||
|
Bluetooth-uart-Peripheral
|
||||||
|
|
||||||
|
Micropython library for the Bluetooth-uart-Peripheral
|
||||||
|
=======================================================
|
||||||
|
#Preliminary composition 202200628
|
||||||
|
#https://github.com/micropython/micropython/tree/master/examples/bluetooth
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import bluetooth
|
||||||
|
from ble_advertising import advertising_payload
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_IRQ_CENTRAL_CONNECT = const(1)
|
||||||
|
_IRQ_CENTRAL_DISCONNECT = const(2)
|
||||||
|
_IRQ_GATTS_WRITE = const(3)
|
||||||
|
|
||||||
|
_FLAG_READ = const(0x0002)
|
||||||
|
_FLAG_WRITE_NO_RESPONSE = const(0x0004)
|
||||||
|
_FLAG_WRITE = const(0x0008)
|
||||||
|
_FLAG_NOTIFY = const(0x0010)
|
||||||
|
|
||||||
|
_UART_UUID = bluetooth.UUID("0000fff0-0000-1000-8000-00805f9b34fb")
|
||||||
|
_UART_TX = (bluetooth.UUID("0000fff1-0000-1000-8000-00805f9b34fb"),_FLAG_READ | _FLAG_NOTIFY,)
|
||||||
|
_UART_RX = (bluetooth.UUID("0000fff2-0000-1000-8000-00805f9b34fb"),_FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE,)
|
||||||
|
_UART_SERVICE = (_UART_UUID,(_UART_TX, _UART_RX),)
|
||||||
|
|
||||||
|
class BLEUART:
|
||||||
|
def __init__(self, name="mpy-uart", rxbuf=100):
|
||||||
|
self._ble = bluetooth.BLE()
|
||||||
|
self._ble.active(True)
|
||||||
|
self._ble.irq(self._irq)
|
||||||
|
((self._tx_handle, self._rx_handle),) = self._ble.gatts_register_services((_UART_SERVICE,))
|
||||||
|
self._ble.gatts_set_buffer(self._rx_handle, rxbuf, True)
|
||||||
|
self._connections = set()
|
||||||
|
self._rx_buffer = bytearray()
|
||||||
|
self._handler = None
|
||||||
|
self._payload = advertising_payload(name=name, services=[_UART_UUID])
|
||||||
|
self._advertise()
|
||||||
|
|
||||||
|
def irq(self, handler):
|
||||||
|
self._handler = handler
|
||||||
|
|
||||||
|
def _irq(self, event, data):
|
||||||
|
# Track connections so we can send notifications.
|
||||||
|
if event == _IRQ_CENTRAL_CONNECT:
|
||||||
|
conn_handle, _, _ = data
|
||||||
|
print("Bluetooth connected")
|
||||||
|
self._connections.add(conn_handle)
|
||||||
|
elif event == _IRQ_CENTRAL_DISCONNECT:
|
||||||
|
conn_handle, _, _ = data
|
||||||
|
print("Bluetooth disconnected")
|
||||||
|
if conn_handle in self._connections:
|
||||||
|
self._connections.remove(conn_handle)
|
||||||
|
# Start advertising again to allow a new connection.
|
||||||
|
self._advertise()
|
||||||
|
elif event == _IRQ_GATTS_WRITE:
|
||||||
|
conn_handle, value_handle = data
|
||||||
|
if conn_handle in self._connections and value_handle == self._rx_handle:
|
||||||
|
self._rx_buffer += self._ble.gatts_read(self._rx_handle)
|
||||||
|
if self._handler:
|
||||||
|
self._handler()
|
||||||
|
|
||||||
|
def any(self):
|
||||||
|
return len(self._rx_buffer)
|
||||||
|
|
||||||
|
def read(self, sz=None):
|
||||||
|
if not sz:
|
||||||
|
sz = len(self._rx_buffer)
|
||||||
|
result = self._rx_buffer[0:sz]
|
||||||
|
self._rx_buffer = self._rx_buffer[sz:]
|
||||||
|
return result
|
||||||
|
|
||||||
|
def write(self, data):
|
||||||
|
for conn_handle in self._connections:
|
||||||
|
self._ble.gatts_notify(conn_handle, self._tx_handle, data)
|
||||||
|
|
||||||
|
def close(self):
|
||||||
|
for conn_handle in self._connections:
|
||||||
|
self._ble.gap_disconnect(conn_handle)
|
||||||
|
self._connections.clear()
|
||||||
|
|
||||||
|
def _advertise(self, interval_us=500000):
|
||||||
|
self._ble.gap_advertise(interval_us, adv_data=self._payload)
|
||||||
67
mixly/boards/default/micropython/build/lib/ble_uart_repl.py
Normal file
67
mixly/boards/default/micropython/build/lib/ble_uart_repl.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# Proof-of-concept of a REPL over BLE UART.
|
||||||
|
# Set the EoL characters to \r\n.
|
||||||
|
|
||||||
|
import io
|
||||||
|
import os
|
||||||
|
from machine import Timer
|
||||||
|
from micropython import schedule
|
||||||
|
from ble_uart_peripheral import BLEUART
|
||||||
|
|
||||||
|
_MP_STREAM_POLL = const(3)
|
||||||
|
_MP_STREAM_POLL_RD = const(0x0001)
|
||||||
|
|
||||||
|
# Batch writes into 50ms intervals.
|
||||||
|
Define_timer = Timer(2)
|
||||||
|
|
||||||
|
def schedule_in(handler, delay_ms):
|
||||||
|
def _wrap(_arg):
|
||||||
|
handler()
|
||||||
|
if Define_timer:
|
||||||
|
Define_timer.init(mode=Timer.ONE_SHOT, period=delay_ms, callback=_wrap)
|
||||||
|
else:
|
||||||
|
schedule(_wrap, None)
|
||||||
|
|
||||||
|
# Simple buffering stream to support the dupterm requirements.
|
||||||
|
class BLEUARTStream(io.IOBase):
|
||||||
|
def __init__(self, name="mpy-repl"):
|
||||||
|
self._uart = BLEUART(name)
|
||||||
|
self._tx_buf = bytearray()
|
||||||
|
self._uart.irq(self._on_rx)
|
||||||
|
|
||||||
|
def _on_rx(self):
|
||||||
|
if hasattr(os, "dupterm_notify"):
|
||||||
|
os.dupterm_notify(None)
|
||||||
|
|
||||||
|
def read(self, sz=None):
|
||||||
|
return self._uart.read(sz)
|
||||||
|
|
||||||
|
def readinto(self, buf):
|
||||||
|
avail = self._uart.read(len(buf))
|
||||||
|
if not avail:
|
||||||
|
return None
|
||||||
|
for i in range(len(avail)):
|
||||||
|
buf[i] = avail[i]
|
||||||
|
return len(avail)
|
||||||
|
|
||||||
|
def ioctl(self, op, arg):
|
||||||
|
if op == _MP_STREAM_POLL:
|
||||||
|
if self._uart.any():
|
||||||
|
return _MP_STREAM_POLL_RD
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def _flush(self):
|
||||||
|
data = self._tx_buf[0:100]
|
||||||
|
self._tx_buf = self._tx_buf[100:]
|
||||||
|
self._uart.write(data)
|
||||||
|
if self._tx_buf:
|
||||||
|
schedule_in(self._flush, 50)
|
||||||
|
|
||||||
|
def write(self, buf):
|
||||||
|
empty = not self._tx_buf
|
||||||
|
self._tx_buf += buf
|
||||||
|
if empty:
|
||||||
|
schedule_in(self._flush, 50)
|
||||||
|
|
||||||
|
def start(ble_name="mpy-repl"):
|
||||||
|
stream = BLEUARTStream(name=ble_name)
|
||||||
|
os.dupterm(stream)
|
||||||
377
mixly/boards/default/micropython/build/lib/blynklib.py
Normal file
377
mixly/boards/default/micropython/build/lib/blynklib.py
Normal file
@@ -0,0 +1,377 @@
|
|||||||
|
# Copyright (c) 2019-2020 Anton Morozenko
|
||||||
|
# Copyright (c) 2015-2019 Volodymyr Shymanskyy.
|
||||||
|
# See the file LICENSE for copying permission.
|
||||||
|
|
||||||
|
__version__ = '0.2.6'
|
||||||
|
|
||||||
|
import usocket as socket
|
||||||
|
import utime as time
|
||||||
|
import ustruct as struct
|
||||||
|
import uselect as select
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
ticks_ms = time.ticks_ms
|
||||||
|
sleep_ms = time.sleep_ms
|
||||||
|
|
||||||
|
IOError = OSError
|
||||||
|
|
||||||
|
LOGO = """
|
||||||
|
___ __ __
|
||||||
|
/ _ )/ /_ _____ / /__
|
||||||
|
/ _ / / // / _ \\/ '_/
|
||||||
|
/____/_/\\_, /_//_/_/\\_\\
|
||||||
|
/___/ for Python v{}\n""".format(__version__)
|
||||||
|
|
||||||
|
|
||||||
|
def stub_log(*args):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BlynkError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RedirectError(Exception):
|
||||||
|
def __init__(self, server, port):
|
||||||
|
self.server = server
|
||||||
|
self.port = port
|
||||||
|
|
||||||
|
|
||||||
|
class Protocol(object):
|
||||||
|
MSG_RSP = const(0)
|
||||||
|
MSG_LOGIN = const(2)
|
||||||
|
MSG_PING = const(6)
|
||||||
|
MSG_TWEET = const(12)
|
||||||
|
MSG_EMAIL = const(13)
|
||||||
|
MSG_NOTIFY = const(14)
|
||||||
|
MSG_BRIDGE = const(15)
|
||||||
|
MSG_HW_SYNC = const(16)
|
||||||
|
MSG_INTERNAL = const(17)
|
||||||
|
MSG_PROPERTY = const(19)
|
||||||
|
MSG_HW = const(20)
|
||||||
|
MSG_REDIRECT = const(41)
|
||||||
|
MSG_HEAD_LEN = const(5)
|
||||||
|
|
||||||
|
STATUS_INVALID_TOKEN = const(9)
|
||||||
|
STATUS_OK = const(200)
|
||||||
|
VPIN_MAX_NUM = const(32)
|
||||||
|
|
||||||
|
_msg_id = 1
|
||||||
|
|
||||||
|
def _get_msg_id(self, **kwargs):
|
||||||
|
if 'msg_id' in kwargs:
|
||||||
|
return kwargs['msg_id']
|
||||||
|
self._msg_id += const(1)
|
||||||
|
return self._msg_id if self._msg_id <= const(0xFFFF) else const(1)
|
||||||
|
|
||||||
|
def _pack_msg(self, msg_type, *args, **kwargs):
|
||||||
|
data = ('\0'.join([str(curr_arg) for curr_arg in args])).encode('utf-8')
|
||||||
|
return struct.pack('!BHH', msg_type, self._get_msg_id(**kwargs), len(data)) + data
|
||||||
|
|
||||||
|
def parse_response(self, rsp_data, msg_buffer):
|
||||||
|
msg_args = []
|
||||||
|
msg_len = 0
|
||||||
|
try:
|
||||||
|
msg_type, msg_id, h_data = struct.unpack('!BHH', rsp_data[:self.MSG_HEAD_LEN])
|
||||||
|
msg_len = self.MSG_HEAD_LEN + h_data
|
||||||
|
except Exception as p_err:
|
||||||
|
raise BlynkError('Message parse error: {}'.format(p_err))
|
||||||
|
if msg_id == 0:
|
||||||
|
raise BlynkError('invalid msg_id == 0')
|
||||||
|
elif h_data >= msg_buffer:
|
||||||
|
raise BlynkError('Command too long. Length = {}'.format(h_data))
|
||||||
|
elif msg_type in (self.MSG_RSP, self.MSG_PING):
|
||||||
|
pass
|
||||||
|
elif msg_type in (self.MSG_HW, self.MSG_BRIDGE, self.MSG_INTERNAL, self.MSG_REDIRECT):
|
||||||
|
msg_body = rsp_data[self.MSG_HEAD_LEN: msg_len]
|
||||||
|
msg_args = [itm.decode('utf-8') for itm in msg_body.split(b'\0')]
|
||||||
|
else:
|
||||||
|
raise BlynkError("Unknown message type: '{}'".format(msg_type))
|
||||||
|
return msg_type, msg_id, h_data, msg_args, msg_len
|
||||||
|
|
||||||
|
def heartbeat_msg(self, heartbeat, rcv_buffer):
|
||||||
|
return self._pack_msg(self.MSG_INTERNAL, 'ver', __version__, 'buff-in', rcv_buffer, 'h-beat', heartbeat,
|
||||||
|
'dev', 'mpython')
|
||||||
|
|
||||||
|
def login_msg(self, token):
|
||||||
|
return self._pack_msg(self.MSG_LOGIN, token)
|
||||||
|
|
||||||
|
def ping_msg(self):
|
||||||
|
return self._pack_msg(self.MSG_PING)
|
||||||
|
|
||||||
|
def response_msg(self, *args, **kwargs):
|
||||||
|
return self._pack_msg(self.MSG_RSP, *args, **kwargs)
|
||||||
|
|
||||||
|
def virtual_write_msg(self, v_pin, *val):
|
||||||
|
return self._pack_msg(self.MSG_HW, 'vw', v_pin, *val)
|
||||||
|
|
||||||
|
def virtual_sync_msg(self, *pins):
|
||||||
|
return self._pack_msg(self.MSG_HW_SYNC, 'vr', *pins)
|
||||||
|
|
||||||
|
def email_msg(self, to, subject, body):
|
||||||
|
return self._pack_msg(self.MSG_EMAIL, to, subject, body)
|
||||||
|
|
||||||
|
def tweet_msg(self, msg):
|
||||||
|
return self._pack_msg(self.MSG_TWEET, msg)
|
||||||
|
|
||||||
|
def notify_msg(self, msg):
|
||||||
|
return self._pack_msg(self.MSG_NOTIFY, msg)
|
||||||
|
|
||||||
|
def set_property_msg(self, pin, prop, *val):
|
||||||
|
return self._pack_msg(self.MSG_PROPERTY, pin, prop, *val)
|
||||||
|
|
||||||
|
def internal_msg(self, *args):
|
||||||
|
return self._pack_msg(self.MSG_INTERNAL, *args)
|
||||||
|
|
||||||
|
|
||||||
|
class Connection(Protocol):
|
||||||
|
SOCK_MAX_TIMEOUT = const(5)
|
||||||
|
SOCK_TIMEOUT = 0.05
|
||||||
|
EAGAIN = const(11)
|
||||||
|
ETIMEDOUT = const(60)
|
||||||
|
RETRIES_TX_DELAY = const(2)
|
||||||
|
RETRIES_TX_MAX_NUM = const(3)
|
||||||
|
RECONNECT_SLEEP = const(1)
|
||||||
|
TASK_PERIOD_RES = const(50)
|
||||||
|
DISCONNECTED = const(0)
|
||||||
|
CONNECTING = const(1)
|
||||||
|
AUTHENTICATING = const(2)
|
||||||
|
AUTHENTICATED = const(3)
|
||||||
|
|
||||||
|
_state = None
|
||||||
|
_socket = None
|
||||||
|
_last_rcv_time = 0
|
||||||
|
_last_ping_time = 0
|
||||||
|
_last_send_time = 0
|
||||||
|
|
||||||
|
def __init__(self, token, server='blynk-cloud.com', port=80, heartbeat=10, rcv_buffer=1024, log=stub_log):
|
||||||
|
self.token = token
|
||||||
|
self.server = server
|
||||||
|
self.port = port
|
||||||
|
self.heartbeat = heartbeat
|
||||||
|
self.rcv_buffer = rcv_buffer
|
||||||
|
self.log = log
|
||||||
|
|
||||||
|
def _set_socket_timeout(self, timeout):
|
||||||
|
if getattr(self._socket, 'settimeout', None):
|
||||||
|
self._socket.settimeout(timeout)
|
||||||
|
else:
|
||||||
|
p = select.poll()
|
||||||
|
p.register(self._socket)
|
||||||
|
p.poll(int(timeout * const(1000)))
|
||||||
|
|
||||||
|
def send(self, data):
|
||||||
|
retries = self.RETRIES_TX_MAX_NUM
|
||||||
|
while retries > 0:
|
||||||
|
try:
|
||||||
|
retries -= 1
|
||||||
|
self._last_send_time = ticks_ms()
|
||||||
|
return self._socket.send(data)
|
||||||
|
except (IOError, OSError):
|
||||||
|
sleep_ms(self.RETRIES_TX_DELAY)
|
||||||
|
|
||||||
|
def receive(self, length, timeout):
|
||||||
|
d_buff = b''
|
||||||
|
try:
|
||||||
|
self._set_socket_timeout(timeout)
|
||||||
|
d_buff += self._socket.recv(length)
|
||||||
|
if len(d_buff) >= length:
|
||||||
|
d_buff = d_buff[:length]
|
||||||
|
return d_buff
|
||||||
|
except (IOError, OSError) as err:
|
||||||
|
if str(err) == 'timed out':
|
||||||
|
return b''
|
||||||
|
if str(self.EAGAIN) in str(err) or str(self.ETIMEDOUT) in str(err):
|
||||||
|
return b''
|
||||||
|
raise
|
||||||
|
|
||||||
|
def is_server_alive(self):
|
||||||
|
now = ticks_ms()
|
||||||
|
h_beat_ms = self.heartbeat * const(1000)
|
||||||
|
rcv_delta = time.ticks_diff(now, self._last_rcv_time)
|
||||||
|
ping_delta = time.ticks_diff(now, self._last_ping_time)
|
||||||
|
send_delta = time.ticks_diff(now, self._last_send_time)
|
||||||
|
if rcv_delta > h_beat_ms + (h_beat_ms // const(2)):
|
||||||
|
return False
|
||||||
|
if (ping_delta > h_beat_ms // const(10)) and (send_delta > h_beat_ms or rcv_delta > h_beat_ms):
|
||||||
|
self.send(self.ping_msg())
|
||||||
|
self.log('Heartbeat time: {}'.format(now))
|
||||||
|
self._last_ping_time = now
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _get_socket(self):
|
||||||
|
try:
|
||||||
|
self._state = self.CONNECTING
|
||||||
|
self._socket = socket.socket()
|
||||||
|
self._socket.connect(socket.getaddrinfo(self.server, self.port)[0][-1])
|
||||||
|
self._set_socket_timeout(self.SOCK_TIMEOUT)
|
||||||
|
self.log('Connected to server')
|
||||||
|
except Exception as g_exc:
|
||||||
|
raise BlynkError('Server connection failed: {}'.format(g_exc))
|
||||||
|
|
||||||
|
def _authenticate(self):
|
||||||
|
self.log('Authenticating device...')
|
||||||
|
self._state = self.AUTHENTICATING
|
||||||
|
self.send(self.login_msg(self.token))
|
||||||
|
rsp_data = self.receive(self.rcv_buffer, self.SOCK_MAX_TIMEOUT)
|
||||||
|
if not rsp_data:
|
||||||
|
raise BlynkError('Auth stage timeout')
|
||||||
|
msg_type, _, status, args, _ = self.parse_response(rsp_data, self.rcv_buffer)
|
||||||
|
if status != self.STATUS_OK:
|
||||||
|
if status == self.STATUS_INVALID_TOKEN:
|
||||||
|
raise BlynkError('Invalid Auth Token')
|
||||||
|
if msg_type == self.MSG_REDIRECT:
|
||||||
|
raise RedirectError(*args)
|
||||||
|
raise BlynkError('Auth stage failed. Status={}'.format(status))
|
||||||
|
self._state = self.AUTHENTICATED
|
||||||
|
self.log('Access granted')
|
||||||
|
|
||||||
|
def _set_heartbeat(self):
|
||||||
|
self.send(self.heartbeat_msg(self.heartbeat, self.rcv_buffer))
|
||||||
|
rcv_data = self.receive(self.rcv_buffer, self.SOCK_MAX_TIMEOUT)
|
||||||
|
if not rcv_data:
|
||||||
|
raise BlynkError('Heartbeat stage timeout')
|
||||||
|
_, _, status, _, _ = self.parse_response(rcv_data, self.rcv_buffer)
|
||||||
|
if status != self.STATUS_OK:
|
||||||
|
raise BlynkError('Set heartbeat returned code={}'.format(status))
|
||||||
|
self.log('Heartbeat = {} sec. MaxCmdBuffer = {} bytes'.format(self.heartbeat, self.rcv_buffer))
|
||||||
|
|
||||||
|
def connected(self):
|
||||||
|
return True if self._state == self.AUTHENTICATED else False
|
||||||
|
|
||||||
|
|
||||||
|
class Blynk(Connection):
|
||||||
|
_CONNECT_TIMEOUT = const(30) # 30sec
|
||||||
|
_VPIN_WILDCARD = '*'
|
||||||
|
_VPIN_READ = 'read v'
|
||||||
|
_VPIN_WRITE = 'write v'
|
||||||
|
_INTERNAL = 'internal_'
|
||||||
|
_CONNECT = 'connect'
|
||||||
|
_DISCONNECT = 'disconnect'
|
||||||
|
_VPIN_READ_ALL = '{}{}'.format(_VPIN_READ, _VPIN_WILDCARD)
|
||||||
|
_VPIN_WRITE_ALL = '{}{}'.format(_VPIN_WRITE, _VPIN_WILDCARD)
|
||||||
|
_events = {}
|
||||||
|
|
||||||
|
def __init__(self, token, **kwargs):
|
||||||
|
Connection.__init__(self, token, **kwargs)
|
||||||
|
self._start_time = ticks_ms()
|
||||||
|
self._last_rcv_time = ticks_ms()
|
||||||
|
self._last_send_time = ticks_ms()
|
||||||
|
self._last_ping_time = ticks_ms()
|
||||||
|
self._state = self.DISCONNECTED
|
||||||
|
print(LOGO)
|
||||||
|
|
||||||
|
def connect(self, timeout=_CONNECT_TIMEOUT):
|
||||||
|
end_time = time.time() + timeout
|
||||||
|
while not self.connected():
|
||||||
|
if self._state == self.DISCONNECTED:
|
||||||
|
try:
|
||||||
|
self._get_socket()
|
||||||
|
self._authenticate()
|
||||||
|
self._set_heartbeat()
|
||||||
|
self._last_rcv_time = ticks_ms()
|
||||||
|
self.log('Registered events: {}\n'.format(list(self._events.keys())))
|
||||||
|
self.call_handler(self._CONNECT)
|
||||||
|
return True
|
||||||
|
except BlynkError as b_err:
|
||||||
|
self.disconnect(b_err)
|
||||||
|
sleep_ms(self.TASK_PERIOD_RES)
|
||||||
|
except RedirectError as r_err:
|
||||||
|
self.disconnect()
|
||||||
|
self.server = r_err.server
|
||||||
|
self.port = r_err.port
|
||||||
|
sleep_ms(self.TASK_PERIOD_RES)
|
||||||
|
if time.time() >= end_time:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def disconnect(self, err_msg=None):
|
||||||
|
self.call_handler(self._DISCONNECT)
|
||||||
|
if self._socket:
|
||||||
|
self._socket.close()
|
||||||
|
self._state = self.DISCONNECTED
|
||||||
|
if err_msg:
|
||||||
|
self.log('[ERROR]: {}\nConnection closed'.format(err_msg))
|
||||||
|
time.sleep(self.RECONNECT_SLEEP)
|
||||||
|
|
||||||
|
def virtual_write(self, v_pin, *val):
|
||||||
|
return self.send(self.virtual_write_msg(v_pin, *val))
|
||||||
|
|
||||||
|
def virtual_sync(self, *v_pin):
|
||||||
|
return self.send(self.virtual_sync_msg(*v_pin))
|
||||||
|
|
||||||
|
def email(self, to, subject, body):
|
||||||
|
return self.send(self.email_msg(to, subject, body))
|
||||||
|
|
||||||
|
def tweet(self, msg):
|
||||||
|
return self.send(self.tweet_msg(msg))
|
||||||
|
|
||||||
|
def notify(self, msg):
|
||||||
|
return self.send(self.notify_msg(msg))
|
||||||
|
|
||||||
|
def set_property(self, v_pin, property_name, *val):
|
||||||
|
return self.send(self.set_property_msg(v_pin, property_name, *val))
|
||||||
|
|
||||||
|
def internal(self, *args):
|
||||||
|
return self.send(self.internal_msg(*args))
|
||||||
|
|
||||||
|
def handle_event(blynk, event_name):
|
||||||
|
class Deco(object):
|
||||||
|
def __init__(self, func):
|
||||||
|
self.func = func
|
||||||
|
# wildcard 'read V*' and 'write V*' events handling
|
||||||
|
if str(event_name).lower() in (blynk._VPIN_READ_ALL, blynk._VPIN_WRITE_ALL):
|
||||||
|
event_base_name = str(event_name).split(blynk._VPIN_WILDCARD)[0]
|
||||||
|
for i in range(blynk.VPIN_MAX_NUM + 1):
|
||||||
|
blynk._events['{}{}'.format(event_base_name.lower(), i)] = func
|
||||||
|
else:
|
||||||
|
blynk._events[str(event_name).lower()] = func
|
||||||
|
|
||||||
|
def __call__(self):
|
||||||
|
return self.func()
|
||||||
|
|
||||||
|
return Deco
|
||||||
|
|
||||||
|
def call_handler(self, event, *args, **kwargs):
|
||||||
|
if event in self._events.keys():
|
||||||
|
self.log("Event: ['{}'] -> {}".format(event, args))
|
||||||
|
self._events[event](*args, **kwargs)
|
||||||
|
|
||||||
|
def process(self, msg_type, msg_id, msg_len, msg_args):
|
||||||
|
if msg_type == self.MSG_RSP:
|
||||||
|
self.log('Response status: {}'.format(msg_len))
|
||||||
|
elif msg_type == self.MSG_PING:
|
||||||
|
self.send(self.response_msg(self.STATUS_OK, msg_id=msg_id))
|
||||||
|
elif msg_type in (self.MSG_HW, self.MSG_BRIDGE, self.MSG_INTERNAL):
|
||||||
|
if msg_type == self.MSG_INTERNAL:
|
||||||
|
self.call_handler("{}{}".format(self._INTERNAL, msg_args[0]), msg_args[1:])
|
||||||
|
elif len(msg_args) >= const(3) and msg_args[0] == 'vw':
|
||||||
|
self.call_handler("{}{}".format(self._VPIN_WRITE, msg_args[1]), int(msg_args[1]), msg_args[2:])
|
||||||
|
elif len(msg_args) == const(2) and msg_args[0] == 'vr':
|
||||||
|
self.call_handler("{}{}".format(self._VPIN_READ, msg_args[1]), int(msg_args[1]))
|
||||||
|
|
||||||
|
def read_response(self, timeout=0.5):
|
||||||
|
end_time = time.ticks_ms() + int(timeout * const(1000))
|
||||||
|
while time.ticks_diff(end_time, time.ticks_ms()) > 0:
|
||||||
|
rsp_data = self.receive(self.rcv_buffer, self.SOCK_TIMEOUT)
|
||||||
|
if rsp_data:
|
||||||
|
self._last_rcv_time = ticks_ms()
|
||||||
|
while rsp_data:
|
||||||
|
msg_type, msg_id, h_data, msg_args, msg_len = self.parse_response(rsp_data, self.rcv_buffer)
|
||||||
|
self.process(msg_type, msg_id, h_data, msg_args)
|
||||||
|
rsp_data = rsp_data[msg_len:]
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
if not self.connected():
|
||||||
|
self.connect()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self.read_response(timeout=self.SOCK_TIMEOUT)
|
||||||
|
if not self.is_server_alive():
|
||||||
|
self.disconnect('Server is offline')
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
raise
|
||||||
|
except BlynkError as b_err:
|
||||||
|
self.log(b_err)
|
||||||
|
self.disconnect()
|
||||||
|
except Exception as g_exc:
|
||||||
|
self.log(g_exc)
|
||||||
133
mixly/boards/default/micropython/build/lib/blynktimer.py
Normal file
133
mixly/boards/default/micropython/build/lib/blynktimer.py
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
# Copyright (c) 2019-2020 Anton Morozenko
|
||||||
|
"""
|
||||||
|
Polling timers for functions.
|
||||||
|
Registers timers and performs run once or periodical function execution after defined time intervals.
|
||||||
|
"""
|
||||||
|
# select.select call used as polling waiter where it is possible
|
||||||
|
# cause time.sleep sometimes may load CPU up to 100% with small polling wait interval
|
||||||
|
try:
|
||||||
|
# cpython
|
||||||
|
import time
|
||||||
|
import select
|
||||||
|
|
||||||
|
polling_wait = lambda x: select.select([], [], [], x)
|
||||||
|
polling_wait(0.01)
|
||||||
|
except OSError:
|
||||||
|
# windows case where select.select call fails
|
||||||
|
polling_wait = lambda x: time.sleep(x)
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# micropython
|
||||||
|
import utime as time
|
||||||
|
|
||||||
|
try:
|
||||||
|
from uselect import select as s_select
|
||||||
|
|
||||||
|
polling_wait = lambda x: s_select([], [], [], x)
|
||||||
|
except ImportError:
|
||||||
|
# case when micropython port does not support select.select
|
||||||
|
polling_wait = lambda x: time.sleep(x)
|
||||||
|
|
||||||
|
WAIT_SEC = 0.05
|
||||||
|
MAX_TIMERS = 16
|
||||||
|
DEFAULT_INTERVAL = 10
|
||||||
|
|
||||||
|
|
||||||
|
class TimerError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Timer(object):
|
||||||
|
timers = {}
|
||||||
|
|
||||||
|
def __init__(self, no_timers_err=True):
|
||||||
|
self.no_timers_err = no_timers_err
|
||||||
|
|
||||||
|
def _get_func_name(self, obj):
|
||||||
|
"""retrieves a suitable name for a function"""
|
||||||
|
if hasattr(obj, 'func'):
|
||||||
|
# handles nested decorators
|
||||||
|
return self._get_func_name(obj.func)
|
||||||
|
# simply returns 'timer' if on port without function attrs
|
||||||
|
return getattr(obj, '__name__', 'timer')
|
||||||
|
|
||||||
|
def register(blynk, *args, **kwargs):
|
||||||
|
# kwargs with defaults are used cause PEP 3102 no supported by Python2
|
||||||
|
interval = kwargs.pop('interval', DEFAULT_INTERVAL)
|
||||||
|
run_once = kwargs.pop('run_once', False)
|
||||||
|
stopped = kwargs.pop('stopped', False)
|
||||||
|
|
||||||
|
class Deco(object):
|
||||||
|
def __init__(self, func):
|
||||||
|
self.func = func
|
||||||
|
if len(list(Timer.timers.keys())) >= MAX_TIMERS:
|
||||||
|
raise TimerError('Max allowed timers num={}'.format(MAX_TIMERS))
|
||||||
|
_timer = _Timer(interval, func, run_once, stopped, *args, **kwargs)
|
||||||
|
Timer.timers['{}_{}'.format(len(list(Timer.timers.keys())), blynk._get_func_name(func))] = _timer
|
||||||
|
|
||||||
|
def __call__(self, *f_args, **f_kwargs):
|
||||||
|
return self.func(*f_args, **f_kwargs)
|
||||||
|
|
||||||
|
return Deco
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def stop(t_id):
|
||||||
|
timer = Timer.timers.get(t_id, None)
|
||||||
|
if timer is None:
|
||||||
|
raise TimerError('Timer id={} not found'.format(t_id))
|
||||||
|
Timer.timers[t_id].stopped = True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def start(t_id):
|
||||||
|
timer = Timer.timers.get(t_id, None)
|
||||||
|
if timer is None:
|
||||||
|
raise TimerError('Timer id={} not found'.format(t_id))
|
||||||
|
Timer.timers[t_id].stopped = False
|
||||||
|
Timer.timers[t_id].fire_time = None
|
||||||
|
Timer.timers[t_id].fire_time_prev = None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def is_stopped(t_id):
|
||||||
|
timer = Timer.timers.get(t_id, None)
|
||||||
|
if timer is None:
|
||||||
|
raise TimerError('Timer id={} not found'.format(t_id))
|
||||||
|
return timer.stopped
|
||||||
|
|
||||||
|
def get_timers(self):
|
||||||
|
states = {True: 'Stopped', False: 'Running'}
|
||||||
|
return {k: states[v.stopped] for k, v in self.timers.items()}
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
polling_wait(WAIT_SEC)
|
||||||
|
timers_intervals = [curr_timer.run() for curr_timer in Timer.timers.values() if not curr_timer.stopped]
|
||||||
|
if not timers_intervals and self.no_timers_err:
|
||||||
|
raise TimerError('Running timers not found')
|
||||||
|
return timers_intervals
|
||||||
|
|
||||||
|
|
||||||
|
class _Timer(object):
|
||||||
|
def __init__(self, interval, deco, run_once, stopped, *args, **kwargs):
|
||||||
|
self.interval = interval
|
||||||
|
self.deco = deco
|
||||||
|
self.args = args
|
||||||
|
self.run_once = run_once
|
||||||
|
self.kwargs = kwargs
|
||||||
|
self.fire_time = None
|
||||||
|
self.fire_time_prev = None
|
||||||
|
self.stopped = stopped
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
timer_real_interval = 0
|
||||||
|
if self.fire_time is None:
|
||||||
|
self.fire_time = time.time() + self.interval
|
||||||
|
if self.fire_time_prev is None:
|
||||||
|
self.fire_time_prev = time.time()
|
||||||
|
curr_time = time.time()
|
||||||
|
if curr_time >= self.fire_time:
|
||||||
|
self.deco(*self.args, **self.kwargs)
|
||||||
|
if self.run_once:
|
||||||
|
self.stopped = True
|
||||||
|
timer_real_interval = curr_time - self.fire_time_prev
|
||||||
|
self.fire_time_prev = self.fire_time
|
||||||
|
self.fire_time = curr_time + self.interval
|
||||||
|
return timer_real_interval
|
||||||
162
mixly/boards/default/micropython/build/lib/bmp280.py
Normal file
162
mixly/boards/default/micropython/build/lib/bmp280.py
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
from ustruct import unpack as unp
|
||||||
|
import utime
|
||||||
|
|
||||||
|
# Power Modes
|
||||||
|
NORMAL = 0
|
||||||
|
BMP280_TEMP_OS_SKIP = 0
|
||||||
|
BMP280_TEMP_OS_1 = 1
|
||||||
|
BMP280_TEMP_OS_2 = 2
|
||||||
|
BMP280_TEMP_OS_4 = 3
|
||||||
|
BMP280_TEMP_OS_8 = 4
|
||||||
|
BMP280_TEMP_OS_16 = 5
|
||||||
|
BMP280_PRES_OS_SKIP = 0
|
||||||
|
BMP280_PRES_OS_1 = 1
|
||||||
|
BMP280_PRES_OS_2 = 2
|
||||||
|
BMP280_PRES_OS_4 = 3
|
||||||
|
BMP280_PRES_OS_8 = 4
|
||||||
|
BMP280_PRES_OS_16 = 5
|
||||||
|
# BMP280 Temperature Registers
|
||||||
|
BMP280_REGISTER_DIG_T1 = 0x88
|
||||||
|
BMP280_REGISTER_DIG_T2 = 0x8A
|
||||||
|
BMP280_REGISTER_DIG_T3 = 0x8C
|
||||||
|
# BMP280 Pressure Registers
|
||||||
|
BMP280_REGISTER_DIG_P1 = 0x8E
|
||||||
|
BMP280_REGISTER_DIG_P2 = 0x90
|
||||||
|
BMP280_REGISTER_DIG_P3 = 0x92
|
||||||
|
BMP280_REGISTER_DIG_P4 = 0x94
|
||||||
|
BMP280_REGISTER_DIG_P5 = 0x96
|
||||||
|
BMP280_REGISTER_DIG_P6 = 0x98
|
||||||
|
BMP280_REGISTER_DIG_P7 = 0x9A
|
||||||
|
BMP280_REGISTER_DIG_P8 = 0x9C
|
||||||
|
BMP280_REGISTER_DIG_P9 = 0x9E
|
||||||
|
BMP280_REGISTER_ID = 0xD0
|
||||||
|
BMP280_REGISTER_RESET = 0xE0
|
||||||
|
BMP280_REGISTER_STATUS = 0xF3
|
||||||
|
BMP280_REGISTER_CONTROL = 0xF4
|
||||||
|
BMP280_REGISTER_CONFIG = 0xF5 # IIR filter config
|
||||||
|
BMP280_REGISTER_DATA = 0xF7
|
||||||
|
|
||||||
|
class BMP280:
|
||||||
|
def __init__(self, i2c_bus, addr=0x77):
|
||||||
|
self._bmp_i2c = i2c_bus
|
||||||
|
self._i2c_addr = addr
|
||||||
|
self.chip_id = self._read(BMP280_REGISTER_ID, 2)
|
||||||
|
|
||||||
|
self._T1 = unp('<H', self._read(BMP280_REGISTER_DIG_T1, 2))[0]
|
||||||
|
self._T2 = unp('<h', self._read(BMP280_REGISTER_DIG_T2, 2))[0]
|
||||||
|
self._T3 = unp('<h', self._read(BMP280_REGISTER_DIG_T3, 2))[0]
|
||||||
|
self._P1 = unp('<H', self._read(BMP280_REGISTER_DIG_P1, 2))[0]
|
||||||
|
self._P2 = unp('<h', self._read(BMP280_REGISTER_DIG_P2, 2))[0]
|
||||||
|
self._P3 = unp('<h', self._read(BMP280_REGISTER_DIG_P3, 2))[0]
|
||||||
|
self._P4 = unp('<h', self._read(BMP280_REGISTER_DIG_P4, 2))[0]
|
||||||
|
self._P5 = unp('<h', self._read(BMP280_REGISTER_DIG_P5, 2))[0]
|
||||||
|
self._P6 = unp('<h', self._read(BMP280_REGISTER_DIG_P6, 2))[0]
|
||||||
|
self._P7 = unp('<h', self._read(BMP280_REGISTER_DIG_P7, 2))[0]
|
||||||
|
self._P8 = unp('<h', self._read(BMP280_REGISTER_DIG_P8, 2))[0]
|
||||||
|
self._P9 = unp('<h', self._read(BMP280_REGISTER_DIG_P9, 2))[0]
|
||||||
|
|
||||||
|
self._t_os = BMP280_TEMP_OS_2 # temperature oversampling
|
||||||
|
self._p_os = BMP280_PRES_OS_16 # pressure oversampling
|
||||||
|
# output raw
|
||||||
|
self._t_raw = 0
|
||||||
|
self._t_fine = 0
|
||||||
|
self._t = 0
|
||||||
|
self._p_raw = 0
|
||||||
|
self._p = 0
|
||||||
|
self._read_wait_ms = 100 # interval between forced measure and readout
|
||||||
|
self._new_read_ms = 200 # interval between
|
||||||
|
self._last_read_ts = 0
|
||||||
|
|
||||||
|
def _read(self, addr, size=1):
|
||||||
|
return self._bmp_i2c.readfrom_mem(self._i2c_addr, addr, size)
|
||||||
|
|
||||||
|
def _write(self, addr, b_arr):
|
||||||
|
if not type(b_arr) is bytearray:
|
||||||
|
b_arr = bytearray([b_arr])
|
||||||
|
return self._bmp_i2c.writeto_mem(self._i2c_addr, addr, b_arr)
|
||||||
|
|
||||||
|
def _gauge(self):
|
||||||
|
# TODO limit new reads
|
||||||
|
now = utime.ticks_ms()
|
||||||
|
if utime.ticks_diff(now, self._last_read_ts) > self._new_read_ms:
|
||||||
|
self._last_read_ts = now
|
||||||
|
r = self._t_os + (self._p_os << 3) + (1 << 6)
|
||||||
|
self._write(BMP280_REGISTER_CONTROL, r)
|
||||||
|
utime.sleep_ms(100) # TODO calc sleep
|
||||||
|
d = self._read(BMP280_REGISTER_DATA, 6) # read all data at once (as by spec)
|
||||||
|
self._p_raw = (d[0] << 12) + (d[1] << 4) + (d[2] >> 4)
|
||||||
|
self._t_raw = (d[3] << 12) + (d[4] << 4) + (d[5] >> 4)
|
||||||
|
self._t_fine = 0
|
||||||
|
self._t = 0
|
||||||
|
self._p = 0
|
||||||
|
|
||||||
|
def load_test_calibration(self):
|
||||||
|
self._T1 = 27504
|
||||||
|
self._T2 = 26435
|
||||||
|
self._T3 = -1000
|
||||||
|
self._P1 = 36477
|
||||||
|
self._P2 = -10685
|
||||||
|
self._P3 = 3024
|
||||||
|
self._P4 = 2855
|
||||||
|
self._P5 = 140
|
||||||
|
self._P6 = -7
|
||||||
|
self._P7 = 15500
|
||||||
|
self._P8 = -14600
|
||||||
|
self._P9 = 6000
|
||||||
|
|
||||||
|
def load_test_data(self):
|
||||||
|
self._t_raw = 519888
|
||||||
|
self._p_raw = 415148
|
||||||
|
|
||||||
|
def print_calibration(self):
|
||||||
|
print("T1: {} {}".format(self._T1, type(self._T1)))
|
||||||
|
print("T2: {} {}".format(self._T2, type(self._T2)))
|
||||||
|
print("T3: {} {}".format(self._T3, type(self._T3)))
|
||||||
|
print("P1: {} {}".format(self._P1, type(self._P1)))
|
||||||
|
print("P2: {} {}".format(self._P2, type(self._P2)))
|
||||||
|
print("P3: {} {}".format(self._P3, type(self._P3)))
|
||||||
|
print("P4: {} {}".format(self._P4, type(self._P4)))
|
||||||
|
print("P5: {} {}".format(self._P5, type(self._P5)))
|
||||||
|
print("P6: {} {}".format(self._P6, type(self._P6)))
|
||||||
|
print("P7: {} {}".format(self._P7, type(self._P7)))
|
||||||
|
print("P8: {} {}".format(self._P8, type(self._P8)))
|
||||||
|
print("P9: {} {}".format(self._P9, type(self._P9)))
|
||||||
|
|
||||||
|
def _calc_t_fine(self):
|
||||||
|
# From datasheet page 22
|
||||||
|
self._gauge()
|
||||||
|
if self._t_fine == 0:
|
||||||
|
var1 = (((self._t_raw >> 3) - (self._T1 << 1)) * self._T2) >> 11
|
||||||
|
var2 = (((((self._t_raw >> 4) - self._T1) * ((self._t_raw >> 4) - self._T1)) >> 12) * self._T3) >> 14
|
||||||
|
self._t_fine = var1 + var2
|
||||||
|
|
||||||
|
# @property
|
||||||
|
def get_BMP_temperature(self):
|
||||||
|
self._calc_t_fine()
|
||||||
|
if self._t == 0:
|
||||||
|
self._t = ((self._t_fine * 5 + 128) >> 8) / 100.
|
||||||
|
return self._t
|
||||||
|
|
||||||
|
# @property
|
||||||
|
def get_BMP_pressure(self):
|
||||||
|
# From datasheet page 22
|
||||||
|
self._calc_t_fine()
|
||||||
|
if self._p == 0:
|
||||||
|
var1 = self._t_fine - 128000
|
||||||
|
var2 = var1 * var1 * self._P6
|
||||||
|
var2 = var2 + ((var1 * self._P5) << 17)
|
||||||
|
var2 = var2 + (self._P4 << 35)
|
||||||
|
var1 = ((var1 * var1 * self._P3) >> 8) + ((var1 * self._P2) << 12)
|
||||||
|
var1 = (((1 << 47) + var1) * self._P1) >> 33
|
||||||
|
|
||||||
|
if var1 == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
p = 1048576 - self._p_raw
|
||||||
|
p = int((((p << 31) - var2) * 3125) / var1)
|
||||||
|
var1 = (self._P9 * (p >> 13) * (p >> 13)) >> 25
|
||||||
|
var2 = (self._P8 * p) >> 19
|
||||||
|
|
||||||
|
p = ((p + var1 + var2) >> 8) + (self._P7 << 4)
|
||||||
|
self._p = p / 256.0
|
||||||
|
return self._p
|
||||||
117
mixly/boards/default/micropython/build/lib/cbr817.py
Normal file
117
mixly/boards/default/micropython/build/lib/cbr817.py
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
"""
|
||||||
|
CBR817
|
||||||
|
|
||||||
|
MicroPython library for the CBR817 (Microwave radar sensor)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from machine import Pin
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
CBR_ADDRESS = const(0x71)
|
||||||
|
CBR_OP_SET = const(0x02)
|
||||||
|
CBR_TX_RF = const(0x03)
|
||||||
|
CBR_POWER = const(0x04)
|
||||||
|
CBR_LIGHT = const(0x0B)
|
||||||
|
CBR_REG_CTR1 = const(0X13)
|
||||||
|
CBR_SENSOR_THR = const(0X18)
|
||||||
|
CBR_NOISE_THR = const(0X1A)
|
||||||
|
CBR_TRIGER = const(0x1C)
|
||||||
|
CBR_DELAY_TIM = const(0X1D)
|
||||||
|
CBR_LOCK_TIM = const(0X20)
|
||||||
|
CBR_SEL_REG = const(0x23)
|
||||||
|
CBR_REG_CTR2 = const(0X24)
|
||||||
|
CBR_FILTER = const(0x2A)
|
||||||
|
CBR_RESULT = const(0x81)
|
||||||
|
|
||||||
|
class CBR817:
|
||||||
|
def __init__(self, i2c_bus, addr=CBR_ADDRESS, tx_power=3, threshold=5000, noise=256, delay=500, lock=500):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
|
||||||
|
self._configure()
|
||||||
|
self.tx_power(tx_power)
|
||||||
|
self.threshold(threshold)
|
||||||
|
self.noise(noise)
|
||||||
|
self.delay_ms(delay)
|
||||||
|
self.lock_ms(lock)
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address, reg, val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg, nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes <= 1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _wake(self):
|
||||||
|
'''Wake up from low power consumption'''
|
||||||
|
try:
|
||||||
|
self._wreg(CBR_SEL_REG, 0xC0)
|
||||||
|
except :
|
||||||
|
pass
|
||||||
|
|
||||||
|
def threshold(self, value=None):
|
||||||
|
self._wake()
|
||||||
|
if value is None:
|
||||||
|
return self._rreg(CBR_SENSOR_THR) | self._rreg(CBR_SENSOR_THR + 1) << 8
|
||||||
|
else:
|
||||||
|
self._wreg(CBR_SENSOR_THR, value & 0xFF)
|
||||||
|
self._wreg(CBR_SENSOR_THR + 1, (value >> 8) & 0xFF)
|
||||||
|
|
||||||
|
def noise(self, value=None):
|
||||||
|
self._wake()
|
||||||
|
if value is None:
|
||||||
|
return self._rreg(CBR_NOISE_THR) | self._rreg(CBR_NOISE_THR + 1) << 8
|
||||||
|
else:
|
||||||
|
self._wreg(CBR_NOISE_THR, value & 0xFF)
|
||||||
|
self._wreg(CBR_NOISE_THR + 1, (value >> 8) & 0xFF)
|
||||||
|
|
||||||
|
def delay_ms(self, value=None):
|
||||||
|
self._wake()
|
||||||
|
if value is None:
|
||||||
|
return round((self._rreg(CBR_DELAY_TIM) | self._rreg(CBR_DELAY_TIM + 1) << 8 | self._rreg(CBR_DELAY_TIM + 2) << 16) / 32)
|
||||||
|
else:
|
||||||
|
value = value * 32
|
||||||
|
self._wreg(CBR_DELAY_TIM, value & 0xFF)
|
||||||
|
self._wreg(CBR_DELAY_TIM + 1, (value >> 8) & 0xFF)
|
||||||
|
self._wreg(CBR_DELAY_TIM + 2, (value >> 16) & 0xFF)
|
||||||
|
|
||||||
|
def lock_ms(self, value=None):
|
||||||
|
self._wake()
|
||||||
|
if value is None:
|
||||||
|
return round((self._rreg(CBR_LOCK_TIM) | self._rreg(CBR_LOCK_TIM + 1) << 8 | self._rreg(CBR_LOCK_TIM + 2) << 16) // 32)
|
||||||
|
else:
|
||||||
|
value = value * 32
|
||||||
|
self._wreg(CBR_LOCK_TIM, value & 0xFF)
|
||||||
|
self._wreg(CBR_LOCK_TIM + 1, (value >> 8) & 0xFF)
|
||||||
|
self._wreg(CBR_LOCK_TIM + 2, (value >> 16) & 0xFF)
|
||||||
|
|
||||||
|
def tx_power(self, value=None):
|
||||||
|
self._wake()
|
||||||
|
if value is None:
|
||||||
|
return self._rreg(CBR_TX_RF) & 0x07
|
||||||
|
else:
|
||||||
|
self._wreg(CBR_TX_RF, (value & 0x07) | 0x30)
|
||||||
|
|
||||||
|
def _configure(self):
|
||||||
|
self._wake()
|
||||||
|
self._wreg(CBR_SEL_REG, 0xC0) #唤醒射频芯片
|
||||||
|
_star = time.ticks_ms()
|
||||||
|
while self._rreg(CBR_SEL_REG) != 0xC0:
|
||||||
|
self._wreg(CBR_SEL_REG, 0xC0)
|
||||||
|
time.sleep_us(10)
|
||||||
|
if time.ticks_diff(time.ticks_ms(), _star) >= 200:
|
||||||
|
raise AttributeError("Cannot find a CBR817")
|
||||||
|
self._wreg(CBR_TRIGER, 0x55) #连续检测
|
||||||
|
self._wreg(CBR_LIGHT, 0x12) #关闭光敏
|
||||||
|
self._wreg(CBR_POWER, 0xA0) #功耗全供电
|
||||||
|
self._wreg(CBR_FILTER, 0x0F) #打开滤波器
|
||||||
|
self._wreg(CBR_OP_SET, 0x5C) #单运放,0.5uA电流
|
||||||
|
self._wreg(CBR_REG_CTR1, 0X61) #感应门限和噪声门限改寄存器控制
|
||||||
|
self._wreg(CBR_REG_CTR2, 0X60) #延时时间和闭锁时间改寄存器控制
|
||||||
|
|
||||||
|
def result(self):
|
||||||
|
self._wake()
|
||||||
|
return bool(self._rreg(CBR_RESULT) & 0x20)
|
||||||
85
mixly/boards/default/micropython/build/lib/cc_g1.py
Normal file
85
mixly/boards/default/micropython/build/lib/cc_g1.py
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
"""
|
||||||
|
CC_G1
|
||||||
|
|
||||||
|
Micropython library for the CC_G1(Remote control handle)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20231222
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from micropython import const
|
||||||
|
from machine import Pin,SoftI2C
|
||||||
|
|
||||||
|
_CC_G1_ADDRESS = const(0x27)
|
||||||
|
_CC_G1_ID = const(0x00)
|
||||||
|
_CC_G1_VBAT = const(0x01)
|
||||||
|
_CC_G1_ADC = const(0x03)
|
||||||
|
_CC_G1_KEY = const(0x07)
|
||||||
|
|
||||||
|
class Handle:
|
||||||
|
def __init__(self, i2c_bus, addr=_CC_G1_ADDRESS):
|
||||||
|
self._i2c=i2c_bus
|
||||||
|
self._addr = addr
|
||||||
|
if self._rreg(_CC_G1_ID)!= 0x27:
|
||||||
|
raise AttributeError("Cannot find a CC_G1")
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
try:
|
||||||
|
self._i2c.writeto_mem(self._addr, reg, val.to_bytes(1, 'little'))
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def _rreg(self, reg, nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
try:
|
||||||
|
self._i2c.writeto(self._addr, reg.to_bytes(1, 'little'))
|
||||||
|
return self._i2c.readfrom(self._addr, nbytes)[0] if nbytes<=1 else self._i2c.readfrom(self._addr, nbytes)[0:nbytes]
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def read_bat(self, ratio=5/1023):
|
||||||
|
'''Read battery power'''
|
||||||
|
vbat = self._rreg(_CC_G1_VBAT)<<2 | self._rreg(_CC_G1_VBAT+1)>>6
|
||||||
|
return round(vbat*ratio, 2)
|
||||||
|
|
||||||
|
def read_joystick(self, ratio=100/1023):
|
||||||
|
'''Read joystick'''
|
||||||
|
y_axis = 1023 - (self._rreg(_CC_G1_ADC) << 2 | self._rreg(_CC_G1_ADC + 1) >> 6)
|
||||||
|
x_axis = self._rreg(_CC_G1_ADC + 2 ) << 2 | self._rreg(_CC_G1_ADC + 3) >> 6
|
||||||
|
return round(x_axis*ratio), round(y_axis*ratio)
|
||||||
|
|
||||||
|
def read_key(self, index):
|
||||||
|
'''Read key1~6'''
|
||||||
|
if not 0 <= index <= 5:
|
||||||
|
raise ValueError("The key number must be a number in the range: 0~5")
|
||||||
|
if index<=4:
|
||||||
|
return bool(self._rreg(_CC_G1_KEY) >> index & 0x01)
|
||||||
|
else:
|
||||||
|
return bool(self._rreg(_CC_G1_KEY) >> 7 & 0x01)
|
||||||
|
|
||||||
|
def shutdown(self, flag=True):
|
||||||
|
"""This function is only available on battery power"""
|
||||||
|
if flag:
|
||||||
|
self._wreg(_CC_G1_KEY, (self._rreg(_CC_G1_KEY)) & 0XBF)
|
||||||
|
else:
|
||||||
|
self._wreg(_CC_G1_KEY, (self._rreg(_CC_G1_KEY)) | 0X40)
|
||||||
|
|
||||||
|
'''Select instantiation objects'''
|
||||||
|
try:
|
||||||
|
#MixGo CC/ME
|
||||||
|
ext_i2c = SoftI2C(scl=Pin(0), sda=Pin(1), freq=100000)
|
||||||
|
handle = Handle(ext_i2c)
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
#MixGo CE
|
||||||
|
ext_i2c = SoftI2C(scl=Pin(17), sda=Pin(18), freq=100000)
|
||||||
|
handle = Handle(ext_i2c)
|
||||||
|
except:
|
||||||
|
try:
|
||||||
|
#MixGo Mini
|
||||||
|
ext_i2c = SoftI2C(scl=Pin(8), sda=Pin(7), freq=100000)
|
||||||
|
handle = Handle(ext_i2c)
|
||||||
|
except:
|
||||||
|
print("MixGo board cannot find a CC_G1")
|
||||||
147
mixly/boards/default/micropython/build/lib/ch914x_at.py
Normal file
147
mixly/boards/default/micropython/build/lib/ch914x_at.py
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
"""
|
||||||
|
Bluetooth AT
|
||||||
|
|
||||||
|
Micropython library for the Bluetooth AT(WCH)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20230106
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from machine import Pin
|
||||||
|
from time import sleep_ms
|
||||||
|
|
||||||
|
class AT:
|
||||||
|
def __init__(self, pin,times=5):
|
||||||
|
self.at_pin = Pin(pin, Pin.OUT)
|
||||||
|
self.at_pin.value(1)
|
||||||
|
self._times = times
|
||||||
|
self._flag = [0,0,0,0,0,0,0,0] #mac0,1 name2,3 power4,5 power6,7
|
||||||
|
self._power = [0,1,2,3,-3,-8,-14,-20]
|
||||||
|
sleep_ms(100)
|
||||||
|
|
||||||
|
def _str_reverse(self,data):
|
||||||
|
data=data.split(':')
|
||||||
|
data.reverse()
|
||||||
|
data=":".join(data)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def ble_mac(self, mac=None):
|
||||||
|
sleep_ms(200)
|
||||||
|
if mac is None:
|
||||||
|
if not (self._flag[0] >= self._times and self._times != 0):
|
||||||
|
self._flag[0]+=1
|
||||||
|
self.at_pin.value(0)
|
||||||
|
sleep_ms(10)
|
||||||
|
data=input('AT+MAC?\r\n')
|
||||||
|
input()
|
||||||
|
self.at_pin.value(1)
|
||||||
|
print('BLE_MAC:',self._str_reverse(data))
|
||||||
|
sleep_ms(100)
|
||||||
|
return self._str_reverse(data)
|
||||||
|
else:
|
||||||
|
print('Please delete this command and upload other programs again')
|
||||||
|
else:
|
||||||
|
if not (self._flag[1] >= self._times and self._times != 0):
|
||||||
|
self._flag[1]+=1
|
||||||
|
self.at_pin.value(0)
|
||||||
|
sleep_ms(10)
|
||||||
|
data=input('AT+MAC={}\r\n'.format(self._str_reverse(mac)))
|
||||||
|
print('\r\n')
|
||||||
|
self.at_pin.value(1)
|
||||||
|
print('BLE_MAC:',mac,data)
|
||||||
|
sleep_ms(100)
|
||||||
|
return True if data is "OK" else False
|
||||||
|
else:
|
||||||
|
print('Please delete this command and upload other programs again')
|
||||||
|
|
||||||
|
def ble_name(self, name=None):
|
||||||
|
sleep_ms(200)
|
||||||
|
if name is None:
|
||||||
|
if not (self._flag[2] >= self._times and self._times != 0):
|
||||||
|
self._flag[2]+=1
|
||||||
|
self.at_pin.value(0)
|
||||||
|
sleep_ms(10)
|
||||||
|
data=input('AT+NAME?\r\n')
|
||||||
|
input()
|
||||||
|
input()
|
||||||
|
self.at_pin.value(1)
|
||||||
|
print('BLE_NAME:',data)
|
||||||
|
sleep_ms(100)
|
||||||
|
return data
|
||||||
|
else:
|
||||||
|
print('Please delete this command and upload other programs again')
|
||||||
|
else:
|
||||||
|
if not (self._flag[3] >= self._times and self._times != 0):
|
||||||
|
self._flag[3]+=1
|
||||||
|
self.at_pin.value(0)
|
||||||
|
sleep_ms(10)
|
||||||
|
data=input('AT+NAME='+name+'\r\n')
|
||||||
|
print('\r\n')
|
||||||
|
self.at_pin.value(1)
|
||||||
|
print('BLE_NAME:',name,data)
|
||||||
|
sleep_ms(100)
|
||||||
|
return True if data is "OK" else False
|
||||||
|
else:
|
||||||
|
print('Please delete this command and upload other programs again')
|
||||||
|
|
||||||
|
def ble_power(self, power=None):
|
||||||
|
sleep_ms(200)
|
||||||
|
if power is None:
|
||||||
|
if not (self._flag[4] >= self._times and self._times != 0):
|
||||||
|
self._flag[4]+=1
|
||||||
|
self.at_pin.value(0)
|
||||||
|
sleep_ms(10)
|
||||||
|
data=input('AT+TPL?\r\n')
|
||||||
|
input()
|
||||||
|
print(' \r\n')
|
||||||
|
self.at_pin.value(1)
|
||||||
|
data=self._power[int(data[4:])]
|
||||||
|
print('BLE_Power: {}DB'.format(data))
|
||||||
|
sleep_ms(100)
|
||||||
|
return data
|
||||||
|
else:
|
||||||
|
print('Please delete this command and upload other programs again')
|
||||||
|
else:
|
||||||
|
if not (self._flag[5] >= self._times and self._times != 0):
|
||||||
|
self._flag[5]+=1
|
||||||
|
self.at_pin.value(0)
|
||||||
|
sleep_ms(10)
|
||||||
|
data=input('AT+TPL={}\r\n'.format(self._power.index(power)))
|
||||||
|
print('\r\n')
|
||||||
|
self.at_pin.value(1)
|
||||||
|
print('BLE_Power:',str(power)+'DB',data)
|
||||||
|
sleep_ms(100)
|
||||||
|
return True if data is "OK" else False
|
||||||
|
else:
|
||||||
|
print('Please delete this command and upload other programs again')
|
||||||
|
|
||||||
|
def ble_pname(self, name=None):
|
||||||
|
sleep_ms(200)
|
||||||
|
if name is None:
|
||||||
|
if not (self._flag[6] >= self._times and self._times != 0):
|
||||||
|
self._flag[6]+=1
|
||||||
|
self.at_pin.value(0)
|
||||||
|
sleep_ms(10)
|
||||||
|
data=input('AT+PNAME?\r\n')
|
||||||
|
input()
|
||||||
|
input()
|
||||||
|
self.at_pin.value(1)
|
||||||
|
print('BLE_PNAME:',data)
|
||||||
|
sleep_ms(100)
|
||||||
|
return data
|
||||||
|
else:
|
||||||
|
print('Please delete this command and upload other programs again')
|
||||||
|
else:
|
||||||
|
if not (self._flag[7] >= self._times and self._times != 0):
|
||||||
|
self._flag[7]+=1
|
||||||
|
self.at_pin.value(0)
|
||||||
|
sleep_ms(10)
|
||||||
|
data=input('AT+PNAME='+name+'\r\n')
|
||||||
|
print('\r\n')
|
||||||
|
self.at_pin.value(1)
|
||||||
|
print('BLE_PNAME:',name,data)
|
||||||
|
sleep_ms(100)
|
||||||
|
return True if data is "OK" else False
|
||||||
|
else:
|
||||||
|
print('Please delete this command and upload other programs again')
|
||||||
129
mixly/boards/default/micropython/build/lib/ci130x.py
Normal file
129
mixly/boards/default/micropython/build/lib/ci130x.py
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
"""
|
||||||
|
CI130X
|
||||||
|
|
||||||
|
MicroPython library for the CI130X (ASR-I2C)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from struct import pack
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_CI_ADDRESS = const(0x64)
|
||||||
|
_CI_ID_GET = const(0x02)
|
||||||
|
_CI_ID_SET = const(0x03)
|
||||||
|
_CI_ID_NUM = const(0x06)
|
||||||
|
_CI_ID_CLE = const(0x07)
|
||||||
|
_CI_ID_PACTRL = const(0x09)
|
||||||
|
_CI_ID_ASREN = const(0x0A)
|
||||||
|
_CI_ID_END = const(0x5A)
|
||||||
|
_TIME_SNUM = const(0x75)
|
||||||
|
|
||||||
|
class CI130X:
|
||||||
|
def __init__(self, i2c_bus, addr=_CI_ADDRESS):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
self._cmd_id = None
|
||||||
|
self._enable = True
|
||||||
|
try:
|
||||||
|
self._rreg(_CI_ID_GET, 3)
|
||||||
|
except:
|
||||||
|
try: #C130X 启动慢,加延时判断
|
||||||
|
time.sleep_ms(850)
|
||||||
|
self._rreg(_CI_ID_GET, 3)
|
||||||
|
except:
|
||||||
|
raise AttributeError("Cannot find a CI130X")
|
||||||
|
|
||||||
|
def _wreg(self, reg):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto(self._address, reg)
|
||||||
|
|
||||||
|
def _rreg(self, reg, nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)
|
||||||
|
|
||||||
|
def status(self):
|
||||||
|
"""返回 (是否唤醒, 是否播放)"""
|
||||||
|
_buf = self._rreg(_CI_ID_GET, 3)
|
||||||
|
return (bool(_buf[1] & 0x01), bool(_buf[1] & 0x10)) if _buf[2] == _CI_ID_END else (None, None)
|
||||||
|
|
||||||
|
def cmd_id(self, repeat=False):
|
||||||
|
"""返回 识别命令词对应ID"""
|
||||||
|
_buf = self._rreg(_CI_ID_GET, 3)
|
||||||
|
if not repeat:
|
||||||
|
self._wreg(bytes([_CI_ID_CLE, 0, 0, _CI_ID_END]))
|
||||||
|
time.sleep_ms(50)
|
||||||
|
self._cmd_id = _buf[0] if _buf[2] == _CI_ID_END else None
|
||||||
|
return self._cmd_id
|
||||||
|
|
||||||
|
def result(self, ext_id=None):
|
||||||
|
"""获取比较结果 或者输出结果"""
|
||||||
|
return self._cmd_id if ext_id is None else bool(self._cmd_id == ext_id)
|
||||||
|
|
||||||
|
def sys_cmd(self, value, blocking=True):
|
||||||
|
"""系统命令,1,2唤醒 202~205音量调整 206,207回复播报开关 208退出唤醒"""
|
||||||
|
self.play_id(value, blocking)
|
||||||
|
|
||||||
|
def play_id(self, value, blocking=True):
|
||||||
|
"""播放命令词对应ID语音"""
|
||||||
|
self._wreg(bytes([_CI_ID_SET, value, 0, _CI_ID_END]))
|
||||||
|
while blocking:
|
||||||
|
time.sleep_ms(15)
|
||||||
|
if not self.status()[1]:
|
||||||
|
break
|
||||||
|
|
||||||
|
def play_num(self, value, blocking=True):
|
||||||
|
"""播放浮点数据的合成语音"""
|
||||||
|
self._wreg(bytes([_CI_ID_NUM]) + pack('d', float(value)) + bytes([0, _CI_ID_END]))
|
||||||
|
while blocking:
|
||||||
|
time.sleep_ms(10)
|
||||||
|
if not self.status()[1]:
|
||||||
|
break
|
||||||
|
|
||||||
|
def play(self, star=None, num=None, end=None, delay=10):
|
||||||
|
"""组合播报名词+数值+单位"""
|
||||||
|
if star is not None:
|
||||||
|
self.play_id(star)
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
if num is not None:
|
||||||
|
self.play_num(num)
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
if end is not None:
|
||||||
|
self.play_id(end)
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
|
||||||
|
def play_time(self, times=None, detail=True, delay=10):
|
||||||
|
"""播报时间"""
|
||||||
|
data = time.localtime() if times is None else times
|
||||||
|
if detail:
|
||||||
|
for i in range(0, 3): #年 月 日
|
||||||
|
self.play_num(data[i])
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
self.play_id(_TIME_SNUM + i)
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
|
||||||
|
for i in range(3, 5): #时 分
|
||||||
|
self.play_num(data[i])
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
self.play_id(_TIME_SNUM + i)
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
|
||||||
|
if detail:
|
||||||
|
self.play_num(data[5]) #秒
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
self.play_id(_TIME_SNUM + 5)
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
self.play_id(_TIME_SNUM + 6) #星期
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
self.play_num(data[6] + 1)
|
||||||
|
|
||||||
|
def pa_ctrl(self, value=True, delay=10):
|
||||||
|
self._wreg(bytes([_CI_ID_PACTRL, int(value), 0, _CI_ID_END]))
|
||||||
|
if value: time.sleep_ms(delay)
|
||||||
|
|
||||||
|
def asr_en(self, value=None):
|
||||||
|
if value is None:
|
||||||
|
return self._enable
|
||||||
|
else:
|
||||||
|
self._enable = bool(value)
|
||||||
|
self._wreg(bytes([_CI_ID_ASREN, self._enable, 0, _CI_ID_END]))
|
||||||
166
mixly/boards/default/micropython/build/lib/debugnet.py
Normal file
166
mixly/boards/default/micropython/build/lib/debugnet.py
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
"""
|
||||||
|
Debugnet(HTTP,MQTT)
|
||||||
|
|
||||||
|
MicroPython library for network request debugging
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20230225
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from umqtt import MQTTClient
|
||||||
|
from ubinascii import hexlify
|
||||||
|
from machine import unique_id
|
||||||
|
from urequests import Response
|
||||||
|
from usocket import socket,getaddrinfo,SOCK_STREAM
|
||||||
|
from mixiot import WILL_TOPIC,ADDITIONAL_TOPIC
|
||||||
|
|
||||||
|
class socket_d(socket):
|
||||||
|
def __init__(self,*args,debug=False,**kw):
|
||||||
|
super().__init__(*args,**kw)
|
||||||
|
self._debug=debug
|
||||||
|
self.client_len=0
|
||||||
|
self.server_len=0
|
||||||
|
|
||||||
|
def write(self,*args):
|
||||||
|
super().write(*args)
|
||||||
|
self.client_len=min(self.client_len+len(args[0]),65535)
|
||||||
|
if self._debug:
|
||||||
|
print('client:',args[0])
|
||||||
|
|
||||||
|
def readline(self,*args):
|
||||||
|
buf=super().readline(*args)
|
||||||
|
self.server_len=min(self.server_len+len(buf),65535) if buf else self.server_len
|
||||||
|
if self._debug:
|
||||||
|
print('server:',buf)
|
||||||
|
return buf
|
||||||
|
|
||||||
|
def read(self,*args):
|
||||||
|
buf=super().read(*args)
|
||||||
|
self.server_len=min(self.server_len+len(buf),65535) if buf else self.server_len
|
||||||
|
if self._debug:
|
||||||
|
print('server:',buf)
|
||||||
|
return buf
|
||||||
|
|
||||||
|
#HTTP
|
||||||
|
def request(method, url, data=None, json=None, headers={}, stream=None, parse_headers=True, debug=False):
|
||||||
|
redir_cnt = 1
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
proto, dummy, host, path = url.split("/", 3)
|
||||||
|
except ValueError:
|
||||||
|
proto, dummy, host = url.split("/", 2)
|
||||||
|
path = ""
|
||||||
|
if proto == "http:":
|
||||||
|
port = 80
|
||||||
|
elif proto == "https:":
|
||||||
|
import ussl
|
||||||
|
port = 443
|
||||||
|
else:
|
||||||
|
raise ValueError("Unsupported protocol: " + proto)
|
||||||
|
if ":" in host:
|
||||||
|
host, port = host.split(":", 1)
|
||||||
|
port = int(port)
|
||||||
|
ai = getaddrinfo(host, port, 0, SOCK_STREAM)
|
||||||
|
ai = ai[0]
|
||||||
|
resp_d = None
|
||||||
|
if parse_headers is not False:
|
||||||
|
resp_d = {}
|
||||||
|
s = socket_d(ai[0], ai[1], ai[2], debug=debug)
|
||||||
|
try:
|
||||||
|
s.connect(ai[-1])
|
||||||
|
if proto == "https:":
|
||||||
|
s = ussl.wrap_socket(s, server_hostname=host)
|
||||||
|
s.write(b"%s /%s HTTP/1.0\r\n" % (method, path))
|
||||||
|
if not "Host" in headers:
|
||||||
|
s.write(b"Host: %s\r\n" % host)
|
||||||
|
for k in headers:
|
||||||
|
s.write(k)
|
||||||
|
s.write(b": ")
|
||||||
|
s.write(headers[k])
|
||||||
|
s.write(b"\r\n")
|
||||||
|
if json is not None:
|
||||||
|
assert data is None
|
||||||
|
import ujson
|
||||||
|
data = ujson.dumps(json)
|
||||||
|
s.write(b"Content-Type: application/json\r\n")
|
||||||
|
if data:
|
||||||
|
s.write(b"Content-Length: %d\r\n" % len(data))
|
||||||
|
s.write(b"Connection: close\r\n\r\n")
|
||||||
|
if data:
|
||||||
|
s.write(data)
|
||||||
|
l = s.readline()
|
||||||
|
l = l.split(None, 2)
|
||||||
|
status = int(l[1])
|
||||||
|
reason = ""
|
||||||
|
if len(l) > 2:
|
||||||
|
reason = l[2].rstrip()
|
||||||
|
while True:
|
||||||
|
l = s.readline()
|
||||||
|
if not l or l == b"\r\n":
|
||||||
|
break
|
||||||
|
if l.startswith(b"Transfer-Encoding:"):
|
||||||
|
if b"chunked" in l:
|
||||||
|
raise ValueError("Unsupported " + l)
|
||||||
|
elif l.startswith(b"Location:") and 300 <= status <= 399:
|
||||||
|
if not redir_cnt:
|
||||||
|
raise ValueError("Too many redirects")
|
||||||
|
redir_cnt -= 1
|
||||||
|
url = l[9:].decode().strip()
|
||||||
|
status = 300
|
||||||
|
break
|
||||||
|
if parse_headers is False:
|
||||||
|
pass
|
||||||
|
elif parse_headers is True:
|
||||||
|
l = l.decode()
|
||||||
|
k, v = l.split(":", 1)
|
||||||
|
resp_d[k] = v.strip()
|
||||||
|
else:
|
||||||
|
parse_headers(l, resp_d)
|
||||||
|
except OSError:
|
||||||
|
s.close()
|
||||||
|
raise
|
||||||
|
if status != 300:
|
||||||
|
break
|
||||||
|
resp = Response(s)
|
||||||
|
resp.status_code = status
|
||||||
|
resp.reason = reason
|
||||||
|
resp.client_len=s.client_len
|
||||||
|
resp.server_len=s.server_len
|
||||||
|
if resp_d is not None:
|
||||||
|
resp.headers = resp_d
|
||||||
|
return resp
|
||||||
|
|
||||||
|
class MQTT_Client(MQTTClient):
|
||||||
|
def __init__(self,*args,debug=False,**kw):
|
||||||
|
super().__init__(*args,**kw)
|
||||||
|
self.sock = socket_d(debug=debug)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def client_len(self): #The length of client data obtained
|
||||||
|
_len=self.sock.client_len
|
||||||
|
self.sock.client_len=0
|
||||||
|
return _len
|
||||||
|
|
||||||
|
@property
|
||||||
|
def server_len(self): #The length of server data obtained
|
||||||
|
_len=self.sock.server_len
|
||||||
|
self.sock.server_len=0
|
||||||
|
return _len
|
||||||
|
|
||||||
|
def time_msg(self,utc=28800): #Get server time information
|
||||||
|
msg=self.wait_msg()
|
||||||
|
if isinstance(msg, dict):
|
||||||
|
if msg['topic'] =='$SYS/hello':
|
||||||
|
val=time.gmtime(int(msg['msg'])//1000-946684800+utc)[0:7]
|
||||||
|
return str(val).replace(' ','')[1:-1]
|
||||||
|
|
||||||
|
#MQTT
|
||||||
|
def init_MQTT_client(address, username, password, MQTT_USR_PRJ, debug=False):
|
||||||
|
client = MQTT_Client(hexlify(unique_id()), address, 1883, username, password, debug=debug)
|
||||||
|
client.set_last_will(topic=MQTT_USR_PRJ+WILL_TOPIC, msg=client.client_id, qos=2)
|
||||||
|
if client.connect()==0:
|
||||||
|
client.publish(MQTT_USR_PRJ+ADDITIONAL_TOPIC, client.client_id, qos=0)
|
||||||
|
time.sleep_ms(200)
|
||||||
|
return client
|
||||||
60
mixly/boards/default/micropython/build/lib/dhtx.py
Normal file
60
mixly/boards/default/micropython/build/lib/dhtx.py
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# DHT11/DHT22 driver for MicroPython
|
||||||
|
# MIT license; Copyright (c) 2016 Damien P. George
|
||||||
|
|
||||||
|
from time import sleep
|
||||||
|
try:
|
||||||
|
from esp import dht_readinto
|
||||||
|
except:
|
||||||
|
from machine import dht_readinto
|
||||||
|
from machine import Pin
|
||||||
|
|
||||||
|
class DHTBase:
|
||||||
|
__species = {}
|
||||||
|
__first_init = True
|
||||||
|
def __new__(cls, pin, *args, **kwargs):
|
||||||
|
if pin not in cls.__species.keys():
|
||||||
|
cls.__first_init = True
|
||||||
|
cls.__species[pin] = object.__new__(cls)
|
||||||
|
return cls.__species[pin]
|
||||||
|
|
||||||
|
def __init__(self, pin):
|
||||||
|
if self.__first_init:
|
||||||
|
self.__first_init = False
|
||||||
|
self.pin = Pin(pin)
|
||||||
|
self.buf = bytearray(5)
|
||||||
|
self.err = 0
|
||||||
|
|
||||||
|
def measure(self):
|
||||||
|
buf = bytearray(5)
|
||||||
|
try:
|
||||||
|
dht_readinto(self.pin, buf)
|
||||||
|
if (buf[0] + buf[1] + buf[2] + buf[3]) & 0xFF == buf[4]:
|
||||||
|
self.buf = buf
|
||||||
|
self.err = 0
|
||||||
|
except:
|
||||||
|
if self.err > 10:
|
||||||
|
raise AttributeError("DHTx operation error")
|
||||||
|
self.err += 1
|
||||||
|
sleep(0.5)
|
||||||
|
return
|
||||||
|
|
||||||
|
class DHT11(DHTBase):
|
||||||
|
def humidity(self):
|
||||||
|
self.measure()
|
||||||
|
return self.buf[0]
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
self.measure()
|
||||||
|
return self.buf[2]
|
||||||
|
|
||||||
|
class DHT22(DHTBase):
|
||||||
|
def humidity(self):
|
||||||
|
self.measure()
|
||||||
|
return (self.buf[0] << 8 | self.buf[1]) * 0.1
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
self.measure()
|
||||||
|
t = ((self.buf[2] & 0x7F) << 8 | self.buf[3]) * 0.1
|
||||||
|
if self.buf[2] & 0x80:
|
||||||
|
t = -t
|
||||||
|
return t
|
||||||
67
mixly/boards/default/micropython/build/lib/ds18b20.py
Normal file
67
mixly/boards/default/micropython/build/lib/ds18b20.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# DS18x20 temperature sensor driver for MicroPython.
|
||||||
|
# MIT license; Copyright (c) 2016 Damien P. George
|
||||||
|
|
||||||
|
import onewire
|
||||||
|
from machine import Pin
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_CONVERT = const(0x44)
|
||||||
|
_RD_SCRATCH = const(0xBE)
|
||||||
|
_WR_SCRATCH = const(0x4E)
|
||||||
|
|
||||||
|
class DS18X20:
|
||||||
|
__species = {}
|
||||||
|
__first_init = True
|
||||||
|
def __new__(cls, pin, *args, **kwargs):
|
||||||
|
if pin not in cls.__species.keys():
|
||||||
|
cls.__first_init = True
|
||||||
|
cls.__species[pin] = object.__new__(cls)
|
||||||
|
return cls.__species[pin]
|
||||||
|
|
||||||
|
def __init__(self, pin):
|
||||||
|
if self.__first_init:
|
||||||
|
self.__first_init = False
|
||||||
|
self._ow = onewire.OneWire(Pin(pin, pull=Pin.PULL_UP))
|
||||||
|
self._buf = bytearray(9)
|
||||||
|
self._roms = self.scan()
|
||||||
|
if len(self._roms) == 0:
|
||||||
|
raise AttributeError("Cannot find a DS18X20")
|
||||||
|
|
||||||
|
def scan(self):
|
||||||
|
return [rom for rom in self._ow.scan() if rom[0] in (0x10, 0x22, 0x28)]
|
||||||
|
|
||||||
|
def convert_temp(self):
|
||||||
|
self._ow.reset(True)
|
||||||
|
self._ow.writebyte(self._ow.SKIP_ROM)
|
||||||
|
self._ow.writebyte(_CONVERT)
|
||||||
|
|
||||||
|
def read_scratch(self, rom):
|
||||||
|
self._ow.reset(True)
|
||||||
|
self._ow.select_rom(rom)
|
||||||
|
self._ow.writebyte(_RD_SCRATCH)
|
||||||
|
self._ow.readinto(self._buf)
|
||||||
|
if self._ow.crc8(self._buf):
|
||||||
|
raise Exception("CRC error")
|
||||||
|
return self._buf
|
||||||
|
|
||||||
|
def read_temp(self, rom):
|
||||||
|
buf = self.read_scratch(rom)
|
||||||
|
if rom[0] == 0x10:
|
||||||
|
if buf[1]:
|
||||||
|
t = buf[0] >> 1 | 0x80
|
||||||
|
t = -((~t + 1) & 0xFF)
|
||||||
|
else:
|
||||||
|
t = buf[0] >> 1
|
||||||
|
return t - 0.25 + (buf[7] - buf[6]) / buf[7]
|
||||||
|
else:
|
||||||
|
t = buf[1] << 8 | buf[0]
|
||||||
|
if t & 0x8000: # sign bit set
|
||||||
|
t = -((t ^ 0xFFFF) + 1)
|
||||||
|
return t / 16
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
temp = []
|
||||||
|
self.convert_temp()
|
||||||
|
for rom in self._roms:
|
||||||
|
temp.append(round(self.read_temp(rom), 2))
|
||||||
|
return temp [0] if len(temp) == 1 else tuple(temp)
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#Take the picture bytes in expression_picture.py
|
||||||
|
#--dahanzimin From the Mixly Team
|
||||||
|
|
||||||
|
Angry=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xe0\x00\x01\x87\xfc\x00\x00\x7f\x80\x00\x01\xd9\xfe\x00\x00\xff\x00\x00\x07\xfc\xff\x00\x01\xfe\x00\x00\x07\xfe\x7f\x80\x01\xfc\x00\x00\x03\x1c?\x80\x03\xf8\x00\x00\x0f\x18\x1f\xc0\x03\xf0\x00\x00\x0e\xdc\x0f\xc0\x07\xf0\x00\x00\x07\xfc\x0f\xe0\x07\xe0\x00\x00\x07\xf8\x07\xe0\x0f\xc0\x00\x00\x02`\x03\xf0\x0f\xc0\x00\x00\x00 \x03\xf0\x1f\xc0\x00\x00\x00\x00\x03\xf8\x1f\x83\x00\x00\x00\x00\xc1\xf8\x1f\x83\xc0\x00\x00\x03\xc1\xf8\x1f\x03\xf0\x00\x00\x1f\xc1\xf8?\x07\xfe\x00\x00?\xe0\xfc?\x03\xff\x80\x01\xff\xc0\xfc?\x03\xff\xe0\x07\xff\xc0\xfc?\x03\xff\xe0\x03\xff\x80\xfc?\x01\xff\xc0\x03\xff\x80|?\x00\xff\x80\x01\xff\x00\xfc>\x00>\x00\x00|\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf8\x1f\xc0\x00\x00\x00\x00\x03\xf0\x0f\xc0\x00\x00\x00\x00\x07\xf0\x07\xe0\x00\x03\x80\x00\x07\xe0\x07\xf0\x00\x07\xc0\x00\x0f\xe0\x03\xf0\x00\x0f\xf0\x00\x0f\xc0\x03\xf8\x00\x1e\xf8\x00\x1f\xc0\x01\xfc\x00\x1c~\x00?\x80\x01\xfe\x00\x00\x1c\x00\x7f\x80\x00\xff\x00\x00\x04\x00\xff\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x05\xff\xe0\x00\x00\x01\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Bored=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf0\x00\x00\x00\x00\x0f\xc0\x07\xf0\x00\x00\x00\x00\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x03\xf0\x1f\x80\x00\x00\x00\x00\x03\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x83[\x00\x00\xdfA\xf8\x1f\x87\xff\x80\x01\xff\xe0\xf8?\x07\xff\x00\x01\xff\xe0\xfc?\x01}\x00\x00\x8e\x00\xfc?\x000\x00\x00\x0e\x00\xfc?\x00p\x00\x00\x1c\x00\xfc>\x05~\x80\x00_\xc0|?\x07\xff\x80\x01\xff\xe0\xfc?\x07\xff\x80\x01\xff\xe0\xfc>\x02D\x00\x00\xa4\x80|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xfc?\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x07\xf0\x00\x03\xf0\x0f\xe0\x00\x1f\xfc\x00\x07\xf0\x07\xe0\x00?\xfe\x00\x07\xe0\x07\xf0\x00|\x1f\x00\x07\xe0\x03\xf8\x00p\x07\x00\x1f\xc0\x03\xf8\x00\xe0\x07\x80\x1f\xc0\x01\xfc\x00s\xe3\x80?\x80\x00\xfe\x00c\xf3\x00\x7f\x00\x00\xff\x00\x03\xe0\x00\xff\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf0\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xfa\xbf\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfe\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x01\xff\xff\xc0\x00\x00\x00\x00\x00_\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Confused=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x06\x00\x00\x00\x1f\xc0\x03\xf0\x0f\x00\x01\xfc\x1f\xc0\x07\xf0\x1f\x00\x01\xff\x0f\xe0\x07\xe0?\x00\x01\xff\x87\xe0\x0f\xc0~\x00\x00\xff\xc7\xf0\x0f\xdf\xfc\x00\x00\x07\xe3\xf0\x1f\xdf\xf8\x00\x00\x01\xf3\xf8\x1f\x9f\xe0\x00\x00\x00\xf1\xf8\x1f\x8f(\x00\x00\x18\xe1\xf8\x1f\x00~\x00\x00~!\xf8?\x00\xff\x00\x00\xfe\x00\xfc?\x00\xff\x80\x00\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc?\x00\xff\x00\x01\xff\x00\xfc?\x00\xff\x80\x00\xff\x00\xfc?\x00~\x00\x00\xfe\x00\xfc>\x00>\x00\x00|\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xf8?\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x03\xf0\x0f\xe0\x00\x00\x00\x00\x03\xf0\x07\xe0\x00\x00\x00\x00\x07\xe0\x07\xf0\x00\x1f\x80\x00\x0f\xe0\x03\xf0\x00?\xc0\x00\x0f\xc0\x03\xf8\x00?\xc7\x00\x1f\xc0\x01\xfc\x009\xe7\x00?\x80\x00\xfe\x001\xe7\x00\x7f\x80\x00\xff\x000\xfe\x00\xff\x00\x00\x7f\xc0\x00~\x03\xfe\x00\x00?\xe0\x00<\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xfe\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf8\x00\x00\x00\x00\x01\xff\xff\x80\x00\x00\x00\x00\x00?\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Happy=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xff\x7f\xff\xc0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x0f\xfc\x00\x00?\xf0\x00\x00\x1f\xf0\x00\x00\x1f\xf8\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xfe\x00\x00\x00\x00\x7f\x00\x03\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf8\x00\x00\x00\x00\x0f\xc0\x07\xe0\x00\x00\x00\x00\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x03\xf0\x1f\xc0\x00\x00\x00\x00\x03\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x14\x00\x008\x01\xf8\x1f\x00~\x00\x00~\x00\xf8?\x00\xff\x00\x00\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc?\x00\xff\x00\x01\xff\x00\xfc?\x00\xff\x80\x00\xff\x00\xfc?\x00\xff\x00\x00\xff\x00\xfc?\x00\x7f\x00\x00\xfe\x00|>\x00<\x00\x00|\x00\xfc?\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xf8?\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\xc0\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x03\xf0\x0f\xe0\x02\xfa\xd5\x80\x07\xf0\x07\xe0\x03\xff\xff\xc0\x07\xe0\x07\xf0\x07\xff\xff\xe0\x0f\xe0\x03\xf8\x03\xff\xff\xc0\x0f\xc0\x03\xf8\x03\xff\xff\xc0\x1f\xc0\x01\xfc\x01\xff\xff\x80?\x80\x01\xfe\x01\xff\xff\x80\x7f\x80\x00\xff\x00\xff\xff\x00\xff\x00\x00\x7f\x80\x7f\xfe\x03\xfe\x00\x00?\xe0?\xfc\x07\xfc\x00\x00\x1f\xf0\x07\xf0\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xfe\xbf\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x01\xff\xff\xc0\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Heart=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\xfe\x00\x00\x7f\xc0\x00\x00\x1f\xff\xc0\x03\xff\xf8\x00\x00\x7f\xff\xf0\x0f\xff\xfe\x00\x00\xff\xff\xf8\x1f\xff\xff\x00\x01\xff\xff\xfe\x7f\xff\xff\x80\x03\xff\xff\xff\x7f\xff\xff\xc0\x07\xff\xff\xff\xff\xff\xff\xe0\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x1f\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xf8?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xfc\x1f\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xff\xff\xff\xf8\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xc0\x03\xff\xff\xff\xff\xff\xff\xc0\x01\xff\xff\xff\xff\xff\xff\x80\x00\xff\xff\xff\xff\xff\xff\x80\x00\xff\xff\xff\xff\xff\xff\x00\x00\x7f\xff\xff\xff\xff\xfe\x00\x00?\xff\xff\xff\xff\xfc\x00\x00\x1f\xff\xff\xff\xff\xf8\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x01\xff\xff\xff\xff\xc0\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x7f\xff\xff\xfe\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x1f\xff\xff\xf8\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x07\xff\xff\xe0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x01\xff\xff\x80\x00\x00\x00\x00\x00\xff\xfe\x00\x00\x00\x00\x00\x00?\xfe\x00\x00\x00\x00\x00\x00\x1f\xf8\x00\x00\x00\x00\x00\x00\x0f\xf0\x00\x00\x00\x00\x00\x00\x07\xe0\x00\x00\x00\x00\x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Paper=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|\x00\x00\x00\x00\x00\x00\x01\xff\x00`\x00\x00\x00\x00\x01\xff\x83\xfc\x00\x00\x00\x00\x07\xff\xc7\xff\x00\x00\x00\x00\x07\xe7\xcf\xff\x80\x00\x00\x00\x0f\x83\xff\xff\x80\x00\x00\x00\x0f\x03\xff\x07\x80\x00\x00\x00\x0f\x03\xfe\x07\xc0\x00\x00\x00\x1f\x01\xfc\x03\xc0\x00\x00\x00\x1e\x01\xf8\x03\xc0\x00\x00\x00\x1e\x01\xf8\x07\xcc\x00\x00\x00\x1e\x03\xf0\x07\xff\x00\x00\x00\x1e\x03\xe0\x0f\xff\x80\x00\xbc\x1e\x03\xe0\x0f\xff\xc0\x01\xff\x1e\x03\xc0\x1f\xff\xc0\x03\xff\xfe\x03\xc0?\xc3\xe0\x07\xff\xfe\x01\xc0?\x81\xe0\x07\xc7\xfe\x00\x00~\x01\xe0\x07\x81\xfe\x00\x00\xfc\x01\xe0\x0f\x80\xfe\x00\x01\xf8\x03\xe0\x0f\x80~\x00\x01\xf0\x07\xc0\x07\x80>\x00\x00\xe0\x0f\xc0\x07\x80\x1e\x00\x00@\x1f\x80\x07\xc0\x0e\x00\x00\x00?\x00\x03\xe0\x06\x00\x00\x00~\x00\x03\xe0\x06\x00\x00\x00\xfc\x00\x01\xf0\x02\x00\x00\x03\xff\x00\x00\xf8\x00\x00\x00\x07\xff\xc0\x00\xfc\x00\x00\x00\x07\xff\xe0\x00|\x00\x00\x00\x07\xff\xe0\x00>\x00\x00\x00\x03\x81\xf0\x00\x1e\x00\x00\x00\x00\x00\xf0\x00\x1e\x00\x00\x00\x00\x00\xf0\x00\x1e\x00\x00\x00\x00\x01\xf0\x00\x1e\x00\x00\x00\x00\x03\xf0\x00\x1e\x00\x00\x00\x00\x07\xe0\x00>\x00\x00\x00\x00\x7f\xc0\x00<\x00\x00\x00\xff\xff\x80\x00|\x00\x00\x01\xff\xff\x00\x00|\x00\x00\x03\xff\xfc\x00\x00<\x00\x00\x03\xff\xe0\x00\x00<\x00\x00\x07\xe0\x00\x00\x00>\x00\x00\x0f\x80\x00\x00\x00>\x00\x00\x1f\x80\x00\x00\x00\x1f\x00\x00?\x00\x00\x00\x00\x0f\x80\x00~\x00\x00\x00\x00\x0f\xc0\x00\xfc\x00\x00\x00\x00\x07\xf0\x03\xf8\x00\x00\x00\x00\x03\xf8\x07\xf0\x00\x00\x00\x00\x01\xff?\xc0\x00\x00\x00\x00\x00\x7f\xff\x80\x00\x00\x00\x00\x00?\xff\x00\x00\x00\x00\x00\x00\x0f\xfc\x00\x00\x00\x00\x00\x00\x03\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Rock=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00~\x00\x00\x00\x00\x00\x00\xc1\xff\xc0\x00\x00\x00\x00\x07\xff\xff\xe0\x00\x00\x00\x00\x1f\xff\xff\xf0\x00\x00\x00\x00?\xff\xc3\xf8\x00\x00\x00\x00?\xff\x00\xff\xf0\x00\x00\x00|\x0f\x00\x7f\xfc\x00\x00\x00x\x0e\x00\xff\xfe\x00\x00\x07\xf8\x1e\x03\xff\xff\x00\x00\x1f\xf8\x1c\x0f\xf0\x1f\x80\x00?\xf0\x1c\x1f\x80\x0f\xc0\x00\x7f\xf0\x1c\x1e\x00\x07\xe0\x00\xfe\xf0\x1e<\x00\x03\xe0\x00\xf8p\x1e8\x00\x01\xe0\x00\xf0p\x0e8\x00\x01\xf0\x01\xf0x\x0e8\x00\x00\xf0\x01\xe0x\x0f8\x00\x00\xf0\x01\xe0<\x078\x00\x00\xf0\x01\xe0<\x07\xfc\x0f\x00\xf0\x03\xe0\x1e\x03\xbf\xff\x00\xf0\x0f\xf0\x1f\x03\xff\xff\x00\xf8\x1f\xf0\x0f\x81\xef\xfc\x00\xf8\x1f\xf0\x07\xc0\xff\xe0\x00x>x\x03\xe0\xff\x80\x00\xf8><\x01\xf1\xfc\x00\x00\xf8<>\x00\xff\xf0\x00\x00\xf8<\x1f\x00\x7f\xc0\x00\x00\xf0<\x0f\x80?\x00\x00\x00\xf0>\x07\xc0~\x00\x00\x00\xf0\x1e\x03\xe1\xf8\x00\x00\x00\xf0\x1f\x01\xf3\xf0\x00\x00\x01\xf0\x1f\x00\xff\xc0\x00\x00\x01\xe0\x0f\x80\x7f\x80\x00\x00\x01\xe0\x0f\x80\x1f\x00\x00\x00\x03\xe0\x07\xc0\x1e\x00\x00\x00\x03\xe0\x03\xe0<\x00\x00\x00\x07\xc0\x03\xf8x\x00\x00\x00\x0f\xc0\x01\xfcx\x00\x00\x00\x1f\x80\x00\xff\xf0\x00\x00\x00\x7f\x00\x00?\xf0\x00\x00\x01\xfe\x00\x00\x1f\xf0\x00\x00\x07\xfc\x00\x00\x07\xf0\x00\x00\x1f\xf0\x00\x00\x00\xf8\x00\x00?\xc0\x00\x00\x00|\x00\x00\xff\x80\x00\x00\x00~\x00\x03\xfe\x00\x00\x00\x00?\x00\x0f\xf8\x00\x00\x00\x00\x1f\x80?\xe0\x00\x00\x00\x00\x1f\xe0\xff\x80\x00\x00\x00\x00\x07\xff\xfe\x00\x00\x00\x00\x00\x03\xff\xf8\x00\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x00\x00\x7f\xc0\x00\x00\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Sad=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfe\xff\xff\xc0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x1f\xf0\x00\x00\x1f\xf8\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf0\x00\x00\x00\x00\x1f\xc0\x07\xf0\x00\x00\x00\x00\x0f\xe0\x0f\xe0\x00\x00\x00\x00\x07\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x03\xf0\x1f\xc0\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8?\x00\x00\x00\x00\x00\x01\xfc\x1f\x07\xff\xe0\x0f\xff\xc0\xf8?\x07\xff\xe0\x0f\xff\xe0\xfc?\x07\xff\xf0\x0f\xff\xc0\xfc?\x07\xff\xe0\x0f\xff\xc0\xfc?\x00\x7f\x00\x00\xfe\x00\xfc?\x00?\x00\x00\xfc\x00\xfc>\x00\x7f\x00\x00\xfe\x00|?\x00?\x00\x00~\x00\xfc?\x00~\x00\x00\xfe\x00\xfc?\x00?\x00\x00\xfe\x00\xfc?\x00\x7f\x00\x00\xfc\x00\xfc\x1f\x00\x7f\x00\x00\xfe\x00\xf8\x1f\x00?\x00\x00\xfe\x01\xfc\x1f\x80\x7f\x00\x00\xfe\x01\xf8\x1f\x80\x7f\x00\x00\xfe\x01\xf8\x1f\xc0?\x00\x00|\x01\xf8\x0f\xc0\x7f\x00\x00\xfe\x03\xf0\x0f\xe0\x7f\x0f\xe0\xfe\x03\xf0\x07\xe0?\x1f\xf8\xfe\x07\xe0\x07\xf0\x7f\x7f\xfe\xfc\x0f\xe0\x03\xf0\x7f|?~\x0f\xc0\x03\xf8?\xf0\x0f\xfe\x1f\xc0\x01\xfc\x7f\xe0\x07\xfe?\x80\x00\xfe\x7f\xc0\x03\xfe\x7f\x00\x00\xff?@\x02\xfe\xff\x00\x00\x7f\xff\x00\x00\xff\xfe\x00\x00?\xff\x00\x00\xff\xfc\x00\x00\x1f\xff\x00\x00\xff\xf8\x00\x00\x0f\xff\x00\x00\xff\xf0\x00\x00\x07\xff\xc0\x00\xff\xe0\x00\x00\x01\xff\xff\x7f\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf8\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Scissors=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x80\x00\x00\x00\x00\x00\x00?\xf0\x00\x00\x00\x00\x00\x00\xff\xfc\x00\x00\x00\x00\x00\x01\xff\xff\x00\x00\x00\x00\x00\x01\xf8\xff\x80\x00\x00\x00\x00\x03\xe0\x1f\xc0\x00\x00\x00\x00\x07\xc0\x07\xf0\x00\x00\x00\x00\x07\xc0\x03\xf8\x00\x00\x00\x00\x07\x80\x01\xfc\x00\x00\x00\x00\x07\x80\x00~\x00\x00\x00\x00\x07\x80\x00?\x00\x00\x00\x00\x07\x80\x00\x1f\xfc\x00\x00\x00\x07\xc0\x00\x0f\xff\x80\x00\x00\x03\xe0\x00\x07\xff\xe0\x00\x00\x03\xf0\x00\x03\xff\xf8\x00\x00\x01\xf8\x00\x00\xe7\xfc\x00\x00\x00\xfc\x00\x01\xe0\xfe\x00\x00\x00\x7f\x00\x01\xe0?\x00\x00\x03\xff\x80\x01\xc0\x1f\x80\x00\x7f\xff\xe0\x03\xc0\x1f\x80\x01\xff\xff\xf8\x03\x80\x1f\xc0\x03\xff\xff\xff\x03\x80\x1f\xe0\x07\xff\xff\xff\x07\x80\x1f\xe0\x0f\xc0\x01\xff\x07\x00\x1f\xe0\x0f\x80\x00\x1e\x07\x00=\xf0\x1f\x00\x00\x00\x07\x00<\xf0\x1e\x00\x00\x00\x07\x008\xf0\x1e\x00\x00\x00\x0f\x00x\xf0\x1e\x00\x00\x00\x7f\x00\xf0\xf0\x1f\x00\x00\x01\xff\x00\xf0\xf8\x0f\x00\x00\x07\xff\x01\xe0\xf8\x0f\x80\x00\x0f\xef\x03\xc0x\x0f\xe0\x00?\x07\x87\xc0\xf8\x07\xff\x7f\xfe\x03\xff\x80\xf8\x03\xff\xff\xfc\x03\xff\x00\xf8\x01\xff\xff\xf8\x01\xfe\x00\xf0\x00\x7f\xff\xf8\x07\xff\x00\xf0\x00\x01\xd0|\x7f\xff\xc0\xf0\x00\x00\x00\x7f\xff\xff\xe0\xf0\x00\x00\x00?\xfc\x01\xf1\xf0\x00\x00\x00\x1f\xe0\x00\xf1\xe0\x00\x00\x00\x0f\x00\x00s\xe0\x00\x00\x00\x0f\x00\x00s\xe0\x00\x00\x00\x0f\x00\x00\xff\xc0\x00\x00\x00\x0f\x00\x00\xff\x80\x00\x00\x00\x0f\x80\x03\xff\x00\x00\x00\x00\x07\xf0\xff\xfe\x00\x00\x00\x00\x07\xff\xff\xfc\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x01\xff\xfe\x00\x00\x00\x00\x00\x007@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Silly=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xf4\x1f\xff\xc0\x00\x00\x07\xff\x00\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00?\xf0\x00\x00\x1f\xf0\x00\x00\x0f\xf8\x00\x00?\xc0\x00\x00\x03\xfc\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xfc\x00\x00\x00\x00?\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x07\xf0\x01\x00\x00\x00\x0f\xc0\x07\xe0\x03\x80\x01\xe0\x07\xe0\x07\xe0\x07\x80\x01\xe0\x07\xe0\x0f\xc0\x0f\x80\x01\xf0\x03\xf0\x0f\xc0?\x00\x00\xfc\x03\xf0\x1f\x87\xfe\x00\x00\x7f\xe1\xf8\x1f\x87\xfc\x00\x00?\xe1\xf8\x1f\x07\xf8\x00\x00\x0f\xf0\xf8\x1f\x07\xcc\x00\x00s\xe1\xf8?\x00\x1f\x00\x00\xf8\x00\xfc?\x00?\x80\x01\xfc\x00\xfc?\x00\x7f\xc0\x03\xfc\x00|>\x00\x7f\xc0\x01\xfe\x00\xfc>\x00?\x80\x03\xfe\x00|>\x00?\x80\x01\xfc\x00|?\x00?\x80\x00\xf8\x00|>\x00\x0e\x00\x00p\x00\xfc>\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x03\xc0\x00\x00\xf8?\x00\x00\x07\xe0\x00\x00\xfc\x1f\x00\x00\x0f\xe0\x00\x00\xf8\x1f\x80\x00\x07\xe0\x00\x01\xf8\x1f\x80\x00\x07\xf0\x00\x01\xf8\x0f\xc0\x00\x0f\xe0\x00\x03\xf0\x0f\xc0\x00\x0f\xe0\x00\x03\xf0\x07\xe0\x00\x07\xe0\x00\x07\xe0\x07\xe0\x00\x07\xf0\x00\x07\xe0\x07\xf0\x00\x0f\xe0\x00\x0f\xc0\x03\xf8\x00\x07\xe0\x00\x1f\xc0\x01\xfc\x00\x0f\xf0\x00?\x80\x00\xfc\x00\x07\xe0\x00?\x00\x00\xff\x00\x07\xe0\x00\xff\x00\x00\x7f\x80\x07\xc0\x01\xfe\x00\x00?\xc0\x00\x80\x03\xfc\x00\x00\x1f\xf0\x00\x00\x0f\xf8\x00\x00\x0f\xfc\x00\x00?\xf0\x00\x00\x07\xff\x00\x01\xff\xe0\x00\x00\x01\xff\xfa7\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Sleep=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x03\xff\xc0\x03\xf0\x00\x00\x00\x07\xef\xc0\x07\xf0\x00\x00\x00\x00\xef\xe0\x07\xe0\x00\x00\x00\x01\xc7\xe0\x0f\xe0\x00\x00\x00\x07\xa7\xf0\x0f\xc0\x00\x00\x00\x07\xe3\xf0\x1f\x80\x00\x00\x00\xf3C\xf8\x1f\x80\x00\x00\x01\xf8\x01\xf8\x1f\x80\x00\x00\x00p\x01\xf8\x1f\x80\x00\x00\x00\xe0\x00\xf8?\x00\x00\x00\x01\xf8\x00\xfc?\x00\x00\x00\x00\xf0\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc>\x03\xff\xe0\x07\xaf\xc0\xfc?\x03\xff\xe0\x07\xff\xc0\xfc?\x03\xff\xe0\x07\xff\xc0|?\x01\xff\x80\x03\xff\x80\xfc>\x00\x00\x00\x00\x10\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\xfc?\x80\x00\x00\x00\x00\x00\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x01@\x00\x01\xf8\x1f\xc0\x00\x1f\xf8\x00\x03\xf8\x0f\xc0\x00\x7f\xfe\x00\x03\xf0\x0f\xe0\x00\xff\xff\x00\x03\xf0\x07\xe0\x01\xff\xff\x80\x07\xe0\x07\xf0\x01\xff\xff\x80\x0f\xe0\x03\xf0\x03\xff\xff\xc0\x0f\xc0\x03\xf8\x03\xff\xff\xc0?\xc0\x01\xfc\x01\xff\xff\x80?\x80\x00\xfe\x01\xff\xff\x80\x7f\x80\x00\xff\x00|\x00\x00\xff\x00\x00\x7f\x80x\x00\x01\xfe\x00\x00?\xe0<\x00\x07\xfc\x00\x00\x1f\xf88\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x03\xff\xfd\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf8\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Small_heart=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\xe0\x07\xf8\x00\x00\x00\x00\x7f\xf8\x1f\xfe\x00\x00\x00\x00\xff\xfe?\xff\x00\x00\x00\x01\xff\xff\x7f\xff\x80\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xf0\x00\x00\x0f\xff\xff\xff\xff\xe0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x07\xff\xff\xff\xff\xe0\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x03\xff\xff\xff\xff\xc0\x00\x00\x01\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x7f\xff\xff\xff\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x1f\xff\xff\xf8\x00\x00\x00\x00\x0f\xff\xff\xe0\x00\x00\x00\x00\x07\xff\xff\xe0\x00\x00\x00\x00\x01\xff\xff\xc0\x00\x00\x00\x00\x01\xff\xff\x00\x00\x00\x00\x00\x00\x7f\xff\x00\x00\x00\x00\x00\x00\x7f\xfc\x00\x00\x00\x00\x00\x00\x1f\xf8\x00\x00\x00\x00\x00\x00\x0f\xf8\x00\x00\x00\x00\x00\x00\x07\xe0\x00\x00\x00\x00\x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Small_paper=b'P4\n32\n32\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x1f\x1e\x00\x00;\xbf\x00\x001\xf3\x00\x00q\xe1\x80\x00a\xc3\xa0\x00a\x83\xf0\x1fa\x87\xf8?\xe1\x87\x181\xe0\x0e\x180\xe0\x1c80`\x08p\x18 \x00\xe0\x1c\x00\x01\xf0\x0e\x00\x03\xf8\x06\x00\x01\x1c\x06\x00\x00\x0c\x06\x00\x00\x1c\x06\x00\x00\xf8\x0e\x00\x1f\xf0\x06\x00\x1f\x80\x06\x000\x00\x07\x00p\x00\x03\x80\xe0\x00\x01\xc3\xc0\x00\x00\xff\x00\x00\x00>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Small_rock=b'P4\n32\n32\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00?\xf8\x00\x00\x7f\x9c\x00\x00\xe3\x0f\xe0\x03\xc6\x1f\xf0\x07\xc6p8\x0e\xc6`\x18\x0c\xc2@\x1c\x18\xc3@\x0c\x18c\xe3\x0c<q\xff\x0c|8\xf8\x0cf\x1d\xe0\x0cg\x0f\x80\x0cc\x8e\x00\x0cq\xdc\x00\x1c0\xf0\x00\x188`\x00\x18\x1c\xc0\x008\x0f\xc0\x00\xf0\x07\xc0\x03\xe0\x00\xc0\x07\x80\x00\xe0\x1e\x00\x00px\x00\x00?\xe0\x00\x00\x1f\x80\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Small_scissors=b'P4\n32\n32\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00|\x00\x00\x01\xff\x00\x00\x01\x87\x80\x00\x03\x81\xc0\x00\x03\x00\xe0\x00\x03\x00~\x00\x01\x80?\x80\x01\xc0\x0b\xe0\x00\xf0\x18p\x0f\xf8\x18p\x1f\xff\x10x8\x1f0xp\x000l`\x000\xccp\x01\xf0\xcc0\x03\xb1\x8c?\xfe\x1f\x0c\x1f\xfc\x1e\x0c\x01\xce\xff\x8c\x00\x07\xe1\xdc\x00\x03\x00\xd8\x00\x03\x00\xf8\x00\x03\x01\xf0\x00\x03\xff\xe0\x00\x01\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Smile=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xff\x7f\xff\xc0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x0f\xfc\x00\x00?\xf0\x00\x00\x1f\xf0\x00\x00\x1f\xf8\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x00\xfe\x00\x00\x00\x00\x7f\x00\x03\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf8\x00\x00\x00\x00\x0f\xc0\x07\xe0\x00\x00\x00\x00\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xe0\x0f\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x03\xf0\x1f\xc0?\x00\x01\xfc\x03\xf8\x1f\x80\x7f\xc0\x03\xfe\x01\xf8\x1f\x80\xff\xe0\x07\xff\x01\xf8\x1f\x01\xff\xf0\x0f\xff\x81\xf8?\x03\xfb\xf0\x1f\xef\xc0\xfc?\x03\xe0\xf8\x1f\x07\xc0\xfc?\x03\xc0\xf8\x1f\x07\xc0\xfc?\x07\xc0\xf8\x1e\x03\xc0\xfc?\x03\xc0x\x1e\x03\xe0|?\x03\xc0x\x1e\x03\xc0\xfc?\x01\x80 \x0c\x00\x80\xfc>\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xf8\x1f\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x0f\xc0\x00\x00\x00\x00\x01\xf0\x0f\xc0\x0e\x00\x000\x03\xf8\x0f\xe0\x0f\x00\x00x\x07\xe0\x07\xe0\x1f\x00\x00\xf0\x07\xf0\x07\xf0\x0f\x00\x00\xf0\x0f\xe0\x03\xf0\x07\x80\x01\xf0\x0f\xc0\x03\xf8\x07\xc0\x03\xe0\x1f\xc0\x01\xfc\x07\xe0\x07\xe0?\x80\x01\xfe\x03\xfc\x1f\xc0\x7f\x80\x00\xff\x01\xff\xff\x80\xff\x00\x00\x7f\xc0\xff\xfe\x03\xfe\x00\x00?\xe0?\xfc\x07\xfc\x00\x00\x1f\xf0\x0f\xf0\x1f\xf8\x00\x00\x0f\xfe\x00\x00?\xf0\x00\x00\x07\xff\xc0\x03\xff\xe0\x00\x00\x03\xff\xff\x7f\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Surprise=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\xff\xff\xfc\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x03\xff\xfd\x7f\xff\xc0\x00\x00\x07\xff\x80\x01\xff\xe0\x00\x00\x0f\xfc\x00\x00\x7f\xf0\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00?\xc0\x00\x00\x07\xfc\x00\x00\x7f\xc0\x00\x00\x01\xfe\x00\x00\xff\x00\x00\x00\x00\xff\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00?\x80\x03\xf8\x00\x00\x00\x00\x1f\xc0\x03\xf0\x00\x00\x00\x00\x1f\xc0\x07\xf0\x00\x00\x00\x00\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x00\x00\x00\x00\x07\xf0\x0f\xc0\x10\x00\x00\x10\x03\xf0\x1f\xc0>\x00\x00|\x01\xf8\x1f\x80\x7f\x00\x00~\x01\xf8\x1f\x80\xff\x00\x00\xff\x01\xf8\x1f\x80\xff\x80\x01\xff\x00\xf8?\x00\xff\x00\x01\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc?\x00\xff\x00\x00\xff\x00\xfc?\x00\xff\x80\x01\xff\x00\xfc>\x00\x7f\x00\x00\xff\x00\xfc?\x00~\x00\x00~\x00|?\x00>\x00\x008\x00\xfc>\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x03\xc0\x00\x01\xf8\x1f\x80\x00\x07\xe0\x00\x01\xf8\x1f\xc0\x00\x0f\xf0\x00\x01\xf8\x0f\xc0\x00\x0f\xf0\x00\x03\xf0\x0f\xe0\x00\x0f\xf0\x00\x07\xf0\x07\xe0\x00\x0f\xf8\x00\x07\xe0\x07\xf0\x00\x1f\xf0\x00\x0f\xe0\x03\xf8\x00\x0f\xf8\x00\x0f\xc0\x03\xf8\x00\x0f\xf0\x00\x1f\xc0\x01\xfc\x00\x0f\xf0\x00?\x80\x00\xfe\x00\x0f\xe0\x00\x7f\x80\x00\xff\x00\x07\xe0\x00\xff\x00\x00\x7f\xc0\x03\xc0\x03\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\x80\x03\xff\xe0\x00\x00\x01\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00/\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Wonderful=b'P4\n64\n64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x02\x00\xff\xff\xff\xff\x00\x00\x07\x03\xff\xff\x7f\xff\xc0\x00\x07\x87\xff\x80\x03\xff\xe0\x00\x1f\xcf\xfc\x00\x00\x7f\xf0\x00\x1f\xdf\xf8\x00\x00\x1f\xf8\x00\x07?\xe0\x00\x00\x07\xfc\x00\x02\x7f\x80\x00\x00\x19\xfe\x00\x02\xff\x00\x00\x00\x1c\xff\x00\x00\xfe\x00\x00\x00>\x7f\x00\x01\xfc\x00\x00\x00\x7f?\x80\x03\xf8\x00\x00\x00\x1c\x1f\xc0\x03\xf0\x00\x00\x00\x18\x1f\xe0\x07\xf0\x00\x00\x00\x08\x0f\xe0\x07\xe0\x00\x00\x00\x00\x07\xe0\x0f\xe0\x00\x00\x00\x00\x07\xf0\x0f\xc0<\x00\x008\x03\xf0\x1f\x80\xff\x00\x00\xff\x01\xf8\x1f\x80\xff\x80\x01\xff\x01\xf8\x1f\x81\xff\x80\x01\xff\x81\xf8?\x83\xff\xc0\x01\xff\xc0\xfc\x1f\x01\xff\xc0\x03\xff\x80\xf8?\x03\xff\xc0\x03\xff\xc0\xfc?\x01\xff\xc0\x03\xff\x80\xfc?\x01\xff\x80\x01\xff\x80\xfc>\x00\xff\x80\x01\xff\x80|?\x00~\x00\x00\xfe\x00\xfc?\x00\x1c\x00\x008\x00\xfc>\x00\x00\x00\x00\x00\x00|?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\xf8\x1f\x80\x00\x00\x00\x00\x01\xfc\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\x80\x00\x00\x00\x00\x01\xf8\x1f\xc0\x00\x00\x00\x01\x03\xf0\x0f\xc0\x00\x00\x00\x01\x83\xf8\x0f\xe0\x00\xff\xff\x03\xc3\xf0\x07\xe0\x00\xff\xff\x0f\xe7\xe0\x07\xf0\x00\xff\xff\x07\xcf\xe0\x03\xf0\x00\x7f\xff\x01\x9f\xc0\x03\xf8\x00\x7f\xfe\x01\x9f\xc0\x01\xfc\x00?\xfc\x00?\x80\x00\xfe\x00\x1f\xf8\x00\x7f\x80\x00\xff\x00\x07\xe0\x00\xff\x00\x00\x7f\x80\x00\x00\x01\xfe\x00\x00?\xe0\x00\x00\x07\xfc\x00\x00\x1f\xf8\x00\x00\x1f\xf8\x00\x00\x0f\xfe\x00\x00\x7f\xf0\x00\x00\x07\xff\xc0\x01\xff\xe0\x00\x00\x03\xff\xff\xff\xff\x80\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00?\xff\xff\xfc\x00\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x03\xff\xff\x80\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
31
mixly/boards/default/micropython/build/lib/eye_picture.py
Normal file
31
mixly/boards/default/micropython/build/lib/eye_picture.py
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#Take the picture bytes in eye_picture.py
|
||||||
|
#--dahanzimin From the Mixly Team
|
||||||
|
|
||||||
|
Eyes_Angry=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1e\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1f\x80\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1f\xe0\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1d\xf8\x00\x00\x07\x000\x00\x00\x00|\x7f\x1c\xfe\x00\x00\x07\x000\x00\x00\x01\xfc\x7f\x1c?\x80\x00\x07\x000\x00\x00\x07\xfc\x7f\x1c\x0f\xe0\x00\x07\x000\x00\x00\x1f\x8c\x7f\x1c\x03\xf8\x00\x07\x000\x00\x00~\x0c\x7f\x1c\x00\xfe\x00\x07\x000\x00\x01\xf8\x0c\x7f\x1c\x00?\x80\x07\x000\x00\x07\xe0\x0c\x7f\x1c\x00\x0f\xe0\x07\x000\x00\x1f\x80\x0c\x7f\x1c\x00\x07\xf8\x07\x000\x00\x7f\x00\x0c\x7f\x1c\x00\x0f\xfe\x07\x000\x01\xfc\x00\x0c\x7f\x1c\x00\x1f\xff\x87\x000\x07\xf6\x80\x0c\x7f\x1c\x00?\x9f\xe7\x000\x1f\xf2\x00\x0c\x7f\x1c\x00\xbf\xbb\xff\x000\x7f\xef\x00\x0c\x7f\x1c\x00\x7f\xfc\xff\x001\xff\xff@\x0c\x7f\x1c\x00\x7f\xfc?\x00?\xff\xff\x00\x0c\x7f\x1c\x00\x7f\xfc\x0f\x00?\xaf\xff@\x0c\x7f\x1c\x00?\xf8\x07\x00>\x0f\xff\x00\x0c\x7f\x1c\x00\xbf\xfa\x07\x008\x07\xfe\x00\x1c\x7f\x0e\x00\x1f\xf0\x0e\x008\x17\xfe\x80\x1c\x7f\x0e\x00\x0f\xe0\x0e\x00<\x03\xfc\x00<\x7f\x0f\x00\x03\x80\x1e\x00\x1c\x04\xf2\x008\x7f\x07\x80\x04 <\x00\x1e\x01\x08\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Awake=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1f\x00\x00\x00\x07\x000\x00\x00\x00|\x7f\x1f\xf8\x00\x00\x07\x000\x00\x00\x07\xfc\x7f\x1f\xff\xc0\x00\x07\x000\x00\x01\xff\xfc\x7f\x1c\x1f\xff\x00\x07\x000\x00?\xfe\x0c\x7f\x1c\x00\xff\xf0\x07\x000\x07\xff\xc0\x0c\x7f\x1c\x00?\xff\x87\x000\x7f\xfe\x00\x0c\x7f\x1c\x01\x7f\xff\xff\x00?\xff\xff\x00\x0c\x7f\x1c\x00~i\xff\x00?\xe1\xfd\xa0\x0c\x7f\x1c\x02\xfeh\x0f\x00<\x03\xf9\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\xff\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x01\x7f\xd0\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x1f\x00\x07\x000\x00~\x00\x0c\x7f\x1c\x00@@\x07\x000\x00\x81\x00\x0c\x7f\x1c\x00\n\x00\x07\x000\x00(\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Black_eye=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00?\xff\xfc\x00\x7f\x00\x00\x00\x00\x00\x00\x01\xff\xff\xff\x80\x7f\x00\x00\x00\x00\x00\x00\x03\xff\xff\xff\xc0\x7f\x00\x1f\xff\xfe\x00\x00\x07\xc0\x00\x03\xe0\x7f\x00\x7f\xff\xff\xc0\x00\x0f\x00\x00\x00\xf0\x7f\x01\xff\xff\xff\xf0\x00\x1e\x00\x00\x00x\x7f\x03\xfa\xaa\xab\xf8\x00\x1c\x00\x00\x008\x7f\x07\xd2U%|\x008\x00\x00\x00\x1c\x7f\x07\xad\xaa\xda\xbc\x008\x00\x00\x00\x1c\x7f\x0fRU%^\x008\x00\x00\x00\x1c\x7f\x0fm\xaa\xda\xae\x000\x00\x00\x00\x0c\x7f\x1e\x92U$\xaf\x000\x00\x00\x00\x0c\x7f\x1dm\xaa\xdbW\x000\x00\x00\x00\x0c\x7f\x1e\x92U$\xaf\x000\x00\x00\x00\x0c\x7f\x1dm\xaa\xdbW\x000\x00\x00\x00\x0c\x7f\x1c\x92U$\xaf\x000\x00\x00\x00\x0c\x7f\x1fm\xaa\xdbW\x000\x00\x00\x00\x0c\x7f\x1c\x92U$\x97\x000\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x000\x00B\x00\x0c\x7f\x1f\xff\xff\xff\xff\x000\x018\x80\x0c\x7f\x1f\xff\xff\xff\xff\x000\x00\x7f\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xfd\xa0\x0c\x7f\x1c\x00\xfe`\x07\x000\x01\xfc\x80\x0c\x7f\x1c\x02\xfe\xe8\x07\x000\x03\xfb\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x01\xff\x80\x0c\x7f\x1f\xff\xff\xff\xff\x000\x05\xff\xa0\x0c\x7f\x1f\xff\xff\xff\xff\x000\x00\xff\x00\x0c\x7f\x1f\xff\xff\xff\xff\x000\x01<\x80\x0c\x7f\x1dUUUW\x000\x00B\x00\x0c\x7f\x1dT\x92UW\x000\x00\x00\x00\x0c\x7f\x1e\xabm\xaa\xaf\x000\x00\x00\x00\x0c\x7f\x1dT\x92UW\x000\x00\x00\x00\x0c\x7f\x1fKm\xaa\xaf\x000\x00\x00\x00\x0c\x7f\x0e\xb4\x92U\xae\x000\x00\x00\x00\x0c\x7f\x0fKm\xaa^\x008\x00\x00\x00\x1c\x7f\x07\xb4\x92U\xbc\x008\x00\x00\x00\x1c\x7f\x07\xcbm\xaa|\x00<\x00\x00\x00<\x7f\x03\xf4\x92K\xf8\x00\x1c\x00\x00\x008\x7f\x01\xff\xff\xff\xf0\x00\x1e\x00\x00\x00x\x7f\x00\x7f\xff\xff\xc0\x00\x0f\x80\x00\x01\xf0\x7f\x00\x1f\xff\xff\x00\x00\x07\xe0\x00\x07\xe0\x7f\x00\x00\x00\x00\x00\x00\x03\xff\xff\xff\xc0\x7f\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Bottom_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x02\x80\x00\x07\x000\x05\x00\x00\x0c\x7f\x1c\x10\x10\x00\x07\x000 @\x00\x0c\x7f\x1c\x07\xc8\x00\x07\x000\x1f\x80\x00\x0c\x7f\x1c_\xf0\x00\x07\x000?\xc0\x00\x0c\x7f\x1c\x1f\x98\x00\x07\x001\x7fh\x00\x0c\x7f\x1c\xbf\x9a\x00\x07\x000\xfep\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c?\xf0\x00\x07\x001\x7f\xe8\x00\x0c\x7f\x1c_\xf4\x00\x07\x000?\xc0\x00\x0c\x7f\x1c\x07\xc0\x00\x07\x000\x1f\x80\x00\x0c\x7f\x1c\x10\x10\x00\x07\x008 @\x00\x1c\x7f\x0e\x02\x80\x00\x0e\x008\n\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Bottom_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00(\x07\x000\x00\x00P\x0c\x7f\x1c\x00\x01\x01\x07\x000\x00\x02\x04\x0c\x7f\x1c\x00\x00|\x87\x000\x00\x01\xf8\x0c\x7f\x1c\x00\x05\xff\x07\x000\x00\x03\xfc\x0c\x7f\x1c\x00\x01\xf9\x87\x000\x00\x17\xf6\x8c\x7f\x1c\x00\x0b\xf9\xa7\x000\x00\x0f\xe7\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x03\xff\x07\x000\x00\x17\xfe\x8c\x7f\x1c\x00\x05\xffG\x000\x00\x03\xfc\x0c\x7f\x1c\x00\x00|\x07\x000\x00\x01\xf8\x0c\x7f\x1c\x00\x01\x01\x07\x008\x00\x02\x04\x1c\x7f\x0e\x00\x00(\x0e\x008\x00\x00\xa0\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Crazy_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x01\x08\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\xe0\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x03\xf8\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x0f\xe6\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xee\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x0f\xfe\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xfe\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x03\xf8\x00\x07\x000\x00\x01@\x0c\x7f\x1c\x00\xe0\x00\x07\x000\x00\x08\x10\x0c\x7f\x1c\x01\x08\x00\x07\x000\x00\x07\xe0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x0f\xf0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xda\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\x9c\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xfa\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x0f\xf0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x07\xe0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x08\x10\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x02\x80\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Crazy_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x04 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x13\x88\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x07\xf0\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xda\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x1f\xc8\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xbc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\xbf\xfd\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00?\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x1f\xf8\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00_\xfa\x0c\x7f\x1c\x00\xa0\x00\x07\x000\x00\x0f\xf0\x0c\x7f\x1c\x04\x04\x00\x07\x000\x00\x13\xc8\x0c\x7f\x1c\x01\xf2\x00\x07\x000\x00\x04 \x0c\x7f\x1c\x17\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xe6\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xe6\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x1f\xff\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c/\xfe\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x0f\xfc\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x17\xfd\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x01\xf0\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x04\x04\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\xa0\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Disappointed=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x1f\xf8\x00\x07\xfc\x00\x03\xe0\x7f\x07\x80\x00><\x00\x0f\x1e\x00\x00\xf0\x7f\x07\x00\x00|\x1c\x00\x1e\x0f\x00\x00x\x7f\x0e\x00\x00\xf8\x0e\x00\x1c\x07\x80\x008\x7f\x0e\x00\x01\xf0\x0e\x008\x03\xc0\x00\x1c\x7f\x1c\x00\x03\xe0\x07\x008\x01\xe0\x00\x1c\x7f\x1c\x00\x07\xc0\x07\x008\x00\xf0\x00\x1c\x7f\x1c\x00\x0f\x80\x07\x000\x00x\x00\x0c\x7f\x1c\x00\x1f\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00>\x00\x07\x000\x00\x1e\x00\x0c\x7f\x1c\x00|@\x07\x000\x00\x9f\x00\x0c\x7f\x1c\x00\xff \x07\x000\x00\x7f\x80\x0c\x7f\x1c\x01\xff\xc0\x07\x000\x00\xff\xc0\x0c\x7f\x1c\x03\xfe`\x07\x000\x05\xfd\xe0\x0c\x7f\x1c\x07\xfeh\x07\x000\x03\xf9\xf0\x0c\x7f\x1c\x0f\xff\xf0\x07\x000\x03\xff\xf8\x0c\x7f\x1c\x1f\xff\xf0\x07\x000\x0b\xff\xfc\x0c\x7f\x1c?\xff\xf0\x07\x000\x03\xff\xde\x0c\x7f\x1c}\xff\xf0\x07\x000\x0b\xff\xdf\x0c\x7f\x1c\xfa\xff\xe8\x07\x000\x03\xff\xc7\x8c\x7f\x1d\xf0\xff\xc0\x07\x000\x05\xff\xa3\xcc\x7f\x1f\xe1\x7f\xd0\x07\x000\x00\xff\x01\xfc\x7f\x1f\xc0\x1f\x00\x07\x000\x00~\x00\xfc\x7f\x1f\x80@@\x07\x000\x00\x81\x00|\x7f\x1f\x00\n\x00\x07\x000\x00(\x00<\x7f\x1e\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Dizzy=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x000\x00\x07\x000\x00\xc0\x00\x0c\x7f\x1c\x00\xf0\x00\x07\x000\x03\xc0\x00\x0c\x7f\x1c\x01\xc0\x00\x07\x000\x07\x00\x00\x0c\x7f\x1c\x03\x9f\xe0\x07\x000\x0e\x7f\x80\x0c\x7f\x1c\x07<\xf8\x07\x000\x1c\xf3\xe0\x0c\x7f\x1c\x06`\x1c\x07\x000\x19\x80p\x0c\x7f\x1c\x0c\xc7\xcc\x07\x0003\x1f0\x0c\x7f\x1c\x0c\xcf\xe6\x07\x0003?\x98\x0c\x7f\x1c\r\x98v\x07\x0006a\xd8\x0c\x7f\x1c\r\x9b3\x07\x0006l\xcc\x0c\x7f\x1c\r\x9b\xb3\x07\x0006n\xcc\x0c\x7f\x1c\r\x9f\xb3\x07\x0006~\xcc\x0c\x7f\x1c\x0c\xcf6\x07\x0003<\xd8\x0c\x7f\x1c\x0e\xe0f\x07\x000;\x81\x98\x0c\x7f\x1c\x06y\xee\x07\x000\x19\xe7\xb8\x0c\x7f\x1c\x03\x1f\x8c\x07\x000\x0c~0\x0c\x7f\x1c\x03\x80\x18\x07\x000\x0e\x00`\x0c\x7f\x1c\x00\xf0p\x07\x000\x03\xc1\xc0\x0c\x7f\x1c\x00\x7f\xe0\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x0f\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Down=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\n\x00\x07\x000\x00(\x00\x0c\x7f\x1c\x00@@\x07\x000\x00\x81\x00\x0c\x7f\x1c\x00\x9f\x00\x07\x000\x00~\x00\x0c\x7f\x1c\x00\x7f\xd0\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\xfe`\x07\x000\x05\xfd\xa0\x0c\x7f\x1c\x02\xfeh\x07\x000\x03\xf9\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\x7f\xe0\x07\x008\x05\xff\xa0\x1c\x7f\x0e\x01\x7f\xd0\x0e\x008\x00\xff\x00\x1c\x7f\x0e\x00\x1f\x00\x0e\x00<\x00~\x00<\x7f\x0f\x00@@\x1e\x00\x1c\x00\x81\x008\x7f\x07\x80\x15\x00<\x00\x1e\x00\x14\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Evil=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x0f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\xf0\x00\x00<\x00\x0f\x00\x00\x03\xf0\x7f\x07\xf8\x00\x00\x1c\x00\x1e\x00\x00\x07\xf8\x7f\x0e<\x00\x00\x0e\x00\x1c\x00\x00\x0e8\x7f\x0e\x1e\x00\x00\x0e\x008\x00\x00<\x1c\x7f\x1c\x0f\x00\x00\x07\x008\x00\x00x\x1c\x7f\x1c\x07\x80\x00\x07\x008\x00\x00\xf0\x1c\x7f\x1c\x01\xe0\x00\x07\x000\x00\x01\xe0\x0c\x7f\x1c\x00\xf0\x00\x07\x000\x00\x03\xc0\x0c\x7f\x1c\x00x\x00\x07\x000\x00\x07\x80\x0c\x7f\x1c\x00<\x00\x07\x000\x00\x0e\x00\x0c\x7f\x1c\x00\x1e\x00\x07\x000\x00>\x00\x0c\x7f\x1c\x00O\x00\x07\x000\x00|\x80\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x7f\xe0\x07\x000\x01\xfd\xa0\x0c\x7f\x1c\x00\xfe\xf0\x07\x000\x03\xfc\x80\x0c\x7f\x1c\x02\xfe\xf8\x07\x000\x07\xfb\xc0\x0c\x7f\x1c\x01\xff\xfc\x07\x000\x1f\xff\xd0\x0c\x7f\x1c\x01\xff\xfe\x07\x000?\xff\xc0\x0c\x7f\x1c\x01\xff\xff\x07\x000\x7f\xff\xd0\x0c\x7f\x1c\x00\xff\xe3\xc7\x000\xf3\xff\xc0\x0c\x7f\x1c\x02\xff\xe9\xe7\x001\xe1\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\xf7\x003\xc5\xff\xa0\x0c\x7f\x1c\x00?\x80\x7f\x00?\x00\xff\x00\x0c\x7f\x1c\x00\x0e\x00?\x00>\x01<\x80\x0c\x7f\x1c\x00\x10\x80\x1f\x00<\x00B\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Hurt=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x0f\x008\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00?\x00>\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\xff\x00?\x80\x00\x00\x0c\x7f\x1c\x00\x00\x03\xff\x00?\xe0\x00\x00\x0c\x7f\x1c\x00\x00\x0f\xe7\x001\xf8\x00\x00\x0c\x7f\x1c\x00\x00?\x87\x000~\x00\x00\x0c\x7f\x1c\x00\x00\xfe\x07\x000\x1f\x80\x00\x0c\x7f\x1c\x00\x03\xf8\x07\x000\x07\xe0\x00\x0c\x7f\x1c\x00\x0f\xf0\x07\x000\x03\xf8\x00\x0c\x7f\x1c\x00?\x80\x07\x000\x04\xfe\x00\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\x80\x0c\x7f\x1c\x03\xff\xf0\x07\x000\x17\xff\xe0\x0c\x7f\x1c\x0f\xff\x98\x07\x000\x07\xf3\xf8\x0c\x7f\x1c?\xbf\xba\x07\x000\x0f\xef~\x0c\x7f\x1c\xff\x7f\xfc\x07\x000/\xff_\x8c\x7f\x1d\xf8\x7f\xfc\x07\x000\x0f\xff\x07\xec\x7f\x1f\xe0\x7f\xfc\x07\x000/\xffA\xfc\x7f\x1f\x80?\xf8\x07\x000\x0f\xff\x00|\x7f\x1e\x00\xbf\xfa\x07\x008\x07\xfe\x00\x1c\x7f\x0e\x00\x1f\xf0\x0e\x008\x17\xfe\x80\x1c\x7f\x0e\x00\x0f\xe0\x0e\x00<\x03\xfc\x00<\x7f\x0f\x00\x03\x80\x1e\x00\x1c\x04\xf2\x008\x7f\x07\x80\x04 <\x00\x1e\x01\x08\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Knocked_out=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x0f\xff\xfe\x07\x000\x1f\xff\xf8\x0c\x7f\x1c\x0f\xff\xfe\x07\x000?\xff\xfc\x0c\x7f\x1c\x0f\xff\xfe\x07\x000?\xff\xf8\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Love=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x07\xe0\xfc\x07\x000\x0f\x81\xf0\x0c\x7f\x1c\x0f\xd1\xfa\x07\x000\x1fC\xf8\x0c\x7f\x1c\x1f\xeb\xfd\x07\x000?\xa7\xf4\x0c\x7f\x1c\x1f\xff\xfd\x07\x000\x7f\xff\xfa\x0c\x7f\x1c?\xff\xfe\x07\x000\x7f\xff\xfa\x0c\x7f\x1c?\xff\xff\x87\x000\x7f\xff\xfe\x0c\x7f\x1c?\xff\xff\x87\x000\x7f\xff\xfe\x0c\x7f\x1c?\xff\xff\x87\x000\x7f\xff\xfe\x0c\x7f\x1c\x1f\xff\xff\x07\x000\x7f\xff\xfe\x0c\x7f\x1c\x1f\xff\xff\x07\x000\x7f\xff\xfe\x0c\x7f\x1c\x1f\xff\xff\x07\x000?\xff\xfc\x0c\x7f\x1c\x0f\xff\xfe\x07\x000\x1f\xff\xf8\x0c\x7f\x1c\x03\xff\xf8\x07\x000\x0f\xff\xf0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x07\xff\xe0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00?\x80\x07\x000\x00~\x00\x0c\x7f\x1c\x00\x1f\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x18\x00\x0c\x7f\x1c\x00\x04\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Middle_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x08@\x00\x07\x000 \x80\x00\x0c\x7f\x1c\x03\x80\x00\x07\x000\x07 \x00\x0c\x7f\x1c\x0f\xe0\x00\x07\x000?\x80\x00\x0c\x7f\x1c\x1f\xf0\x00\x07\x001\x7f\xe8\x00\x0c\x7f\x1c?\x98\x00\x07\x000\x7f \x00\x0c\x7f\x1c\xbf\xba\x00\x07\x002\xfe\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf4\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf4\x00\x0c\x7f\x1c?\xf8\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\x7f\xe0\x00\x0c\x7f\x1c\x1f\xf0\x00\x07\x001\x7f\xe8\x00\x0c\x7f\x1c\x0f\xe0\x00\x07\x000?\xc0\x00\x0c\x7f\x1c\x03\x80\x00\x07\x000O \x00\x0c\x7f\x1c\x08@\x00\x07\x000\x10\x80\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Middle_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x84\x07\x000\x00\x02\x08\x0c\x7f\x1c\x00\x008\x07\x000\x00\x00r\x0c\x7f\x1c\x00\x00\xfe\x07\x000\x00\x03\xf8\x0c\x7f\x1c\x00\x01\xff\x07\x000\x00\x17\xfe\x8c\x7f\x1c\x00\x03\xf9\x87\x000\x00\x07\xf2\x0c\x7f\x1c\x00\x0b\xfb\xa7\x000\x00\x0f\xef\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xff\x0c\x7f\x1c\x00\x03\xff\x87\x000\x00\x0f\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x07\xfe\x0c\x7f\x1c\x00\x01\xff\x07\x000\x00\x17\xfe\x8c\x7f\x1c\x00\x00\xfe\x07\x000\x00\x03\xfc\x0c\x7f\x1c\x00\x008\x07\x000\x00\x04\xf2\x0c\x7f\x1c\x00\x00\x84\x07\x000\x00\x01\x08\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Neutral=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00!\x00\x07\x000\x00\x82\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x1c\x80\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xfe\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x00\xfe`\x07\x000\x01\xfc\x80\x0c\x7f\x1c\x02\xfe\xe8\x07\x000\x03\xfb\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x01<\x80\x0c\x7f\x1c\x00!\x00\x07\x000\x00B\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Nuclear=b"P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x1e\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00\xf3\xc0\x07\x000\x01\xe7\x80\x0c\x7f\x1c\x03\x800\x07\x000\x07\x00`\x0c\x7f\x1c\x06\x00\x08\x07\x000\x0c\x00\x10\x0c\x7f\x1c\r\x80$\x07\x000\x1b\x00H\x0c\x7f\x1c\x1b\x80r\x07\x0007\x00\xe4\x0c\x7f\x1c\x13\xc0\xfb\x07\x000'\x81\xf6\x0c\x7f\x1c7\xe0\xfd\x07\x000o\xc1\xfa\x0c\x7f\x1c/\xe1\xfd\x87\x000_\xc3\xfb\x0c\x7f\x1c/\xe1\xfc\x87\x000_\xc3\xf9\x0c\x7f\x1co\xe4\xfe\x87\x000\xdf\xc9\xfd\x0c\x7f\x1cO\xce\xfe\x87\x000\x9f\x9d\xfd\x0c\x7f\x1c@\x1e\x00\x87\x000\x80<\x01\x0c\x7f\x1c@\x0c\x00\x87\x000\x80\x18\x01\x0c\x7f\x1c \x00\x00\x87\x000@\x00\x01\x0c\x7f\x1c \x0e\x00\x87\x000@\x1c\x01\x0c\x7f\x1c \x1f\x01\x87\x000@>\x03\x0c\x7f\x1c\x10?\x01\x07\x000 ~\x02\x0c\x7f\x1c\x18?\x82\x07\x0000\x7f\x04\x0c\x7f\x1c\x08\x7f\x86\x07\x000\x10\xff\x0c\x0c\x7f\x1c\x04\x7f\xcc\x07\x000\x08\xff\x98\x0c\x7f\x1c\x03\x1e\x18\x07\x000\x06<0\x0c\x7f\x1c\x01\xc0`\x07\x000\x03\x80\xc0\x0c\x7f\x1c\x00\x7f\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f"
|
||||||
|
Pinch_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1d\x7f\xbd\x00\x07\x00:\xfe\xfc\x00\x1c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf4\x00\x0c\x7f\x1c?\xf8\x00\x07\x002\xff\xf0\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\x7f\xe0\x00\x0c\x7f\x1c\x1f\xf0\x00\x07\x000\x7f\xe8\x00\x0c\x7f\x1c\x0f\xe0\x00\x07\x000\xbf\xd0\x00\x0c\x7f\x1c\x03\x80\x00\x07\x000\x0f\x00\x00\x0c\x7f\x1c\x18`\x00\x07\x0000\xc0\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Pinch_middle=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x05\xfe\xf4\x07\x008\x0b\xfb\xf0\x1c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x01\xff\xa0\x0c\x7f\x1c\x00?\x80\x07\x000\x02\xff@\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00<\x00\x0c\x7f\x1c\x00a\x80\x07\x000\x00\xc3\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Pinch_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x17\xfb\xd7\x008\x00/\xef\\\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xff\x0c\x7f\x1c\x00\x03\xff\x87\x000\x00\x0f\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x07\xfe\x0c\x7f\x1c\x00\x01\xff\x07\x000\x00\x07\xfe\x8c\x7f\x1c\x00\x00\xfe\x07\x000\x00\x0b\xfd\x0c\x7f\x1c\x00\x008\x07\x000\x00\x00\xf0\x0c\x7f\x1c\x00\x01C\x07\x000\x00\x03\x0c\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Tear=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1e\x00\x00\x00\x0f\x008\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\xbf\xa0\x07\x008\x02\xfe@\x1c\x7f\x1c\x00\x7f\xc0\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\xfe`\x07\x000\x05\xfd\xa0\x0c\x7f\x1c\x02\xfeh\x07\x000\x03\xf9\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00 \x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x000\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00p\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00p\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\xf8\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x01\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x01\xf6\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x03\xfa\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x03\xfe\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x03\xfe\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x01\xfe\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\xfc\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00p\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Tired_left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\xbf\xba\x00\x07\x00:\xfet\x00\x1c\x7f\x1c\x7f\xf8\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x7f\xfc\x00\x07\x002\xff\xf4\x00\x0c\x7f\x1c\xbf\xfa\x00\x07\x000\xff\xf0\x00\x0c\x7f\x1c\x1f\xf8\x00\x07\x009\x7f\xe8\x00\x1c\x7f\x0e_\xf4\x00\x0e\x008?\xc0\x00\x1c\x7f\x0e\x07\xc0\x00\x0e\x00<\x1f\x80\x00<\x7f\x0f\x10\x10\x00\x1e\x00\x1c @\x008\x7f\x07\x85@\x00<\x00\x1e\x05\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Tired_middle=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x02\xff\xe8\x07\x008\x0b\xfb\xd0\x1c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x008\x05\xff\xa0\x1c\x7f\x0e\x00?\x80\x0e\x008\x00\xff\x00\x1c\x7f\x0e\x00\x0e\x00\x0e\x00<\x01<\x80<\x7f\x0f\x00!\x00\x1e\x00\x1c\x00B\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Tired_right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x1c\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1f\xff\xff\xff\xff\x00?\xff\xff\xff\xfc\x7f\x1c\x00\x0b\xfb\xa7\x008\x00/\xe7\\\x7f\x1c\x00\x07\xff\x87\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x07\xff\xc7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x07\xff\xc7\x000\x00/\xffL\x7f\x1c\x00\x0b\xff\xa7\x000\x00\x0f\xff\x0c\x7f\x1c\x00\x01\xff\x87\x008\x00\x17\xfe\x9c\x7f\x0e\x00\x05\xffN\x008\x00\x03\xfc\x1c\x7f\x0e\x00\x00|\x0e\x00<\x00\x01\xf8<\x7f\x0f\x00\x01\x01\x1e\x00\x1c\x00\x02\x048\x7f\x07\x80\x00(<\x00\x1e\x00\x00Px\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Toxic=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x008\x00\x0c\x7f\x1c\x00\x7f@\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x01\xff\x00\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\x80\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xc4p\x07\x000\x03\x18\xc0\x0c\x7f\x1c\x01\xc4p\x07\x000\x03\x08\xc0\x0c\x7f\x1c\x00\xce`\x07\x000\x03\x99\xc0\x0c\x7f\x1c\x00\xf9\xe0\x07\x000\x01\xe7\x80\x0c\x7f\x1c\x00y\xc0\x07\x000\x00\xe7\x00\x0c\x7f\x1c\x04\x1f\x02\x07\x000\x18>\x0c\x0c\x7f\x1c\x0f\x8a\x1e\x07\x000?\x10<\x0c\x7f\x1c\x0c\xf0\xf3\x07\x0003\xe1\xec\x0c\x7f\x1c\x00>@\x07\x000\x00|\x00\x0c\x7f\x1c\r\xe3\xe6\x07\x000\x1b\xcf\xc8\x0c\x7f\x1c\x0f\xc0\xfe\x07\x000\x1f\x81\xfc\x0c\x7f\x1c\x06\x00\x0e\x07\x000\x0c\x008\x0c\x7f\x1c\x06\x00\x0c\x07\x000\x08\x00\x18\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Up=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00!\x00\x1c\x00\x1e\x00\x82\x00x\x7f\x0e\x00\x0e\x00\x0e\x00\x1c\x00\x1c\x808\x7f\x0e\x00?\x80\x0e\x008\x00\xfe\x00\x1c\x7f\x1c\x00\x7f\xc0\x07\x008\x05\xff\xa0\x1c\x7f\x1c\x00\xfe`\x07\x008\x01\xfc\x80\x1c\x7f\x1c\x02\xfe\xe8\x07\x000\x03\xfb\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x01\xff\xf0\x07\x000\x0b\xff\xd0\x0c\x7f\x1c\x00\xff\xe0\x07\x000\x03\xff\xc0\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x01\xff\x80\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x05\xff\xa0\x0c\x7f\x1c\x00?\x80\x07\x000\x00\xff\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x01<\x80\x0c\x7f\x1c\x00!\x00\x07\x000\x00B\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Winking=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x1f\xff\xff\x00\x00\x00?\xff\xfc\x00\x7f\x00\x7f\xff\xff\xc0\x00\x01\xff\xff\xff\x80\x7f\x01\xff\xff\xff\xf0\x00\x03\xff\xff\xff\xc0\x7f\x03\xe0\x00\x00\xf8\x00\x07\xc0\x00\x03\xe0\x7f\x07\x80\x00\x00<\x00\x0f\x00\x00\x00\xf0\x7f\x07\x00\x00\x00\x1c\x00\x1e\x00\x00\x00x\x7f\x0e\x00\x00\x00\x0e\x00\x1c\x00\x00\x008\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00!\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00?\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\xfe`\x07\x000\x00\x00\x00\x0c\x7f\x1c\x02\xfe\xe8\x07\x000\x00\x00\x00\x0c\x7f\x1c\x01\xff\xf0\x07\x00?\xff\xff\xff\xfc\x7f\x1c\x01\xff\xf0\x07\x00?\xff\xff\xff\xfc\x7f\x1c\x01\xff\xf0\x07\x00?\xff\xff\xff\xfc\x7f\x1c\x00\xff\xe0\x07\x000\x00\x00\x00\x0c\x7f\x1c\x02\xff\xe8\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x7f\xc0\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00?\x80\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x0e\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00!\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x000\x00\x00\x00\x0c\x7f\x1c\x00\x00\x00\x07\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x008\x00\x00\x00\x1c\x7f\x0e\x00\x00\x00\x0e\x00<\x00\x00\x00<\x7f\x0f\x00\x00\x00\x1e\x00\x1c\x00\x00\x008\x7f\x07\x80\x00\x00<\x00\x1e\x00\x00\x00x\x7f\x03\xc0\x00\x00x\x00\x0f\x80\x00\x01\xf0\x7f\x01\xf8\x00\x03\xf0\x00\x07\xe0\x00\x07\xe0\x7f\x00\xff\xff\xff\xe0\x00\x03\xff\xff\xff\xc0\x7f\x00?\xff\xff\x80\x00\x00\xff\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
91
mixly/boards/default/micropython/build/lib/gnss.py
Normal file
91
mixly/boards/default/micropython/build/lib/gnss.py
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
"""
|
||||||
|
GNSS
|
||||||
|
|
||||||
|
Micropython library for the GNSS(NMEA0183/GPS,DBS)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from time import sleep_ms
|
||||||
|
from ubinascii import unhexlify
|
||||||
|
|
||||||
|
class NMEA0183:
|
||||||
|
def __init__(self, uart, baudrate=9600, timeout=200):
|
||||||
|
self._uart=uart
|
||||||
|
self._uart.init(baudrate=baudrate, timeout=timeout, rxbuf=1024)
|
||||||
|
self.time=[None, None, None, None, None, None]
|
||||||
|
self.locate=['', None, '', None, None, None, None] #0'1经度,2'3纬度,4海拔m,5速度m/s,6航向°
|
||||||
|
self.status=[False, ' ', 0] #有效标注,定位模式,卫星量
|
||||||
|
if not self._chip_id():
|
||||||
|
raise AttributeError("Cannot find a GNSS device")
|
||||||
|
|
||||||
|
def _crc8(self, buffer):
|
||||||
|
'''对数据进行CRC校验'''
|
||||||
|
crc = 0x00
|
||||||
|
for byte in buffer:
|
||||||
|
crc ^= byte
|
||||||
|
return crc & 0xff
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
for _ in range(10):
|
||||||
|
sleep_ms(300)
|
||||||
|
if self.any():
|
||||||
|
self._uart.write(("$PCAS02,1000*2E\r\n").encode()) #更新频率1HZ
|
||||||
|
self._uart.write("$PCAS03,1,0,0,0,1,0,0,0,0,0,,,0,0*02\r\n".encode()) #只加载GNGGA和GNRMC
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _judge(self, buffer, dlen):
|
||||||
|
try:
|
||||||
|
data=buffer.strip().decode().split(',')
|
||||||
|
if len(data) == dlen:
|
||||||
|
if unhexlify(data[-1][-2:])[0] == self._crc8(buffer[1:-5]):
|
||||||
|
return True,data
|
||||||
|
return False,None
|
||||||
|
except :
|
||||||
|
return False,None
|
||||||
|
|
||||||
|
def any(self):
|
||||||
|
flag_rmc,flag_gga=False,False
|
||||||
|
while self._uart.any():
|
||||||
|
_data=self._uart.readline()
|
||||||
|
if b'$GNGGA' in _data:
|
||||||
|
flag_gga,data=self._judge(_data, 15)
|
||||||
|
#print("GGA----",flag_gga)
|
||||||
|
if flag_gga:
|
||||||
|
self.time[3]= int(data[1][0:2]) if data[1] else None
|
||||||
|
self.time[4]= int(data[1][2:4]) if data[1] else None
|
||||||
|
self.time[5]= int(data[1][4:6]) if data[1] else None
|
||||||
|
self.locate[0]= data[5]
|
||||||
|
self.locate[1]= int(data[4][:3])+int(data[4][3:].replace('.',''))/6000000 if data[4] else None
|
||||||
|
self.locate[2]= data[3]
|
||||||
|
self.locate[3]= int(data[2][:2])+int(data[2][2:].replace('.',''))/6000000 if data[2] else None
|
||||||
|
self.locate[4]= float(data[9]) if data[3] else None
|
||||||
|
self.status[0]= False if '0' in data[6] else True
|
||||||
|
self.status[2]= int(data[7])
|
||||||
|
if b'$GNRMC' in _data:
|
||||||
|
flag_rmc,data=self._judge(_data, 14)
|
||||||
|
#print("RMC----",flag_rmc)
|
||||||
|
if flag_rmc:
|
||||||
|
self.time[0]= int(data[9][4:6])+2000 if data[9] else None
|
||||||
|
self.time[1]= int(data[9][2:4]) if data[9] else None
|
||||||
|
self.time[2]= int(data[9][0:2]) if data[9] else None
|
||||||
|
self.time[3]= int(data[1][0:2])+8 if data[1] else None
|
||||||
|
self.time[4]= int(data[1][2:4]) if data[1] else None
|
||||||
|
self.time[5]= int(data[1][4:6]) if data[1] else None
|
||||||
|
self.locate[0]= data[6]
|
||||||
|
self.locate[1]= int(data[5][:3])+int(data[5][3:].replace('.',''))/6000000 if data[5] else None
|
||||||
|
self.locate[2]= data[4]
|
||||||
|
self.locate[3]= int(data[3][:2])+int(data[3][2:].replace('.',''))/6000000 if data[3] else None
|
||||||
|
self.locate[5]= round(float(data[7])*0.514, 2) if data[7] else None
|
||||||
|
self.locate[6]= float(data[8]) if data[8] else None
|
||||||
|
self.status[0]= False if 'V' in data[2] else True
|
||||||
|
self.status[1]= data[12]
|
||||||
|
return flag_rmc | flag_gga
|
||||||
|
|
||||||
|
def time(self):
|
||||||
|
return tuple(self.time)
|
||||||
|
|
||||||
|
def locate(self):
|
||||||
|
return tuple(self.locate)
|
||||||
|
|
||||||
|
def status(self):
|
||||||
|
return tuple(self.status)
|
||||||
87
mixly/boards/default/micropython/build/lib/hmac.py
Normal file
87
mixly/boards/default/micropython/build/lib/hmac.py
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
# Implements the hmac module from the Python standard library.
|
||||||
|
|
||||||
|
|
||||||
|
class HMAC:
|
||||||
|
def __init__(self, key, msg=None, digestmod=None):
|
||||||
|
if not isinstance(key, (bytes, bytearray)):
|
||||||
|
raise TypeError("key: expected bytes/bytearray")
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
|
||||||
|
if digestmod is None:
|
||||||
|
# TODO: Default hash algorithm is now deprecated.
|
||||||
|
digestmod = hashlib.md5
|
||||||
|
|
||||||
|
if callable(digestmod):
|
||||||
|
# A hashlib constructor returning a new hash object.
|
||||||
|
make_hash = digestmod # A
|
||||||
|
elif isinstance(digestmod, str):
|
||||||
|
# A hash name suitable for hashlib.new().
|
||||||
|
make_hash = lambda d=b"": getattr(hashlib, digestmod)(d)
|
||||||
|
else:
|
||||||
|
# A module supporting PEP 247.
|
||||||
|
make_hash = digestmod.new # C
|
||||||
|
|
||||||
|
self._outer = make_hash()
|
||||||
|
self._inner = make_hash()
|
||||||
|
|
||||||
|
self.digest_size = getattr(self._inner, "digest_size", None)
|
||||||
|
# If the provided hash doesn't support block_size (e.g. built-in
|
||||||
|
# hashlib), 64 is the correct default for all built-in hash
|
||||||
|
# functions (md5, sha1, sha256).
|
||||||
|
self.block_size = getattr(self._inner, "block_size", 64)
|
||||||
|
|
||||||
|
# Truncate to digest_size if greater than block_size.
|
||||||
|
if len(key) > self.block_size:
|
||||||
|
key = make_hash(key).digest()
|
||||||
|
|
||||||
|
# Pad to block size.
|
||||||
|
key = key + bytes(self.block_size - len(key))
|
||||||
|
|
||||||
|
self._outer.update(bytes(x ^ 0x5C for x in key))
|
||||||
|
self._inner.update(bytes(x ^ 0x36 for x in key))
|
||||||
|
|
||||||
|
if msg is not None:
|
||||||
|
self.update(msg)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return "hmac-" + getattr(self._inner, "name", type(self._inner).__name__)
|
||||||
|
|
||||||
|
def update(self, msg):
|
||||||
|
self._inner.update(msg)
|
||||||
|
|
||||||
|
def copy(self):
|
||||||
|
if not hasattr(self._inner, "copy"):
|
||||||
|
# Not supported for built-in hash functions.
|
||||||
|
raise NotImplementedError()
|
||||||
|
# Call __new__ directly to avoid the expensive __init__.
|
||||||
|
other = self.__class__.__new__(self.__class__)
|
||||||
|
other.block_size = self.block_size
|
||||||
|
other.digest_size = self.digest_size
|
||||||
|
other._inner = self._inner.copy()
|
||||||
|
other._outer = self._outer.copy()
|
||||||
|
return other
|
||||||
|
|
||||||
|
def _current(self):
|
||||||
|
h = self._outer
|
||||||
|
if hasattr(h, "copy"):
|
||||||
|
# built-in hash functions don't support this, and as a result,
|
||||||
|
# digest() will finalise the hmac and further calls to
|
||||||
|
# update/digest will fail.
|
||||||
|
h = h.copy()
|
||||||
|
h.update(self._inner.digest())
|
||||||
|
return h
|
||||||
|
|
||||||
|
def digest(self):
|
||||||
|
h = self._current()
|
||||||
|
return h.digest()
|
||||||
|
|
||||||
|
def hexdigest(self):
|
||||||
|
import binascii
|
||||||
|
|
||||||
|
return str(binascii.hexlify(self.digest()), "utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
def new(key, msg=None, digestmod=None):
|
||||||
|
return HMAC(key, msg, digestmod)
|
||||||
88
mixly/boards/default/micropython/build/lib/hp203x.py
Normal file
88
mixly/boards/default/micropython/build/lib/hp203x.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
"""
|
||||||
|
HP203X
|
||||||
|
|
||||||
|
MicroPython library for the HP203X(Air pressure sensor)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Changed from circuitpython to micropython 20220211
|
||||||
|
#Format unified 20220623
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
HP203X_ADDRESS = const(0x76)
|
||||||
|
HP203X_REG_RST = const(0x06)
|
||||||
|
HP203X_REG_RDY = const(0x0D)
|
||||||
|
HP20X_READ_P = const(0x30)
|
||||||
|
HP20X_READ_H = const(0x31)
|
||||||
|
HP20X_READ_T = const(0x32)
|
||||||
|
HP20X_READ_CAL = const(0x28)
|
||||||
|
HP20X_WR_CONVERT_CMD = const(0x40)
|
||||||
|
|
||||||
|
#转换时间 越大时间越久
|
||||||
|
#HP20X_CONVERT_OSR4096 =0<<2
|
||||||
|
HP20X_CONVERT_OSR2048 =1<<2
|
||||||
|
#HP20X_CONVERT_OSR1024 =2<<2
|
||||||
|
#HP20X_CONVERT_OSR512 =3<<2
|
||||||
|
#HP20X_CONVERT_OSR256 =4<<2
|
||||||
|
#HP20X_CONVERT_OSR128 =5<<2
|
||||||
|
|
||||||
|
class HP203X:
|
||||||
|
def __init__(self, i2c_bus,cal=False):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = HP203X_ADDRESS
|
||||||
|
self.data_reg = bytearray(3)
|
||||||
|
self._buffer = bytearray(1)
|
||||||
|
self.osr = HP20X_CONVERT_OSR2048 #SET time
|
||||||
|
|
||||||
|
if self._read_rdy()&0x40 ==0:
|
||||||
|
raise AttributeError("Cannot find a HP203X")
|
||||||
|
|
||||||
|
self._rst() #Reset
|
||||||
|
time.sleep(0.1)
|
||||||
|
if cal: #Calibration
|
||||||
|
self._write_cmd(HP20X_WR_CONVERT_CMD|self.osr)
|
||||||
|
time.sleep(0.1)
|
||||||
|
self._calibration()
|
||||||
|
print("calibration")
|
||||||
|
|
||||||
|
def _read_data(self, address):
|
||||||
|
self._buffer[0] = address & 0xFF
|
||||||
|
self._device.writeto(self._address,self._buffer)
|
||||||
|
self._device.readfrom_into(self._address,self.data_reg)
|
||||||
|
return self.data_reg
|
||||||
|
|
||||||
|
def _write_cmd(self,command):
|
||||||
|
self._buffer[0] = command & 0xFF
|
||||||
|
self._device.writeto(self._address,self._buffer)
|
||||||
|
|
||||||
|
def _read_rdy(self):
|
||||||
|
return self._read_data(HP203X_REG_RDY)[0]
|
||||||
|
|
||||||
|
def _calibration(self):
|
||||||
|
self._write_cmd(HP20X_READ_CAL)
|
||||||
|
|
||||||
|
def _rst(self):
|
||||||
|
self._write_cmd(HP203X_REG_RST)
|
||||||
|
|
||||||
|
def u2s(self,n):
|
||||||
|
return n if n < (1 << 23) else n - (1 << 24)
|
||||||
|
|
||||||
|
def get_data(self,flag):
|
||||||
|
self._write_cmd(HP20X_WR_CONVERT_CMD|self.osr)
|
||||||
|
time.sleep(0.1)
|
||||||
|
self._read_data(flag)
|
||||||
|
hp_data=(self.data_reg[0]<<16)|(self.data_reg[1]<<8)|self.data_reg[2]
|
||||||
|
return self.u2s(hp_data)/100
|
||||||
|
|
||||||
|
def pressure(self):
|
||||||
|
return self.get_data(HP20X_READ_P)
|
||||||
|
|
||||||
|
def altitude(self):
|
||||||
|
return self.get_data(HP20X_READ_H)
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
return self.get_data(HP20X_READ_T)
|
||||||
59
mixly/boards/default/micropython/build/lib/ht16k33.py
Normal file
59
mixly/boards/default/micropython/build/lib/ht16k33.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
"""
|
||||||
|
HT16K33-framebuf
|
||||||
|
|
||||||
|
Micropython library for the HT16K33 Matrix16x8
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20230411
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import uframebuf
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_HT16K33_BLINK_CMD = const(0x80)
|
||||||
|
_HT16K33_BLINK_DISPLAYON = const(0x01)
|
||||||
|
_HT16K33_CMD_BRIGHTNESS = const(0xE0)
|
||||||
|
_HT16K33_OSCILATOR_ON = const(0x21)
|
||||||
|
|
||||||
|
class HT16K33(uframebuf.FrameBuffer_Ascall):
|
||||||
|
def __init__(self, i2c, address=0x70, brightness=0.3, width=16, height=8):
|
||||||
|
self._i2c = i2c
|
||||||
|
self._address = address
|
||||||
|
self._blink_rate=0
|
||||||
|
self._brightness=brightness
|
||||||
|
self._buffer = bytearray((width + 7) // 8 * height)
|
||||||
|
super().__init__(self._buffer, width, height, uframebuf.MONO_HMSB)
|
||||||
|
self._write_cmd(_HT16K33_OSCILATOR_ON)
|
||||||
|
self.blink_rate(0)
|
||||||
|
self.set_brightness(brightness)
|
||||||
|
self.fill(0)
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
def _write_cmd(self, val):
|
||||||
|
'''I2C write command'''
|
||||||
|
self._i2c.writeto(self._address,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def blink_rate(self, rate=None):
|
||||||
|
if rate is None:
|
||||||
|
return self._blink_rate
|
||||||
|
if not 0 <= rate <= 3:
|
||||||
|
raise ValueError("Blink rate must be an integer in the range: 0-3")
|
||||||
|
rate = rate & 0x03
|
||||||
|
self._blink_rate = rate
|
||||||
|
self._write_cmd(_HT16K33_BLINK_CMD | _HT16K33_BLINK_DISPLAYON | rate << 1)
|
||||||
|
|
||||||
|
def get_brightness(self):
|
||||||
|
return self._brightness
|
||||||
|
|
||||||
|
def set_brightness(self, brightness):
|
||||||
|
if not 0.0 <= brightness <= 1.0:
|
||||||
|
raise ValueError("Brightness must be a decimal number in the range: 0.0-1.0")
|
||||||
|
self._brightness = brightness
|
||||||
|
xbright = round(15 * brightness)
|
||||||
|
xbright = xbright & 0x0F
|
||||||
|
self._write_cmd(_HT16K33_CMD_BRIGHTNESS | xbright)
|
||||||
|
|
||||||
|
def show(self):
|
||||||
|
"""Refresh the display and show the changes."""
|
||||||
|
self._i2c.writeto_mem(self._address, 0x00, self._buffer)
|
||||||
305
mixly/boards/default/micropython/build/lib/huskylens.py
Normal file
305
mixly/boards/default/micropython/build/lib/huskylens.py
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
"""
|
||||||
|
HuskyLens
|
||||||
|
|
||||||
|
MicroPython library for the HuskyLens-I2C(DF)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20220224
|
||||||
|
#base on https://github.com/HuskyLens/HUSKYLENSPython 20220623
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
from ubinascii import unhexlify,hexlify
|
||||||
|
|
||||||
|
commandHeaderAndAddress = "55AA11"
|
||||||
|
algorthimsByteID = {
|
||||||
|
"ALGORITHM_OBJECT_TRACKING": "0100", #物体追踪
|
||||||
|
"ALGORITHM_FACE_RECOGNITION": "0000", #人脸识别
|
||||||
|
"ALGORITHM_OBJECT_RECOGNITION": "0200", #物体识别
|
||||||
|
"ALGORITHM_LINE_TRACKING": "0300", #巡线
|
||||||
|
"ALGORITHM_COLOR_RECOGNITION": "0400", #颜色识别
|
||||||
|
"ALGORITHM_TAG_RECOGNITION": "0500", #标签识别
|
||||||
|
"ALGORITHM_OBJECT_CLASSIFICATION": "0600", #物体分类
|
||||||
|
"ALGORITHM_QR_CODE_RECOGNTITION" : "0700", #二维码识别(教育版独有)
|
||||||
|
"ALGORITHM_BARCODE_RECOGNTITION":"0800", #条形码识别(教育版独有)
|
||||||
|
}
|
||||||
|
|
||||||
|
class Arrow:
|
||||||
|
def __init__(self, xTail, yTail , xHead , yHead, ID):
|
||||||
|
self.xTarget=xTail
|
||||||
|
self.yTarget=yTail
|
||||||
|
self.xOrigin=xHead
|
||||||
|
self.yOrigin=yHead
|
||||||
|
self.id=ID
|
||||||
|
self.learned= True if ID > 0 else False
|
||||||
|
self.type="arrows"
|
||||||
|
|
||||||
|
class Block:
|
||||||
|
def __init__(self, x, y , width , height, ID):
|
||||||
|
self.xCenter = x
|
||||||
|
self.yCenter=y
|
||||||
|
self.width=width
|
||||||
|
self.height=height
|
||||||
|
self.id=ID
|
||||||
|
self.learned= True if ID > 0 else False
|
||||||
|
self.type="blocks"
|
||||||
|
|
||||||
|
class HuskyLens:
|
||||||
|
def __init__(self, i2c,address=0x32):
|
||||||
|
self._address = address
|
||||||
|
self.checkOnceAgain=True
|
||||||
|
self._device = i2c
|
||||||
|
self._buffer=[]
|
||||||
|
self._learned_number=0
|
||||||
|
if not self.knock():
|
||||||
|
raise AttributeError("Cannot find a HuskyLens")
|
||||||
|
|
||||||
|
def _write_cmd(self, cmd):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto(self._address, unhexlify(cmd))
|
||||||
|
|
||||||
|
def _read_cmd(self, nbytes):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom(self._address, nbytes)
|
||||||
|
|
||||||
|
def _checksum(self, hexStr):
|
||||||
|
'''data checksums'''
|
||||||
|
total = 0
|
||||||
|
for i in range(0, len(hexStr), 2):
|
||||||
|
total += int(hexStr[i:i+2], 16)
|
||||||
|
hexStr = hex(total)[-2:]
|
||||||
|
return hexStr
|
||||||
|
|
||||||
|
def _read_data(self):
|
||||||
|
'''Read data'''
|
||||||
|
while True:
|
||||||
|
time.sleep(0.01)
|
||||||
|
buffer = self._read_cmd(5)
|
||||||
|
if buffer[0] == 0x55:
|
||||||
|
break
|
||||||
|
buffer += self._read_cmd(int(buffer[3])+1)
|
||||||
|
strs=hexlify(buffer).decode()
|
||||||
|
|
||||||
|
headers = strs[0:4]
|
||||||
|
address = strs[4:6]
|
||||||
|
data_length = int(strs[6:8], 16)
|
||||||
|
command = strs[8:10]
|
||||||
|
if(data_length > 0):
|
||||||
|
data = strs[10:10+data_length*2]
|
||||||
|
else:
|
||||||
|
data = ''
|
||||||
|
checkSum = strs[2*(6+data_length-1):2*(6+data_length-1)+2]
|
||||||
|
return [headers, address, data_length, command, data, checkSum]
|
||||||
|
|
||||||
|
def getBlockOrArrowCommand(self):
|
||||||
|
commandSplit = self._read_data()
|
||||||
|
isBlock = True if commandSplit[3] == "2a" else False
|
||||||
|
return (commandSplit[4],isBlock)
|
||||||
|
|
||||||
|
def processReturnData(self):
|
||||||
|
inProduction = True
|
||||||
|
byteString=""
|
||||||
|
if inProduction :
|
||||||
|
commandSplit = self._read_data()
|
||||||
|
|
||||||
|
if commandSplit[3] == "2e":
|
||||||
|
return "Knock Recieved"
|
||||||
|
else:
|
||||||
|
returnData = []
|
||||||
|
numberOfBlocksOrArrow = int(commandSplit[4][2:4]+commandSplit[4][0:2], 16)
|
||||||
|
self._learned_number = int(commandSplit[4][6:8]+commandSplit[4][4:6], 16)
|
||||||
|
|
||||||
|
for i in range(numberOfBlocksOrArrow):
|
||||||
|
tmpObj=self.getBlockOrArrowCommand()
|
||||||
|
isBlock=tmpObj[1]
|
||||||
|
returnData.append(tmpObj[0])
|
||||||
|
|
||||||
|
if returnData :
|
||||||
|
finalData = []
|
||||||
|
tmp = []
|
||||||
|
for i in returnData:
|
||||||
|
tmp = []
|
||||||
|
for q in range(0, len(i), 4):
|
||||||
|
low=int(i[q:q+2], 16)
|
||||||
|
high=int(i[q+2:q+4], 16)
|
||||||
|
if(high>0):
|
||||||
|
val=low+255+high
|
||||||
|
else:
|
||||||
|
val=low
|
||||||
|
tmp.append(val)
|
||||||
|
finalData.append(tmp)
|
||||||
|
tmp = []
|
||||||
|
self.checkOnceAgain=True
|
||||||
|
self._buffer=self.convert_to_class_object(finalData,isBlock)
|
||||||
|
return "Data processing completed"
|
||||||
|
else:
|
||||||
|
self._buffer=[]
|
||||||
|
|
||||||
|
def convert_to_class_object(self,data,isBlock):
|
||||||
|
tmp=[]
|
||||||
|
for i in data:
|
||||||
|
if(isBlock):
|
||||||
|
obj = Block(i[0],i[1],i[2],i[3],i[4])
|
||||||
|
else:
|
||||||
|
obj = Arrow(i[0],i[1],i[2],i[3],i[4])
|
||||||
|
tmp.append(obj)
|
||||||
|
return tmp
|
||||||
|
|
||||||
|
def knock(self):
|
||||||
|
'''Send a simple knock to the HuskyLens to ensure that you are connected and can communicate.'''
|
||||||
|
self._write_cmd(commandHeaderAndAddress+"002c3c")
|
||||||
|
return self._read_data()[3] == "2e"
|
||||||
|
|
||||||
|
def command_request_algorthim(self, alg):
|
||||||
|
'''切换xx算法'''
|
||||||
|
if alg in algorthimsByteID:
|
||||||
|
cmd = commandHeaderAndAddress+"022d"+algorthimsByteID[alg]
|
||||||
|
cmd += self._checksum(cmd)
|
||||||
|
self._write_cmd(cmd)
|
||||||
|
return self.processReturnData()
|
||||||
|
else:
|
||||||
|
print("INCORRECT ALGORITHIM NAME")
|
||||||
|
|
||||||
|
def command_request(self):
|
||||||
|
'''请求一次数据 存入结果'''
|
||||||
|
self._write_cmd(commandHeaderAndAddress+"002030")
|
||||||
|
self.processReturnData()
|
||||||
|
|
||||||
|
def read_learned_id_count(self):
|
||||||
|
'''从结果中获取 已学习ID总数'''
|
||||||
|
return self._learned_number
|
||||||
|
|
||||||
|
def is_appear_direct(self,shape):
|
||||||
|
'''从结果中获取 方块或箭头 是否在画面中'''
|
||||||
|
if len(self._buffer) > 0:
|
||||||
|
return self._buffer[0].type == shape
|
||||||
|
|
||||||
|
|
||||||
|
def read_block_center_parameter_direct(self,shape):
|
||||||
|
'''从结果中获取靠近中心 方块或箭头 的信息'''
|
||||||
|
if len(self._buffer) > 0:
|
||||||
|
if self._buffer[0].type == shape :
|
||||||
|
return self._buffer[0]
|
||||||
|
else :
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_learned(self,get_id):
|
||||||
|
'''从结果中获取获取IDx是否已学习'''
|
||||||
|
if 0 < get_id < self._learned_number:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_appear(self,get_id,shape):
|
||||||
|
'''从结果中获取获取IDx 方块或箭头 是否在画面中'''
|
||||||
|
if len(self._buffer) > 0:
|
||||||
|
for i in self._buffer :
|
||||||
|
if i.id == get_id :
|
||||||
|
return i.type == shape
|
||||||
|
|
||||||
|
def read_blocks_arrows_parameter(self,get_id,number,shape):
|
||||||
|
'''从结果中获取获取IDx 第number个方块或箭头 的信息'''
|
||||||
|
if len(self._buffer) > 0:
|
||||||
|
id_list=[]
|
||||||
|
for i in self._buffer :
|
||||||
|
if i.id == get_id and i.type == shape:
|
||||||
|
id_list.append(i)
|
||||||
|
if number is None:
|
||||||
|
return id_list[0]
|
||||||
|
else:
|
||||||
|
return id_list[number-1]
|
||||||
|
|
||||||
|
def read_count(self,get_id,shape):
|
||||||
|
'''从结果中获取获取IDx 方块或箭头 的总数'''
|
||||||
|
num=0
|
||||||
|
if len(self._buffer) > 0:
|
||||||
|
for i in self._buffer :
|
||||||
|
if get_id is None and i.type == shape:
|
||||||
|
num+=1
|
||||||
|
if i.id == get_id and i.type == shape:
|
||||||
|
num+=1
|
||||||
|
return num
|
||||||
|
|
||||||
|
def read_blocks_arrows_parameter_direct(self,number,shape):
|
||||||
|
'''从结果中获取获取第x个 方块或箭头 的信息'''
|
||||||
|
if len(self._buffer) >= number :
|
||||||
|
print(len(self._buffer))
|
||||||
|
if self._buffer[number-1].type == shape :
|
||||||
|
return self._buffer[number-1]
|
||||||
|
|
||||||
|
def command_request_learn_once(self,get_id):
|
||||||
|
'''自动学习一次 IDx'''
|
||||||
|
data = "{:04x}".format(get_id)
|
||||||
|
part1=data[2:]
|
||||||
|
part2=data[0:2]
|
||||||
|
#reverse to correct endiness
|
||||||
|
data=part1+part2
|
||||||
|
dataLen = "{:02x}".format(len(data)//2)
|
||||||
|
cmd = commandHeaderAndAddress+dataLen+"36"+data
|
||||||
|
print("-----",cmd)
|
||||||
|
cmd += self._checksum(cmd)
|
||||||
|
self._write_cmd(cmd)
|
||||||
|
|
||||||
|
def command_request_forget(self):
|
||||||
|
'''遗忘当前算法的所有学习数据'''
|
||||||
|
self._write_cmd(commandHeaderAndAddress+"003747")
|
||||||
|
|
||||||
|
def command_request_customnames(self,name,get_id):
|
||||||
|
'''设置当前算法 IDx 名字为 name'''
|
||||||
|
nameDataSize = "{:02x}".format(len(name)+1)
|
||||||
|
name = hexlify(name).decode()+"00"
|
||||||
|
localId = "{:02x}".format(get_id)
|
||||||
|
data = localId+nameDataSize+name
|
||||||
|
dataLen = "{:02x}".format(len(data)//2)
|
||||||
|
cmd = commandHeaderAndAddress+dataLen+"2f"+data
|
||||||
|
cmd += self._checksum(cmd)
|
||||||
|
self._write_cmd(cmd)
|
||||||
|
|
||||||
|
def command_request_custom_text(self,name,x,y):
|
||||||
|
'''屏幕叠加显示文字name 在 xy'''
|
||||||
|
name=hexlify(name).decode()
|
||||||
|
nameDataSize = "{:02x}".format(len(name)//2)
|
||||||
|
if x>255:
|
||||||
|
x="ff"+"{:02x}".format(x%255)
|
||||||
|
else:
|
||||||
|
x="00"+"{:02x}".format(x)
|
||||||
|
y="{:02x}".format(y)
|
||||||
|
data = nameDataSize+x+y+name
|
||||||
|
dataLen = "{:02x}".format(len(data)//2)
|
||||||
|
cmd = commandHeaderAndAddress+dataLen+"34"+data
|
||||||
|
cmd += self._checksum(cmd)
|
||||||
|
self._write_cmd(cmd)
|
||||||
|
|
||||||
|
def command_request_clear_text(self):
|
||||||
|
'''清除屏幕显示的文字'''
|
||||||
|
self._write_cmd(commandHeaderAndAddress+"003545")
|
||||||
|
|
||||||
|
def command_request_photo(self):
|
||||||
|
'''触发拍照保存到SD卡'''
|
||||||
|
self._write_cmd(commandHeaderAndAddress+"003040")
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
def command_request_screenshot(self):
|
||||||
|
'''触发截屏保存到SD卡'''
|
||||||
|
self._write_cmd(commandHeaderAndAddress+"003949")
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
def command_request_save_model_to_SD_card(self,idVal):
|
||||||
|
'''保存当前算法数据位SD卡 (0~4) 号模型'''
|
||||||
|
idVal = "{:04x}".format(idVal)
|
||||||
|
idVal = idVal[2:]+idVal[0:2]
|
||||||
|
cmd = commandHeaderAndAddress+"0232"+idVal
|
||||||
|
cmd += self._checksum(cmd)
|
||||||
|
self._write_cmd(cmd)
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
def command_request_load_model_from_SD_card(self,idVal):
|
||||||
|
'''加载当前算法数据位SD卡 (0~4) 号模型'''
|
||||||
|
idVal = "{:04x}".format(idVal)
|
||||||
|
idVal = idVal[2:]+idVal[0:2]
|
||||||
|
cmd = commandHeaderAndAddress+"0233"+idVal
|
||||||
|
cmd += self._checksum(cmd)
|
||||||
|
self._write_cmd(cmd)
|
||||||
|
time.sleep(0.5)
|
||||||
69
mixly/boards/default/micropython/build/lib/hx720.py
Normal file
69
mixly/boards/default/micropython/build/lib/hx720.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
"""
|
||||||
|
HX720/HX711
|
||||||
|
|
||||||
|
Micropython library for the HX720/HX711(Load Cell)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from machine import Pin
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
DATA_BITS = const(24)
|
||||||
|
READY_TIMEOUT_SEC = const(500)
|
||||||
|
|
||||||
|
class HX720:
|
||||||
|
def __init__(self, sck_pin, dat_pin, scale=500, pulse_obj=1):
|
||||||
|
self._sck = Pin(sck_pin, Pin.OUT, value=0)
|
||||||
|
self._dat = Pin(dat_pin, Pin.IN, Pin.PULL_UP)
|
||||||
|
self._obj = min(max(pulse_obj, 1), 3)
|
||||||
|
self.scale = scale
|
||||||
|
self.tare()
|
||||||
|
|
||||||
|
def _wait(self):
|
||||||
|
"""超时响应报错"""
|
||||||
|
star = time.ticks_ms()
|
||||||
|
while not self.is_ready():
|
||||||
|
if time.ticks_diff(time.ticks_ms(), star) > READY_TIMEOUT_SEC:
|
||||||
|
raise AttributeError("Cannot find a HX711/HX720")
|
||||||
|
|
||||||
|
def is_ready(self):
|
||||||
|
"""检查是否有数据可以读取"""
|
||||||
|
return self._dat.value() == 0
|
||||||
|
|
||||||
|
def set_scale(self, scale):
|
||||||
|
"""设置比例因子"""
|
||||||
|
self.scale = scale
|
||||||
|
|
||||||
|
def read_raw(self):
|
||||||
|
"""读取传感器的原始数据"""
|
||||||
|
if not self.is_ready():
|
||||||
|
self._wait()
|
||||||
|
raw_data = 0
|
||||||
|
for _ in range(DATA_BITS):
|
||||||
|
self._sck.value(1)
|
||||||
|
self._sck.value(0)
|
||||||
|
raw_data = raw_data << 1 | self._dat.value()
|
||||||
|
|
||||||
|
# 根据脉冲功能设置多读几次
|
||||||
|
for _ in range(self._obj):
|
||||||
|
self._sck.value(1)
|
||||||
|
self._sck.value(0)
|
||||||
|
|
||||||
|
return raw_data if raw_data < (1 << (DATA_BITS - 1)) else raw_data - (1 << DATA_BITS)
|
||||||
|
|
||||||
|
def tare(self, times=10):
|
||||||
|
"""清零传感器"""
|
||||||
|
_values = []
|
||||||
|
for _ in range(max(times, 5)):
|
||||||
|
_values.append(self.read_raw())
|
||||||
|
_values = sorted(_values)[2: -2]
|
||||||
|
self.offset = sum(_values) / len(_values)
|
||||||
|
|
||||||
|
def read_weight(self, times=5):
|
||||||
|
"""读取重量数据,返回去掉偏移量的平均值"""
|
||||||
|
_values = []
|
||||||
|
for _ in range(max(times, 3)):
|
||||||
|
_values.append(self.read_raw())
|
||||||
|
_values = sorted(_values)[1: -1]
|
||||||
|
return round((sum(_values) / len(_values)- self.offset) / self.scale, 2)
|
||||||
280
mixly/boards/default/micropython/build/lib/i2cdevice.py
Normal file
280
mixly/boards/default/micropython/build/lib/i2cdevice.py
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
"""
|
||||||
|
I2C_Device
|
||||||
|
|
||||||
|
Micropython library for the I2C communication Device(TD)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import random
|
||||||
|
from machine import SoftI2C
|
||||||
|
|
||||||
|
def _u2s(value, n=8):
|
||||||
|
return value if value < (1 << (n-1)) else value - (1 << n)
|
||||||
|
|
||||||
|
'''i2c-Inheritance'''
|
||||||
|
class I2C_device(SoftI2C):
|
||||||
|
|
||||||
|
CRC8_Table =b'\x00^\xbc\xe2a?\xdd\x83\xc2\x9c~ \xa3\xfd\x1fA\x9d\xc3!\x7f\xfc\xa2@\x1e_\x01\xe3\xbd>`\x82\xdc#}\x9f\xc1B\x1c\xfe\xa0\xe1\xbf]\x03\x80\xde<b\xbe\xe0\x02\\\xdf\x81c=|"\xc0\x9e\x1dC\xa1\xffF\x18\xfa\xa4\'y\x9b\xc5\x84\xda8f\xe5\xbbY\x07\xdb\x85g9\xba\xe4\x06X\x19G\xa5\xfbx&\xc4\x9ae;\xd9\x87\x04Z\xb8\xe6\xa7\xf9\x1bE\xc6\x98z$\xf8\xa6D\x1a\x99\xc7%{:d\x86\xd8[\x05\xe7\xb9\x8c\xd20n\xed\xb3Q\x0fN\x10\xf2\xac/q\x93\xcd\x11O\xad\xf3p.\xcc\x92\xd3\x8do1\xb2\xec\x0eP\xaf\xf1\x13M\xce\x90r,m3\xd1\x8f\x0cR\xb0\xee2l\x8e\xd0S\r\xef\xb1\xf0\xaeL\x12\x91\xcf-s\xca\x94v(\xab\xf5\x17I\x08V\xb4\xeai7\xd5\x8bW\t\xeb\xb56h\x8a\xd4\x95\xcb)w\xf4\xaaH\x16\xe9\xb7U\x0b\x88\xd64j+u\x97\xc9J\x14\xf6\xa8t*\xc8\x96\x15K\xa9\xf7\xb6\xe8\nT\xd7\x89k5'
|
||||||
|
|
||||||
|
def _crc8(self, buf):
|
||||||
|
_sum = 0
|
||||||
|
for i in range(0, len(buf)):
|
||||||
|
_sum = self.CRC8_Table[_sum ^ buf[i]]
|
||||||
|
return _sum
|
||||||
|
|
||||||
|
def read_device(self, addr, cmd, nbytes=1):
|
||||||
|
buf = self.readfrom_mem(addr, cmd, nbytes+2)
|
||||||
|
if self._crc8(buf[:-1]) == buf[-1]:
|
||||||
|
return buf[1] if nbytes<=1 else buf[1:-1]
|
||||||
|
|
||||||
|
def write_device(self, addr, cmd, buf=0):
|
||||||
|
buf = buf.to_bytes(1, 'little') if type(buf) is int else buf
|
||||||
|
buf = bytearray([cmd, random.randint(0, 255)]) + buf
|
||||||
|
crc8 = self._crc8(buf).to_bytes(1, 'little')
|
||||||
|
self.writeto(addr, buf + crc8)
|
||||||
|
if crc8 == self.readfrom(addr, 1):
|
||||||
|
return True
|
||||||
|
|
||||||
|
'''Fundamentals of Sensors'''
|
||||||
|
class Base:
|
||||||
|
def __init__(self, i2c_bus):
|
||||||
|
self._i2c = i2c_bus
|
||||||
|
|
||||||
|
def addr_set(self, old=0, new=0):
|
||||||
|
try:
|
||||||
|
self._i2c.write_device(self._addrs[old], 0x04, bytearray([self._addrs[old], self._addrs[new]]))
|
||||||
|
except Exception as e:
|
||||||
|
print("Warning: No serial number can be changed or", e)
|
||||||
|
|
||||||
|
def addr_get(self):
|
||||||
|
_addred = []
|
||||||
|
for add in self._i2c.scan():
|
||||||
|
if add in self._addrs:
|
||||||
|
_addred.append(self._addrs.index(add))
|
||||||
|
return tuple(_addred)
|
||||||
|
|
||||||
|
'''Motor'''
|
||||||
|
class Motor(Base):
|
||||||
|
_addrs = [0x30, 0x31, 0x32, 0x33]
|
||||||
|
|
||||||
|
def run(self, naddr=0, speed=None):
|
||||||
|
'''普票电机参数 speed: 速度-100~100%, None返回速度值'''
|
||||||
|
try:
|
||||||
|
if speed is None:
|
||||||
|
return _u2s(self._i2c.read_device(self._addrs[naddr], 0x10))
|
||||||
|
else:
|
||||||
|
speed = max(min(speed, 100), -100)
|
||||||
|
self._i2c.write_device(self._addrs[naddr], 0xA0, speed)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Motor device", e)
|
||||||
|
|
||||||
|
'''Traffic light'''
|
||||||
|
class Traffic_LED(Base):
|
||||||
|
_addrs = [0x48, 0x49, 0x4A, 0x4B]
|
||||||
|
|
||||||
|
def led(self, naddr=0, num=0, value=0):
|
||||||
|
'''交通灯参数 value: 0,全灭 1,长亮 -1,闪烁(1hz)'''
|
||||||
|
try:
|
||||||
|
if value == 0:
|
||||||
|
self._i2c.write_device(self._addrs[naddr], 0xA0, 0x00)
|
||||||
|
elif value == 1:
|
||||||
|
self._i2c.write_device(self._addrs[naddr], 0xA0, 0x04 >> num)
|
||||||
|
elif value == -1:
|
||||||
|
self._i2c.write_device(self._addrs[naddr], 0xA0, 0x40 >> num)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Traffic lights", e)
|
||||||
|
|
||||||
|
'''LED'''
|
||||||
|
class LED(Base):
|
||||||
|
|
||||||
|
def brightness(self, naddr=0, value=None):
|
||||||
|
'''LED灯参数 value: 亮度0~100%, None返回亮度值'''
|
||||||
|
try:
|
||||||
|
if value is None:
|
||||||
|
return self._i2c.read_device(self._addrs[naddr], 0x10)
|
||||||
|
else:
|
||||||
|
value = max(min(value, 100), 0)
|
||||||
|
self._i2c.write_device(self._addrs[naddr], 0xA0, value)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a LED device", e)
|
||||||
|
|
||||||
|
class W_LED(LED):
|
||||||
|
_addrs = [0x38, 0x39, 0x3A, 0x3B]
|
||||||
|
|
||||||
|
class R_LED(LED):
|
||||||
|
_addrs = [0x3C, 0x3D, 0x3E, 0x3F]
|
||||||
|
|
||||||
|
class Y_LED(LED):
|
||||||
|
_addrs = [0x40, 0x41, 0x42, 0x43]
|
||||||
|
|
||||||
|
class G_LED(LED):
|
||||||
|
_addrs = [0x44, 0x45, 0x46, 0x47]
|
||||||
|
|
||||||
|
class B_LED(LED):
|
||||||
|
_addrs = [0x78, 0x79, 0x7A, 0x7B]
|
||||||
|
|
||||||
|
'''button*5'''
|
||||||
|
class Buttonx5(Base):
|
||||||
|
_addrs = [0x68, 0x69, 0x6A, 0x6B]
|
||||||
|
|
||||||
|
def value(self, naddr=0):
|
||||||
|
'''十字按键返回 (上,下,左,右,中)/bool'''
|
||||||
|
try:
|
||||||
|
flag = self._i2c.read_device(self._addrs[naddr], 0x10)
|
||||||
|
return bool(flag >> 4 & 1), bool(flag >> 3 & 1), bool(flag >> 2 & 1), bool(flag >> 1 & 1), bool(flag & 1)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Button sensor", e)
|
||||||
|
|
||||||
|
'''button*1'''
|
||||||
|
class Button(Base):
|
||||||
|
_addrs = [0x54, 0x55, 0x56, 0x57]
|
||||||
|
|
||||||
|
def value(self, naddr=0):
|
||||||
|
'''触碰传感器返回 数值/bool'''
|
||||||
|
try:
|
||||||
|
return bool(self._i2c.read_device(self._addrs[naddr], 0x10))
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Touch sensor", e)
|
||||||
|
|
||||||
|
'''Infrared sensor'''
|
||||||
|
class Infrared(Base):
|
||||||
|
_addrs = [0x6C, 0x6D, 0x6E, 0x6F]
|
||||||
|
|
||||||
|
def value(self, naddr=0):
|
||||||
|
'''红外接近返回 数值0~100%'''
|
||||||
|
try:
|
||||||
|
return self._i2c.read_device(self._addrs[naddr], 0x10)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Infrared sensor", e)
|
||||||
|
|
||||||
|
'''ultrasonic sensor'''
|
||||||
|
class Sonar(Base):
|
||||||
|
_addrs = [0x24, 0x25, 0x26, 0x27]
|
||||||
|
_state = 0x00
|
||||||
|
def value(self, naddr=0):
|
||||||
|
'''超声波测距返回 距离数值cm'''
|
||||||
|
try:
|
||||||
|
value = self._i2c.read_device(self._addrs[naddr], 0x10, 2)
|
||||||
|
return value[0] << 8 | value[1]
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Ultrasonic sensor", e)
|
||||||
|
|
||||||
|
def led(self, naddr=0, num=0, value=0):
|
||||||
|
'''超声波指示灯参数 num:序号0~3,value:0灭,1亮,-1反转 '''
|
||||||
|
try:
|
||||||
|
if value > 0:
|
||||||
|
self._state |= 1 << num
|
||||||
|
elif value < 0:
|
||||||
|
self._state ^= 1 << num
|
||||||
|
else:
|
||||||
|
self._state &= ~ (1 << num)
|
||||||
|
self._i2c.write_device(self._addrs[naddr], 0xA0, bytearray([self._state & 0xff, 0x00]))
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Ultrasonic sensor", e)
|
||||||
|
|
||||||
|
'''Potentiometer'''
|
||||||
|
class Dimmer(Base):
|
||||||
|
_addrs = [0x2C, 0x2D, 0x2E, 0x2F]
|
||||||
|
|
||||||
|
def value(self, naddr=0):
|
||||||
|
'''旋钮传感器返回 数值0~100%'''
|
||||||
|
try:
|
||||||
|
return self._i2c.read_device(self._addrs[naddr], 0x10)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Potentiometer", e)
|
||||||
|
|
||||||
|
'''Color sensor'''
|
||||||
|
class Color_ID(Base):
|
||||||
|
_id = ('Black', 'Violet', 'Unknown', 'Blue', 'Cyan', 'Green', 'Unknown', 'Yellow', 'Unknown', 'Red', 'White', 'Unknown')
|
||||||
|
_addrs = [0x20, 0x21, 0x22, 0x23]
|
||||||
|
|
||||||
|
def recognition(self, naddr=0):
|
||||||
|
'''颜色识别返回 (颜色名,(R,G,B),环境亮度0~100,反射亮度0~100)'''
|
||||||
|
try:
|
||||||
|
color = self._i2c.read_device(self._addrs[naddr], 0x10, 6)
|
||||||
|
return self._id[min(color[0],11)], (color[1],color[2],color[3]), color[4], color[5]
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Color sensor", e)
|
||||||
|
|
||||||
|
'''Laser Sensor'''
|
||||||
|
class TOF(Base):
|
||||||
|
_addrs = [0x5C, 0x5D, 0x5E, 0x5F]
|
||||||
|
|
||||||
|
def value(self, naddr=0):
|
||||||
|
'''激光测距传感器返回 数值cm'''
|
||||||
|
try:
|
||||||
|
flag = self._i2c.read_device(self._addrs[naddr], 0x10, 2)
|
||||||
|
return (flag[0] << 8 | flag[1]) / 100
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Laser Sensor", e)
|
||||||
|
|
||||||
|
def enable(self, naddr=0, en=True):
|
||||||
|
'''激光测距传感器 en:0关闭,1打开'''
|
||||||
|
try:
|
||||||
|
self._i2c.write_device(self._addrs[naddr], 0xA0, int(en) & 0x01)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Laser Sensor", e)
|
||||||
|
|
||||||
|
'''Servo Motor'''
|
||||||
|
class Motor_servo(Base):
|
||||||
|
_addrs = [0x60, 0x61, 0x62, 0x63]
|
||||||
|
_mstop = [0, 0, 0, 0]
|
||||||
|
|
||||||
|
def stop_mode(self, naddr=0, mode=0):
|
||||||
|
'''电机停止模式 mode:0,保持位置 1,惯性滑行 2,阻力制动'''
|
||||||
|
self._mstop[naddr] = mode
|
||||||
|
|
||||||
|
def _write(self, naddr=0, mode=0, value=0, direction=0, angle=0, origin=0, keep=0, select=0):
|
||||||
|
'''寄存器参数设置'''
|
||||||
|
try:
|
||||||
|
_bytes1 = direction<<6 | mode<<5 | select<<4 | origin<<3 | keep<<2 | self._mstop[naddr]
|
||||||
|
_bytes2 = max(min(value, 100), 0)
|
||||||
|
_bytes3 = angle & 0xFF
|
||||||
|
_bytes4 = angle>>8 & 0xFF
|
||||||
|
_bytes5 = angle>>16 & 0xFF
|
||||||
|
self._i2c.write_device(self._addrs[naddr], 0xA0, bytearray([_bytes1, _bytes2, _bytes3, _bytes4, _bytes5]))
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Servo Motor", e)
|
||||||
|
|
||||||
|
def absolute_run(self, naddr=0, mode=0, value=50, direction=0, angle=0):
|
||||||
|
''' 绝对角度运行模式(类舵机)
|
||||||
|
运行模式mode 0:速度模式,1:功率模式
|
||||||
|
模式数值value 0~100%
|
||||||
|
转向设置direction 0:顺时针,1:最短路径,2:逆时针
|
||||||
|
旋转角度angle 0~360°
|
||||||
|
'''
|
||||||
|
self._write(naddr=naddr, mode=mode, value=value, direction=direction, angle=angle, select=0)
|
||||||
|
|
||||||
|
def relative_run(self, naddr=0, mode=0, value=50, angle=0):
|
||||||
|
''' 相对角度运行模式(类编码电机)
|
||||||
|
运行模式mode 0:速度模式,1:功率模式
|
||||||
|
模式数值value 0~100%
|
||||||
|
旋转角度angle -8388607~8388607°
|
||||||
|
'''
|
||||||
|
self._write(naddr=naddr, mode=mode, value=value, angle=angle, select=1)
|
||||||
|
|
||||||
|
def relative_origin(self, naddr=0):
|
||||||
|
'''当前位置设置为原点'''
|
||||||
|
self._write(naddr=naddr, origin=1, select=1)
|
||||||
|
|
||||||
|
def relative_continue(self, naddr=0, mode=0, value=50, direction=0):
|
||||||
|
''' 相对角度运行模式(类普通电机)
|
||||||
|
运行模式mode 0:速度模式,1:功率模式
|
||||||
|
模式数值value 0~100%
|
||||||
|
转向设置direction 0:顺时针,2:逆时针
|
||||||
|
'''
|
||||||
|
self._write(naddr=naddr, mode=mode, value=value, direction=direction, keep=1, select=1)
|
||||||
|
|
||||||
|
def stop(self, naddr=0):
|
||||||
|
'''电机停止'''
|
||||||
|
self._write(naddr=naddr, keep=1)
|
||||||
|
|
||||||
|
def state(self,naddr=0):
|
||||||
|
'''运行状态返回 (功率, 速度, 绝对角度, 相对角度, 是否堵住, 是否转完) '''
|
||||||
|
try:
|
||||||
|
_buf = self._i2c.read_device(self._addrs[naddr], 0x10, 7)
|
||||||
|
return _u2s(_buf[0]), _u2s(_buf[1]), (_buf[2] & 0x01)<<8 | _buf[3], _u2s((_buf[4]<<16 | _buf[5]<<8 | _buf[6]),24), bool(_buf[2] & 0x40), bool(_buf[2] & 0x80)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("Cannot find a Servo Motor", e)
|
||||||
79
mixly/boards/default/micropython/build/lib/i2clcd.py
Normal file
79
mixly/boards/default/micropython/build/lib/i2clcd.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
"""
|
||||||
|
LCD1602、LCD2004_I2C
|
||||||
|
|
||||||
|
Micropython library for the I2C(LCD1602、LCD2004)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20221117
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from time import sleep_ms
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
LCD_DAT = const(0x01) # Mode - Sending data
|
||||||
|
LCD_CMD = const(0x00) # Mode - Sending command
|
||||||
|
LCD_LINES = (0x80, 0xC0, 0x94, 0xD4)
|
||||||
|
|
||||||
|
class LCD():
|
||||||
|
def __init__(self, i2c_bus, i2c_addr=0x27, lcd_width=16):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = i2c_addr
|
||||||
|
self._lcd_width = lcd_width
|
||||||
|
self._backlight = True
|
||||||
|
self._last_data = 0x00
|
||||||
|
|
||||||
|
for i in [0x30, 0x30, 0x30,0x20]:
|
||||||
|
self._i2c_write(i)
|
||||||
|
sleep_ms(1)
|
||||||
|
for i in [0x28, 0x0C, 0x06]:
|
||||||
|
self.write_byte(i , LCD_CMD)
|
||||||
|
self.clear()
|
||||||
|
|
||||||
|
def _i2c_write(self, data , pulse_en=True):
|
||||||
|
"""write one byte to I2C bus"""
|
||||||
|
self._last_data = data
|
||||||
|
self._device.writeto(self._address,data.to_bytes(1, 'little'))
|
||||||
|
sleep_ms(0)
|
||||||
|
if pulse_en :
|
||||||
|
self._device.writeto(self._address,(data | 0b00000100).to_bytes(1, 'little'))
|
||||||
|
sleep_ms(0)
|
||||||
|
self._device.writeto(self._address,(data & ~0b00000100).to_bytes(1, 'little'))
|
||||||
|
sleep_ms(0)
|
||||||
|
|
||||||
|
def write_byte(self, data, mode):
|
||||||
|
"""write one byte to LCD"""
|
||||||
|
data_H = (data & 0xF0) | self._backlight * 0x08 | mode
|
||||||
|
data_L = ((data << 4) & 0xF0) | self._backlight * 0x08 | mode
|
||||||
|
self._i2c_write(data_H)
|
||||||
|
self._i2c_write(data_L)
|
||||||
|
|
||||||
|
def clear(self):
|
||||||
|
"""Clear the display and reset the cursor position"""
|
||||||
|
self.write_byte(0x01, LCD_CMD)
|
||||||
|
sleep_ms(1)
|
||||||
|
|
||||||
|
def backlight(self, on_off):
|
||||||
|
""" Set whether the LCD backlight is on or off"""
|
||||||
|
self._backlight = on_off & 0x01
|
||||||
|
i2c_data = (self._last_data & 0xF7) + self._backlight * 0x08
|
||||||
|
self._i2c_write(i2c_data,pulse_en=False)
|
||||||
|
|
||||||
|
def shows(self, text, line=0, column=0, center=False):
|
||||||
|
'''Character display'''
|
||||||
|
text = str(text).encode('ascii')
|
||||||
|
column=(self._lcd_width-len(text))//2 if center else column
|
||||||
|
self.write_byte(LCD_LINES[line] + column, LCD_CMD)
|
||||||
|
for b in text:
|
||||||
|
self.write_byte(0x0C+0*0x02+0*0x01, LCD_CMD)
|
||||||
|
self.write_byte(b, LCD_DAT)
|
||||||
|
|
||||||
|
def print(self, text, line=0, column=0, delay=500):
|
||||||
|
'''Print Effect Character Display'''
|
||||||
|
text = str(text).encode('ascii')
|
||||||
|
self.write_byte(LCD_LINES[line] + column, LCD_CMD)
|
||||||
|
for b in text:
|
||||||
|
self.write_byte(0x0C+1*0x02+1*0x01, LCD_CMD)
|
||||||
|
sleep_ms(delay)
|
||||||
|
self.write_byte(b, LCD_DAT)
|
||||||
|
sleep_ms(delay)
|
||||||
94
mixly/boards/default/micropython/build/lib/icm42670.py
Normal file
94
mixly/boards/default/micropython/build/lib/icm42670.py
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
"""
|
||||||
|
ICM42670P
|
||||||
|
|
||||||
|
Micropython library for the ICM42670P(Accelerometer+Gyroscope)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20220716
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
ICM42670_REG_DEVICE_ID = const(0x00)
|
||||||
|
ICM42670_REG_RESET = const(0x02)
|
||||||
|
ICM42670_REG_DATA = const(0x09)
|
||||||
|
ICM42670_REG_PWR_MGMT0 = const(0x1F)
|
||||||
|
ICM42670_REG_GYRO_CONFIG0 = const(0x20)
|
||||||
|
ICM42670_REG_ACCEL_CONFIG0 = const(0x21)
|
||||||
|
ICM42670_REG_APEX_DATA0 = const(0x31)
|
||||||
|
ICM42670_REG_WHO_AM_I = const(0x75)
|
||||||
|
|
||||||
|
AccRange_16g = 0
|
||||||
|
AccRange_8g = 1
|
||||||
|
AccRange_4g = 2
|
||||||
|
AccRange_2g = 3
|
||||||
|
|
||||||
|
GyrRange_2000dps = 0
|
||||||
|
GyrRange_1000dps = 1
|
||||||
|
GyrRange_500dps = 2
|
||||||
|
GyrRange_250dps = 3
|
||||||
|
|
||||||
|
Acc_Gyr_Odr_1600Hz = 0x05
|
||||||
|
Acc_Gyr_Odr_800Hz = 0x06
|
||||||
|
Acc_Gyr_Odr_400Hz = 0x07
|
||||||
|
Acc_Gyr_Odr_200Hz = 0x08
|
||||||
|
Acc_Gyr_Odr_100Hz = 0x09
|
||||||
|
Acc_Gyr_Odr_50Hz = 0x0A
|
||||||
|
Acc_Gyr_Odr_25Hz = 0x0B
|
||||||
|
Acc_Gyr_Odr_12_5Hz = 0x0C
|
||||||
|
|
||||||
|
class ICM42670:
|
||||||
|
def __init__(self, i2c_bus, addr=0x68, AccRange=AccRange_16g, GyrRange=GyrRange_2000dps, Acc_Gyr_Odr=Acc_Gyr_Odr_100Hz):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
if self._chip_id() != 0x67:
|
||||||
|
raise AttributeError("Cannot find a ICM42670")
|
||||||
|
|
||||||
|
self._wreg(ICM42670_REG_RESET,0x10) #Software reset enabled
|
||||||
|
time.sleep(0.1)
|
||||||
|
self._wreg(ICM42670_REG_GYRO_CONFIG0,(GyrRange << 4) | Acc_Gyr_Odr) #Gyr-500HZ/2000dps
|
||||||
|
self._wreg(ICM42670_REG_ACCEL_CONFIG0,(AccRange << 4) | Acc_Gyr_Odr) #ACC-100HZ/16G
|
||||||
|
self._wreg(ICM42670_REG_PWR_MGMT0,0x1E)
|
||||||
|
time.sleep(0.1)
|
||||||
|
self.acc_lsb_div= 2 ** (11 + AccRange)
|
||||||
|
self.gyr_lsb_div= 2 ** (14 + GyrRange)
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg,nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
return self._rreg(ICM42670_REG_WHO_AM_I)
|
||||||
|
|
||||||
|
def u2s(self,n):
|
||||||
|
return n if n < (1 << 15) else n - (1 << 16)
|
||||||
|
|
||||||
|
def getdata(self):
|
||||||
|
_buffer=self._rreg(ICM42670_REG_DATA,14)
|
||||||
|
tmp= float(self.u2s(_buffer[0]<<8|_buffer[1]))/128+25
|
||||||
|
acc_x=float(self.u2s(_buffer[2]<<8|_buffer[3]))/self.acc_lsb_div
|
||||||
|
acc_y=float(self.u2s(_buffer[4]<<8|_buffer[5]))/self.acc_lsb_div
|
||||||
|
acc_z=float(self.u2s(_buffer[6]<<8|_buffer[7]))/self.acc_lsb_div
|
||||||
|
gyr_x=float(self.u2s(_buffer[8]<<8|_buffer[9]))/self.gyr_lsb_div
|
||||||
|
gyr_y=float(self.u2s(_buffer[10]<<8|_buffer[11]))/self.gyr_lsb_div
|
||||||
|
gyr_z=float(self.u2s(_buffer[12]<<8|_buffer[13]))/self.gyr_lsb_div
|
||||||
|
return (acc_x,acc_y,acc_z),(gyr_x,gyr_y,gyr_z),round(tmp,2)
|
||||||
|
|
||||||
|
def accelerometer(self):
|
||||||
|
return self.getdata()[0]
|
||||||
|
|
||||||
|
def strength(self):
|
||||||
|
from math import sqrt
|
||||||
|
return sqrt(self.accelerometer()[0]**2+self.accelerometer()[1]**2+self.accelerometer()[2]**2)
|
||||||
|
|
||||||
|
def gyroscope(self):
|
||||||
|
return self.getdata()[1]
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
return self.getdata()[2]
|
||||||
87
mixly/boards/default/micropython/build/lib/image.py
Normal file
87
mixly/boards/default/micropython/build/lib/image.py
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
"""
|
||||||
|
Iamge
|
||||||
|
|
||||||
|
MicroPython library for the Iamge(jpeg C module)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import gc
|
||||||
|
import urequests
|
||||||
|
from base64 import b64encode
|
||||||
|
from jpeg import Encoder, Decoder
|
||||||
|
|
||||||
|
class IMG:
|
||||||
|
def __init__(self, image, width, height):
|
||||||
|
self.image = image
|
||||||
|
self.width = width
|
||||||
|
self.height = height
|
||||||
|
self.format = "RGB565"
|
||||||
|
|
||||||
|
class Image:
|
||||||
|
def save(self, img, path="mixly.jpg", **kwargs):
|
||||||
|
'''quality(1-100), rotation (0, 90, 180, 270)'''
|
||||||
|
_encoder = Encoder(pixel_format="RGB565_BE", width=img.width, height=img.height, **kwargs)
|
||||||
|
_jpeg = _encoder.encode(img.image)
|
||||||
|
del _encoder
|
||||||
|
gc.collect()
|
||||||
|
if isinstance(path, str):
|
||||||
|
with open(path, 'wb') as f:
|
||||||
|
f.write(_jpeg)
|
||||||
|
else:
|
||||||
|
return _jpeg
|
||||||
|
|
||||||
|
def open(self, path="mixly.jpg", scale_width=None, scale_height=None, tft_width=240, tft_height=240, **kwargs):
|
||||||
|
'''rotation (0, 90, 180, 270), clipper_width, clipper_height'''
|
||||||
|
with open(path, "rb") as f:
|
||||||
|
_jpeg = f.read()
|
||||||
|
return self._jpg_decoder(_jpeg, scale_width, scale_height, tft_width, tft_height, **kwargs)
|
||||||
|
|
||||||
|
def convert(self, img, formats=0, **kwargs):
|
||||||
|
if formats == 0:
|
||||||
|
return self.save(img, None, **kwargs)
|
||||||
|
elif formats == 1:
|
||||||
|
return b'data:image/jpg;base64,' + b64encode(self.save(img, None, **kwargs))
|
||||||
|
|
||||||
|
def download(self, url, path=None, scale_width=None, scale_height=None, tft_width=240, tft_height=240, block=1024, **kwargs):
|
||||||
|
'''rotation (0, 90, 180, 270), clipper_width, clipper_height'''
|
||||||
|
response = urequests.get(url, stream=True)
|
||||||
|
if path is None:
|
||||||
|
_image = self._jpg_decoder(response.raw.read(), scale_width, scale_height, tft_width, tft_height, **kwargs)
|
||||||
|
response.close()
|
||||||
|
return _image
|
||||||
|
else:
|
||||||
|
with open(path, 'wb') as f:
|
||||||
|
while True:
|
||||||
|
_data = response.raw.read(block)
|
||||||
|
if not _data:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
f.write(_data)
|
||||||
|
response.close()
|
||||||
|
|
||||||
|
def _jpg_decoder(self, jpg, scale_width, scale_height, tft_width, tft_height, **kwargs):
|
||||||
|
'''Automatically zoom based on the screen'''
|
||||||
|
if scale_width is None or scale_height is None:
|
||||||
|
_width = tft_width
|
||||||
|
_height = tft_height
|
||||||
|
for i in range(min(len(jpg), 1024)):
|
||||||
|
if jpg[i] == 0xFF and (jpg[i + 1] & 0xF0) == 0xC0:
|
||||||
|
if jpg[i + 1] not in [0xC4, 0xC8, 0xCC]:
|
||||||
|
_width = jpg[i + 7] << 8 | jpg[i + 8]
|
||||||
|
_height = jpg[i + 5] << 8| jpg[i + 6]
|
||||||
|
break
|
||||||
|
if _width > tft_width or _height > tft_height:
|
||||||
|
_scale = max(_width / tft_width, _height / tft_height) * 8
|
||||||
|
_decoder = Decoder(pixel_format="RGB565_BE", scale_width=round(_width / _scale) * 8, scale_height=round(_height / _scale) * 8, **kwargs)
|
||||||
|
else:
|
||||||
|
_decoder = Decoder(pixel_format="RGB565_BE", **kwargs)
|
||||||
|
else:
|
||||||
|
_decoder = Decoder(pixel_format="RGB565_BE", scale_width=scale_width // 8 * 8, scale_height=scale_height // 8 * 8, **kwargs)
|
||||||
|
_info = _decoder.get_img_info(jpg)
|
||||||
|
_image = IMG(_decoder.decode(jpg), _info[0], _info[1])
|
||||||
|
del _decoder, jpg
|
||||||
|
gc.collect()
|
||||||
|
return _image
|
||||||
|
|
||||||
|
#图像处理
|
||||||
|
Image = Image()
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
#Take the picture bytes in informatio_picture.py
|
||||||
|
#--dahanzimin From the Mixly Team
|
||||||
|
|
||||||
|
Accept=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x8c\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x01\xa7\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x03y\x80\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x02~`\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x04\xff0\x00\x7f\x00\x00\x00\x00\x00\x00\x00\t\xff\xec\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x1b\xff\xf6\x00\x7f\x00\x00\x00\x00\x00\x00\x007\xff\xfd\x80\x7f\x00\x00\x00\x00\x00\x00\x00o\xff\xff\x80\x7f\x00\x00\x00\x00\x00\x00\x00_\xff\xff\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x9f\xff\xfe\x00\x7f\x00\x00\x00\x00\x00\x00\x01\xbf\xff\xfc\x00\x7f\x00\x00\x00\x00\x00\x00\x03\x7f\xff\xf8\x00\x7f\x00\x00\x00\x00\x00\x00\x06\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\x00\x05\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\x00\x0b\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x00\x00\x17\xff\xff\x80\x00\x7f\x00\x00\x00\x00\x00\x007\xff\xfe\x00\x00\x7f\x00\x00\x00\x00\x00\x00o\xff\xfc\x00\x00\x7f\x00\x00\x00\x00\x00\x00_\xff\xf8\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xbf\xff\xf0\x00\x00\x7f\x00\x00\x00\x00\x00\x01\x7f\xff\xe0\x00\x00\x7f\x00\x00\x00\x00\x00\x03\x7f\xff\xc0\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xff\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\r\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0b\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x00\x00/\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\xff\xf0\x00\x00\x00\x7f\x00\x00\x01\xc0\x00\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x1e@\x00\xff\xff\xc0\x00\x00\x00\x7f\x00\x01\xeb \x01\xff\xff\x80\x00\x00\x00\x7f\x00\x1e\xff\xa0\x03\xff\xff\x00\x00\x00\x00\x7f\x00w\xff\xb0\x07\xff\xfe\x00\x00\x00\x00\x7f\x00?\xff\x90\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x1f\xff\xd0\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x1f\xff\xf8\x1f\xff\xf0\x00\x00\x00\x00\x7f\x00\x0f\xff\xe8?\xff\xe0\x00\x00\x00\x00\x7f\x00\x07\xff\xf8\x7f\xff\xc0\x00\x00\x00\x00\x7f\x00\x03\xff\xf4\xff\xff\x80\x00\x00\x00\x00\x7f\x00\x03\xff\xfd\xff\xff\x00\x00\x00\x00\x00\x7f\x00\x01\xff\xff\xff\xfe\x00\x00\x00\x00\x00\x7f\x00\x00\xff\xff\xff\xfc\x00\x00\x00\x00\x00\x7f\x00\x00\x7f\xff\xff\xf8\x00\x00\x00\x00\x00\x7f\x00\x00\x7f\xff\xff\xf0\x00\x00\x00\x00\x00\x7f\x00\x00?\xff\xff\xe0\x00\x00\x00\x00\x00\x7f\x00\x00\x1f\xff\xff\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x0f\xff\xff\x80\x00\x00\x00\x00\x00\x7f\x00\x00\x07\xff\xff\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x07\xff\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x03\xff\xf8\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x01\xff\xf0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xff\xe0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00?\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Backward=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0b\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xf7\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xfdW\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xf2\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xe4\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xe8\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xd8\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xb0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xa0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff@\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xfe\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xfd\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Decline=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x000\x00\x00\x00\x02\x00\x00\x00\x7f\x00\x00\x00x\x00\x00\x00\x05\x00\x00\x00\x7f\x00\x00\x00\xfc\x00\x00\x00\x0f\x80\x00\x00\x7f\x00\x00\x01\xfe\x00\x00\x00\x17\xc0\x00\x00\x7f\x00\x00\x03\xff\x00\x00\x00?\xa0\x00\x00\x7f\x00\x00\x07\xff\x80\x00\x00_\xf0\x00\x00\x7f\x00\x00\x0f\xff\xc0\x00\x00\xff\xe8\x00\x00\x7f\x00\x00\x1f\xff\xe0\x00\x01\x7f\xfc\x00\x00\x7f\x00\x00?\xff\xf0\x00\x03\xff\xfa\x00\x00\x7f\x00\x00\x7f\xff\xf8\x00\x05\xff\xff\x00\x00\x7f\x00\x00\xff\xff\xfc\x00\x0f\xff\xfe\x80\x00\x7f\x00\x01\xff\xff\xfe\x00\x17\xff\xff\xc0\x00\x7f\x00\x01\xff\xff\xff\x00?\xff\xff\xc0\x00\x7f\x00\x00\xff\xff\xff\x80_\xff\xff\x80\x00\x7f\x00\x00\x7f\xff\xff\xc0\xff\xff\xff\x00\x00\x7f\x00\x00?\xff\xff\xe1\x7f\xff\xfe\x00\x00\x7f\x00\x00\x1f\xff\xff\xf3\xff\xff\xfc\x00\x00\x7f\x00\x00\x0f\xff\xff\xfd\xff\xff\xf8\x00\x00\x7f\x00\x00\x07\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x03\xff\xff\xff\xff\xff\xe0\x00\x00\x7f\x00\x00\x01\xff\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\x00\xff\xff\xff\xff\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x0b\xff\xff\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00/\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x80\x00\x00\x7f\x00\x00\x00\xbf\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\x01\xff\xff\xff\xff\xff\xe0\x00\x00\x7f\x00\x00\x02\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x07\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0b\xff\xff\xf7\xff\xff\xfc\x00\x00\x7f\x00\x00\x1f\xff\xff\xe3\xff\xff\xfe\x00\x00\x7f\x00\x00/\xff\xff\xc1\xff\xff\xff\x00\x00\x7f\x00\x00\x7f\xff\xff\x80\xff\xff\xff\x80\x00\x7f\x00\x00\xbf\xff\xff\x00\x7f\xff\xff\xc0\x00\x7f\x00\x01\xff\xff\xfe\x00?\xff\xff\xc0\x00\x7f\x00\x00\xff\xff\xfc\x00\x1f\xff\xff\xc0\x00\x7f\x00\x00\x7f\xff\xf8\x00\x0f\xff\xff\x80\x00\x7f\x00\x00?\xff\xf0\x00\x07\xff\xff\x00\x00\x7f\x00\x00\x1f\xff\xe0\x00\x03\xff\xfe\x00\x00\x7f\x00\x00\x0f\xff\xc0\x00\x01\xff\xfc\x00\x00\x7f\x00\x00\x07\xff\x80\x00\x00\xff\xf8\x00\x00\x7f\x00\x00\x03\xff\x00\x00\x00\x7f\xf0\x00\x00\x7f\x00\x00\x01\xfe\x00\x00\x00?\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00\x00\x00\x1f\xc0\x00\x00\x7f\x00\x00\x00x\x00\x00\x00\x0f\x80\x00\x00\x7f\x00\x00\x000\x00\x00\x00\x07\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Forward=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x006\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00+\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00]\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xdc\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xbe\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x7f`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x02\xff\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\x90\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x05\xff\xd8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xec\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x17\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xf2\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xfb\x00\x00\x00\x00\x7f\x00\x00\x00\x00_\xff\xfd\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xfe\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xfe@\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff`\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xb0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xd0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xc8\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xec\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xf4\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf2\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Left=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x12\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00b\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xce\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01>\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x06~\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\r\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x13\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00g\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xdf\xff\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x01?\xffUUUUX\x00\x7f\x00\x00\x06\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xff\xe8\x00\x7f\x00\x00\x17\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x01\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x01\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x7f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x1f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x03\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x01\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x00\xff\xff\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00?\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x1f\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x0f\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x03\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00~\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
No_go=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xfc>\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xc3\x80\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xf8`\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\x18\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xcc\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf3\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xc1\xff\xfd\x80\x00\x00\x7f\x00\x00\x00\xff\xfc\x00\x1f\xfc\xc0\x00\x00\x7f\x00\x00\x01\xff\xf0\x00\x03\xff`\x00\x00\x7f\x00\x00\x03\xff\xc0\x00\x00\xf7\xb0\x00\x00\x7f\x00\x00\x07\xff\x00\x00\x00\x7f\xd0\x00\x00\x7f\x00\x00\x0f\xfe\x00\x00\x00_\xe8\x00\x00\x7f\x00\x00\x0f\xf8\x00\x00\x00\xff\xf4\x00\x00\x7f\x00\x00\x1f\xf0\x00\x00\x01\x7f\xf4\x00\x00\x7f\x00\x00?\xf0\x00\x00\x03\xff\xfa\x00\x00\x7f\x00\x00?\xe0\x00\x00\x05\xff\xfb\x00\x00\x7f\x00\x00\x7f\xc0\x00\x00\x0f\xfd\xfd\x00\x00\x7f\x00\x00\x7f\xc0\x00\x00\x17\xf8\xfd\x00\x00\x7f\x00\x00\x7f\x80\x00\x00?\xf0\xff\x80\x00\x7f\x00\x00\xff\x80\x00\x00_\xe0~\x80\x00\x7f\x00\x00\xff\x00\x00\x00\xff\xc0\x7f\x80\x00\x7f\x00\x00\xff\x00\x00\x01\x7f\x80?@\x00\x7f\x00\x00\xfe\x00\x00\x03\xff\x00?@\x00\x7f\x00\x01\xfe\x00\x00\x05\xfe\x00?@\x00\x7f\x00\x01\xfe\x00\x00\x0f\xfc\x00\x1f\xc0\x00\x7f\x00\x01\xfe\x00\x00\x17\xf8\x00\x1f\xc0\x00\x7f\x00\x01\xfc\x00\x00?\xf0\x00\x1f\xe0\x00\x7f\x00\x01\xfc\x00\x00_\xe0\x00\x1f\xa0\x00\x7f\x00\x01\xfc\x00\x00\xff\xc0\x00\x1f\xe0\x00\x7f\x00\x01\xfc\x00\x01\x7f\x80\x00\x1f\xa0\x00\x7f\x00\x01\xfc\x00\x03\xff\x00\x00\x1f\xe0\x00\x7f\x00\x01\xfe\x00\x05\xfe\x00\x00\x1f\xe0\x00\x7f\x00\x01\xfe\x00\x0f\xfc\x00\x00\x1f\xc0\x00\x7f\x00\x01\xfe\x00\x17\xf8\x00\x00?\xc0\x00\x7f\x00\x01\xfe\x00?\xf0\x00\x00?\xc0\x00\x7f\x00\x00\xff\x00_\xe0\x00\x00?\xc0\x00\x7f\x00\x00\xff\x00\xff\xc0\x00\x00\x7f\xc0\x00\x7f\x00\x00\xff\x01\xff\x80\x00\x00\x7f\x80\x00\x7f\x00\x00\xff\x83\xff\x00\x00\x00\x7f\x80\x00\x7f\x00\x00\x7f\x87\xfe\x00\x00\x00\xff\x80\x00\x7f\x00\x00\x7f\xcf\xfc\x00\x00\x01\xff\x00\x00\x7f\x00\x00?\xff\xf8\x00\x00\x01\xff\x00\x00\x7f\x00\x00?\xff\xf0\x00\x00\x03\xfe\x00\x00\x7f\x00\x00\x1f\xff\xe0\x00\x00\x07\xfe\x00\x00\x7f\x00\x00\x1f\xff\xc0\x00\x00\x07\xfc\x00\x00\x7f\x00\x00\x0f\xff\x80\x00\x00\x1f\xfc\x00\x00\x7f\x00\x00\x07\xff\x00\x00\x00?\xf8\x00\x00\x7f\x00\x00\x07\xff\x80\x00\x00\xff\xf0\x00\x00\x7f\x00\x00\x03\xff\xe0\x00\x01\xff\xe0\x00\x00\x7f\x00\x00\x01\xff\xf8\x00\x0f\xff\xc0\x00\x00\x7f\x00\x00\x00\xff\xff\x00\x7f\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xff\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Question_mark=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\x1e\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xe3\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xfc\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff \x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\x90\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xc8\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xe4\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xf1\xff\xf2\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\x80\x7f\xf9\x00\x00\x00\x7f\x00\x00\x00?\xfe\x00\x1f\xfd\x00\x00\x00\x7f\x00\x00\x00?\xfc\x00\x07\xfd\x80\x00\x00\x7f\x00\x00\x00?\xf8\x00\x07\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf8\x00\x03\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf0\x00\x03\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf0\x00\x01\xfe\x80\x00\x00\x7f\x00\x00\x00\x7f\xf0\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xe0\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x7f\xe0\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x01\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x03\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x07\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0f\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x7f\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x01\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x03\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0f\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\xff\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xf8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xfd\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xfe\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff@\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Right=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00&\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00;\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00,\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?`\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00/\xb0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xcc\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00/\xf6\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xfb\x00\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xef\xfc\xc0\x00\x00\x7f\x00\x05UUUU_\xff`\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xb0\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xcc\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xf6\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfb\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfc\xc0\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff`\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xb0\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xb0\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfe`\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfc\x80\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xfb\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xf6\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xb0\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff`\x00\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xff\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xfc\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xf0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x008\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Stop_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xfc\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff \x00\x00\x00\x7f\x00\x00\x00\x07\x80\x00\x00\xd0\x00\x00\x00\x7f\x00\x00\x00\x0f\x00\x00\x00h\x00\x00\x00\x7f\x00\x00\x00\x1e\x7f\xff\xff4\x00\x00\x00\x7f\x00\x00\x00<\xff\xff\xff\x9a\x00\x00\x00\x7f\x00\x00\x00y\xff\xff\xff\xcd\x00\x00\x00\x7f\x00\x00\x00\xf3\xff\xff\xff\xe6\x80\x00\x00\x7f\x00\x00\x01\xe7\xff\xff\xff\xf3@\x00\x00\x7f\x00\x00\x03\xcf\xff\xff\xff\xf9\xa0\x00\x00\x7f\x00\x00\x07\x9f\xff\xff\xff\xfc\xd0\x00\x00\x7f\x00\x00\x0f?\xff\xff\xff\xfeh\x00\x00\x7f\x00\x00\x1e\x7f\xff\xff\xff\xff4\x00\x00\x7f\x00\x00<\xff\xff\xff\xff\xff\x9a\x00\x00\x7f\x00\x00y\xff\xff\xff\xff\xff\xcd\x00\x00\x7f\x00\x00\xf3\xff\xff\xff\xff\xff\xe6\x80\x00\x7f\x00\x01\xe7\xff\xff\xff\xff\xff\xf3@\x00\x7f\x00\x03\xcf\xff\xff\xff\xff\xff\xf9\xa0\x00\x7f\x00\x03\x9f\xff\xff\xff\xff\xff\xfc\xa0\x00\x7f\x00\x03\x9f\xff\xff\xff\xff\xff\xfc\xa0\x00\x7f\x00\x03\x9e\x0f\x00<\x0f\xc0<\xa0\x00\x7f\x00\x03\x9c\x02\x00\x18\x07\x80\x0c\xa0\x00\x7f\x00\x03\x98\x02\x00\x10\x03\x80\x04\xa0\x00\x7f\x00\x03\x90\xe1\xe0\xf1\xe3\x8f\xc4\xa0\x00\x7f\x00\x03\x91\xf7\xf1\xe3\xf1\x8f\xe4\xa0\x00\x7f\x00\x03\x91\xff\xf1\xe3\xf1\x8f\xe0\xa0\x00\x7f\x00\x03\x98\xff\xf1\xc7\xf9\x8f\xe4\xa0\x00\x7f\x00\x03\x98?\xf1\xc7\xf8\x8f\xc4\xa0\x00\x7f\x00\x03\x9c\x0f\xf1\xc7\xf8\x87\x84\xa0\x00\x7f\x00\x03\x9e\x03\xf1\xc7\xf8\x80\x0c\xa0\x00\x7f\x00\x03\x9f\x81\xf1\xc7\xf8\x80\x1c\xa0\x00\x7f\x00\x03\x9f\xe1\xf1\xc7\xf8\x87\xfc\xa0\x00\x7f\x00\x03\x9f\xf1\xf1\xc7\xf8\x87\xfc\xa0\x00\x7f\x00\x03\x9f\xf8\xf1\xe3\xf1\x87\xfc\xa0\x00\x7f\x00\x03\x9f\xf8\xf1\xe3\xf1\x87\xfc\xa0\x00\x7f\x00\x03\x91\xf1\xf1\xe1\xe1\x87\xfc\xa0\x00\x7f\x00\x03\x90\x01\xf1\xf0\xc3\x87\xfc\xa0\x00\x7f\x00\x03\x98\x01\xf1\xf8\x07\x87\xfc\xa0\x00\x7f\x00\x03\x9c\x07\xf1\xfc\x0f\x87\xfc\xa0\x00\x7f\x00\x03\x9f\x1f\xff\xff?\xff\xfc\xa0\x00\x7f\x00\x03\x9f\xff\xff\xff\xff\xff\xfc\xa0\x00\x7f\x00\x03\xcf\xff\xff\xff\xff\xff\xf9\xa0\x00\x7f\x00\x01\xe7\xff\xff\xff\xff\xff\xf3@\x00\x7f\x00\x00\xf3\xff\xff\xff\xff\xff\xe6\x80\x00\x7f\x00\x00y\xff\xff\xff\xff\xff\xcd\x00\x00\x7f\x00\x00<\xff\xff\xff\xff\xff\x9a\x00\x00\x7f\x00\x00\x1e\x7f\xff\xff\xff\xff4\x00\x00\x7f\x00\x00\x0f?\xff\xff\xff\xfeh\x00\x00\x7f\x00\x00\x07\x9f\xff\xff\xff\xfc\xf0\x00\x00\x7f\x00\x00\x03\xcf\xff\xff\xff\xf9\xe0\x00\x00\x7f\x00\x00\x01\xe7\xff\xff\xff\xf3\xc0\x00\x00\x7f\x00\x00\x00\xf3\xff\xff\xff\xe7\x80\x00\x00\x7f\x00\x00\x00y\xff\xff\xff\xcf\x00\x00\x00\x7f\x00\x00\x00<\xff\xff\xff\x9e\x00\x00\x00\x7f\x00\x00\x00\x1e\x7f\xff\xff<\x00\x00\x00\x7f\x00\x00\x00\x0f\x00\x00\x00x\x00\x00\x00\x7f\x00\x00\x00\x07\x80\x00\x00\xf0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Stop_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xfc\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff \x00\x00\x00\x7f\x00\x00\x00\x07\xc0\x00\x00\xd0\x00\x00\x00\x7f\x00\x00\x00\x0f\x00\x00\x00h\x00\x00\x00\x7f\x00\x00\x00\x1e\x00\x00\x004\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1a\x00\x00\x00\x7f\x00\x00\x00x\x00\x00\x00\r\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x06\x80\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x03@\x00\x00\x7f\x00\x00\x03\xc0\x00\x00\x00\x01\xa0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00\xd0\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x00h\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x004\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x1a\x00\x00\x7f\x00\x00x\x00\x00\x00\x00\x00\r\x00\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x06\x80\x00\x7f\x00\x01\xe0\x00\x00\x00\x00\x00\x03@\x00\x7f\x00\x03\xc0\x00\x00\x00\x00\x00\x01\xa0\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00\xa0\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00\xa0\x00\x7f\x00\x03\x81\xf0\xff\xc3\xf0?\xc0\xa0\x00\x7f\x00\x03\x83\xfd\xff\xe7\xf8\x7f\xf0\xa0\x00\x7f\x00\x03\x87\xff\xff\xef\xfc\x7f\xf8\xa0\x00\x7f\x00\x03\x8f\x1e\x1f\x0e\x1cp8\xa0\x00\x7f\x00\x03\x8e\x08\x0e\x1c\x0ep\x1c\xa0\x00\x7f\x00\x03\x8e\x00\x0e\x1c\x0ep\x1c\xa0\x00\x7f\x00\x03\x87\x00\x0e8\x06p\x1c\xa0\x00\x7f\x00\x03\x87\xc0\x0e8\x07p8\xa0\x00\x7f\x00\x03\x83\xf0\x0e8\x07xx\xa0\x00\x7f\x00\x03\x81\xfc\x0e8\x07\x7f\xf0\xa0\x00\x7f\x00\x03\x80~\x0e8\x07\x7f\xe0\xa0\x00\x7f\x00\x03\x80\x1e\x0e8\x07x\x00\xa0\x00\x7f\x00\x03\x80\x0e\x0e8\x07x\x00\xa0\x00\x7f\x00\x03\x80\x07\x0e\x1c\x0ex\x00\xa0\x00\x7f\x00\x03\x80\x07\x0e\x1c\x0ex\x00\xa0\x00\x7f\x00\x03\x8e\x0e\x0e\x1e\x1ex\x00\xa0\x00\x7f\x00\x03\x8f\xfe\x0e\x0f<x\x00\xa0\x00\x7f\x00\x03\x87\xfe\x0e\x07\xf8x\x00\xa0\x00\x7f\x00\x03\x83\xf8\x0e\x03\xf0x\x00\xa0\x00\x7f\x00\x03\x80\xe0\x00\x00\xc0\x00\x00\xa0\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00\xa0\x00\x7f\x00\x03\xc0\x00\x00\x00\x00\x00\x01\xa0\x00\x7f\x00\x01\xe0\x00\x00\x00\x00\x00\x03@\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x06\x80\x00\x7f\x00\x00x\x00\x00\x00\x00\x00\r\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x1a\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x004\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x00h\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00\xf0\x00\x00\x7f\x00\x00\x03\xc0\x00\x00\x00\x01\xe0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x03\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\x80\x00\x00\x7f\x00\x00\x00x\x00\x00\x00\x0f\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1e\x00\x00\x00\x7f\x00\x00\x00\x1e\x00\x00\x00<\x00\x00\x00\x7f\x00\x00\x00\x0f\x00\x00\x00x\x00\x00\x00\x7f\x00\x00\x00\x07\x80\x00\x00\xf0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Thumbs_down=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x07\xff\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x0f\xff\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x0c\x00\xc7\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x0e\xaa\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\rT\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\x0c\xaa\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\r\xfe\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xe0\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xea\xa0\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xd5@\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\r\xff\xc1\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x0e\xaa\xc0\x7f\xff\xff\xe0\x00\x00\x7f\x00\x00\x0f\xff\xc0?\xff\xff\xe0\x00\x00\x7f\x00\x00\x07\xff\x80?\xff\xff\x80\x00\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0f\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x03\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x01\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Thumbs_up=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x1f\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x01\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x01\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x03\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0f\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\xff\xff\x80\x00\x00\x7f\x00\x00\x07\xff\xc0?\xff\xff\xe0\x00\x00\x7f\x00\x00\x0f\xff\xc0\x7f\xff\xff\xe0\x00\x00\x7f\x00\x00\x0c\x00\xc1\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\rT\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x0c\xaa\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\rT\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\r\xfe\xff\xff\xff\xea\xa0\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xea\xa0\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xf8\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xf0\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xe0\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\r\xff\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\x0f\xff\xff\xff\xff\xff\xc0\x00\x00\x7f\x00\x00\r\xff\xc7\xff\xff\xff\x00\x00\x00\x7f\x00\x00\rT\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x0f\xff\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x07\xff\x80\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Warning=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00=\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00?\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff@\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xf3\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xe1\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xe1\xd0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xc0\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xc0\xe8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\x80|\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\x80|\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\x00:\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\x00>\x00\x00\x00\x00\x7f\x00\x00\x00\x00>>\x1d\x00\x00\x00\x00\x7f\x00\x00\x00\x00<{\x0f\x00\x00\x00\x00\x7f\x00\x00\x00\x00|y\x0e\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xf8\xfe\x87\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xf8\xfe\x87\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\xff\x83\xa0\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\xfe\x83\xe0\x00\x00\x00\x7f\x00\x00\x00\x03\xe0\xff\x81\xd0\x00\x00\x00\x7f\x00\x00\x00\x03\xc0\xff\x80\xf0\x00\x00\x00\x7f\x00\x00\x00\x07\xc0\x7f\x00\xe8\x00\x00\x00\x7f\x00\x00\x00\x0f\x80\x7f\x00|\x00\x00\x00\x7f\x00\x00\x00\x0f\x80\x7f\x00t\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x7f\x00>\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x7f\x00>\x00\x00\x00\x7f\x00\x00\x00>\x00\x7f\x00\x1d\x00\x00\x00\x7f\x00\x00\x00>\x00\x7f\x00\x1f\x00\x00\x00\x7f\x00\x00\x00|\x00\x7f\x00\x0e\x80\x00\x00\x7f\x00\x00\x00\xf8\x00\x7f\x00\x07\xc0\x00\x00\x7f\x00\x00\x00\xf8\x00\x7f\x00\x07@\x00\x00\x7f\x00\x00\x01\xf0\x00\x7f\x00\x03\xe0\x00\x00\x7f\x00\x00\x01\xf0\x00\x7f\x00\x03\xe0\x00\x00\x7f\x00\x00\x03\xe0\x00>\x00\x01\xd0\x00\x00\x7f\x00\x00\x03\xe0\x00>\x00\x01\xf0\x00\x00\x7f\x00\x00\x07\xc0\x00>\x00\x00\xe8\x00\x00\x7f\x00\x00\x0f\xc0\x00>\x00\x00\xfc\x00\x00\x7f\x00\x00\x0f\x80\x00\x1c\x00\x00t\x00\x00\x7f\x00\x00\x1f\x00\x00\x00\x00\x00>\x00\x00\x7f\x00\x00\x1f\x00\x00\x00\x00\x00:\x00\x00\x7f\x00\x00>\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00>\x00\x00>\x00\x00\x1f\x00\x00\x7f\x00\x00|\x00\x00}\x00\x00\x0e\x80\x00\x7f\x00\x00\xfc\x00\x00~\x80\x00\x0f\xc0\x00\x7f\x00\x00\xf8\x00\x00\x7f\x80\x00\x07@\x00\x7f\x00\x01\xf8\x00\x00\x7f\x80\x00\x07\xe0\x00\x7f\x00\x01\xf0\x00\x00\x7f\x00\x00\x03\xa0\x00\x7f\x00\x03\xe0\x00\x00?\x00\x00\x01\xf0\x00\x7f\x00\x03\xe0\x00\x00\x1e\x00\x00\x01\xf0\x00\x7f\x00\x07\xc0\x00\x00\x00\x00\x00\x00\xe8\x00\x7f\x00\x0f\xc0\x00\x00\x00\x00\x00\x00\xfc\x00\x7f\x00\x0f\x80\x00\x00\x00\x00\x00\x00\xf4\x00\x7f\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x7f\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x7f\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x7f\x00\x07\xff\xff\xff\xff\xff\xff\xff\xf8\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
YES=Accept
|
||||||
|
NO=Decline
|
||||||
259
mixly/boards/default/micropython/build/lib/irremote.py
Normal file
259
mixly/boards/default/micropython/build/lib/irremote.py
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
"""
|
||||||
|
IR-Remote
|
||||||
|
|
||||||
|
Micropython library for the IR-Remote/Timer(IR_RX&TX)
|
||||||
|
===============================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import array, time, gc
|
||||||
|
from machine import Pin, Timer
|
||||||
|
from os import uname
|
||||||
|
try:
|
||||||
|
from esp32 import RMT
|
||||||
|
TX_MOED = 1
|
||||||
|
except:
|
||||||
|
from machine import PWM
|
||||||
|
TX_MOED = 0
|
||||||
|
|
||||||
|
'''接收部分'''
|
||||||
|
class IR_RX:
|
||||||
|
BADSTART = 'Invalid start pulse'
|
||||||
|
BADDATA = 'Invalid data'
|
||||||
|
def __init__(self, pin, callback=None, timeout=15000, timer_id=1):
|
||||||
|
self._start = 0
|
||||||
|
self._ready = False
|
||||||
|
self._enable = False
|
||||||
|
self._timeout = timeout
|
||||||
|
self._callback = callback
|
||||||
|
self._pulses = array.array('H')
|
||||||
|
self.code = [None, None, None, memoryview(self._pulses)] #存放[cmd, addr, data, pulses]
|
||||||
|
Pin(pin, Pin.IN).irq(handler=self._irq_cb, trigger=(Pin.IRQ_FALLING | Pin.IRQ_RISING))
|
||||||
|
Timer(0 if "-C2" in uname().machine else timer_id).init(period=5, mode=Timer.PERIODIC, callback=self._timer_cb)
|
||||||
|
|
||||||
|
def _irq_cb(self, pin):
|
||||||
|
if not self._enable:
|
||||||
|
_intime = time.ticks_us()
|
||||||
|
if self._start == 0:
|
||||||
|
self._start = _intime
|
||||||
|
return
|
||||||
|
self._pulses.append(time.ticks_diff(_intime, self._start))
|
||||||
|
self._start = _intime
|
||||||
|
else:
|
||||||
|
self._start = 0
|
||||||
|
self._pulses = array.array('H')
|
||||||
|
|
||||||
|
def _timer_cb(self, tim):
|
||||||
|
if len(self._pulses) >= 3 and time.ticks_diff(time.ticks_us(), self._start) > self._timeout:
|
||||||
|
#接收完成,开始解码
|
||||||
|
self.code[3] = memoryview(self._pulses)
|
||||||
|
if self.decode() is None and self._callback:
|
||||||
|
self._callback(self.code[0], self.code[1], self.code[2], self.code[3])
|
||||||
|
self._ready = True
|
||||||
|
self._start = 0
|
||||||
|
self._pulses = array.array('H')
|
||||||
|
gc.collect()
|
||||||
|
|
||||||
|
def recv_cb(self, callback):
|
||||||
|
self._callback = callback
|
||||||
|
|
||||||
|
def timeout(self, timeout=15000):
|
||||||
|
self._timeout = timeout
|
||||||
|
|
||||||
|
def any(self):
|
||||||
|
ready = self._ready
|
||||||
|
self._ready = False
|
||||||
|
return ready
|
||||||
|
|
||||||
|
def enable(self, onoff):
|
||||||
|
self._enable = onoff
|
||||||
|
|
||||||
|
class NEC_RX(IR_RX):
|
||||||
|
def __init__(self, pin, bits=None, callback=None, timer_id=1):
|
||||||
|
super().__init__(pin, callback, timer_id=timer_id)
|
||||||
|
self._bits = bits
|
||||||
|
|
||||||
|
def decode(self):
|
||||||
|
pulse_len = len(self._pulses)
|
||||||
|
if pulse_len < 3:
|
||||||
|
print("Warning:", self.BADSTART)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
start_i = 0
|
||||||
|
value = 0
|
||||||
|
#跳过帧头(各厂家定义不一)
|
||||||
|
for i in range(pulse_len):
|
||||||
|
if self._pulses[i] <= 2250:
|
||||||
|
start_i = i
|
||||||
|
break
|
||||||
|
val = 1 << ((pulse_len - start_i - 1) // 2) - 1 if (pulse_len - start_i) >= 3 else 0
|
||||||
|
#根据高低脉冲定义转码
|
||||||
|
for edge in range(start_i, pulse_len - 1, 2):
|
||||||
|
value >>= 1
|
||||||
|
if self._pulses[edge + 1] > 1120:
|
||||||
|
value |= val
|
||||||
|
#判读是8、16位解码
|
||||||
|
if self._bits == 8 or self._bits == 16:
|
||||||
|
cmd = value >> 16 & 0xff
|
||||||
|
if cmd != (value >> 24 ^ 0xff) and value != 0x0:
|
||||||
|
print("Warning:", self.BADDATA)
|
||||||
|
return False
|
||||||
|
addr = value & 0xff if self._bits == 8 else value & 0xffff
|
||||||
|
self.code[0:3] = cmd, addr, value
|
||||||
|
#其他未定义直接输出转码
|
||||||
|
else:
|
||||||
|
self.code[0:3] = None, None, value
|
||||||
|
|
||||||
|
class RC5_RX(IR_RX):
|
||||||
|
def __init__(self, pin, callback=None, timer_id=1):
|
||||||
|
super().__init__(pin, callback, timer_id=timer_id)
|
||||||
|
|
||||||
|
def decode(self):
|
||||||
|
pulse_len = len(self._pulses)
|
||||||
|
if pulse_len < 3:
|
||||||
|
print("Warning:", self.BADSTART)
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
bit = 1
|
||||||
|
value = 0
|
||||||
|
num = 0
|
||||||
|
while True:
|
||||||
|
short = self._pulses[num] < 1334
|
||||||
|
if not short:
|
||||||
|
bit ^= 1
|
||||||
|
value <<= 1
|
||||||
|
value |= bit
|
||||||
|
num += 1 + int(short)
|
||||||
|
if num >= pulse_len:
|
||||||
|
value >>= 1
|
||||||
|
break
|
||||||
|
#判读解码
|
||||||
|
cmd = (value & 0x3f) | (0 if ((value >> 12) & 1) else 0x40)
|
||||||
|
addr = (value >> 6) & 0x1f
|
||||||
|
self.code[0:3] = cmd, addr, value
|
||||||
|
|
||||||
|
'''发射部分'''
|
||||||
|
class IR_TX:
|
||||||
|
def __init__(self, pin, cfreq=38000, power=60):
|
||||||
|
if TX_MOED:
|
||||||
|
self._rmt = RMT(0, pin=Pin(pin), clock_div=80, tx_carrier = (cfreq, round(power * 0.75), 1))
|
||||||
|
else:
|
||||||
|
self._pwm = PWM(Pin(pin), freq=cfreq, duty_u16=0)
|
||||||
|
self._duty = round(power * 65535 / 100 * 0.75)
|
||||||
|
self._busy = False
|
||||||
|
self._pulses = array.array('H')
|
||||||
|
self.carrier = False
|
||||||
|
|
||||||
|
def _pwm_write_pulses(self, pulses):
|
||||||
|
_flip = True
|
||||||
|
self._busy = True
|
||||||
|
for pulse in pulses:
|
||||||
|
if _flip:
|
||||||
|
self._pwm.duty_u16(self._duty)
|
||||||
|
time.sleep_us(pulse)
|
||||||
|
_flip = False
|
||||||
|
else:
|
||||||
|
self._pwm.duty_u16(0)
|
||||||
|
time.sleep_us(pulse)
|
||||||
|
_flip = True
|
||||||
|
self._pwm.duty_u16(0)
|
||||||
|
self._busy = False
|
||||||
|
|
||||||
|
def transmit(self, cmd=None, addr=None, toggle=None, pulses=None, raw=None):
|
||||||
|
if pulses is None:
|
||||||
|
self.carrier = False
|
||||||
|
if raw is None:
|
||||||
|
self.tx(cmd, addr, toggle)
|
||||||
|
else:
|
||||||
|
self.tx_raw(raw)
|
||||||
|
if TX_MOED:
|
||||||
|
self._rmt.write_pulses(tuple(self._pulses))
|
||||||
|
else:
|
||||||
|
self._pwm_write_pulses(tuple(self._pulses))
|
||||||
|
self._pulses = array.array('H')
|
||||||
|
else:
|
||||||
|
if TX_MOED:
|
||||||
|
self._rmt.write_pulses(tuple(pulses))
|
||||||
|
else:
|
||||||
|
self._pwm_write_pulses(tuple(pulses))
|
||||||
|
|
||||||
|
def busy(self):
|
||||||
|
return not self._rmt.wait_done() if TX_MOED else self._busy
|
||||||
|
|
||||||
|
def _append(self, *times):
|
||||||
|
for t in times:
|
||||||
|
self._pulses.append(t)
|
||||||
|
self.carrier = not self.carrier
|
||||||
|
|
||||||
|
def _add(self, t):
|
||||||
|
assert t > 0
|
||||||
|
self._pulses[len(self._pulses)-1] +=t
|
||||||
|
|
||||||
|
class NEC_TX(IR_TX):
|
||||||
|
_TBURST = const(563)
|
||||||
|
_T_ONE = const(1687)
|
||||||
|
def __init__(self, pin, samsung=False, power=60):
|
||||||
|
super().__init__(pin, 38000, power)
|
||||||
|
self._samsung = samsung
|
||||||
|
|
||||||
|
def _bit(self, b):
|
||||||
|
self._append(_TBURST, _T_ONE if b else _TBURST)
|
||||||
|
|
||||||
|
def tx(self, cmd, addr, toggle=0): #cmd:0~0xff, addr:0~0xffff, toggle:0,1
|
||||||
|
if self._samsung:
|
||||||
|
self._append(4500, 4500)
|
||||||
|
else:
|
||||||
|
self._append(9000, 4500)
|
||||||
|
if addr < 256: # Short address: append complement
|
||||||
|
if self._samsung:
|
||||||
|
addr |= addr << 8
|
||||||
|
else:
|
||||||
|
addr |= ((addr ^ 0xff) << 8)
|
||||||
|
for _ in range(16):
|
||||||
|
self._bit(addr & 1)
|
||||||
|
addr >>= 1
|
||||||
|
cmd |= ((cmd ^ 0xff) << 8)
|
||||||
|
for _ in range(16):
|
||||||
|
self._bit(cmd & 1)
|
||||||
|
cmd >>= 1
|
||||||
|
self._append(_TBURST)
|
||||||
|
if toggle == 1:
|
||||||
|
self._append(30000, 9000, 2250, _TBURST)
|
||||||
|
|
||||||
|
def tx_raw(self, raw):
|
||||||
|
self._append(9000, 4500)
|
||||||
|
while raw:
|
||||||
|
self._bit(raw & 1)
|
||||||
|
raw >>= 1
|
||||||
|
self._append(_TBURST)
|
||||||
|
|
||||||
|
class RC5_TX(IR_TX):
|
||||||
|
_T_RC5 = const(889)
|
||||||
|
def __init__(self, pin, power=60):
|
||||||
|
super().__init__(pin, 36000, power)
|
||||||
|
|
||||||
|
def tx(self, cmd, addr, toggle): #cmd:0~0x3f, addr:0~0x1f, toggle:0,1
|
||||||
|
d = (cmd & 0x3f) | ((addr & 0x1f) << 6) | (((cmd & 0x40) ^ 0x40) << 6) | ((toggle & 1) << 11)
|
||||||
|
mask = 0x2000
|
||||||
|
while mask:
|
||||||
|
if mask == 0x2000:
|
||||||
|
self._append(_T_RC5)
|
||||||
|
else:
|
||||||
|
bit = bool(d & mask)
|
||||||
|
if bit ^ self.carrier:
|
||||||
|
self._add(_T_RC5)
|
||||||
|
self._append(_T_RC5)
|
||||||
|
else:
|
||||||
|
self._append(_T_RC5, _T_RC5)
|
||||||
|
mask >>= 1
|
||||||
|
|
||||||
|
def tx_raw(self, raw):
|
||||||
|
self._append(_T_RC5)
|
||||||
|
mask = 1 << len(bin(raw)) - 3
|
||||||
|
while mask:
|
||||||
|
if bool(raw & mask) ^ self.carrier:
|
||||||
|
self._add(_T_RC5)
|
||||||
|
self._append(_T_RC5)
|
||||||
|
else:
|
||||||
|
self._append(_T_RC5, _T_RC5)
|
||||||
|
mask >>= 1
|
||||||
|
self._append(_T_RC5)
|
||||||
49
mixly/boards/default/micropython/build/lib/keypad.py
Normal file
49
mixly/boards/default/micropython/build/lib/keypad.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
"""
|
||||||
|
Simple Keypad
|
||||||
|
|
||||||
|
Micropython library for the Simple Keypad
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Based on Author: 'Teeraphat Kullanankanjana'
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
from machine import Pin
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
class Keypad:
|
||||||
|
def __init__(self, row_pins, column_pins, keys):
|
||||||
|
"""Initialize the keypad object."""
|
||||||
|
if not all(isinstance(pin, Pin) for pin in row_pins):
|
||||||
|
raise ValueError("Row pins must be instances of Pin.")
|
||||||
|
|
||||||
|
if not all(isinstance(pin, Pin) for pin in column_pins):
|
||||||
|
raise ValueError("Column pins must be instances of Pin.")
|
||||||
|
|
||||||
|
if not isinstance(keys, list) or not all(isinstance(row, list) for row in keys):
|
||||||
|
raise ValueError("Keys must be a 2D list.")
|
||||||
|
|
||||||
|
self.row_pins = row_pins
|
||||||
|
self.column_pins = column_pins
|
||||||
|
self.keys = keys
|
||||||
|
|
||||||
|
for pin in self.row_pins:
|
||||||
|
pin.init(Pin.IN, Pin.PULL_UP)
|
||||||
|
|
||||||
|
for pin in self.column_pins:
|
||||||
|
pin.init(Pin.OUT)
|
||||||
|
|
||||||
|
if len(self.row_pins) > len(self.keys) or len(self.column_pins) > len(self.keys[0]):
|
||||||
|
raise ValueError("Number of row/column pins does not match the key layout size.")
|
||||||
|
|
||||||
|
def read_keypad(self):
|
||||||
|
"""Read the keypad and return the pressed key."""
|
||||||
|
for col_pin in self.column_pins:
|
||||||
|
col_pin.value(0)
|
||||||
|
for i, row_pin in enumerate(self.row_pins):
|
||||||
|
if not row_pin.value():
|
||||||
|
key_pressed = self.keys[i][self.column_pins.index(col_pin)]
|
||||||
|
col_pin.value(1)
|
||||||
|
return key_pressed
|
||||||
|
col_pin.value(1)
|
||||||
|
return None
|
||||||
76
mixly/boards/default/micropython/build/lib/ltr308al.py
Normal file
76
mixly/boards/default/micropython/build/lib/ltr308al.py
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
"""
|
||||||
|
LTR-308ALS
|
||||||
|
|
||||||
|
Micropython library for the LTR-308ALS
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Changed from circuitpython to micropython 20220211
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
LTR_308ALS_ADDRESS = const(0x53)
|
||||||
|
|
||||||
|
LTR_308ALS_REG_CTRL = const(0x00)
|
||||||
|
LTR_308ALS_REG_GAIN = const(0x05) #设置增益
|
||||||
|
LTR_308ALS_REG_DEVICE_ID = const(0x06)
|
||||||
|
LTR_308ALS_REG_DATA = const(0x0D)
|
||||||
|
|
||||||
|
#设置增益范围
|
||||||
|
LTR_308ALS_CMD_ALS_Enable = const(0x02)
|
||||||
|
LTR_308ALS_CMD_X1GAIN =const(0x00)
|
||||||
|
LTR_308ALS_CMD_X3GAIN =const(0x01)
|
||||||
|
LTR_308ALS_CMD_X6GAIN =const(0x02)
|
||||||
|
LTR_308ALS_CMD_X9GAIN =const(0x03)
|
||||||
|
LTR_308ALS_CMD_X18GAIN =const(0x04)
|
||||||
|
|
||||||
|
_GAINS = (
|
||||||
|
LTR_308ALS_CMD_X1GAIN, # 1x
|
||||||
|
LTR_308ALS_CMD_X3GAIN, # 3x
|
||||||
|
LTR_308ALS_CMD_X6GAIN, # 6x
|
||||||
|
LTR_308ALS_CMD_X9GAIN, # 9x
|
||||||
|
LTR_308ALS_CMD_X18GAIN # 18x
|
||||||
|
)
|
||||||
|
|
||||||
|
_GAINS_X = (
|
||||||
|
1, # 1x
|
||||||
|
3, # 3x
|
||||||
|
6, # 6x
|
||||||
|
9, # 9x
|
||||||
|
18 # 18x
|
||||||
|
)
|
||||||
|
|
||||||
|
class LTR_308ALS:
|
||||||
|
def __init__(self, i2c_bus,gain=1):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = LTR_308ALS_ADDRESS
|
||||||
|
self._gain = gain
|
||||||
|
|
||||||
|
if self._chip_id() != 0xB1:
|
||||||
|
raise AttributeError("Cannot find a LTR_308ALS")
|
||||||
|
self._Enable() #star
|
||||||
|
time.sleep(0.2)
|
||||||
|
self._wreg(LTR_308ALS_REG_GAIN,_GAINS[self._gain])
|
||||||
|
|
||||||
|
#Write memory address
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
#Read memory address
|
||||||
|
def _rreg(self, reg,nbytes=1):
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
return self._rreg(LTR_308ALS_REG_DEVICE_ID)
|
||||||
|
|
||||||
|
def _Enable(self):
|
||||||
|
self._wreg(LTR_308ALS_REG_CTRL,LTR_308ALS_CMD_ALS_Enable)
|
||||||
|
|
||||||
|
def getdata(self):
|
||||||
|
buffer=self._rreg(LTR_308ALS_REG_DATA,3)
|
||||||
|
als_data= buffer[2]<<16 | buffer[1]<<8| buffer[0]
|
||||||
|
als_lux=float(0.6*als_data/_GAINS_X[self._gain])
|
||||||
|
return als_lux
|
||||||
|
|
||||||
78
mixly/boards/default/micropython/build/lib/ltr381rgb.py
Normal file
78
mixly/boards/default/micropython/build/lib/ltr381rgb.py
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
"""
|
||||||
|
LTR-381RGB-XX
|
||||||
|
|
||||||
|
MicroPython library for the LTR-381RGB-XX (Color sensor)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20230417
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
LTR_MAIN_CTRL = const(0x00)
|
||||||
|
LTR_ALS_CS_MEAS_RATE = const(0x04)
|
||||||
|
LTR_ALS_CS_GAIN = const(0x05)
|
||||||
|
LTR_PART_ID = const(0x06)
|
||||||
|
LTR_MAIN_STATUS = const(0x07)
|
||||||
|
LTR_CS_DATA = const(0x0A)
|
||||||
|
#1x 3x 6x 9x 18x
|
||||||
|
_GAINS_X = (1, 3, 6, 9, 18)
|
||||||
|
|
||||||
|
class LTR_381RGB:
|
||||||
|
def __init__(self, i2c_bus, addr=0x53, gain=1):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
self._gain = gain
|
||||||
|
self._color = [0, 0, 0]
|
||||||
|
self._ir = 0
|
||||||
|
self._als = 0
|
||||||
|
|
||||||
|
if (self._chip_id() & 0xF0) != 0xC0:
|
||||||
|
raise AttributeError("Cannot find a LTR-381RGB")
|
||||||
|
|
||||||
|
self._configure()
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg, nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
'''Proofreading device ID'''
|
||||||
|
return self._rreg(LTR_PART_ID)
|
||||||
|
|
||||||
|
def _configure(self):
|
||||||
|
'''Configuration Register'''
|
||||||
|
self._wreg(LTR_MAIN_CTRL, 0x06) #CS mode & ALS/CS Enable
|
||||||
|
self._wreg(LTR_ALS_CS_MEAS_RATE, 0x22) #Resolution = 18 bit, Meas Rate =100ms
|
||||||
|
self._wreg(LTR_ALS_CS_GAIN, self._gain & 0x07) #CS measurement Gain Range
|
||||||
|
|
||||||
|
def status(self):
|
||||||
|
'''Data conversion status'''
|
||||||
|
return self._rreg(LTR_MAIN_STATUS) & 0x08
|
||||||
|
|
||||||
|
def getdata(self):
|
||||||
|
'''Processing data acquisition'''
|
||||||
|
if self.status():
|
||||||
|
_buf=self._rreg(LTR_CS_DATA, 12)
|
||||||
|
self._ir = _buf[2] << 16 | _buf[1] << 8 | _buf[0]
|
||||||
|
self._color [1] = _buf[5] << 16 | _buf[4] << 8 | _buf[3]
|
||||||
|
self._color [0] = _buf[8] << 16 | _buf[7] << 8 | _buf[6]
|
||||||
|
self._color [2] = _buf[11] << 16 | _buf[10] << 8 | _buf[9]
|
||||||
|
self._als = 0.8 * self._color [1] * (1 - 0.033 * self._ir / self._color [1]) / _GAINS_X[self._gain]
|
||||||
|
return round(self._als, 2), self._ir, self._color
|
||||||
|
|
||||||
|
def color(self):
|
||||||
|
return self.getdata()[2]
|
||||||
|
|
||||||
|
def ir(self):
|
||||||
|
return self.getdata()[1]
|
||||||
|
|
||||||
|
def als(self):
|
||||||
|
return self.getdata()[0]
|
||||||
75
mixly/boards/default/micropython/build/lib/ltr390uv.py
Normal file
75
mixly/boards/default/micropython/build/lib/ltr390uv.py
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
"""
|
||||||
|
LTR-390UV
|
||||||
|
|
||||||
|
Micropython library for the LTR-390UV(ALS+UV)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20240120
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_LTR390_ADDRESS = const(0x53)
|
||||||
|
_LTR390_REG_CTRL = const(0x00)
|
||||||
|
_LTR390_REG_MEAS = const(0x04)
|
||||||
|
_LTR390_REG_GAIN = const(0x05)
|
||||||
|
_LTR390_REG_ID = const(0x06)
|
||||||
|
_LTR390_REG_ALS = const(0x0D)
|
||||||
|
_LTR390_REG_UVS = const(0x10)
|
||||||
|
|
||||||
|
_RATE_DEFAULT = const(0x02) #100ms
|
||||||
|
_RESOLUTION_20BIT = (0<<4, 4)
|
||||||
|
_RESOLUTION_19BIT = (1<<4, 2)
|
||||||
|
_RESOLUTION_18BIT = (2<<4, 1)
|
||||||
|
_RESOLUTION_17BIT = (3<<4, 0.5)
|
||||||
|
_RESOLUTION_16BIT = (4<<4, 0.25)
|
||||||
|
_RESOLUTION_13BIT = (5<<4, 0.125)
|
||||||
|
|
||||||
|
_GAIN_X1 = (0, 1)
|
||||||
|
_GAIN_X3 = (1, 3)
|
||||||
|
_GAIN_X6 = (2, 6)
|
||||||
|
_GAIN_X9 = (3, 9)
|
||||||
|
_GAIN_X18 = (4, 18)
|
||||||
|
|
||||||
|
class ALS_UVS:
|
||||||
|
def __init__(self, i2c_bus, addr=_LTR390_ADDRESS, gain=_GAIN_X1, resolution=_RESOLUTION_17BIT):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
self._gain = gain
|
||||||
|
self._reso = resolution
|
||||||
|
self._flaga = False
|
||||||
|
self._flagu = False
|
||||||
|
|
||||||
|
if self._rreg(_LTR390_REG_ID) != 0xB2:
|
||||||
|
raise AttributeError("Cannot find a LTR-390UV")
|
||||||
|
|
||||||
|
self._wreg(_LTR390_REG_MEAS, self._reso[0] | _RATE_DEFAULT)
|
||||||
|
self._wreg(_LTR390_REG_GAIN, self._gain[0])
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg, nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def ultraviolet(self):
|
||||||
|
if not self._flagu:
|
||||||
|
self._wreg(_LTR390_REG_CTRL, 0x0A) #UVS in Active Mode
|
||||||
|
time.sleep_ms(int(self._reso[1] * 100))
|
||||||
|
self._flagu = True
|
||||||
|
self._flaga = False
|
||||||
|
buf = self._rreg(_LTR390_REG_UVS, 3)
|
||||||
|
return buf[2] << 16 | buf[1] << 8 | buf[0]
|
||||||
|
|
||||||
|
def ambient_light(self):
|
||||||
|
if not self._flaga:
|
||||||
|
self._wreg(_LTR390_REG_CTRL, 0x02) #ALS in Active Mode
|
||||||
|
time.sleep_ms(int(self._reso[1] * 100))
|
||||||
|
self._flaga = True
|
||||||
|
self._flagu = False
|
||||||
|
buf = self._rreg(_LTR390_REG_ALS, 3)
|
||||||
|
return 0.6 * (buf[2] << 16 | buf[1] << 8 | buf[0]) / (self._gain[1] * self._reso[1])
|
||||||
106
mixly/boards/default/micropython/build/lib/ltr553als.py
Normal file
106
mixly/boards/default/micropython/build/lib/ltr553als.py
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
"""
|
||||||
|
LTR-553ALS-XX
|
||||||
|
|
||||||
|
MicroPython library for the LTR-553ALS-XX(ALS,PS)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20220224
|
||||||
|
#Format unified 20220623
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
LTR_553ALS_ADDRESS = const(0x23)
|
||||||
|
LTR_ALS_REG_CONTR = const(0x80)
|
||||||
|
LTR_PS_REG_CONTR = const(0x81)
|
||||||
|
LTR_PS_REG_LED = const(0x82)
|
||||||
|
LTR_PS_REG_PULSES = const(0x83)
|
||||||
|
LTR_PS_REG_RATE = const(0x84)
|
||||||
|
LTR_ALS_REG_RATE = const(0x85)
|
||||||
|
LTR_553ALS_REG_ID = const(0x87)
|
||||||
|
LTR_ALS_REG_DATA1 = const(0x88)
|
||||||
|
LTR_553ALS_REG_ATATUS = const(0x8C)
|
||||||
|
LTR_PS_REG_DATA1 = const(0x8D)
|
||||||
|
|
||||||
|
_ALS_GAIN={
|
||||||
|
"X1":(1,0x01), # For Gain X1
|
||||||
|
"X2":(2,0x05), # For Gain X2
|
||||||
|
"X4":(4,0x09), # For Gain X4
|
||||||
|
"X8":(8,0x0D), # For Gain X8
|
||||||
|
"X48":(48,0x19), # For Gain X48
|
||||||
|
"X96":(96,0x1D), # For Gain X96
|
||||||
|
}
|
||||||
|
|
||||||
|
class LTR_553ALS:
|
||||||
|
|
||||||
|
def __init__(self, i2c_bus,addr=LTR_553ALS_ADDRESS,ALS_Gain="X1"):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
self.ALS_IR = 0
|
||||||
|
self.ALS_VIS = 0
|
||||||
|
self.PS = 0
|
||||||
|
self.ALS_gain = ALS_Gain
|
||||||
|
|
||||||
|
if self._chip_id() != 0x05:
|
||||||
|
raise AttributeError("Cannot find a LTR_553ALS")
|
||||||
|
|
||||||
|
self._configure()
|
||||||
|
#time.sleep(0.1)
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg,nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
'''校对设备ID'''
|
||||||
|
return self._rreg(LTR_553ALS_REG_ID)
|
||||||
|
|
||||||
|
def _configure(self):
|
||||||
|
'''配置寄存器'''
|
||||||
|
self._wreg(LTR_ALS_REG_CONTR,_ALS_GAIN[self.ALS_gain][1]) # ALS_CONTR: Active mode
|
||||||
|
self._wreg(LTR_PS_REG_CONTR,0x03) # PS_CONTR: Active mode
|
||||||
|
self._wreg(LTR_PS_REG_LED,0x5B) #PS_LED: LED_pulse_period=50khz,DUTY = 100%,LED_pulsed_current_level = 50mA
|
||||||
|
self._wreg(LTR_PS_REG_PULSES,0x0A) #PS_N_Pulses: Number_of_pulses = 10
|
||||||
|
self._wreg(LTR_PS_REG_RATE,0x08) #PS_Measurement_Rate=10ms
|
||||||
|
self._wreg(LTR_ALS_REG_RATE,0x12) #ALS_Measurement_Rate=200ms,ALS_integration_time=200ms
|
||||||
|
|
||||||
|
def _status(self):
|
||||||
|
'''数据转换状态'''
|
||||||
|
status=self._rreg(LTR_553ALS_REG_ATATUS)
|
||||||
|
return status&0x84, status&0x01 #ALS,PS status
|
||||||
|
|
||||||
|
@property
|
||||||
|
def getdata(self):
|
||||||
|
'''处理获取数据'''
|
||||||
|
if self._status()[0]:
|
||||||
|
data_als=self._rreg(LTR_ALS_REG_DATA1,4)
|
||||||
|
als_ch1=data_als[0] | data_als[1]<<8
|
||||||
|
als_ch0=data_als[2] | data_als[3]<<8
|
||||||
|
ratio=als_ch1/(als_ch1+als_ch0) if (als_ch1+als_ch0)>0 else 0
|
||||||
|
self.ALS_IR =als_ch1*ratio/_ALS_GAIN[self.ALS_gain][0]
|
||||||
|
self.ALS_VIS=als_ch0*ratio/_ALS_GAIN[self.ALS_gain][0]
|
||||||
|
|
||||||
|
if self._status()[1]:
|
||||||
|
data_ps=self._rreg(LTR_PS_REG_DATA1,2)
|
||||||
|
self.PS =data_ps[0] | data_ps[1]<<8
|
||||||
|
|
||||||
|
return round(self.ALS_VIS,2),round(self.ALS_IR,2),self.PS
|
||||||
|
|
||||||
|
def als_vis(self):
|
||||||
|
'''可见光Lux'''
|
||||||
|
return self.getdata[0]
|
||||||
|
|
||||||
|
def als_ir(self):
|
||||||
|
'''红外Lux'''
|
||||||
|
return self.getdata[1]
|
||||||
|
|
||||||
|
def ps_nl(self):
|
||||||
|
'''接近距离'''
|
||||||
|
return self.getdata[2]
|
||||||
1110
mixly/boards/default/micropython/build/lib/map.json
Normal file
1110
mixly/boards/default/micropython/build/lib/map.json
Normal file
File diff suppressed because it is too large
Load Diff
97
mixly/boards/default/micropython/build/lib/matcher.py
Normal file
97
mixly/boards/default/micropython/build/lib/matcher.py
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
# SPDX-FileCopyrightText: 2017 Yoch <https://github.com/yoch>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: EPL-1.0
|
||||||
|
|
||||||
|
"""
|
||||||
|
`matcher`
|
||||||
|
====================================================================================
|
||||||
|
|
||||||
|
MQTT topic filter matcher from the Eclipse Project's Paho.MQTT.Python
|
||||||
|
https://github.com/eclipse/paho.mqtt.python/blob/master/src/paho/mqtt/matcher.py
|
||||||
|
* Author(s): Yoch (https://github.com/yoch)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class MQTTMatcher:
|
||||||
|
"""Intended to manage topic filters including wildcards.
|
||||||
|
|
||||||
|
Internally, MQTTMatcher use a prefix tree (trie) to store
|
||||||
|
values associated with filters, and has an iter_match()
|
||||||
|
method to iterate efficiently over all filters that match
|
||||||
|
some topic name.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# pylint: disable=too-few-public-methods
|
||||||
|
class Node:
|
||||||
|
"""Individual node on the MQTT prefix tree."""
|
||||||
|
|
||||||
|
__slots__ = "children", "content"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.children = {}
|
||||||
|
self.content = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._root = self.Node()
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
"""Add a topic filter :key to the prefix tree
|
||||||
|
and associate it to :value"""
|
||||||
|
node = self._root
|
||||||
|
for sym in key.split("/"):
|
||||||
|
node = node.children.setdefault(sym, self.Node())
|
||||||
|
node.content = value
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
"""Retrieve the value associated with some topic filter :key"""
|
||||||
|
try:
|
||||||
|
node = self._root
|
||||||
|
for sym in key.split("/"):
|
||||||
|
node = node.children[sym]
|
||||||
|
if node.content is None:
|
||||||
|
raise KeyError(key)
|
||||||
|
return node.content
|
||||||
|
except KeyError:
|
||||||
|
raise KeyError(key) from None
|
||||||
|
|
||||||
|
def __delitem__(self, key):
|
||||||
|
"""Delete the value associated with some topic filter :key"""
|
||||||
|
lst = []
|
||||||
|
try:
|
||||||
|
parent, node = None, self._root
|
||||||
|
for k in key.split("/"):
|
||||||
|
parent, node = node, node.children[k]
|
||||||
|
lst.append((parent, k, node))
|
||||||
|
node.content = None
|
||||||
|
except KeyError:
|
||||||
|
raise KeyError(key) from None
|
||||||
|
else: # cleanup
|
||||||
|
for parent, k, node in reversed(lst):
|
||||||
|
if node.children or node.content is not None:
|
||||||
|
break
|
||||||
|
del parent.children[k]
|
||||||
|
|
||||||
|
def iter_match(self, topic):
|
||||||
|
"""Return an iterator on all values associated with filters
|
||||||
|
that match the :topic"""
|
||||||
|
lst = topic.split("/")
|
||||||
|
normal = not topic.startswith("$")
|
||||||
|
|
||||||
|
def rec(node, i=0):
|
||||||
|
if i == len(lst):
|
||||||
|
if node.content is not None:
|
||||||
|
yield node.content
|
||||||
|
else:
|
||||||
|
part = lst[i]
|
||||||
|
if part in node.children:
|
||||||
|
for content in rec(node.children[part], i + 1):
|
||||||
|
yield content
|
||||||
|
if "+" in node.children and (normal or i > 0):
|
||||||
|
for content in rec(node.children["+"], i + 1):
|
||||||
|
yield content
|
||||||
|
if "#" in node.children and (normal or i > 0):
|
||||||
|
content = node.children["#"].content
|
||||||
|
if content is not None:
|
||||||
|
yield content
|
||||||
|
|
||||||
|
return rec(self._root)
|
||||||
71
mixly/boards/default/micropython/build/lib/matrix16x8.py
Normal file
71
mixly/boards/default/micropython/build/lib/matrix16x8.py
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
"""
|
||||||
|
Matrix16x8 Displays
|
||||||
|
|
||||||
|
Micropython library for the HT16K33 Matrix16x8 Displays
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20230411
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from ht16k33 import HT16K33
|
||||||
|
|
||||||
|
class Matrix(HT16K33):
|
||||||
|
"""A single matrix."""
|
||||||
|
def __init__(self, i2c, address=0x70, brightness=0.3, font="5x8", font_address=0x3A0000, width=16, height=8):
|
||||||
|
super().__init__(i2c, address, brightness, width, height)
|
||||||
|
self.font(font)
|
||||||
|
self.uin_font(font_address)
|
||||||
|
|
||||||
|
"""Graph module"""
|
||||||
|
HEART=b' \x02p\x07\xf8\x0f\xf8\x0f\xf0\x07\xe0\x03\xc0\x01\x80\x00'
|
||||||
|
HEART_SMALL=b'\x00\x00 \x02p\x07\xf0\x07\xe0\x03\xc0\x01\x80\x00\x00\x00'
|
||||||
|
HAPPY=b'\x00\x00\x00\x00\x18\x18\x18\x18\x00\x00 \x04@\x02\x80\x01'
|
||||||
|
SAD=b'\x00\x00\x00\x008\x1c\x04 \x00\x00\x80\x01@\x02 \x04'
|
||||||
|
SMILE=b'\x00\x00\x18\x18$$\x00\x00\x00\x00 \x04@\x02\x80\x01'
|
||||||
|
SILLY=b'\x00\x00\x18\x18$$\x18\x18\x00\x00\xc0\x03@\x02\x80\x01'
|
||||||
|
FABULOUS=b'8\x1cD"|>\x00\x00\x00\x00\xe0\x07 \x04\xc0\x03'
|
||||||
|
SURPRISED=b'\x00\x00\x80\x00\x80\x00\x80\x00\x80\x00\x80\x00\x00\x00\x80\x00'
|
||||||
|
ASLEEP=b'\x00\x00\x00\x00<<\x00\x00\x00\x00\xc0\x03 \x04\xc0\x03'
|
||||||
|
ANGRY=b'D"(\x14\x10\x08\x00\x00\x80\x01@\x02 \x04\x10\x08'
|
||||||
|
CONFUSED=b'\x00\x00\xc0\x01 \x02\x00\x02\x00\x01\x80\x00\x00\x00\x80\x00'
|
||||||
|
NO=b'\x00\x00\x10\x02 \x01\xc0\x00\xc0\x00 \x01\x10\x02\x00\x00'
|
||||||
|
YES=b'\x00\x00\x00\x10\x00\x08\x00\x04\x10\x02 \x01\xc0\x00\x00\x00'
|
||||||
|
LEFT_ARROW=b'\x00\x00 \x00\x10\x00\x08\x00\xf4?\x08\x00\x10\x00 \x00'
|
||||||
|
RIGHT_ARROW=b'\x00\x00\x00\x04\x00\x08\x00\x10\xfc/\x00\x10\x00\x08\x00\x04'
|
||||||
|
DRESS=b' \x02\xf0\x07`\x03\xc0\x01\xa0\x02P\x05\xa8\n\xf0\x07'
|
||||||
|
TRANSFORMERS=b'\x00\x00\x80\x00`\x03\xa0\x02\xa0\x02@\x01@\x01 \x02'
|
||||||
|
SCISSORS=b' \x08`\x0c\xc0\x06\x80\x03\x00\x01\xc0\x06\xa0\n@\x04'
|
||||||
|
EXIT=b'\x00\x0c\x00\x07\x80\x0e@2\x00\x05@\t\x00\x11\x00 '
|
||||||
|
TREE=b'\x80\x00\xc0\x01\xe0\x03\xf0\x07\xf8\x0f\x80\x00\x80\x00\x80\x00'
|
||||||
|
PACMAN=b'\xf0\x03\x18\x04L\x02\x04\x01\x0c\x02\x18\x04\xf0\x03\x00\x00'
|
||||||
|
TARGET=b'\x00\x00\x00\x00\x80\x03@\x04@\x05@\x04\x80\x03\x00\x00'
|
||||||
|
TSHIRT=b' \x04\xd0\x0b\x08\x100\x0c \x04 \x04 \x04\xe0\x07'
|
||||||
|
ROLLERSKATE=b'\xf0\x00\x90\x00\x90\x07\x10\x08\xf0\x0f(\x148\x1c\x00\x00'
|
||||||
|
DUCK=b'\xe0\x00\x90\x01\x08\x01<\x01 \x7f \x10\xe0\x0f'
|
||||||
|
HOUSE=b"\xfc?\x06`\x03\xc0\xe4'$$\xa4$$$$$"
|
||||||
|
TORTOISE=b'\x80\x01\xa0\x05\xe0\x07\xe0\x07\xe0\x07\xc0\x03 \x04\x00\x00'
|
||||||
|
BUTTERFLY=b'\x00\x00`\x0c\x90\x12\xe0\x0f\x80\x03@\x05\xa0\n`\x0c'
|
||||||
|
STICKFIGURE=b'\x80\x00@\x01\x80\x00\xc0\x01\xa0\x02\x80\x00@\x01 \x02'
|
||||||
|
GHOST=b'\xe0\x03\xb0\x06\xb0\x06\xf0\x07\xb0\x06P\x05\xf0\x0f\xf0\x1f'
|
||||||
|
PITCHFORK=b'\x00\xf8\x00\x04\x00\x04\xff\xff\x00\x04\x00\x04\x00\xf8\x00\x00'
|
||||||
|
MUSIC_QUAVERS=b'\x00\x00\x00\x00\x18\x86<O\xf2<a\x18\x00\x00\x00\x00'
|
||||||
|
MUSIC_QUAVER=b'\xfe\x00\x01\x01\xff\x0f\x00\x1e\x00?\x00?\x00>\x00\x1c'
|
||||||
|
MUSIC_CROTCHET=b'\x00\x00\xff\x0f\x00\x1e\x00?\x00?\x00>\x00\x1c\x00\x00'
|
||||||
|
COW=b'\x08\x00\x1e\x00\xfa\x07\xfe\x0f\xfe70F0\x060\x06'
|
||||||
|
RABBIT=b'\xc0?~@\x01Q>\\\x01Q~@\xc0?\x00\x00'
|
||||||
|
SQUARE_SMALL=b'\x00\x00\x00\x00\xc0\x03@\x02@\x02\xc0\x03\x00\x00\x00\x00'
|
||||||
|
SQUARE=b'\xf0\x0f\x10\x08\x10\x08\x10\x08\x10\x08\x10\x08\x10\x08\xf0\x0f'
|
||||||
|
DIAMOND_SMALL=b'\x00\x00\x00\x00\xc0\x01\xa0\x02@\x01\x80\x00\x00\x00\x00\x00'
|
||||||
|
DIAMOND=b'\xf0\x07X\r\xec\x1b\xd8\r\xb0\x06`\x03\xc0\x01\x80\x00'
|
||||||
|
CHESSBOARD=b'\x00\x00\xf8?\xa8*\xf8?\xa8*\xf8?\xa8*\xf8?'
|
||||||
|
TRIANGLE_LEFT=b'\x00\x00\x00\x01\x80\x01\xc0\x01\xe0\x01\xc0\x01\x80\x01\x00\x01'
|
||||||
|
TRIANGLE=b'\x00\x00\x80\x01\xc0\x03\xe0\x07\xf0\x0f\xf8\x1f\xfc?\x00\x00'
|
||||||
|
SNAKE=b'\x00\x0e\x00\n\x00\x0e\xf0\x03\xf8\x03\x1c\x00\x0e\x00\x00\x00'
|
||||||
|
UMBRELLA=b'\x80\x00\xe0\x03\xf0\x07\xf8\x0f\x80\x00\x80\x00\x80\x02\x80\x03'
|
||||||
|
SKULL=b'\xe0\x03\x90\x04\x88\x08x\x0f\xf0\x07 \x02\xa0\x02\xc0\x01'
|
||||||
|
GIRAFFE=b'\x80\x01\x80\x03\x80\x00\x80\x00\x80\x00\xf0\x00\x90\x00\x90\x00'
|
||||||
|
SWORD=b'\x00\x00\x10\x000\x00\xfc\x1f\xfc\x1f0\x00\x10\x00\x00\x00'
|
||||||
|
DOOR_OPENING=b'\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\xff\xff'
|
||||||
|
DOOR_OPEN=b'\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff'
|
||||||
|
DOOR_CLOSE=b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
|
||||||
70
mixly/boards/default/micropython/build/lib/matrix32x12.py
Normal file
70
mixly/boards/default/micropython/build/lib/matrix32x12.py
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
"""
|
||||||
|
Matrix Displays
|
||||||
|
|
||||||
|
Micropython library for the TM1680 Matrix Displays
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20230414
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from tm1680 import TM1680
|
||||||
|
|
||||||
|
class Matrix(TM1680):
|
||||||
|
"""A single matrix."""
|
||||||
|
def __init__(self, i2c, address=0x72, brightness=0.3, font_address=0x3A0000, width=32, height=12):
|
||||||
|
super().__init__(i2c, address, brightness, width, height)
|
||||||
|
self.font(font_address)
|
||||||
|
|
||||||
|
"""Graph module"""
|
||||||
|
HEART_SMALL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x02\x00\x00p\x07\x00\x00\xf8\x0f\x00\x00\xf8\x0f\x00\x00\xf0\x07\x00\x00\xe0\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
HEART=b'\x00\x00\x00\x00\x00 \x02\x00\x00p\x07\x00\x00\xf8\x0f\x00\x00\xfc\x1f\x00\x00\xfc\x1f\x00\x00\xf8\x0f\x00\x00\xf0\x07\x00\x00\xe0\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00'
|
||||||
|
HAPPY=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x08\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\x00\x00\x00\x00\x00'
|
||||||
|
SAD=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1c8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00@\x02\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x00\x00\x00'
|
||||||
|
SMILE=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04 \x00\x00\x0c0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c0\x00\x008\x1c\x00\x00\xe0\x07\x00\x00\x00\x00\x00'
|
||||||
|
SILLY=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04 \x00\x00\x08\x10\x00\x00\x04 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x07\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\x00\x00\x00\x00\x00'
|
||||||
|
FABULOUS=b'\x00\x00\x00\x00\x00\x04 \x00\x00\x08\x10\x00\x00\x0c0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\x1f\x00\x00\x08\x10\x00\x00\x08\x10\x00\x00\x10\x08\x00\x00\xe0\x07\x00\x00\x00\x00\x00'
|
||||||
|
SURPRISED=b'\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00'
|
||||||
|
ASLEEP=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x07\x00\x00\x10\x08\x00\x00\xe0\x07\x00\x00\x00\x00\x00'
|
||||||
|
ANGRY=b'\x00\x00\x00\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x08\x10\x00\x00\x04 \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00@\x02\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x08\x10\x00'
|
||||||
|
CONFUSED=b'\x00\xc0\x03\x00\x00`\x06\x00\x000\x0c\x00\x000\x0c\x00\x00\x00\x0c\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x80\x01\x00'
|
||||||
|
NO=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x08\x00\x00 \x04\x00\x00@\x02\x00\x00\x80\x01\x00\x00\x80\x01\x00\x00@\x02\x00\x00 \x04\x00\x00\x10\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
YES=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x18\x00\x00\x00\x0c\x00\x00\x00\x06\x00\x00\x0c\x03\x00\x00\x98\x01\x00\x00\xf0\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
LEFT_ARROW=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00 \x00\x00\x00\x10\x00\x00\x00\xe8\x1f\x00\x00\x10\x00\x00\x00 \x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
RIGHT_ARROW=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x00\x08\x00\x00\xf8\x17\x00\x00\x00\x08\x00\x00\x00\x04\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
DRESS=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x02\x00\x00\xf0\x07\x00\x00`\x03\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00P\x05\x00\x00\xa8\n\x00\x00\xf0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
TRANSFORMERS=b'\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xc0\x06\x00\x00@\x05\x00\x00@\x05\x00\x00@\x05\x00\x00\x80\x02\x00\x00\x80\x02\x00\x00@\x04\x00\x00 \x08\x00\x00\x00\x00\x00'
|
||||||
|
SCISSORS=b'\x00\x00\x00\x00\x00\x04\x10\x00\x00\x0c\x18\x00\x00\x18\x0c\x00\x000\x06\x00\x00`\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00p\x07\x00\x00H\t\x00\x00H\t\x00\x000\x06\x00'
|
||||||
|
EXIT=b'\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x01\x00\x00\xc0\x01\x00\x00\xa0\x03\x00\x00\x90\x0c\x00\x00\x80\x00\x00\x00P\x01\x00\x00@\x02\x00\x00@\x04\x00\x00\x00\x08\x00\x00\x00\x00\x00'
|
||||||
|
TREE=b'\x00\x00\x00\x00\x00\x80\x00\x00\x00\xc0\x01\x00\x00\xe0\x03\x00\x00\xf0\x07\x00\x00\xf8\x0f\x00\x00\xfc\x1f\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00'
|
||||||
|
PACMAN=b'\x00\x00\x00\x00\x00\xf0\x07\x00\x00\x18\x08\x00\x00\x8c\x04\x00\x00\x0c\x02\x00\x00\x04\x01\x00\x00\x0c\x02\x00\x00\x0c\x04\x00\x00\x18\x08\x00\x00\xf0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
TARGET=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x07\x00\x00 \x08\x00\x00 \x08\x00\x00 \t\x00\x00 \x08\x00\x00 \x08\x00\x00\xc0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
TSHIRT=b'\x00@\x04\x00\x00\xa0\x0b\x00\x00\x10\x10\x00\x00\x08 \x00\x000\x18\x00\x00 \x08\x00\x00 \x08\x00\x00 \x08\x00\x00 \x08\x00\x00 \x08\x00\x00\xe0\x0f\x00\x00\x00\x00\x00'
|
||||||
|
ROLLERSKATE=b'\x00\x00\x00\x00\x00\xf8\x00\x00\x00\x88\x00\x00\x00\x88\x00\x00\x00\x88\x0f\x00\x00\x08\x10\x00\x00\x08\x10\x00\x00\xf8\x1f\x00\x00\x14(\x00\x00\x1c8\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
DUCK=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x00\x00\x00\x90\x00\x00\x00\x08\x01\x00\x00<\x01\x00\x00 ?\x00\x00 \x10\x00\x00 \x08\x00\x00\xe0\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
HOUSE=b'\x00\x00\x00\x00\x00\xf0\x0f\x00\x00\x18\x18\x00\x00\x0c0\x00\x00\xd0\x0b\x00\x00P\n\x00\x00P\n\x00\x00\xd0\n\x00\x00P\n\x00\x00P\n\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
TORTOISE=b'\x00\x00\x00\x00\x00\x80\x01\x00\x00\xa0\x05\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xe0\x07\x00\x00\xc0\x03\x00\x00 \x04\x00\x00\x00\x00\x00'
|
||||||
|
BUTTERFLY=b'\x00\x00\x00\x00\x00\x18\x0c\x00\x00$\x12\x00\x00D\x11\x00\x00\xf8\x0f\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00\xd0\x05\x00\x00(\n\x00\x00\x18\x0c\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
STICKFIGURE=b'\x00\x80\x00\x00\x00@\x01\x00\x00@\x01\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00\x90\x04\x00\x00@\x01\x00\x00 \x02\x00\x00\x10\x04\x00\x00\x00\x00\x00'
|
||||||
|
GHOST=b'\x00\x00\x00\x00\x00\xe0\x03\x00\x00\xb0\x06\x00\x00\xb0\x06\x00\x00\xb0\x06\x00\x00\xf0\x07\x00\x00\xb0\x06\x00\x00\xb0\x06\x00\x00P\x05\x00\x00\xf0\x0f\x00\x00\xf0\x1f\x00\x00\x00\x00\x00'
|
||||||
|
PITCHFORK=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00<\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\xfc?\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
MUSIC_QUAVERS=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x000\x06\x00\x00x\x0f\x00\x00\xe4=\x00\x00\xc0\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
MUSIC_QUAVER=b'\x00\x00\x03\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x05\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00`\x01\x00\x00\xf0\x01\x00\x00\xf8\x01\x00\x00\xf8\x00\x00\x00p\x00\x00'
|
||||||
|
MUSIC_CROTCHET=b'\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00`\x01\x00\x00\xf0\x01\x00\x00\xf8\x01\x00\x00\xf8\x00\x00\x00p\x00\x00'
|
||||||
|
COW=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00 \x00\x00\x00x\x00\x00\x00\xe8\x0f\x00\x00\xf8\x1f\x00\x00\xf8/\x00\x00`,\x00\x00`\x0c\x00\x00`\x0c\x00\x00`\x0c\x00\x00\x00\x00\x00'
|
||||||
|
RABBIT=b'\x00@\x01\x00\x00\xa0\x02\x00\x00\xa0\x02\x00\x00\xa0\x02\x00\x00\xa0\x02\x00\x000\x06\x00\x00\x10\x04\x00\x00P\x05\x00\x00\x10\x04\x00\x00\x90\x04\x00\x00\xd0\x05\x00\x00\xe0\x03\x00'
|
||||||
|
SQUARE_SMALL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x03\x00\x00@\x02\x00\x00@\x02\x00\x00\xc0\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
SQUARE=b'\x00\xfc?\x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\x04 \x00\x00\xfc?\x00'
|
||||||
|
DIAMOND_SMALL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x01\x00\x00\xa0\x02\x00\x00@\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
DIAMOND=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x07\x00\x00X\r\x00\x00\xec\x1b\x00\x00\xd8\r\x00\x00\xb0\x06\x00\x00`\x03\x00\x00\xc0\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
CHESSBOARD=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfc\x1f\x00\x00T\x15\x00\x00\xfc\x1f\x00\x00T\x15\x00\x00\xfc\x1f\x00\x00T\x15\x00\x00\xfc\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
TRIANGLE_LEFT=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x80\x03\x00\x00\xc0\x03\x00\x00\x80\x03\x00\x00\x00\x03\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
TRIANGLE=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\xc0\x03\x00\x00\xe0\x07\x00\x00\xf0\x0f\x00\x00\xf8\x1f\x00\x00\xfc?\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
SNAKE=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x008\x00\x00\x00(\x00\x00\x008\x00\x00\xc0\x0f\x00\x00\xe0\x0f\x00\x00p\x00\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
UMBRELLA=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\xe0\x03\x00\x00\xf0\x07\x00\x00\xf8\x0f\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x00\x00\x00\x80\x02\x00\x00\x00\x01\x00\x00\x00\x00\x00'
|
||||||
|
SKULL=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\xe0\x03\x00\x00\x90\x04\x00\x00\x88\x08\x00\x00x\x0f\x00\x00\xf0\x07\x00\x00 \x02\x00\x00 \x02\x00\x00\xa0\x02\x00\x00\xc0\x01\x00\x00\x00\x00\x00'
|
||||||
|
GIRAFFE=b'\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\xe0\x01\x00\x00 \x01\x00\x00 \x01\x00\x00 \x01\x00'
|
||||||
|
SWORD=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x000\x00\x00\x00\xfc\x1f\x00\x00\xfc\x1f\x00\x000\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
DOOR_OPEN=b'\x00\xf8\x1f\x00\x00\x04 \x00\x00\x0c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00\x00\x1c \x00'
|
||||||
|
DOOR_OPENING=b'\x00\xf8\x1f\x00\x004 \x00\x00L \x00\x00\x8c \x00\x00\x0c!\x00\x00\x0c!\x00\x00L!\x00\x00L!\x00\x00\x0c!\x00\x00\x0c!\x00\x00\x0c!\x00\x00\x0c!\x00'
|
||||||
|
DOOR_CLOSE=b'\x00\xf8\x1f\x00\x00\xf4/\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c6\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00\x00\x0c0\x00'
|
||||||
67
mixly/boards/default/micropython/build/lib/matrix8x5.py
Normal file
67
mixly/boards/default/micropython/build/lib/matrix8x5.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
"""
|
||||||
|
Matrix8x5 Displays
|
||||||
|
|
||||||
|
Micropython library for the TM1652 Matrix8x5 Displays
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary compositio 20230411
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from tm1652 import TM1652
|
||||||
|
|
||||||
|
class Matrix(TM1652):
|
||||||
|
"""A single matrix."""
|
||||||
|
def __init__(self, pin, brightness=0.3, font="4x5", width=8, height=5):
|
||||||
|
super().__init__(pin, brightness, width, height)
|
||||||
|
self.font(font)
|
||||||
|
|
||||||
|
"""Graph module 5x8"""
|
||||||
|
HEART = b'\x14>>\x1c\x08'
|
||||||
|
HEART_SMALL = b'\x00\x14\x1c\x08\x00'
|
||||||
|
HAPPY = b'\x00\x14\x00"\x1c'
|
||||||
|
SAD = b'\x00\x14\x00\x1c"'
|
||||||
|
SMILE = b'\x00\x14\x00"\x1c'
|
||||||
|
SILLY = b'"\x00>(8'
|
||||||
|
FABULOUS = b'>6\x00\x14\x1c'
|
||||||
|
SURPRISED = b'\x14\x00\x08\x14\x08'
|
||||||
|
ASLEEP = b'\x006\x00\x1c\x00'
|
||||||
|
ANGRY = b'"\x14\x00>*'
|
||||||
|
CONFUSED = b'\x00\x14\x00\x14*'
|
||||||
|
NO = b'"\x14\x08\x14"'
|
||||||
|
YES = b'\x00 \x10\n\x04'
|
||||||
|
LEFT_ARROW = b'\x08\x04~\x04\x08'
|
||||||
|
RIGHT_ARROW = b'\x10 ~ \x10'
|
||||||
|
DRESS = b'$f<Z\xbd'
|
||||||
|
TRANSFORMERS = b'\x08\x1c*\x14"'
|
||||||
|
SCISSORS = b'&\x16\x08\x16&'
|
||||||
|
EXIT = b'\x08\x1c*\x16 '
|
||||||
|
TREE = b'\x08\x1c>\x08\x08'
|
||||||
|
PACMAN = b'<\x16\x0e\x1e<'
|
||||||
|
TARGET = b'\x08\x1c6\x1c\x08'
|
||||||
|
TSHIRT = b'6>\x1c\x1c\x1c'
|
||||||
|
ROLLERSKATE = b'00>>\x14'
|
||||||
|
DUCK = b'\x0c\x0e<\x1c\x00'
|
||||||
|
HOUSE = b'\x08\x1c>\x1c\x14'
|
||||||
|
TORTOISE = b'\x00\x1c>\x14\x00'
|
||||||
|
BUTTERFLY = b'6>\x08>6'
|
||||||
|
STICKFIGURE = b'\x08>\x08\x14"'
|
||||||
|
GHOST = b'>*>>*'
|
||||||
|
PITCHFORK = b'**>\x08\x08'
|
||||||
|
MUSIC_QUAVERS = b'<$$66'
|
||||||
|
MUSIC_QUAVER = b'\x08\x18(\x0e\x0e'
|
||||||
|
MUSIC_CROTCHET = b'\x08\x08\x08\x0e\x0e'
|
||||||
|
COW = b'"">\x1c\x08'
|
||||||
|
RABBIT = b'\n\n\x1e\x16\x1e'
|
||||||
|
SQUARE_SMALL = b'\x00\x1c\x14\x1c\x00'
|
||||||
|
SQUARE = b'>""">'
|
||||||
|
DIAMOND_SMALL = b'\x00\x08\x14\x08\x00'
|
||||||
|
DIAMOND = b'\x08\x14"\x14\x08'
|
||||||
|
CHESSBOARD = b'\x14*\x14*\x14'
|
||||||
|
TRIANGLE_LEFT = b'\x02\x06\n\x12>'
|
||||||
|
TRIANGLE = b'\x00\x08\x14>\x00'
|
||||||
|
SNAKE = b'\x066\x14\x1c\x00'
|
||||||
|
UMBRELLA = b'\x1c>\x08\n\x0c'
|
||||||
|
SKULL = b'\x1c*>\x1c\x1c'
|
||||||
|
GIRAFFE = b'\x06\x04\x04\x1c\x14'
|
||||||
|
SWORD = b'\x08\x08\x08\x1c\x08'
|
||||||
291
mixly/boards/default/micropython/build/lib/max30102.py
Normal file
291
mixly/boards/default/micropython/build/lib/max30102.py
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
"""
|
||||||
|
MAX30102
|
||||||
|
|
||||||
|
MicroPython library for the MAX30102(bmp_and_spo2)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20220723
|
||||||
|
#base on https://github.com/doug-burrell/max30102.git 20220723
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
# Address of each register.
|
||||||
|
REG_INTR_STATUS_1 = const(0x00)
|
||||||
|
REG_INTR_STATUS_2 = const(0x01)
|
||||||
|
REG_INTR_ENABLE_1 = const(0x02)
|
||||||
|
REG_INTR_ENABLE_2 = const(0x03)
|
||||||
|
REG_FIFO_WR_PTR = const(0x04)
|
||||||
|
REG_OVF_COUNTER = const(0x05)
|
||||||
|
REG_FIFO_RD_PTR = const(0x06)
|
||||||
|
REG_FIFO_DATA = const(0x07)
|
||||||
|
REG_FIFO_CONFIG = const(0x08)
|
||||||
|
REG_MODE_CONFIG = const(0x09)
|
||||||
|
REG_SPO2_CONFIG = const(0x0A)
|
||||||
|
REG_LED1_PA = const(0x0C)
|
||||||
|
REG_LED2_PA = const(0x0D)
|
||||||
|
REG_PILOT_PA = const(0x10)
|
||||||
|
REG_MULTI_LED_CTRL1 = const(0x11)
|
||||||
|
REG_MULTI_LED_CTRL2 = const(0x12)
|
||||||
|
REG_TEMP_INTR = const(0x1F)
|
||||||
|
REG_TEMP_FRAC = const(0x20)
|
||||||
|
REG_TEMP_CONFIG = const(0x21)
|
||||||
|
REG_PART_ID = const(0xFF)
|
||||||
|
|
||||||
|
class MAX30102:
|
||||||
|
def __init__(self, i2c, address=0x57):
|
||||||
|
"""Initiate MAX30102 class ond each function responsible for correct device start-up"""
|
||||||
|
self._device = i2c
|
||||||
|
self._address = address
|
||||||
|
|
||||||
|
if self._chip_id() != 0x15:
|
||||||
|
raise AttributeError("Cannot find a MAX30102")
|
||||||
|
|
||||||
|
self.reset()
|
||||||
|
time.sleep(1)
|
||||||
|
self.setup()
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg,nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
return self._rreg(REG_PART_ID)
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Set default values of all registers"""
|
||||||
|
self._wreg(REG_MODE_CONFIG, 0x40)
|
||||||
|
|
||||||
|
def shutdown(self):
|
||||||
|
"""Shutdown the device"""
|
||||||
|
self._wreg(mode_config, 0x80) # 0b10000000 = 0x80
|
||||||
|
|
||||||
|
def setup(self,led_mode=0x03):
|
||||||
|
"""Set all registers needed to correct work of sensor"""
|
||||||
|
self._wreg(REG_INTR_ENABLE_1, 0xC0) # 0xc0 : A_FULL_EN and PPG_RDY_EN = Interrupt will be triggered when
|
||||||
|
self._wreg(REG_INTR_ENABLE_2, 0x00) # fifo almost full & new fifo data ready
|
||||||
|
|
||||||
|
self._wreg(REG_FIFO_WR_PTR, 0x00) # FIFO_WR_PTR[4:0]
|
||||||
|
self._wreg(REG_OVF_COUNTER, 0x00) # OVF_COUNTER[4:0]
|
||||||
|
self._wreg(REG_FIFO_RD_PTR, 0x00) # FIFO_RD_PTR[4:0]
|
||||||
|
|
||||||
|
self._wreg(REG_FIFO_CONFIG, 0x4F) # sample avg = 4, fifo rollover = false, fifo almost full = 17
|
||||||
|
self._wreg(REG_MODE_CONFIG, led_mode) # 0x02 for read-only, 0x03 for SpO2 mode, 0x07 multimode LED
|
||||||
|
self._wreg(REG_SPO2_CONFIG, 0x27) # SPO2_ADC range = 4096nA, SPO2 sample rate = 100Hz, LED pulse-width = 411uS
|
||||||
|
|
||||||
|
self._wreg(REG_LED1_PA, 0x40) # choose value for ~7mA for LED1
|
||||||
|
self._wreg(REG_LED2_PA, 0x40) # choose value for ~7mA for LED2
|
||||||
|
self._wreg(REG_PILOT_PA, 0x7F) # choose value fro ~25mA for Pilot LED
|
||||||
|
|
||||||
|
def get_data_present(self):
|
||||||
|
read_ptr = self._rreg(REG_FIFO_RD_PTR)
|
||||||
|
write_ptr = self._rreg(REG_FIFO_WR_PTR)
|
||||||
|
if read_ptr == write_ptr:
|
||||||
|
return 0
|
||||||
|
else:
|
||||||
|
num_samples = write_ptr - read_ptr # account for pointer wrap around
|
||||||
|
if num_samples < 0:
|
||||||
|
num_samples += 32
|
||||||
|
return num_samples
|
||||||
|
|
||||||
|
def read_fifo(self):
|
||||||
|
"""This function will read the data register"""
|
||||||
|
reg_INTR1 = self._rreg(REG_INTR_STATUS_1)
|
||||||
|
reg_INTR2 = self._rreg(REG_INTR_STATUS_2)
|
||||||
|
d = self._rreg(REG_FIFO_DATA, 6)
|
||||||
|
|
||||||
|
red_led = (d[0] << 16 | d[1] << 8 | d[2]) & 0x03FFFF
|
||||||
|
ir_led = (d[3] << 16 | d[4] << 8 | d[5]) & 0x03FFFF
|
||||||
|
return ir_led,red_led
|
||||||
|
|
||||||
|
def read_sequential(self, amount=100):
|
||||||
|
"""This function will read the red-led and ir-led `amount` times"""
|
||||||
|
red_buf = []
|
||||||
|
ir_buf = []
|
||||||
|
count = amount
|
||||||
|
while count > 0:
|
||||||
|
num_bytes = self.get_data_present()
|
||||||
|
while num_bytes > 0:
|
||||||
|
ir, red = self.read_fifo()
|
||||||
|
red_buf.append(red)
|
||||||
|
ir_buf.append(ir)
|
||||||
|
num_bytes -= 1
|
||||||
|
count -= 1
|
||||||
|
return ir_buf,red_buf
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
"""Read temperature as sum of integer and fraction value """
|
||||||
|
self._wreg(REG_TEMP_CONFIG, 0x01)
|
||||||
|
status = self._rreg(REG_INTR_STATUS_2)
|
||||||
|
count = 1
|
||||||
|
while status != 2 and count < 5:
|
||||||
|
status = self._rreg(REG_INTR_STATUS_2)
|
||||||
|
count += 1
|
||||||
|
integer = self._rreg(REG_TEMP_INTR)
|
||||||
|
fraction = self._rreg(REG_TEMP_FRAC)
|
||||||
|
return round(integer + fraction * 0.0625,2)
|
||||||
|
|
||||||
|
def heartrate(self,amount=5):
|
||||||
|
bpms = []
|
||||||
|
sop2 = []
|
||||||
|
for _ in range(amount):
|
||||||
|
ir_data, red_data=self.read_sequential()
|
||||||
|
if get_mean(ir_data) < 50000 and get_mean(red_data) < 50000 :
|
||||||
|
return 0,0
|
||||||
|
raw_bpm, valid_bpm, raw_spo2, valid_spo2 = calc_hr_and_spo2(ir_data, red_data)
|
||||||
|
if valid_bpm:
|
||||||
|
bpms.append(raw_bpm)
|
||||||
|
if valid_spo2:
|
||||||
|
sop2.append(raw_spo2)
|
||||||
|
bpms_len=len(bpms)
|
||||||
|
sop2_len=len(sop2)
|
||||||
|
if bpms_len<=2 or sop2_len<=2:
|
||||||
|
return 0,0
|
||||||
|
else:
|
||||||
|
return sum(sorted(bpms)[1:bpms_len-1])//(bpms_len-2),round(sum(sorted(sop2)[1:sop2_len-1])/(sop2_len-2),2)
|
||||||
|
|
||||||
|
"""-----------以下心率算法-----------"""
|
||||||
|
|
||||||
|
SAMPLE_FREQ = 25 # 25 samples per second
|
||||||
|
MA_SIZE = 4
|
||||||
|
BUFFER_SIZE = 100 # sampling frequency * 4
|
||||||
|
|
||||||
|
def get_mean(ls):
|
||||||
|
return sum(ls)/len(ls)
|
||||||
|
|
||||||
|
def calc_hr_and_spo2(ir_data, red_data):
|
||||||
|
ir_mean = int(get_mean(ir_data))
|
||||||
|
x = []
|
||||||
|
for k in ir_data:
|
||||||
|
x.append((k-ir_mean)*-1)
|
||||||
|
for i in range(len(x) - MA_SIZE):
|
||||||
|
x[i] = sum(x[i:i+MA_SIZE]) / MA_SIZE
|
||||||
|
|
||||||
|
n_th = int(get_mean(x))
|
||||||
|
n_th = 30 if n_th < 30 else n_th # min allowed
|
||||||
|
n_th = 60 if n_th > 60 else n_th # max allowed
|
||||||
|
|
||||||
|
ir_valley_locs, n_peaks = find_peaks(x, BUFFER_SIZE, n_th, 4, 15)
|
||||||
|
peak_interval_sum = 0
|
||||||
|
if n_peaks >= 2:
|
||||||
|
for i in range(1, n_peaks):
|
||||||
|
peak_interval_sum += (ir_valley_locs[i] - ir_valley_locs[i-1])
|
||||||
|
peak_interval_sum = int(peak_interval_sum / (n_peaks - 1))
|
||||||
|
hr = int(SAMPLE_FREQ * 60 / peak_interval_sum)
|
||||||
|
hr_valid = True
|
||||||
|
else:
|
||||||
|
hr = -999
|
||||||
|
hr_valid = False
|
||||||
|
|
||||||
|
exact_ir_valley_locs_count = n_peaks
|
||||||
|
for i in range(exact_ir_valley_locs_count):
|
||||||
|
if ir_valley_locs[i] > BUFFER_SIZE:
|
||||||
|
spo2 = -999
|
||||||
|
spo2_valid = False
|
||||||
|
return hr, hr_valid, spo2, spo2_valid
|
||||||
|
i_ratio_count = 0
|
||||||
|
ratio = []
|
||||||
|
# find max between two valley locations
|
||||||
|
red_dc_max_index = -1
|
||||||
|
ir_dc_max_index = -1
|
||||||
|
for k in range(exact_ir_valley_locs_count-1):
|
||||||
|
red_dc_max = -16777216
|
||||||
|
ir_dc_max = -16777216
|
||||||
|
if ir_valley_locs[k+1] - ir_valley_locs[k] > 3:
|
||||||
|
for i in range(ir_valley_locs[k], ir_valley_locs[k+1]):
|
||||||
|
if ir_data[i] > ir_dc_max:
|
||||||
|
ir_dc_max = ir_data[i]
|
||||||
|
ir_dc_max_index = i
|
||||||
|
if red_data[i] > red_dc_max:
|
||||||
|
red_dc_max = red_data[i]
|
||||||
|
red_dc_max_index = i
|
||||||
|
|
||||||
|
red_ac = int((red_data[ir_valley_locs[k+1]] - red_data[ir_valley_locs[k]]) * (red_dc_max_index - ir_valley_locs[k]))
|
||||||
|
red_ac = red_data[ir_valley_locs[k]] + int(red_ac / (ir_valley_locs[k+1] - ir_valley_locs[k]))
|
||||||
|
red_ac = red_data[red_dc_max_index] - red_ac # subtract linear DC components from raw
|
||||||
|
|
||||||
|
ir_ac = int((ir_data[ir_valley_locs[k+1]] - ir_data[ir_valley_locs[k]]) * (ir_dc_max_index - ir_valley_locs[k]))
|
||||||
|
ir_ac = ir_data[ir_valley_locs[k]] + int(ir_ac / (ir_valley_locs[k+1] - ir_valley_locs[k]))
|
||||||
|
ir_ac = ir_data[ir_dc_max_index] - ir_ac # subtract linear DC components from raw
|
||||||
|
|
||||||
|
nume = red_ac * ir_dc_max
|
||||||
|
denom = ir_ac * red_dc_max
|
||||||
|
if (denom > 0 and i_ratio_count < 5) and nume != 0:
|
||||||
|
ratio.append(int(((nume * 100) & 0xffffffff) / denom))
|
||||||
|
i_ratio_count += 1
|
||||||
|
# choose median value since PPG signal may vary from beat to beat
|
||||||
|
ratio = sorted(ratio) # sort to ascending order
|
||||||
|
mid_index = int(i_ratio_count / 2)
|
||||||
|
|
||||||
|
ratio_ave = 0
|
||||||
|
if mid_index > 1:
|
||||||
|
ratio_ave = int((ratio[mid_index-1] + ratio[mid_index])/2)
|
||||||
|
else:
|
||||||
|
if len(ratio) != 0:
|
||||||
|
ratio_ave = ratio[mid_index]
|
||||||
|
|
||||||
|
if ratio_ave > 2 and ratio_ave < 184:
|
||||||
|
# -45.060 * ratioAverage * ratioAverage / 10000 + 30.354 * ratioAverage / 100 + 94.845
|
||||||
|
spo2 = -45.060 * (ratio_ave**2) / 10000.0 + 30.054 * ratio_ave / 100.0 + 94.845
|
||||||
|
spo2_valid = True
|
||||||
|
else:
|
||||||
|
spo2 = -999
|
||||||
|
spo2_valid = False
|
||||||
|
|
||||||
|
return hr, hr_valid, spo2, spo2_valid
|
||||||
|
|
||||||
|
def find_peaks(x, size, min_height, min_dist, max_num):
|
||||||
|
""" Find at most MAX_NUM peaks above MIN_HEIGHT separated by at least MIN_DISTANCE"""
|
||||||
|
ir_valley_locs, n_peaks = find_peaks_above_min_height(x, size, min_height, max_num)
|
||||||
|
ir_valley_locs, n_peaks = remove_close_peaks(n_peaks, ir_valley_locs, x, min_dist)
|
||||||
|
n_peaks = min([n_peaks, max_num])
|
||||||
|
return ir_valley_locs, n_peaks
|
||||||
|
|
||||||
|
def find_peaks_above_min_height(x, size, min_height, max_num):
|
||||||
|
"""Find all peaks above MIN_HEIGHT """
|
||||||
|
i = 0
|
||||||
|
n_peaks = 0
|
||||||
|
ir_valley_locs = [] # [0 for i in range(max_num)]
|
||||||
|
while i < size - 1:
|
||||||
|
if x[i] > min_height and x[i] > x[i-1]: # find the left edge of potential peaks
|
||||||
|
n_width = 1
|
||||||
|
while i + n_width < size - 1 and x[i] == x[i+n_width]: # find flat peaks
|
||||||
|
n_width += 1
|
||||||
|
if x[i] > x[i+n_width] and n_peaks < max_num: # find the right edge of peaks
|
||||||
|
ir_valley_locs.append(i)
|
||||||
|
n_peaks += 1 # original uses post increment
|
||||||
|
i += n_width + 1
|
||||||
|
else:
|
||||||
|
i += n_width
|
||||||
|
else:
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
return ir_valley_locs, n_peaks
|
||||||
|
|
||||||
|
def remove_close_peaks(n_peaks, ir_valley_locs, x, min_dist):
|
||||||
|
""" Remove peaks separated by less than MIN_DISTANCE"""
|
||||||
|
sorted_indices = sorted(ir_valley_locs, key=lambda i: x[i])
|
||||||
|
sorted_indices.reverse()
|
||||||
|
|
||||||
|
i = -1
|
||||||
|
while i < n_peaks:
|
||||||
|
old_n_peaks = n_peaks
|
||||||
|
n_peaks = i + 1
|
||||||
|
j = i + 1
|
||||||
|
while j < old_n_peaks:
|
||||||
|
n_dist = (sorted_indices[j] - sorted_indices[i]) if i != -1 else (sorted_indices[j] + 1) # lag-zero peak of autocorr is at index -1
|
||||||
|
if n_dist > min_dist or n_dist < -1 * min_dist:
|
||||||
|
sorted_indices[n_peaks] = sorted_indices[j]
|
||||||
|
n_peaks += 1 # original uses post increment
|
||||||
|
j += 1
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
sorted_indices[:n_peaks] = sorted(sorted_indices[:n_peaks])
|
||||||
|
return sorted_indices, n_peaks
|
||||||
206
mixly/boards/default/micropython/build/lib/mixgo_ai.py
Normal file
206
mixly/boards/default/micropython/build/lib/mixgo_ai.py
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
"""
|
||||||
|
AI COM
|
||||||
|
|
||||||
|
MicroPython library for the AI COM ( for MixGo AI)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20220905
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time,gc
|
||||||
|
|
||||||
|
|
||||||
|
class INFO:
|
||||||
|
def __init__(self, info1,info2,rect):
|
||||||
|
self.info1=info1
|
||||||
|
self.info2=info2
|
||||||
|
self.rect=rect
|
||||||
|
self.x=None
|
||||||
|
self.y=None
|
||||||
|
self.w=None
|
||||||
|
self.h=None
|
||||||
|
self.xc=None
|
||||||
|
self.yc=None
|
||||||
|
if type(rect) in [tuple,list]:
|
||||||
|
self.x=rect[0]
|
||||||
|
self.y=rect[1]
|
||||||
|
self.w=rect[2]
|
||||||
|
self.h=rect[3]
|
||||||
|
self.xc=rect[0]+rect[2]//2
|
||||||
|
self.yc=rect[1]+rect[3]//2
|
||||||
|
self.type="info"
|
||||||
|
|
||||||
|
class AI:
|
||||||
|
def __init__(self, uart, quick=False):
|
||||||
|
self._uart=uart
|
||||||
|
self._uart.init(baudrate=115200, timeout=500)
|
||||||
|
self._info=[]
|
||||||
|
self._sdata=[]
|
||||||
|
self._removal=quick
|
||||||
|
if not self._chip_id():
|
||||||
|
raise AttributeError("Cannot find a MixGo AI")
|
||||||
|
|
||||||
|
def send(self,data):
|
||||||
|
eec=0
|
||||||
|
buffer=str(data).encode()
|
||||||
|
for i in range(len(buffer)):
|
||||||
|
eec^=int(buffer[i])
|
||||||
|
eec=0 if eec==10 else eec
|
||||||
|
self._uart.write(buffer+chr(eec)+b'\n')
|
||||||
|
|
||||||
|
def recv(self,timeout=500,warn=True):
|
||||||
|
t_star=time.ticks_ms()
|
||||||
|
while not self._uart.any():
|
||||||
|
if time.ticks_diff(time.ticks_ms(), t_star) >timeout:
|
||||||
|
if warn:
|
||||||
|
print("Warning: MixGo AI timeout not responding")
|
||||||
|
return False
|
||||||
|
buffer = self._uart.readline()
|
||||||
|
if buffer:
|
||||||
|
eec=0
|
||||||
|
if len(buffer)>=3:
|
||||||
|
for i in range(len(buffer)-2):
|
||||||
|
eec^=int(buffer[i])
|
||||||
|
if eec==buffer[-2] or buffer[-2]==0:
|
||||||
|
try:
|
||||||
|
return eval(buffer[:-2].decode())
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
def _chip_id(self):
|
||||||
|
for _ in range(10):
|
||||||
|
self.send(["ok",[[],'']])
|
||||||
|
if self.recv(1000,False):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def request(self,func='', para=[], name=None, timeout=1000):
|
||||||
|
if self._sdata != para:
|
||||||
|
self._sdata=para if self._removal else None
|
||||||
|
self.send([func,[para,name]])
|
||||||
|
else:
|
||||||
|
self.send([func,[[],name]])
|
||||||
|
|
||||||
|
#print(func)
|
||||||
|
if func in ['ailr','ailt','play','record','asr']: #不需要警告提醒
|
||||||
|
data=self.recv(timeout,False)
|
||||||
|
else:
|
||||||
|
data=self.recv(timeout,True)
|
||||||
|
|
||||||
|
self._info=[]
|
||||||
|
if data:
|
||||||
|
#报错处理
|
||||||
|
if "err" in data[0] and type(data[1])==list:
|
||||||
|
if type(data[1][0]) == IndexError or "Missing parameter" == data[1][0]:
|
||||||
|
self.send(["ok",[[],name]]) #恢复出厂
|
||||||
|
self.send([func,[para,name]]) #在发送参数
|
||||||
|
else:
|
||||||
|
raise RuntimeError("Error from MixGo AI",data[1][0])
|
||||||
|
else:
|
||||||
|
_len=max(len(data[0]),len(data[1]))
|
||||||
|
for i in range(_len):
|
||||||
|
if type(data[0][i]) == list:
|
||||||
|
info1=data[0][i][0]
|
||||||
|
info2=data[0][i][1]
|
||||||
|
else:
|
||||||
|
info1=data[0][i]
|
||||||
|
info2=None
|
||||||
|
|
||||||
|
if data[1]:
|
||||||
|
rect=data[1][i]
|
||||||
|
else:
|
||||||
|
rect=None
|
||||||
|
self._info.append(INFO(info1,info2,rect))
|
||||||
|
return self._info
|
||||||
|
|
||||||
|
def info_len(self):
|
||||||
|
return len(self._info)
|
||||||
|
|
||||||
|
def info_number(self,number):
|
||||||
|
if self.info_len() > number:
|
||||||
|
return self._info[number]
|
||||||
|
|
||||||
|
def configure(self, tx_pin, rx_pin, restart=False):
|
||||||
|
info=self.request('start',para=[["uart",tx_pin,rx_pin],restart])
|
||||||
|
return info[0].info1 if info else False
|
||||||
|
|
||||||
|
def find_qrcode(self):
|
||||||
|
info=self.request('qr')
|
||||||
|
return (info[0].info1,info[0].rect) if info else (None,None)
|
||||||
|
|
||||||
|
def find_barcode(self):
|
||||||
|
info=self.request('bar')
|
||||||
|
return (info[0].info1,info[0].rect) if info else (None,None)
|
||||||
|
|
||||||
|
def find_apriltag(self):
|
||||||
|
info=self.request('tag')
|
||||||
|
return (info[0].info1,info[0].rect) if info else (None,None)
|
||||||
|
|
||||||
|
def find_qrcodes(self):
|
||||||
|
return self.request('qr')
|
||||||
|
|
||||||
|
def find_barcodes(self):
|
||||||
|
return self.request('bar')
|
||||||
|
|
||||||
|
def find_apriltags(self):
|
||||||
|
return self.request('tag')
|
||||||
|
|
||||||
|
def find_lines(self, threshold=2500, theta_margin=25, rho_margin=25):
|
||||||
|
return self.request('line', para=[threshold, theta_margin, rho_margin])
|
||||||
|
|
||||||
|
def find_circles(self, threshold=2500, r_min=2, r_max=100):
|
||||||
|
return self.request('circle', para=[threshold, r_min, r_max])
|
||||||
|
|
||||||
|
def find_rects(self, threshold=2500):
|
||||||
|
return self.request('rect', para=[threshold])
|
||||||
|
|
||||||
|
def find_colors(self, scale=2):
|
||||||
|
info=self.request('color', para=[scale])
|
||||||
|
if info:
|
||||||
|
return info[0].info1,info[0].info2
|
||||||
|
else:
|
||||||
|
return None,None
|
||||||
|
|
||||||
|
def color_track(self, lab=[0, 100, 0, 100, 0, 0], pixels_threshold=10, margin=1):
|
||||||
|
return self.request('ctrace', para=[lab, pixels_threshold, margin])
|
||||||
|
|
||||||
|
def ailocal_train(self, lsit_names, path="mixgo", number=5, disname='自模型训练'):
|
||||||
|
info= self.request('ailt', para=[lsit_names, path, number], name=disname)
|
||||||
|
return info[0].info1 if info else False
|
||||||
|
|
||||||
|
def ailocal_class(self, lsit_names, path="mixgo", disname='自模型识别'):
|
||||||
|
return self.request('ailr', para=[lsit_names, path], name=disname)
|
||||||
|
|
||||||
|
def yolo_recognize(self, anchor, path, disname='物品识别'):
|
||||||
|
return self.request('aild', para=[anchor, path], name=disname)
|
||||||
|
|
||||||
|
def led_rgb(self, rgb1=(0,0,0), rgb2=(0,0,0)):
|
||||||
|
info= self.request('rgb', para=[rgb1, rgb2])
|
||||||
|
return info[0].info1 if info else False
|
||||||
|
|
||||||
|
def audio_play(self, bck_pin=12, ws_pin=13, dat_pin=14, path="mixgo.wav", volume=80):
|
||||||
|
info= self.request('play', para=[[bck_pin, ws_pin, dat_pin], path, volume])
|
||||||
|
return info[0].info1 if info else False
|
||||||
|
|
||||||
|
def audio_record(self, sample_rate=16000, path="mixgo.wav", times=5):
|
||||||
|
info= self.request('record', para=[sample_rate, path, times])
|
||||||
|
return info[0].info1 if info else False
|
||||||
|
|
||||||
|
def asr_recognize(self, corpus,threshold=0.1):
|
||||||
|
clist=[]
|
||||||
|
for cor in corpus:
|
||||||
|
clist.append([cor,threshold])
|
||||||
|
info=self.request('asr', para=[dict(clist)])
|
||||||
|
if info:
|
||||||
|
return info[0].info1,info[0].info2
|
||||||
|
else:
|
||||||
|
return None,None
|
||||||
|
|
||||||
|
def find_licenseplate(self):
|
||||||
|
return self.request('alpr')
|
||||||
|
|
||||||
|
def find_20object(self):
|
||||||
|
return self.request('voc20')
|
||||||
|
|
||||||
|
def face_detect(self):
|
||||||
|
return self.request('face_d')
|
||||||
353
mixly/boards/default/micropython/build/lib/mixiot.py
Normal file
353
mixly/boards/default/micropython/build/lib/mixiot.py
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
import time
|
||||||
|
import usocket as socket
|
||||||
|
import ustruct as struct
|
||||||
|
from machine import unique_id
|
||||||
|
from ubinascii import hexlify
|
||||||
|
from matcher import MQTTMatcher
|
||||||
|
|
||||||
|
ADDITIONAL_TOPIC = 'b640a0ce465fa2a4150c36b305c1c11b'
|
||||||
|
WILL_TOPIC = '9d634e1a156dc0c1611eb4c3cff57276'
|
||||||
|
|
||||||
|
def wlan_connect(ssid='MYSSID', password='MYPASS', timeout=10):
|
||||||
|
import network
|
||||||
|
wlan = network.WLAN(network.STA_IF)
|
||||||
|
if not wlan.active():
|
||||||
|
wlan.active(True)
|
||||||
|
time.sleep(0.5)
|
||||||
|
if not wlan.isconnected():
|
||||||
|
print('connecting to:', ssid, end ="")
|
||||||
|
try:
|
||||||
|
wlan.connect(ssid, password)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
_num = 0
|
||||||
|
while not wlan.isconnected():
|
||||||
|
_num += 1
|
||||||
|
time.sleep(1)
|
||||||
|
print('.',end ="")
|
||||||
|
if _num > timeout:
|
||||||
|
wlan.active(False)
|
||||||
|
print('')
|
||||||
|
import os
|
||||||
|
if 'c5' in os.uname().machine.lower():
|
||||||
|
raise RuntimeError("WiFi connection timeout. Please check the SSID and password")
|
||||||
|
else:
|
||||||
|
raise RuntimeError("WiFi connection timeout, Please check the SSID and password (only 2.4GHz networks are supported)")
|
||||||
|
print('\nnetwork config:', wlan.ifconfig())
|
||||||
|
return wlan
|
||||||
|
|
||||||
|
def image_base64(path="mixly.jpg"):
|
||||||
|
from base64 import b64encode
|
||||||
|
if isinstance(path, str):
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
_data = f.read()
|
||||||
|
return 'data:image/{};base64,'.format(path.split('.')[-1]).encode() + b64encode(_data)
|
||||||
|
else:
|
||||||
|
return b'data:image/jpg;base64,' + b64encode(path)
|
||||||
|
|
||||||
|
def ntp(url='mixio.mixly.cn'):
|
||||||
|
import urequests
|
||||||
|
try:
|
||||||
|
results=eval(urequests.get('http://{}/time.php'.format(url)).text)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("API request failed or WiFi is not connected",e)
|
||||||
|
return results
|
||||||
|
|
||||||
|
def init_MQTT_client(address, username, password,MQTT_USR_PRJ):
|
||||||
|
client = MQTTClient(hexlify(unique_id()), address, 1883, username, password)
|
||||||
|
client.set_last_will(topic=MQTT_USR_PRJ+WILL_TOPIC, msg=client.client_id, qos=2)
|
||||||
|
if client.connect()==0:
|
||||||
|
client.publish(MQTT_USR_PRJ+ADDITIONAL_TOPIC, client.client_id, qos=0)
|
||||||
|
time.sleep_ms(200)
|
||||||
|
return client
|
||||||
|
|
||||||
|
# Add by Mixly Team
|
||||||
|
def str_len(object):
|
||||||
|
if isinstance(object, str):
|
||||||
|
return len(object.encode('utf-8'))
|
||||||
|
else:
|
||||||
|
return len(object)
|
||||||
|
#####################################################
|
||||||
|
|
||||||
|
class MQTTException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class MQTTClient:
|
||||||
|
def __init__(self, client_id, server, port=0, username=None, password=None, keepalive=60, ssl=False, ssl_params={}):
|
||||||
|
if port == 0:
|
||||||
|
port = 8883 if ssl else 1883
|
||||||
|
self.client_id = client_id
|
||||||
|
self.sock = None
|
||||||
|
self.server = server
|
||||||
|
self.addr = socket.getaddrinfo(server, port)[0][-1]
|
||||||
|
self.ssl = ssl
|
||||||
|
self.ssl_params = ssl_params
|
||||||
|
self.pid = 0
|
||||||
|
self._on_message = None
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
self.keepalive = keepalive
|
||||||
|
self.lw_topic = None
|
||||||
|
self.lw_msg = None
|
||||||
|
self.lw_qos = 0
|
||||||
|
self.lw_retain = False
|
||||||
|
self._on_message_filtered = MQTTMatcher()
|
||||||
|
self._star_time = time.ticks_ms()
|
||||||
|
|
||||||
|
def _send_str(self, s):
|
||||||
|
self.sock.write(struct.pack("!H", str_len(s)))
|
||||||
|
self.sock.write(s)
|
||||||
|
|
||||||
|
def _recv_len(self):
|
||||||
|
n = 0
|
||||||
|
sh = 0
|
||||||
|
while 1:
|
||||||
|
b = self.sock.read(1)[0]
|
||||||
|
n |= (b & 0x7f) << sh
|
||||||
|
if not b & 0x80:
|
||||||
|
return n
|
||||||
|
sh += 7
|
||||||
|
|
||||||
|
def set_callback(self, mqtt_topic, callback_method, MQTT_USR_PRJ):
|
||||||
|
"""Registers a callback_method for a specific MQTT topic"""
|
||||||
|
if mqtt_topic is None or callback_method is None:
|
||||||
|
raise ValueError("MQTT topic and callback method must both be defined.")
|
||||||
|
self._on_message_filtered[MQTT_USR_PRJ+mqtt_topic] = callback_method
|
||||||
|
|
||||||
|
def remove_callback(self, mqtt_topic):
|
||||||
|
"""Removes a registered callback method"""
|
||||||
|
if mqtt_topic is None:
|
||||||
|
raise ValueError("MQTT Topic must be defined.")
|
||||||
|
try:
|
||||||
|
del self._on_message_filtered[mqtt_topic]
|
||||||
|
except KeyError:
|
||||||
|
raise KeyError(
|
||||||
|
"MQTT topic callback not added with add_topic_callback."
|
||||||
|
) from None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def on_message(self):
|
||||||
|
"""Called when a new message has been received on a subscribed topic"""
|
||||||
|
return self._on_message
|
||||||
|
|
||||||
|
@on_message.setter
|
||||||
|
def on_message(self, method):
|
||||||
|
self._on_message = method
|
||||||
|
|
||||||
|
def _handle_on_message(self, client, topic, message):
|
||||||
|
matched = False
|
||||||
|
if topic is not None:
|
||||||
|
for callback in self._on_message_filtered.iter_match(topic):
|
||||||
|
callback(client, topic.split("/")[-1], message) # on_msg with callback
|
||||||
|
matched = True
|
||||||
|
|
||||||
|
if not matched and self.on_message: # regular on_message
|
||||||
|
self.on_message(client, topic.split("/")[-1], message)
|
||||||
|
|
||||||
|
def set_last_will(self, topic, msg, retain=False, qos=0):
|
||||||
|
assert 0 <= qos <= 2
|
||||||
|
assert topic
|
||||||
|
self.lw_topic = topic
|
||||||
|
self.lw_msg = msg
|
||||||
|
self.lw_qos = qos
|
||||||
|
self.lw_retain = retain
|
||||||
|
|
||||||
|
def connect(self, clean_session=True):
|
||||||
|
self.sock = socket.socket()
|
||||||
|
self.sock.connect(self.addr)
|
||||||
|
print(self.addr)
|
||||||
|
if self.ssl:
|
||||||
|
import ussl
|
||||||
|
self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)
|
||||||
|
msg_header=bytearray([0x10])
|
||||||
|
msg = bytearray(b"\x04MQTT\x04\x02\0\0")
|
||||||
|
msg_length = 12 + str_len(self.client_id)
|
||||||
|
msg[6] = clean_session << 1
|
||||||
|
|
||||||
|
if self.username is not None:
|
||||||
|
msg_length += 2 + str_len(self.username) + 2 + str_len(self.password)
|
||||||
|
msg[6] |= 0xC0
|
||||||
|
if self.keepalive:
|
||||||
|
assert self.keepalive < 65536
|
||||||
|
msg[7] |= self.keepalive >> 8
|
||||||
|
msg[8] |= self.keepalive & 0x00FF
|
||||||
|
if self.lw_topic:
|
||||||
|
msg_length += 2 + str_len(self.lw_topic) + 2 + str_len(self.lw_msg)
|
||||||
|
msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3
|
||||||
|
msg[6] |= self.lw_retain << 5
|
||||||
|
|
||||||
|
if msg_length > 0x7F:
|
||||||
|
while msg_length>0:
|
||||||
|
encoded_byte = msg_length % 0x80
|
||||||
|
msg_length = msg_length // 0x80
|
||||||
|
if msg_length > 0:
|
||||||
|
encoded_byte |= 0x80
|
||||||
|
msg_header.append(encoded_byte)
|
||||||
|
msg_header.append(0x00)
|
||||||
|
else:
|
||||||
|
msg_header.append(msg_length)
|
||||||
|
msg_header.append(0x00)
|
||||||
|
|
||||||
|
self.sock.write(msg_header)
|
||||||
|
self.sock.write(msg)
|
||||||
|
#print(hexlify(msg_header, ":"), hexlify(msg, ":"))
|
||||||
|
self._send_str(self.client_id)
|
||||||
|
if self.lw_topic:
|
||||||
|
self._send_str(self.lw_topic)
|
||||||
|
self._send_str(self.lw_msg)
|
||||||
|
if self.username is not None:
|
||||||
|
self._send_str(self.username)
|
||||||
|
self._send_str(self.password)
|
||||||
|
resp = self.sock.read(4)
|
||||||
|
assert resp[0] == 0x20 and resp[1] == 0x02
|
||||||
|
if resp[3] != 0:
|
||||||
|
if resp[3] == 1:
|
||||||
|
raise MQTTException("Unsupported Protocol")
|
||||||
|
elif resp[3] == 2:
|
||||||
|
raise MQTTException("Illegal ClientID")
|
||||||
|
elif resp[3] == 3:
|
||||||
|
raise MQTTException("Server Unavailable")
|
||||||
|
elif resp[3] == 4:
|
||||||
|
raise MQTTException("Invalid username and password format")
|
||||||
|
elif resp[3] == 5:
|
||||||
|
raise MQTTException("Unauthorized")
|
||||||
|
else:
|
||||||
|
raise MQTTException(resp[3])
|
||||||
|
return resp[2] & 1
|
||||||
|
|
||||||
|
|
||||||
|
def disconnect(self,MQTT_USR_PRJ):
|
||||||
|
#MQTT_USR_PRJ = "{}/{}/".format(self.username,self.project)
|
||||||
|
self.publish(MQTT_USR_PRJ+WILL_TOPIC, self.client_id, qos=1)
|
||||||
|
self.sock.write(b"\xe0\0")
|
||||||
|
self.sock.close()
|
||||||
|
|
||||||
|
def ping(self):
|
||||||
|
self.sock.write(b"\xc0\0")
|
||||||
|
|
||||||
|
def pingSync(self):
|
||||||
|
self.ping()
|
||||||
|
for i in range(0,10):
|
||||||
|
msg = self.check_msg()
|
||||||
|
if msg == "PINGRESP":
|
||||||
|
return True
|
||||||
|
time.sleep_ms(100)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def publish(self, topic, msg, retain=False, qos=0):
|
||||||
|
# msg = pubData(msg)
|
||||||
|
if "+" in topic or "#" in topic:
|
||||||
|
raise MQTTException("Publish topic can not contain wildcards.")
|
||||||
|
# check msg/qos kwargs
|
||||||
|
if msg is None:
|
||||||
|
raise MQTTException("Message can not be None.")
|
||||||
|
if isinstance(msg, (int, float)):
|
||||||
|
msg = str(msg).encode("ascii")
|
||||||
|
elif isinstance(msg, str):
|
||||||
|
msg = str(msg).encode("utf-8")
|
||||||
|
elif isinstance(msg, bytes):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise MQTTException("Invalid message data type.")
|
||||||
|
pkt = bytearray(b"\x30\0\0\0")
|
||||||
|
pkt[0] |= qos << 1 | retain
|
||||||
|
sz = 2 + str_len(topic) + str_len(msg)
|
||||||
|
if qos > 0:
|
||||||
|
sz += 2
|
||||||
|
assert sz < 2097152
|
||||||
|
i = 1
|
||||||
|
while sz > 0x7f:
|
||||||
|
pkt[i] = (sz & 0x7f) | 0x80
|
||||||
|
sz >>= 7
|
||||||
|
i += 1
|
||||||
|
pkt[i] = sz
|
||||||
|
#print(hex(str_len(pkt)), hexlify(pkt, ":"))
|
||||||
|
self.sock.settimeout(0.05)
|
||||||
|
#self.sock.setblocking(True)
|
||||||
|
self.sock.write(pkt, i + 1)
|
||||||
|
self._send_str(topic)
|
||||||
|
if qos > 0:
|
||||||
|
self.pid += 1
|
||||||
|
pid = self.pid
|
||||||
|
struct.pack_into("!H", pkt, 0, pid)
|
||||||
|
self.sock.write(pkt, 2)
|
||||||
|
self.sock.write(msg)
|
||||||
|
if qos == 1:
|
||||||
|
while 1:
|
||||||
|
op = self.wait_msg()
|
||||||
|
if op == 0x40:
|
||||||
|
sz = self.sock.read(1)
|
||||||
|
assert sz == b"\x02"
|
||||||
|
rcv_pid = self.sock.read(2)
|
||||||
|
rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]
|
||||||
|
if pid == rcv_pid:
|
||||||
|
return
|
||||||
|
elif qos == 2:
|
||||||
|
assert 0
|
||||||
|
|
||||||
|
def subscribe(self, topic, qos=0):
|
||||||
|
#assert self.cb is not None, "Subscribe callback is not set"
|
||||||
|
pkt = bytearray(b"\x82\0\0\0")
|
||||||
|
self.pid += 1
|
||||||
|
if isinstance(topic, str):
|
||||||
|
topic=topic.encode()
|
||||||
|
struct.pack_into("!BH", pkt, 1, 2 + 2 + str_len(topic) + 1, self.pid)
|
||||||
|
#print(hex(str_len(pkt)), hexlify(pkt, ":"))
|
||||||
|
self.sock.write(pkt)
|
||||||
|
self._send_str(topic)
|
||||||
|
self.sock.write(qos.to_bytes(1, "little"))
|
||||||
|
while 1:
|
||||||
|
op = self.wait_msg()
|
||||||
|
if op == 0x90:
|
||||||
|
resp = self.sock.read(4)
|
||||||
|
#print(resp)
|
||||||
|
assert resp[1] == pkt[2] and resp[2] == pkt[3]
|
||||||
|
if resp[3] == 0x80:
|
||||||
|
raise MQTTException(resp[3])
|
||||||
|
return
|
||||||
|
|
||||||
|
# Wait for a single incoming MQTT message and process it.
|
||||||
|
def wait_msg(self):
|
||||||
|
res = self.sock.read(1)
|
||||||
|
time.sleep_ms(50)
|
||||||
|
self.sock.settimeout(0.05)
|
||||||
|
#self.sock.setblocking(True)
|
||||||
|
if res is None:
|
||||||
|
return None
|
||||||
|
if res == b"":
|
||||||
|
raise OSError(-1)
|
||||||
|
if res == b"\xd0": # PINGRESP
|
||||||
|
sz = self.sock.read(1)[0]
|
||||||
|
assert sz == 0
|
||||||
|
return "PINGRESP"
|
||||||
|
op = res[0]
|
||||||
|
if op & 0xf0 != 0x30:
|
||||||
|
return op
|
||||||
|
sz = self._recv_len()
|
||||||
|
topic_len = self.sock.read(2)
|
||||||
|
topic_len = (topic_len[0] << 8) | topic_len[1]
|
||||||
|
topic = self.sock.read(topic_len)
|
||||||
|
sz -= topic_len + 2
|
||||||
|
if op & 6:
|
||||||
|
pid = self.sock.read(2)
|
||||||
|
pid = pid[0] << 8 | pid[1]
|
||||||
|
sz -= 2
|
||||||
|
msg = self.sock.read(sz)
|
||||||
|
self._handle_on_message(self, str(topic, "utf-8"), str(msg, "utf-8"))
|
||||||
|
if op & 6 == 2:
|
||||||
|
pkt = bytearray(b"\x40\x02\0\0")
|
||||||
|
struct.pack_into("!H", pkt, 2, pid)
|
||||||
|
self.sock.write(pkt)
|
||||||
|
elif op & 6 == 4:
|
||||||
|
assert 0
|
||||||
|
|
||||||
|
# Checks whether a pending message from server is available.
|
||||||
|
def check_msg(self):
|
||||||
|
self.sock.settimeout(0.05)
|
||||||
|
if time.ticks_diff(time.ticks_ms(), self._star_time) >60000:
|
||||||
|
self._star_time = time.ticks_ms()
|
||||||
|
self.ping()
|
||||||
|
return self.wait_msg()
|
||||||
|
|
||||||
|
def get_server_info(self):
|
||||||
|
return (self.server, self.username, self.password)
|
||||||
94
mixly/boards/default/micropython/build/lib/mixpy.py
Normal file
94
mixly/boards/default/micropython/build/lib/mixpy.py
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#coding=utf-8
|
||||||
|
import math
|
||||||
|
|
||||||
|
def math_map(v, al, ah, bl, bh):
|
||||||
|
if al==ah:
|
||||||
|
return bl
|
||||||
|
if al < ah:
|
||||||
|
v = max(min(ah,v),al)
|
||||||
|
if al > ah:
|
||||||
|
v = max(min(al,v),ah)
|
||||||
|
return bl + (bh - bl) * (v - al) / (ah - al)
|
||||||
|
|
||||||
|
def math_mean(myList):
|
||||||
|
localList = [e for e in myList if type(e) == int or type(e) == float]
|
||||||
|
if not localList: return
|
||||||
|
return float(sum(localList)) / len(localList)
|
||||||
|
|
||||||
|
def math_median(myList):
|
||||||
|
localList = sorted([e for e in myList if type(e) == int or type(e) == float])
|
||||||
|
if not localList: return
|
||||||
|
if len(localList) % 2 == 0:
|
||||||
|
return (localList[len(localList) // 2 - 1] + localList[len(localList) // 2]) / 2.0
|
||||||
|
else:
|
||||||
|
return localList[(len(localList) - 1) // 2]
|
||||||
|
|
||||||
|
def math_modes(some_list):
|
||||||
|
modes = []
|
||||||
|
# Using a lists of [item, count] to keep count rather than dict
|
||||||
|
# to avoid "unhashable" errors when the counted item is itself a list or dict.
|
||||||
|
counts = []
|
||||||
|
maxCount = 1
|
||||||
|
for item in some_list:
|
||||||
|
found = False
|
||||||
|
for count in counts:
|
||||||
|
if count[0] == item:
|
||||||
|
count[1] += 1
|
||||||
|
maxCount = max(maxCount, count[1])
|
||||||
|
found = True
|
||||||
|
if not found:
|
||||||
|
counts.append([item, 1])
|
||||||
|
for counted_item, item_count in counts:
|
||||||
|
if item_count == maxCount:
|
||||||
|
modes.append(counted_item)
|
||||||
|
return modes
|
||||||
|
|
||||||
|
def math_standard_deviation(numbers):
|
||||||
|
n = len(numbers)
|
||||||
|
if n == 0: return
|
||||||
|
mean = float(sum(numbers)) / n
|
||||||
|
variance = sum((x - mean) ** 2 for x in numbers) / n
|
||||||
|
return math.sqrt(variance)
|
||||||
|
|
||||||
|
def lists_sort(my_list, type, reverse):
|
||||||
|
def try_float(s):
|
||||||
|
try:
|
||||||
|
return float(s)
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
key_funcs = {
|
||||||
|
"NUMERIC": try_float,
|
||||||
|
"TEXT": str,
|
||||||
|
"IGNORE_CASE": lambda s: str(s).lower()
|
||||||
|
}
|
||||||
|
key_func = key_funcs[type]
|
||||||
|
list_cpy = list(my_list)
|
||||||
|
return sorted(list_cpy, key=key_func, reverse=reverse)
|
||||||
|
|
||||||
|
def format_content(mydict, cid):
|
||||||
|
if 'lat' in mydict and 'long' in mydict:
|
||||||
|
res = '{'+'"lat": "{}", "long": "{}", "clientid": "{}"'.format(mydict.pop('lat'),mydict.pop('long'),cid)
|
||||||
|
if len(mydict)>0:
|
||||||
|
res += ', "message": ['
|
||||||
|
for d in mydict:
|
||||||
|
res += '{{"label": "{}", "value": "{}"}},'.format(d,mydict[d])
|
||||||
|
res = res[:-1] + "]"
|
||||||
|
res += '}'
|
||||||
|
return res
|
||||||
|
else:
|
||||||
|
print('Invalid Input')
|
||||||
|
|
||||||
|
def format_str(d):
|
||||||
|
return str(d).replace("'",'"')
|
||||||
|
|
||||||
|
|
||||||
|
def analyse_sharekey(url):
|
||||||
|
import urequests
|
||||||
|
import json
|
||||||
|
response = urequests.get(url)
|
||||||
|
|
||||||
|
if response.text == '-1':
|
||||||
|
raise AttributeError('Invalid share key')
|
||||||
|
else:
|
||||||
|
result = json.loads(response.text)
|
||||||
|
return (result['0'], result['1'], result['2'])
|
||||||
74
mixly/boards/default/micropython/build/lib/mk_pb4023.py
Normal file
74
mixly/boards/default/micropython/build/lib/mk_pb4023.py
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
"""
|
||||||
|
MK-PB4023PS&ASL&VC-A01E
|
||||||
|
|
||||||
|
MicroPython library for the MK-PB4023PS&ASL&VC-A01E (PS,ASL,CS)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_MK_SYSM = const(0x80)
|
||||||
|
_MK_ID = const(0x98)
|
||||||
|
_MK_DATA = const(0xA0)
|
||||||
|
|
||||||
|
class MK_PB4023:
|
||||||
|
def __init__(self, i2c_bus, addr=0x39):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
if self._rreg(_MK_ID) != 0xA0:
|
||||||
|
raise AttributeError("Cannot find a MK-PB4023")
|
||||||
|
self._configure()
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg, nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)
|
||||||
|
|
||||||
|
def _configure(self):
|
||||||
|
'''Configuration Register'''
|
||||||
|
self._wreg(0X82, 0x80)
|
||||||
|
self._wreg(0x83, 0x01)
|
||||||
|
self._wreg(0x84, 0x07)
|
||||||
|
self._wreg(0x85, 0x0B)
|
||||||
|
self._wreg(0x86, 0x03)
|
||||||
|
self._wreg(0x87, 0x1A)
|
||||||
|
self._wreg(0x89, 0x38)
|
||||||
|
self._wreg(_MK_SYSM,0x0F) #Enable Register
|
||||||
|
|
||||||
|
def getdata(self):
|
||||||
|
'''Processing data acquisition'''
|
||||||
|
_buf = self._rreg(_MK_DATA, 12)
|
||||||
|
_r = _buf[0] | _buf[1] << 8
|
||||||
|
_g = _buf[2] | _buf[3] << 8
|
||||||
|
_b = _buf[4] | _buf[5] << 8
|
||||||
|
_c = _buf[6] | _buf[7] << 8
|
||||||
|
_ir = _buf[8] | _buf[9] << 8
|
||||||
|
_ps = _buf[10] | _buf[11] << 8
|
||||||
|
return _c, _ir, (_r, _g, _b), _ps
|
||||||
|
|
||||||
|
def color(self):
|
||||||
|
w, _, (r, g, b), _ = self.getdata()
|
||||||
|
if w == 0:
|
||||||
|
return (0, 0, 0)
|
||||||
|
else:
|
||||||
|
red = int(pow((int((r / w) * 256) / 255), 2.5) * 255)
|
||||||
|
green = int(pow((int((g / w) * 256) / 255), 2.5) * 255)
|
||||||
|
blue = int(pow((int((b / w) * 256) / 255), 2.5) * 255)
|
||||||
|
return (min(red, 255), min(green, 255), min(blue, 255))
|
||||||
|
|
||||||
|
def color_raw(self):
|
||||||
|
return self.getdata()[2]
|
||||||
|
|
||||||
|
def ir(self):
|
||||||
|
return self.getdata()[1]
|
||||||
|
|
||||||
|
def als(self):
|
||||||
|
w, ir, (r, g, b), _ = self.getdata()
|
||||||
|
return round((w + ir + r + g + b) / 17.8, 2)
|
||||||
|
|
||||||
|
def ps(self):
|
||||||
|
return self.getdata()[3]
|
||||||
149
mixly/boards/default/micropython/build/lib/mmc5603.py
Normal file
149
mixly/boards/default/micropython/build/lib/mmc5603.py
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
"""
|
||||||
|
MMC5603
|
||||||
|
|
||||||
|
Micropython library for the MMC5603NJ(Magnetic)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20221017
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time,math
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
MMC5603_ADDRESS = const(0x30)
|
||||||
|
|
||||||
|
MMC5603_REG_DATA = const(0x00)
|
||||||
|
MMC5603_REG_TMP = const(0x09)
|
||||||
|
MMC5603_REG_ODR = const(0x1A)
|
||||||
|
MMC5603_REG_CTRL0 = const(0x1B)
|
||||||
|
MMC5603_REG_CTRL1 = const(0x1C)
|
||||||
|
MMC5603_REG_CTRL2 = const(0x1D)
|
||||||
|
|
||||||
|
MMC5603_REG_X_THD = const(0x1E)
|
||||||
|
MMC5603_REG_Y_THD = const(0x1F)
|
||||||
|
MMC5603_REG_Z_THD = const(0x20)
|
||||||
|
MMC5603_REG_ST_X_VAL = const(0x27)
|
||||||
|
MMC5603_REG_DEVICE_ID = const(0x39)
|
||||||
|
|
||||||
|
class MMC5603:
|
||||||
|
def __init__(self, i2c_bus):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = MMC5603_ADDRESS
|
||||||
|
self.raw_x = 0.0
|
||||||
|
self.raw_y = 0.0
|
||||||
|
self.raw_z = 0.0
|
||||||
|
|
||||||
|
if self._chip_id() != 0x10: #Check product ID
|
||||||
|
raise AttributeError("Cannot find a MMC5603")
|
||||||
|
try: #Read calibration file
|
||||||
|
import magnetic_cal
|
||||||
|
self._offset_x = magnetic_cal._offset_x
|
||||||
|
self._offset_y = magnetic_cal._offset_y
|
||||||
|
self._offset_z = magnetic_cal._offset_z
|
||||||
|
except:
|
||||||
|
self._offset_x = 524288
|
||||||
|
self._offset_y = 524288
|
||||||
|
self._offset_z = 524288
|
||||||
|
#print("offset:",self._offset_x ,self._offset_y,self._offset_z)
|
||||||
|
|
||||||
|
self._auto_selftest() #Auto self-test registers configuration
|
||||||
|
self._set()
|
||||||
|
self._continuous_mode(0x00, 50) #Work mode setting
|
||||||
|
time.sleep(0.05)
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg,nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
return self._rreg(MMC5603_REG_DEVICE_ID)
|
||||||
|
|
||||||
|
def _auto_selftest(self):
|
||||||
|
'''Auto self-test registers configuration'''
|
||||||
|
st_thd_reg=[0,0,0]
|
||||||
|
st_thr_data=[0,0,0]
|
||||||
|
#/* Read trim data from reg 0x27-0x29 */
|
||||||
|
_buffer=self._rreg(MMC5603_REG_ST_X_VAL,3)
|
||||||
|
for i in range(0, 3, 1):
|
||||||
|
st_thr_data[i]=(_buffer[i]-128)*32
|
||||||
|
if st_thr_data[i] < 0:
|
||||||
|
st_thr_data[i]=-st_thr_data[i]
|
||||||
|
st_thd=(st_thr_data[i]-st_thr_data[i]//5)//8
|
||||||
|
if st_thd > 255:
|
||||||
|
st_thd_reg[i]=0xFF
|
||||||
|
else:
|
||||||
|
st_thd_reg[i]=st_thd
|
||||||
|
#/* Write threshold into the reg 0x1E-0x20 */
|
||||||
|
self._wreg(MMC5603_REG_X_THD, st_thd_reg[0])
|
||||||
|
self._wreg(MMC5603_REG_Y_THD, st_thd_reg[1])
|
||||||
|
self._wreg(MMC5603_REG_Z_THD, st_thd_reg[2])
|
||||||
|
|
||||||
|
def _set(self):
|
||||||
|
'''Do SET operation'''
|
||||||
|
self._wreg(MMC5603_REG_CTRL0, 0X08)
|
||||||
|
time.sleep(0.005)
|
||||||
|
|
||||||
|
def _continuous_mode(self,bandwith,sampling_rate):
|
||||||
|
'''Work mode setting'''
|
||||||
|
self._wreg(MMC5603_REG_CTRL1, bandwith)
|
||||||
|
self._wreg(MMC5603_REG_ODR, sampling_rate)
|
||||||
|
self._wreg(MMC5603_REG_CTRL0, 0X80|0X20)
|
||||||
|
self._wreg(MMC5603_REG_CTRL2, 0x10)
|
||||||
|
|
||||||
|
def getdata(self):
|
||||||
|
_buf=self._rreg( MMC5603_REG_DATA,9)
|
||||||
|
#/* Transform to unit Gauss */
|
||||||
|
self.raw_x=(_buf[0] << 12) | (_buf[1] << 4) | (_buf[6] >> 4)
|
||||||
|
self.raw_y=(_buf[2] << 12) | (_buf[3] << 4) | (_buf[7] >> 4)
|
||||||
|
self.raw_z=(_buf[4] << 12) | (_buf[5] << 4) | (_buf[8] >> 4)
|
||||||
|
return (-0.0625*(self.raw_x-self._offset_x), -0.0625*(self.raw_y-self._offset_y), -0.0625*(self.raw_z-self._offset_z))
|
||||||
|
|
||||||
|
def calibrate(self):
|
||||||
|
print("The magnetic field will be calibrated")
|
||||||
|
print("Please pick up the board and rotate the '8' shape in the air")
|
||||||
|
time.sleep(2)
|
||||||
|
self.getdata()
|
||||||
|
min_x = max_x = self.raw_x
|
||||||
|
min_y = max_y = self.raw_y
|
||||||
|
min_z = max_z = self.raw_z
|
||||||
|
ticks_start = time.ticks_ms()
|
||||||
|
while (time.ticks_diff(time.ticks_ms(), ticks_start) < 20000) :
|
||||||
|
self.getdata()
|
||||||
|
min_x = min(self.raw_x, min_x)
|
||||||
|
max_x = max(self.raw_x, max_x)
|
||||||
|
min_y = min(self.raw_y, min_y)
|
||||||
|
max_y = max(self.raw_y, max_y)
|
||||||
|
min_z = min(self.raw_z, min_z)
|
||||||
|
max_z = max(self.raw_z, max_z)
|
||||||
|
time.sleep_ms(20)
|
||||||
|
if time.ticks_diff(time.ticks_ms(), ticks_start) % 20 ==0:
|
||||||
|
print("=",end ="")
|
||||||
|
print(" 100%")
|
||||||
|
self._offset_x = (max_x + min_x) / 2
|
||||||
|
self._offset_y = (max_y + min_y) / 2
|
||||||
|
self._offset_z = (max_z + min_z) / 2
|
||||||
|
print("Save x_offset:{}, y_offset:{}, z_offset:{}".format(self._offset_x,self._offset_y,self._offset_z))
|
||||||
|
s_f = open("magnetic_cal.py", "w+")
|
||||||
|
s_f.write("_offset_x="+str(self._offset_x)+"\n")
|
||||||
|
s_f.write("_offset_y="+str(self._offset_y)+"\n")
|
||||||
|
s_f.write("_offset_z="+str(self._offset_z)+"\n")
|
||||||
|
s_f.close()
|
||||||
|
time.sleep(2)
|
||||||
|
|
||||||
|
def getstrength(self):
|
||||||
|
_x,_y,_z=self.getdata()
|
||||||
|
return (math.sqrt(math.pow(_x, 2) + pow(_y, 2) + pow(_z, 2)))
|
||||||
|
|
||||||
|
def getangle(self,upright=False):
|
||||||
|
_x,_y,_z=self.getdata()
|
||||||
|
if upright: #vertical
|
||||||
|
angle=math.atan2(_z, -_x)*(180 / math.pi) + 180 + 3
|
||||||
|
return angle if angle<360 else angle-360
|
||||||
|
else: #horizontal
|
||||||
|
angle=math.atan2(_y, -_x)*(180 / math.pi) + 180 + 3
|
||||||
|
return angle if angle<360 else angle-360
|
||||||
585
mixly/boards/default/micropython/build/lib/mpu9250.py
Normal file
585
mixly/boards/default/micropython/build/lib/mpu9250.py
Normal file
@@ -0,0 +1,585 @@
|
|||||||
|
"""
|
||||||
|
MicroPython I2C driver for MPU9250 9-axis motion tracking device
|
||||||
|
"""
|
||||||
|
from micropython import const
|
||||||
|
import ustruct
|
||||||
|
import time
|
||||||
|
import math
|
||||||
|
from machine import Pin,SoftI2C
|
||||||
|
|
||||||
|
_GYRO_CONFIG = const(0x1b)
|
||||||
|
_ACCEL_CONFIG = const(0x1c)
|
||||||
|
_ACCEL_CONFIG2 = const(0x1d)
|
||||||
|
_INT_PIN_CFG = const(0x37)
|
||||||
|
_ACCEL_XOUT_H = const(0x3b)
|
||||||
|
_ACCEL_XOUT_L = const(0x3c)
|
||||||
|
_ACCEL_YOUT_H = const(0x3d)
|
||||||
|
_ACCEL_YOUT_L = const(0x3e)
|
||||||
|
_ACCEL_ZOUT_H = const(0x3f)
|
||||||
|
_ACCEL_ZOUT_L= const(0x40)
|
||||||
|
_TEMP_OUT_H = const(0x41)
|
||||||
|
_TEMP_OUT_L = const(0x42)
|
||||||
|
_GYRO_XOUT_H = const(0x43)
|
||||||
|
_GYRO_XOUT_L = const(0x44)
|
||||||
|
_GYRO_YOUT_H = const(0x45)
|
||||||
|
_GYRO_YOUT_L = const(0x46)
|
||||||
|
_GYRO_ZOUT_H = const(0x47)
|
||||||
|
_GYRO_ZOUT_L = const(0x48)
|
||||||
|
_WHO_AM_I = const(0x75)
|
||||||
|
|
||||||
|
#_ACCEL_FS_MASK = const(0b00011000)
|
||||||
|
ACCEL_FS_SEL_2G = const(0b00000000)
|
||||||
|
ACCEL_FS_SEL_4G = const(0b00001000)
|
||||||
|
ACCEL_FS_SEL_8G = const(0b00010000)
|
||||||
|
ACCEL_FS_SEL_16G = const(0b00011000)
|
||||||
|
|
||||||
|
_ACCEL_SO_2G = 16384 # 1 / 16384 ie. 0.061 mg / digit
|
||||||
|
_ACCEL_SO_4G = 8192 # 1 / 8192 ie. 0.122 mg / digit
|
||||||
|
_ACCEL_SO_8G = 4096 # 1 / 4096 ie. 0.244 mg / digit
|
||||||
|
_ACCEL_SO_16G = 2048 # 1 / 2048 ie. 0.488 mg / digit
|
||||||
|
|
||||||
|
#_GYRO_FS_MASK = const(0b00011000)
|
||||||
|
GYRO_FS_SEL_250DPS = const(0b00000000)
|
||||||
|
GYRO_FS_SEL_500DPS = const(0b00001000)
|
||||||
|
GYRO_FS_SEL_1000DPS = const(0b00010000)
|
||||||
|
GYRO_FS_SEL_2000DPS = const(0b00011000)
|
||||||
|
|
||||||
|
_GYRO_SO_250DPS = 131
|
||||||
|
_GYRO_SO_500DPS = 62.5
|
||||||
|
_GYRO_SO_1000DPS = 32.8
|
||||||
|
_GYRO_SO_2000DPS = 16.4
|
||||||
|
|
||||||
|
# Used for enablind and disabling the i2c bypass access
|
||||||
|
_I2C_BYPASS_MASK = const(0b00000010)
|
||||||
|
_I2C_BYPASS_EN = const(0b00000010)
|
||||||
|
_I2C_BYPASS_DIS = const(0b00000000)
|
||||||
|
|
||||||
|
SF_G = 1
|
||||||
|
SF_M_S2 = 9.80665 # 1 g = 9.80665 m/s2 ie. standard gravity
|
||||||
|
SF_DEG_S = 1
|
||||||
|
SF_RAD_S = 57.295779578552 # 1 rad/s is 57.295779578552 deg/s
|
||||||
|
|
||||||
|
|
||||||
|
_WIA = const(0x00)
|
||||||
|
_HXL = const(0x03)
|
||||||
|
_HXH = const(0x04)
|
||||||
|
_HYL = const(0x05)
|
||||||
|
_HYH = const(0x06)
|
||||||
|
_HZL = const(0x07)
|
||||||
|
_HZH = const(0x08)
|
||||||
|
_ST2 = const(0x09)
|
||||||
|
_CNTL1 = const(0x0a)
|
||||||
|
_ASAX = const(0x10)
|
||||||
|
_ASAY = const(0x11)
|
||||||
|
_ASAZ = const(0x12)
|
||||||
|
|
||||||
|
_MODE_POWER_DOWN = 0b00000000
|
||||||
|
MODE_SINGLE_MEASURE = 0b00000001
|
||||||
|
MODE_CONTINOUS_MEASURE_1 = 0b00000010 # 8Hz
|
||||||
|
MODE_CONTINOUS_MEASURE_2 = 0b00000110 # 100Hz
|
||||||
|
MODE_EXTERNAL_TRIGGER_MEASURE = 0b00000100
|
||||||
|
_MODE_SELF_TEST = 0b00001000
|
||||||
|
_MODE_FUSE_ROM_ACCESS = 0b00001111
|
||||||
|
|
||||||
|
OUTPUT_14_BIT = 0b00000000
|
||||||
|
OUTPUT_16_BIT = 0b00010000
|
||||||
|
|
||||||
|
_SO_14BIT = 0.6 # per digit when 14bit mode
|
||||||
|
_SO_16BIT = 0.15 # per digit when 16bit mode
|
||||||
|
|
||||||
|
class MPU6500:
|
||||||
|
"""Class which provides interface to MPU6500 6-axis motion tracking device."""
|
||||||
|
def __init__(
|
||||||
|
self, i2c, address=0x68,
|
||||||
|
accel_fs=ACCEL_FS_SEL_2G, gyro_fs=GYRO_FS_SEL_250DPS,
|
||||||
|
accel_sf=SF_M_S2, gyro_sf=SF_RAD_S
|
||||||
|
):
|
||||||
|
self.i2c = i2c
|
||||||
|
self.address = address
|
||||||
|
|
||||||
|
if 0x71 != self.whoami:
|
||||||
|
raise RuntimeError("MPU9250 not found in I2C bus.")
|
||||||
|
|
||||||
|
self._accel_so = self._accel_fs(accel_fs)
|
||||||
|
self._gyro_so = self._gyro_fs(gyro_fs)
|
||||||
|
self._accel_sf = accel_sf
|
||||||
|
self._gyro_sf = gyro_sf
|
||||||
|
|
||||||
|
# Enable I2C bypass to access for MPU9250 magnetometer access.
|
||||||
|
char = self._register_char(_INT_PIN_CFG)
|
||||||
|
char &= ~_I2C_BYPASS_MASK # clear I2C bits
|
||||||
|
char |= _I2C_BYPASS_EN
|
||||||
|
self._register_char(_INT_PIN_CFG, char)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def temperature(self):
|
||||||
|
tempbuf=self._register_short(0x41)
|
||||||
|
return tempbuf/333.87 + 21 # I think
|
||||||
|
|
||||||
|
# @property
|
||||||
|
def acceleration(self):
|
||||||
|
so = self._accel_so
|
||||||
|
sf = self._accel_sf
|
||||||
|
|
||||||
|
xyz = self._register_three_shorts(_ACCEL_XOUT_H)
|
||||||
|
return tuple([value / so * sf for value in xyz])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def gyro(self):
|
||||||
|
""" X, Y, Z radians per second as floats."""
|
||||||
|
so = self._gyro_so
|
||||||
|
sf = self._gyro_sf
|
||||||
|
|
||||||
|
xyz = self._register_three_shorts(_GYRO_XOUT_H)
|
||||||
|
return tuple([value / so * sf for value in xyz])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def whoami(self):
|
||||||
|
""" Value of the whoami register. """
|
||||||
|
return self._register_char(_WHO_AM_I)
|
||||||
|
|
||||||
|
def _register_short(self, register, value=None, buf=bytearray(2)):
|
||||||
|
if value is None:
|
||||||
|
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||||
|
return ustruct.unpack(">h", buf)[0]
|
||||||
|
|
||||||
|
ustruct.pack_into(">h", buf, 0, value)
|
||||||
|
return self.i2c.writeto_mem(self.address, register, buf)
|
||||||
|
|
||||||
|
def _register_three_shorts(self, register, buf=bytearray(6)):
|
||||||
|
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||||
|
return ustruct.unpack(">hhh", buf)
|
||||||
|
|
||||||
|
def _register_char(self, register, value=None, buf=bytearray(1)):
|
||||||
|
if value is None:
|
||||||
|
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||||
|
return buf[0]
|
||||||
|
|
||||||
|
ustruct.pack_into("<b", buf, 0, value)
|
||||||
|
return self.i2c.writeto_mem(self.address, register, buf)
|
||||||
|
|
||||||
|
def _accel_fs(self, value):
|
||||||
|
self._register_char(_ACCEL_CONFIG, value)
|
||||||
|
|
||||||
|
# Return the sensitivity divider
|
||||||
|
if ACCEL_FS_SEL_2G == value:
|
||||||
|
return _ACCEL_SO_2G
|
||||||
|
elif ACCEL_FS_SEL_4G == value:
|
||||||
|
return _ACCEL_SO_4G
|
||||||
|
elif ACCEL_FS_SEL_8G == value:
|
||||||
|
return _ACCEL_SO_8G
|
||||||
|
elif ACCEL_FS_SEL_16G == value:
|
||||||
|
return _ACCEL_SO_16G
|
||||||
|
|
||||||
|
def _gyro_fs(self, value):
|
||||||
|
self._register_char(_GYRO_CONFIG, value)
|
||||||
|
|
||||||
|
# Return the sensitivity divider
|
||||||
|
if GYRO_FS_SEL_250DPS == value:
|
||||||
|
return _GYRO_SO_250DPS
|
||||||
|
elif GYRO_FS_SEL_500DPS == value:
|
||||||
|
return _GYRO_SO_500DPS
|
||||||
|
elif GYRO_FS_SEL_1000DPS == value:
|
||||||
|
return _GYRO_SO_1000DPS
|
||||||
|
elif GYRO_FS_SEL_2000DPS == value:
|
||||||
|
return _GYRO_SO_2000DPS
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exception_type, exception_value, traceback):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class AK8963:
|
||||||
|
"""Class which provides interface to AK8963 magnetometer."""
|
||||||
|
def __init__(
|
||||||
|
self, i2c, address=0x0c,
|
||||||
|
mode=MODE_CONTINOUS_MEASURE_1, output=OUTPUT_16_BIT,
|
||||||
|
offset=(0, 0, 0), scale=(1, 1, 1)
|
||||||
|
):
|
||||||
|
self.i2c = i2c
|
||||||
|
self.address = address
|
||||||
|
self._offset = offset
|
||||||
|
self._scale = scale
|
||||||
|
|
||||||
|
if 0x48 != self.whoami:
|
||||||
|
raise RuntimeError("MPU9250 not found in I2C bus.")
|
||||||
|
|
||||||
|
# Sensitivity adjustement values
|
||||||
|
self._register_char(_CNTL1, _MODE_FUSE_ROM_ACCESS)
|
||||||
|
asax = self._register_char(_ASAX)
|
||||||
|
asay = self._register_char(_ASAY)
|
||||||
|
asaz = self._register_char(_ASAZ)
|
||||||
|
self._register_char(_CNTL1, _MODE_POWER_DOWN)
|
||||||
|
|
||||||
|
# Should wait atleast 100us before next mode
|
||||||
|
self._adjustement = (
|
||||||
|
(0.5 * (asax - 128)) / 128 + 1,
|
||||||
|
(0.5 * (asay - 128)) / 128 + 1,
|
||||||
|
(0.5 * (asaz - 128)) / 128 + 1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Power on
|
||||||
|
self._register_char(_CNTL1, (mode | output))
|
||||||
|
|
||||||
|
if output is OUTPUT_16_BIT:
|
||||||
|
self._so = _SO_16BIT
|
||||||
|
else:
|
||||||
|
self._so = _SO_14BIT
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def magnetic(self):
|
||||||
|
"""
|
||||||
|
X, Y, Z axis micro-Tesla (uT) as floats.
|
||||||
|
"""
|
||||||
|
xyz = list(self._register_three_shorts(_HXL))
|
||||||
|
self._register_char(_ST2) # Enable updating readings again
|
||||||
|
|
||||||
|
# Apply factory axial sensitivy adjustements
|
||||||
|
xyz[0] *= self._adjustement[0]
|
||||||
|
xyz[1] *= self._adjustement[1]
|
||||||
|
xyz[2] *= self._adjustement[2]
|
||||||
|
|
||||||
|
# Apply output scale determined in constructor
|
||||||
|
so = self._so
|
||||||
|
xyz[0] *= so
|
||||||
|
xyz[1] *= so
|
||||||
|
xyz[2] *= so
|
||||||
|
|
||||||
|
# Apply hard iron ie. offset bias from calibration
|
||||||
|
xyz[0] -= self._offset[0]
|
||||||
|
xyz[1] -= self._offset[1]
|
||||||
|
xyz[2] -= self._offset[2]
|
||||||
|
|
||||||
|
# Apply soft iron ie. scale bias from calibration
|
||||||
|
xyz[0] *= self._scale[0]
|
||||||
|
xyz[1] *= self._scale[1]
|
||||||
|
xyz[2] *= self._scale[2]
|
||||||
|
|
||||||
|
return tuple(xyz)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def adjustement(self):
|
||||||
|
return self._adjustement
|
||||||
|
|
||||||
|
@property
|
||||||
|
def whoami(self):
|
||||||
|
""" Value of the whoami register. """
|
||||||
|
return self._register_char(_WIA)
|
||||||
|
|
||||||
|
def calibrate(self, count=3, delay=200):
|
||||||
|
self._offset = (0, 0, 0)
|
||||||
|
self._scale = (1, 1, 1)
|
||||||
|
|
||||||
|
reading = self.magnetic
|
||||||
|
minx = maxx = reading[0]
|
||||||
|
miny = maxy = reading[1]
|
||||||
|
minz = maxz = reading[2]
|
||||||
|
|
||||||
|
while count:
|
||||||
|
time.sleep_ms(delay)
|
||||||
|
reading = self.magnetic
|
||||||
|
minx = min(minx, reading[0])
|
||||||
|
maxx = max(maxx, reading[0])
|
||||||
|
miny = min(miny, reading[1])
|
||||||
|
maxy = max(maxy, reading[1])
|
||||||
|
minz = min(minz, reading[2])
|
||||||
|
maxz = max(maxz, reading[2])
|
||||||
|
count -= 1
|
||||||
|
|
||||||
|
|
||||||
|
# Hard iron correction
|
||||||
|
offset_x = (maxx + minx) / 2
|
||||||
|
offset_y = (maxy + miny) / 2
|
||||||
|
offset_z = (maxz + minz) / 2
|
||||||
|
|
||||||
|
self._offset = (offset_x, offset_y, offset_z)
|
||||||
|
|
||||||
|
# Soft iron correction
|
||||||
|
avg_delta_x = (maxx - minx) / 2
|
||||||
|
avg_delta_y = (maxy - miny) / 2
|
||||||
|
avg_delta_z = (maxz - minz) / 2
|
||||||
|
|
||||||
|
avg_delta = (avg_delta_x + avg_delta_y + avg_delta_z) / 3
|
||||||
|
|
||||||
|
scale_x = avg_delta / avg_delta_x
|
||||||
|
scale_y = avg_delta / avg_delta_y
|
||||||
|
scale_z = avg_delta / avg_delta_z
|
||||||
|
|
||||||
|
self._scale = (scale_x, scale_y, scale_z)
|
||||||
|
|
||||||
|
return self._offset, self._scale
|
||||||
|
|
||||||
|
def _register_short(self, register, value=None, buf=bytearray(2)):
|
||||||
|
if value is None:
|
||||||
|
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||||
|
return ustruct.unpack("<h", buf)[0]
|
||||||
|
|
||||||
|
ustruct.pack_into("<h", buf, 0, value)
|
||||||
|
return self.i2c.writeto_mem(self.address, register, buf)
|
||||||
|
|
||||||
|
def _register_three_shorts(self, register, buf=bytearray(6)):
|
||||||
|
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||||
|
return ustruct.unpack("<hhh", buf)
|
||||||
|
|
||||||
|
def _register_char(self, register, value=None, buf=bytearray(1)):
|
||||||
|
if value is None:
|
||||||
|
self.i2c.readfrom_mem_into(self.address, register, buf)
|
||||||
|
return buf[0]
|
||||||
|
|
||||||
|
ustruct.pack_into("<b", buf, 0, value)
|
||||||
|
return self.i2c.writeto_mem(self.address, register, buf)
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exception_type, exception_value, traceback):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MPU9250:
|
||||||
|
"""Class which provides interface to MPU9250 9-axis motion tracking device."""
|
||||||
|
def __init__(self, i2c, mpu6500 = None, ak8963 = None):
|
||||||
|
if mpu6500 is None:
|
||||||
|
self.mpu6500 = MPU6500(i2c)
|
||||||
|
else:
|
||||||
|
self.mpu6500 = mpu6500
|
||||||
|
|
||||||
|
if ak8963 is None:
|
||||||
|
self.ak8963 = AK8963(i2c)
|
||||||
|
else:
|
||||||
|
self.ak8963 = ak8963
|
||||||
|
|
||||||
|
def mpu9250_get_temperature(self):
|
||||||
|
return self.mpu6500.temperature
|
||||||
|
|
||||||
|
def mpu9250_get_values(self):
|
||||||
|
g = self.mpu6500.acceleration()
|
||||||
|
a = [round(x/9.8, 2) for x in g]
|
||||||
|
return tuple(a)
|
||||||
|
|
||||||
|
def mpu9250_get_x(self):
|
||||||
|
return round(self.mpu6500.acceleration()[0]/9.8, 2)
|
||||||
|
|
||||||
|
def mpu9250_get_y(self):
|
||||||
|
return round(self.mpu6500.acceleration()[1]/9.8, 2)
|
||||||
|
|
||||||
|
def mpu9250_get_z(self):
|
||||||
|
return round(self.mpu6500.acceleration()[2]/9.8, 2)
|
||||||
|
|
||||||
|
|
||||||
|
def mpu9250_is_gesture(self,choice):
|
||||||
|
if choice == 'face up':
|
||||||
|
if self.mpu6500.acceleration()[2] <= -9:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
if choice == 'face down':
|
||||||
|
if self.mpu6500.acceleration()[2] >= 9:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
if choice == 'shake':
|
||||||
|
if abs(self.mpu6500.acceleration()[0]) >= 9 and abs(self.mpu6500.acceleration()[1]) >= 9 :
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
if choice == 'up':
|
||||||
|
if self.mpu6500.acceleration()[1] >= 9:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
if choice == 'down':
|
||||||
|
if self.mpu6500.acceleration()[1] <= -9:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
if choice == 'right':
|
||||||
|
if self.mpu6500.acceleration()[0] <= -9:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
if choice == 'left':
|
||||||
|
if self.mpu6500.acceleration()[0] >= 9:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mpu9250_gyro(self):
|
||||||
|
return self.mpu6500.gyro
|
||||||
|
|
||||||
|
def mpu9250_gyro_x(self):
|
||||||
|
return self.mpu6500.gyro[0]
|
||||||
|
|
||||||
|
def mpu9250_gyro_y(self):
|
||||||
|
return self.mpu6500.gyro[1]
|
||||||
|
|
||||||
|
def mpu9250_gyro_z(self):
|
||||||
|
return self.mpu6500.gyro[2]
|
||||||
|
|
||||||
|
def mpu9250_gyro_values(self):
|
||||||
|
return self.mpu6500.gyro
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mpu9250_magnetic(self):
|
||||||
|
"""X, Y, Z axis micro-Tesla (uT) as floats."""
|
||||||
|
return self.ak8963.magnetic
|
||||||
|
|
||||||
|
def mpu9250_magnetic_x(self):
|
||||||
|
return self.mpu9250_magnetic[0]
|
||||||
|
|
||||||
|
def mpu9250_magnetic_y(self):
|
||||||
|
return self.mpu9250_magnetic[1]
|
||||||
|
|
||||||
|
def mpu9250_magnetic_z(self):
|
||||||
|
return self.mpu9250_magnetic[2]
|
||||||
|
|
||||||
|
def mpu9250_magnetic_values(self):
|
||||||
|
return self.mpu9250_magnetic
|
||||||
|
|
||||||
|
# @property
|
||||||
|
def mpu9250_get_field_strength(self):
|
||||||
|
x=self.mpu9250_magnetic[0]
|
||||||
|
y=self.mpu9250_magnetic[1]
|
||||||
|
z=self.mpu9250_magnetic[2]
|
||||||
|
return (x**2+y**2+z**2)**0.5*1000
|
||||||
|
|
||||||
|
def mpu9250_heading(self):
|
||||||
|
x=self.mpu9250_magnetic[0]
|
||||||
|
y=self.mpu9250_magnetic[1]
|
||||||
|
z=self.mpu9250_magnetic[2]
|
||||||
|
a=math.atan(z/x)
|
||||||
|
b=math.atan(z/y)
|
||||||
|
xr=x*math.cos(a)+y*math.sin(a)*math.sin(b)-z*math.cos(b)*math.sin(a)
|
||||||
|
yr=x*math.cos(b)+z*math.sin(b)
|
||||||
|
return 60*math.atan(yr/xr)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def whoami(self):
|
||||||
|
return self.mpu6500.whoami
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exception_type, exception_value, traceback):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Compass:
|
||||||
|
RAD_TO_DEG = 57.295779513082320876798154814105
|
||||||
|
|
||||||
|
def __init__(self, sensor):
|
||||||
|
self.sensor = sensor
|
||||||
|
|
||||||
|
def get_x(self):
|
||||||
|
return self.sensor.mpu9250_magnetic[0]
|
||||||
|
|
||||||
|
def get_y(self):
|
||||||
|
return self.sensor.mpu9250_magnetic[1]
|
||||||
|
|
||||||
|
def get_z(self):
|
||||||
|
return self.sensor.mpu9250_magnetic[2]
|
||||||
|
|
||||||
|
def get_field_strength(self):
|
||||||
|
return self.sensor.mpu9250_get_field_strength()
|
||||||
|
|
||||||
|
def heading(self):
|
||||||
|
from math import atan2
|
||||||
|
xyz = self.sensor.mpu9250_magnetic
|
||||||
|
return int(((atan2(xyz[1], xyz[0]) * Compass.RAD_TO_DEG) + 180) % 360)
|
||||||
|
|
||||||
|
def calibrate(self):
|
||||||
|
import matrix16x8
|
||||||
|
mp_i2c=SoftI2C(scl = Pin(7), sda = Pin(6), freq = 400000)
|
||||||
|
mp_matrix = matrix32x12.Matrix(mp_i2c)
|
||||||
|
if self.is_calibrate() is False:
|
||||||
|
# print('The calibration need to shaking in the air (e.g. 8 or 0) and waiting for a moment')
|
||||||
|
print('First write 8 or 0 in the air with the board about 30 seconds, and then try to rotate the board in different direnctions several times.')
|
||||||
|
mp_matrix.pixel(7, 3, 1)
|
||||||
|
#mp_matrix.blink_rate(2)
|
||||||
|
l1=0
|
||||||
|
l2=0
|
||||||
|
l3=0
|
||||||
|
l4=0
|
||||||
|
l5=0
|
||||||
|
l6=0
|
||||||
|
l7=0
|
||||||
|
l8=0
|
||||||
|
while True:
|
||||||
|
x = self.sensor.mpu6500.acceleration()[0]
|
||||||
|
y = self.sensor.mpu6500.acceleration()[1]
|
||||||
|
z = self.sensor.mpu6500.acceleration()[2]
|
||||||
|
a=(x**2+y**2+z**2)**0.5
|
||||||
|
if z > 0:
|
||||||
|
if x > 0 and y > 0 and a >= 12:
|
||||||
|
l1=l1 + 1
|
||||||
|
if x > 0 and y < 0 and a >= 12:
|
||||||
|
l2=l2 + 1
|
||||||
|
if x < 0 and y > 0 and a >= 12:
|
||||||
|
l3=l3 + 1
|
||||||
|
if x < 0 and y < 0 and a >= 12:
|
||||||
|
l4=l4 + 1
|
||||||
|
if z < 0:
|
||||||
|
if x > 0 and y > 0 and a >= 12:
|
||||||
|
l5=l5 + 1
|
||||||
|
if x > 0 and y < 0 and a >= 12:
|
||||||
|
l6=l6 + 1
|
||||||
|
if x < 0 and y > 0 and a >= 12:
|
||||||
|
l7=l7 + 1
|
||||||
|
if x < 0 and y < 0 and a >= 12:
|
||||||
|
l8=l8 + 1
|
||||||
|
if l1 >= 2:
|
||||||
|
mp_matrix.pixel(7, 0, 1)
|
||||||
|
mp_matrix.pixel(8, 0, 1)
|
||||||
|
mp_matrix.pixel(9, 1, 1)
|
||||||
|
if l2 >= 2:
|
||||||
|
mp_matrix.pixel(10, 2, 1)
|
||||||
|
mp_matrix.pixel(10, 3, 1)
|
||||||
|
if l3 >= 2:
|
||||||
|
mp_matrix.pixel(10, 4, 1)
|
||||||
|
mp_matrix.pixel(10, 5, 1)
|
||||||
|
if l4 >= 2:
|
||||||
|
mp_matrix.pixel(9, 6, 1)
|
||||||
|
mp_matrix.pixel(8, 7, 1)
|
||||||
|
if l5 >= 2:
|
||||||
|
mp_matrix.pixel(7, 7, 1)
|
||||||
|
mp_matrix.pixel(6, 7, 1)
|
||||||
|
if l6 >= 2:
|
||||||
|
mp_matrix.pixel(5, 6, 1)
|
||||||
|
mp_matrix.pixel(4, 5, 1)
|
||||||
|
if l7 >= 2:
|
||||||
|
mp_matrix.pixel(4, 4, 1)
|
||||||
|
mp_matrix.pixel(4, 3, 1)
|
||||||
|
if l8 >= 2:
|
||||||
|
mp_matrix.pixel(4, 2, 1)
|
||||||
|
mp_matrix.pixel(5, 1, 1)
|
||||||
|
mp_matrix.pixel(6, 0, 1)
|
||||||
|
if l1>=2 and l2>=2 and l3>=2 and l4>=2 and l5>=2 and l6>=2 and l7>=2 and l8>=2:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.sensor.ak8963.calibrate()
|
||||||
|
with open("compass_cfg.py", "w") as f:
|
||||||
|
f.write('\n_offset = ' + str(self.sensor.ak8963._offset) + '\n_scale = ' + str(self.sensor.ak8963._offset))
|
||||||
|
else:
|
||||||
|
print('The calibration configuration already exists. If you need to recalibrate, enter os.remove("compass_cfg.py") in repl and restart')
|
||||||
|
try:
|
||||||
|
import compass_cfg
|
||||||
|
self.sensor.ak8963._offset = compass_cfg._offset
|
||||||
|
self.sensor.ak8963._scale = compass_cfg._scale
|
||||||
|
except Exception as e:
|
||||||
|
print('compass_cfg error! delete it, please.')
|
||||||
|
with open("compass_cfg.py") as f:
|
||||||
|
for line in f:
|
||||||
|
print(line)
|
||||||
|
|
||||||
|
def is_calibrate(self):
|
||||||
|
try:
|
||||||
|
import compass_cfg
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def reset_calibrate(self):
|
||||||
|
import os
|
||||||
|
os.remove("compass_cfg.py")
|
||||||
137
mixly/boards/default/micropython/build/lib/ms32006.py
Normal file
137
mixly/boards/default/micropython/build/lib/ms32006.py
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
"""
|
||||||
|
MS32006
|
||||||
|
|
||||||
|
Micropython library for the MS32006 step diever
|
||||||
|
=======================================================
|
||||||
|
#Changed from circuitpython to micropython 20211206
|
||||||
|
#Fix register read / write bug 20211215
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
|
||||||
|
MS32006_REG_RESET = const(0x00) #复位
|
||||||
|
MS32006_FCLK = const(25000000) #芯片输入时钟选择,此参数与运动速度有关。 范围是:5-30MHZ
|
||||||
|
|
||||||
|
ADDRESS_A = 0x10
|
||||||
|
ADDRESS_B = 0x18
|
||||||
|
MOT_FULL = 0
|
||||||
|
MOT_HALF = 1
|
||||||
|
MOT_A = 0
|
||||||
|
MOT_B = 4
|
||||||
|
MOT_N = 0
|
||||||
|
MOT_CW = 1
|
||||||
|
MOT_CCW = 2
|
||||||
|
MOT_P = 3
|
||||||
|
class MS32006:
|
||||||
|
|
||||||
|
_buffer = bytearray(2)
|
||||||
|
|
||||||
|
def __init__(self, i2c_bus,addr=ADDRESS_A,mode=MOT_FULL):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
self.reset()
|
||||||
|
self.mode=mode
|
||||||
|
|
||||||
|
|
||||||
|
def _read_u8(self, reg):
|
||||||
|
return self._device.readfrom_mem(self._address, reg, 1)[0]
|
||||||
|
|
||||||
|
def _write_u8(self, reg, val):
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self._write_u8(MS32006_REG_RESET,0x00)
|
||||||
|
time.sleep(0.1)
|
||||||
|
self._write_u8(MS32006_REG_RESET,0xC1)
|
||||||
|
|
||||||
|
def move(self,moto,mot_dir,mot_pps,mot_step):
|
||||||
|
readstate_0H = self._read_u8(0x00)
|
||||||
|
readstate_9H = self._read_u8(0x09)
|
||||||
|
speed_data=MS32006_FCLK//mot_pps//128 #设置速度 xx pps 128是固定参数
|
||||||
|
|
||||||
|
if speed_data<32: #限定转速
|
||||||
|
speed_data=32
|
||||||
|
elif speed_data>16383:
|
||||||
|
speed_data=16383
|
||||||
|
|
||||||
|
mot_speed_l=speed_data&0x00ff #取低8位
|
||||||
|
mot_speed_h=speed_data//0x100 #取高6位
|
||||||
|
|
||||||
|
if self.mode==MOT_FULL: #设置整步、半步驱动模式
|
||||||
|
mot_speed_h|=0x80
|
||||||
|
else:
|
||||||
|
mot_speed_h&=0x7f
|
||||||
|
|
||||||
|
if mot_step>2047:
|
||||||
|
raise AttributeError("Reach the set upper limit, up to 2047 step")
|
||||||
|
|
||||||
|
mot_step_l=mot_step&0x00ff
|
||||||
|
mot_step_h=mot_step//0x100
|
||||||
|
mot_step_h|=0x80
|
||||||
|
|
||||||
|
if mot_dir==MOT_CW:
|
||||||
|
mot_step_h&=0xBF
|
||||||
|
else:
|
||||||
|
mot_step_h|=0x40
|
||||||
|
self._write_u8(0x01+moto,mot_speed_l)
|
||||||
|
self._write_u8(0x02+moto,mot_speed_h)
|
||||||
|
self._write_u8(0x03+moto,mot_step_l)
|
||||||
|
self._write_u8(0x04+moto,mot_step_h)
|
||||||
|
|
||||||
|
if moto==MOT_A:
|
||||||
|
self._write_u8(0x00, readstate_0H&0xfb)
|
||||||
|
self._write_u8(0x09, readstate_9H|0x80)
|
||||||
|
else:
|
||||||
|
self._write_u8(0x00, readstate_0H&0xfd)
|
||||||
|
self._write_u8(0x09, readstate_9H|0x40)
|
||||||
|
|
||||||
|
def close(self,moto): #停止并关闭输出
|
||||||
|
if moto==MOT_A:
|
||||||
|
self._write_u8(0x04,0x00)
|
||||||
|
else:
|
||||||
|
self._write_u8(0x08,0x00)
|
||||||
|
|
||||||
|
def stop(self,moto): #此停止函数,强制让电机停止
|
||||||
|
readstate = self._read_u8(0x00)
|
||||||
|
if moto==MOT_A:
|
||||||
|
self._write_u8(0x00,readstate|0x04)
|
||||||
|
else:
|
||||||
|
self._write_u8(0x00,readstate|0x02)
|
||||||
|
|
||||||
|
def readstep(self,moto): #读取电机运动步数
|
||||||
|
if moto==MOT_A:
|
||||||
|
rdb =self._read_u8(0x0b)
|
||||||
|
rdc =self._read_u8(0x0c)
|
||||||
|
else:
|
||||||
|
rdb =self._read_u8(0x0d)
|
||||||
|
rdc =self._read_u8(0x0e)
|
||||||
|
return (rdb*0x100+rdc)&0xfff
|
||||||
|
|
||||||
|
def readbusy(self,moto): #读取电机缓存是否有数据
|
||||||
|
if moto==MOT_A:
|
||||||
|
busy =(self._read_u8(0x0b)>>6)&1
|
||||||
|
else:
|
||||||
|
busy =(self._read_u8(0x0d)>>6)&1
|
||||||
|
return bool(busy)
|
||||||
|
|
||||||
|
def readwork(self,moto): #读取电机是否在运行
|
||||||
|
if moto==MOT_A:
|
||||||
|
busy =(self._read_u8(0x0b)>>4)&1
|
||||||
|
else:
|
||||||
|
busy =(self._read_u8(0x0d)>>4)&1
|
||||||
|
return bool(busy)
|
||||||
|
|
||||||
|
def dc_motor(self,state,speed=100): #直流电机驱动
|
||||||
|
if (state==MOT_CW) | (state==MOT_CCW) :
|
||||||
|
speed_st=speed*127//100 |0x80
|
||||||
|
self._write_u8(0x0A,speed_st)
|
||||||
|
|
||||||
|
readstate = self._read_u8(0x09) & 0xA0
|
||||||
|
state_st=(state<<2) | 0X03 | readstate
|
||||||
|
self._write_u8(0x09,state_st)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
81
mixly/boards/default/micropython/build/lib/ms5611.py
Normal file
81
mixly/boards/default/micropython/build/lib/ms5611.py
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
import utime
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_MS5611_ADDR = const(0x77)
|
||||||
|
_CMD_ADC_READ = const(0x00)
|
||||||
|
_CMD_RESET = const(0x1E)
|
||||||
|
_CMD_CONVERT_D1 = const(0x40)
|
||||||
|
_CMD_CONVERT_D2 = const(0x50)
|
||||||
|
_CAL_DATA_C1 = const(0xA2)
|
||||||
|
_CAL_DATA_C2 = const(0xA4)
|
||||||
|
_CAL_DATA_C3 = const(0xA6)
|
||||||
|
_CAL_DATA_C4 = const(0xA8)
|
||||||
|
_CAL_DATA_C5 = const(0xAA)
|
||||||
|
_CAL_DATA_C6 = const(0xAC)
|
||||||
|
|
||||||
|
# Oversampling settings
|
||||||
|
OSR={"OSR_256":0, "OSR_512":2, "OSR_1024":4, "OSR_2048":6, "OSR_4096":8}
|
||||||
|
|
||||||
|
class MS5611:
|
||||||
|
def __init__(self, i2c_bus, addr=_MS5611_ADDR, osr='OSR_4096'):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
self._wreg(_CMD_RESET)
|
||||||
|
utime.sleep_ms(50)
|
||||||
|
|
||||||
|
self.c1 = self._rreg(_CAL_DATA_C1, 2)
|
||||||
|
self.c2 = self._rreg(_CAL_DATA_C2, 2)
|
||||||
|
self.c3 = self._rreg(_CAL_DATA_C3, 2)
|
||||||
|
self.c4 = self._rreg(_CAL_DATA_C4, 2)
|
||||||
|
self.c5 = self._rreg(_CAL_DATA_C5, 2)
|
||||||
|
self.c6 = self._rreg(_CAL_DATA_C6, 2)
|
||||||
|
self.pressure_cmd_rate = _CMD_CONVERT_D1 + OSR[osr]
|
||||||
|
self.temp_cmd_rate = _CMD_CONVERT_D2 + OSR[osr]
|
||||||
|
|
||||||
|
def _wreg(self, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto(self._address, bytes([val]))
|
||||||
|
|
||||||
|
def _rreg(self, reg, nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return int.from_bytes(self._device.readfrom_mem(self._address, reg, nbytes), 'big')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def getdata(self):
|
||||||
|
'''处理获取数据'''
|
||||||
|
self._wreg(self.pressure_cmd_rate)
|
||||||
|
utime.sleep_ms(15)
|
||||||
|
D1 = self._rreg(_CMD_ADC_READ, 3)
|
||||||
|
|
||||||
|
self._wreg(self.temp_cmd_rate)
|
||||||
|
utime.sleep_ms(15)
|
||||||
|
D2 = self._rreg(_CMD_ADC_READ, 3)
|
||||||
|
|
||||||
|
dT = D2 - self.c5 * 2 ** 8
|
||||||
|
TEMP = 2000 + dT * self.c6 / 2 ** 23
|
||||||
|
OFF = self.c2 * 2 ** 16 + dT * self.c4 / 2 ** 7
|
||||||
|
SENS = self.c1 * 2 ** 15 + dT * self.c3 / 2 ** 8
|
||||||
|
|
||||||
|
if TEMP < 2000:
|
||||||
|
T2 = dT * dT / 2 ** 31
|
||||||
|
OFF2 = 5 * (TEMP - 2000) ** 2 / 2
|
||||||
|
SENS2 = 5 * (TEMP - 2000) ** 2 / 4
|
||||||
|
if TEMP < -1500:
|
||||||
|
OFF2 = OFF2 + 7 * (TEMP + 1500) ** 2
|
||||||
|
SENS2 = SENS2 + 11 * (TEMP + 1500) ** 2 / 2
|
||||||
|
TEMP = TEMP - T2
|
||||||
|
OFF = OFF - OFF2
|
||||||
|
SENS = SENS - SENS2
|
||||||
|
|
||||||
|
P = (D1 * SENS / 2 ** 21 - OFF) / 2 ** 15
|
||||||
|
H = (1 - (P / 101325) ** (1 / 5.255)) * 44330
|
||||||
|
return round(P / 100, 2), round(TEMP / 100, 2), round(H, 2)
|
||||||
|
|
||||||
|
def pressure(self):
|
||||||
|
return self.getdata[0]
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
return self.getdata[1]
|
||||||
|
|
||||||
|
def altitude(self, reference=1013.25):
|
||||||
|
return (pow((reference / 33.8639), 0.190255) - pow((self.getdata[0] / 33.8639), 0.190255)) / 0.000013125214
|
||||||
57
mixly/boards/default/micropython/build/lib/msa301.py
Normal file
57
mixly/boards/default/micropython/build/lib/msa301.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
"""
|
||||||
|
MSA301
|
||||||
|
|
||||||
|
Micropython library for the MSA301 Accelerometer
|
||||||
|
=======================================================
|
||||||
|
#Preliminary composition 20220817
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
MSA301_ADDRESS = const(0x26)
|
||||||
|
MSA301_REG_DEVICE_ID = const(0x01)
|
||||||
|
MSA301_REG_DATA = const(0x02)
|
||||||
|
MSA301_REG_ODR = const(0x10)
|
||||||
|
MSA301_REG_POWERMODE = const(0x11)
|
||||||
|
MSA301_REG_RESRANGE = const(0x0F)
|
||||||
|
|
||||||
|
class MSA301:
|
||||||
|
def __init__(self, i2c_bus, front=False):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = MSA301_ADDRESS
|
||||||
|
self._front = front
|
||||||
|
if self._chip_id() != 0x13:
|
||||||
|
raise AttributeError("Cannot find a MSA301")
|
||||||
|
|
||||||
|
self._wreg(MSA301_REG_ODR,0X09) #RATE_500_HZ
|
||||||
|
self._wreg(MSA301_REG_POWERMODE,0X12) #NORMAL & WIDTH_250_HZ
|
||||||
|
self._wreg(MSA301_REG_RESRANGE,0X02) #RESOLUTION_14_BIT & RANGE_8_G
|
||||||
|
|
||||||
|
def _rreg(self, reg,nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
return self._rreg(MSA301_REG_DEVICE_ID)
|
||||||
|
|
||||||
|
def u2s(self,n):
|
||||||
|
return n if n < (1 << 7) else n - (1 << 8)
|
||||||
|
|
||||||
|
def acceleration(self):
|
||||||
|
data_reg=self._rreg(MSA301_REG_DATA,6)
|
||||||
|
x_acc=((self.u2s(data_reg[1])<<8|data_reg[0])>>2)/1024.0
|
||||||
|
y_acc=((self.u2s(data_reg[3])<<8|data_reg[2])>>2)/1024.0
|
||||||
|
z_acc=((self.u2s(data_reg[5])<<8|data_reg[4])>>2)/1024.0
|
||||||
|
return (-y_acc,-x_acc,z_acc) if self._front else (y_acc,-x_acc,z_acc)
|
||||||
|
|
||||||
|
def eulerangles(self,upright=False):
|
||||||
|
x,y,z=self.acceleration()
|
||||||
|
pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2)))
|
||||||
|
roll = degrees(atan(x / sqrt(y ** 2 + z ** 2)))
|
||||||
|
return round(pitch,2),round(roll,2)
|
||||||
174
mixly/boards/default/micropython/build/lib/music.py
Normal file
174
mixly/boards/default/micropython/build/lib/music.py
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
"""
|
||||||
|
Music buzzer
|
||||||
|
|
||||||
|
Micropython library for the Music buzzer
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import _thread, gc
|
||||||
|
from time import sleep_ms
|
||||||
|
from machine import Pin, PWM
|
||||||
|
|
||||||
|
normal_tone = {
|
||||||
|
'A1': 55, 'B1': 62, 'C1': 33, 'D1': 37, 'E1': 41, 'F1': 44, 'G1': 49,
|
||||||
|
'A2': 110, 'B2': 123, 'C2': 65, 'D2': 73, 'E2': 82, 'F2': 87, 'G2': 98,
|
||||||
|
'A3': 220, 'B3': 247, 'C3': 131, 'D3': 147, 'E3': 165, 'F3': 175, 'G3': 196,
|
||||||
|
'A4': 440, 'B4': 494, 'C4': 262, 'D4': 294, 'E4': 330, 'F4': 349, 'G4': 392,
|
||||||
|
'A5': 880, 'B5': 988, 'C5': 523, 'D5': 587, 'E5': 659, 'F5': 698, 'G5': 784,
|
||||||
|
'A6': 1760, 'B6': 1976, 'C6': 1047, 'D6': 1175, 'E6': 1319, 'F6': 1397, 'G6': 1568,
|
||||||
|
'A7': 3520, 'B7': 3951, 'C7': 2093, 'D7': 2349, 'E7': 2637, 'F7': 2794, 'G7': 3135,
|
||||||
|
'A8': 7040, 'B8': 7902, 'C8': 4186, 'D8': 4699, 'E8': 5274, 'F8': 5588, 'G8': 6271,
|
||||||
|
'A9': 14080, 'B9': 15804 }
|
||||||
|
|
||||||
|
Letter = 'ABCDEFG#R'
|
||||||
|
|
||||||
|
class MIDI():
|
||||||
|
def __init__(self, pin, volume=100, invert=0, pa_ctrl=None):
|
||||||
|
self.reset()
|
||||||
|
self._invert = invert
|
||||||
|
self._pin = pin
|
||||||
|
self._volume = volume
|
||||||
|
self._play = False
|
||||||
|
self._over = True
|
||||||
|
self._pwm = None
|
||||||
|
self._pa_ctrl = pa_ctrl
|
||||||
|
|
||||||
|
def set_volume(self, volume):
|
||||||
|
if not 0 <= volume <= 100:
|
||||||
|
raise ValueError("Volume value is in the range: 0-100")
|
||||||
|
self._volume=volume
|
||||||
|
|
||||||
|
def set_tempo(self, ticks=4, bpm=120):
|
||||||
|
self.ticks = ticks
|
||||||
|
self.bpm = bpm
|
||||||
|
self.beat = 60000 / self.bpm / self.ticks
|
||||||
|
|
||||||
|
def set_octave(self, octave=4):
|
||||||
|
self.octave = octave
|
||||||
|
|
||||||
|
def set_duration(self, duration=4):
|
||||||
|
self.duration = duration
|
||||||
|
|
||||||
|
def get_tempo(self):
|
||||||
|
return (self.ticks, self.bpm)
|
||||||
|
|
||||||
|
def get_octave(self):
|
||||||
|
return self.octave
|
||||||
|
|
||||||
|
def get_duration(self):
|
||||||
|
return self.duration
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self.set_duration()
|
||||||
|
self.set_octave()
|
||||||
|
self.set_tempo()
|
||||||
|
|
||||||
|
def parse(self, tone, dict):
|
||||||
|
time = self.beat * self.duration
|
||||||
|
pos = tone.find(':')
|
||||||
|
if pos != -1:
|
||||||
|
time = self.beat * int(tone[(pos + 1):])
|
||||||
|
tone = tone[:pos]
|
||||||
|
freq, tone_size = 1, len(tone)
|
||||||
|
if 'R' in tone:
|
||||||
|
freq = 400000
|
||||||
|
elif tone_size == 1:
|
||||||
|
freq = dict[tone[0] + str(self.octave)]
|
||||||
|
elif tone_size == 2:
|
||||||
|
freq = dict[tone]
|
||||||
|
self.set_octave(tone[1:])
|
||||||
|
return int(freq), int(time)
|
||||||
|
|
||||||
|
def midi(self, tone):
|
||||||
|
pos = tone.find('#')
|
||||||
|
if pos != -1:
|
||||||
|
return self.parse(tone.replace('#', ''), normal_tone)
|
||||||
|
pos = tone.find('B')
|
||||||
|
if pos != -1 and pos != 0:
|
||||||
|
return self.parse(tone.replace('B', ''), normal_tone)
|
||||||
|
return self.parse(tone, normal_tone)
|
||||||
|
|
||||||
|
def set_default(self, tone):
|
||||||
|
pos = tone.find(':')
|
||||||
|
if pos != -1:
|
||||||
|
self.set_duration(int(tone[(pos + 1):]))
|
||||||
|
tone = tone[:pos]
|
||||||
|
|
||||||
|
def play(self, tune, duration=None, pa_delay=100):
|
||||||
|
if self._pa_ctrl: self._pa_ctrl(1, pa_delay)
|
||||||
|
self._pwm = PWM(Pin(self._pin), duty=1023 if self._invert else 0)
|
||||||
|
self._play = True
|
||||||
|
self._over = False
|
||||||
|
if duration is None:
|
||||||
|
self.set_default(tune[0])
|
||||||
|
else:
|
||||||
|
self.set_duration(duration)
|
||||||
|
for tone in tune:
|
||||||
|
tone = tone.upper()
|
||||||
|
if not self._play:
|
||||||
|
break
|
||||||
|
if tone[0] not in Letter:
|
||||||
|
continue
|
||||||
|
midi = self.midi(tone)
|
||||||
|
if self._play: self._pwm.duty((1023-self._volume) if self._invert else self._volume)
|
||||||
|
if self._play: self._pwm.freq(midi[0])
|
||||||
|
sleep_ms(midi[1])
|
||||||
|
if self._play: self._pwm.freq(400000)
|
||||||
|
sleep_ms(1)
|
||||||
|
if self._pa_ctrl: self._pa_ctrl(0, 0)
|
||||||
|
self._pwm.deinit()
|
||||||
|
sleep_ms(10)
|
||||||
|
self._over = True
|
||||||
|
|
||||||
|
def play_thread(self, tune, duration=None, pa_delay=100):
|
||||||
|
self._play = False
|
||||||
|
while not self._over:
|
||||||
|
sleep_ms(10)
|
||||||
|
if not self._play:
|
||||||
|
gc.collect()
|
||||||
|
_thread.start_new_thread(self.play, (tune, duration, pa_delay))
|
||||||
|
sleep_ms(100)
|
||||||
|
|
||||||
|
def pitch(self, freq, pa_delay=100):
|
||||||
|
if self._pa_ctrl: self._pa_ctrl(1, pa_delay)
|
||||||
|
self._pwm = PWM(Pin(self._pin))
|
||||||
|
self._pwm.duty((1023-self._volume) if self._invert else self._volume)
|
||||||
|
self._pwm.freq(int(freq))
|
||||||
|
|
||||||
|
def pitch_time(self, freq, delay, pa_delay=100):
|
||||||
|
if self._pa_ctrl: self._pa_ctrl(1, pa_delay)
|
||||||
|
self._pwm = PWM(Pin(self._pin))
|
||||||
|
self._pwm.duty((1023-self._volume) if self._invert else self._volume)
|
||||||
|
self._pwm.freq(int(freq))
|
||||||
|
sleep_ms(delay)
|
||||||
|
if self._pa_ctrl: self._pa_ctrl(0, 0)
|
||||||
|
self._pwm.deinit()
|
||||||
|
sleep_ms(10)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self._play = False
|
||||||
|
if self._pa_ctrl: self._pa_ctrl(0, 0)
|
||||||
|
if self._pwm: self._pwm.deinit()
|
||||||
|
sleep_ms(10)
|
||||||
|
|
||||||
|
DADADADUM=['r4:2','g','g','g','eb:8','r:2','f','f','f','d:8']
|
||||||
|
ENTERTAINER=['d4:1','d#','e','c5:2','e4:1','c5:2','e4:1','c5:3','c:1','d','d#','e','c','d','e:2','b4:1','d5:2','c:4']
|
||||||
|
PRELUDE=['c4:1','e','g','c5','e','g4','c5','e','c4','e','g','c5','e','g4','c5','e','c4','d','g','d5','f','g4','d5','f','c4','d','g','d5','f','g4','d5','f','b3','d4','g','d5','f','g4','d5','f','b3','d4','g','d5','f','g4','d5','f','c4','e','g','c5','e','g4','c5','e','c4','e','g','c5','e','g4','c5','e']
|
||||||
|
ODE=['e4','e','f','g','g','f','e','d','c','c','d','e','e:6','d:2','d:8','e:4','e','f','g','g','f','e','d','c','c','d','e','d:6','c:2','c:8']
|
||||||
|
NYAN=['f#5:1','g#','c#:1','d#:2','b4:1','d5:1','c#','b4:2','b','c#5','d','d:1','c#','b4:1','c#5:1','d#','f#','g#','d#','f#','c#','d','b4','c#5','b4','d#5:2','f#','g#:1','d#','f#','c#','d#','b4','d5','d#','d','c#','b4','c#5','d:2','b4:1','c#5','d#','f#','c#','d','c#','b4','c#5:2','b4','c#5','b4','f#:1','g#','b:2','f#:1','g#','b','c#5','d#','b4','e5','d#','e','f#','b4:2','b','f#:1','g#','b','f#','e5','d#','c#','b4','f#','d#','e','f#','b:2','f#:1','g#','b:2','f#:1','g#','b','b','c#5','d#','b4','f#','g#','f#','b:2','b:1','a#','b','f#','g#','b','e5','d#','e','f#','b4:2','c#5']
|
||||||
|
RINGTONE=['c4:1','d','e:2','g','d:1','e','f:2','a','e:1','f','g:2','b','c5:4']
|
||||||
|
FUNK=['c2:2','c','d#','c:1','f:2','c:1','f:2','f#','g','c','c','g','c:1','f#:2','c:1','f#:2','f','d#']
|
||||||
|
BLUES=['c2:2','e','g','a','a#','a','g','e','c2:2','e','g','a','a#','a','g','e','f','a','c3','d','d#','d','c','a2','c2:2','e','g','a','a#','a','g','e','g','b','d3','f','f2','a','c3','d#','c2:2','e','g','e','g','f','e','d']
|
||||||
|
BIRTHDAY=['c4:4','c:1','d:4','c:4','f','e:8','c:3','c:1','d:4','c:4','g','f:8','c:3','c:1','c5:4','a4','f','e','d','a#:3','a#:1','a:4','f','g','f:8']
|
||||||
|
WEDDING=['c4:4','f:3','f:1','f:8','c:4','g:3','e:1','f:8','c:4','f:3','a:1','c5:4','a4:3','f:1','f:4','e:3','f:1','g:8']
|
||||||
|
FUNERAL=['c3:4','c:3','c:1','c:4','d#:3','d:1','d:3','c:1','c:3','b2:1','c3:4']
|
||||||
|
PUNCHLINE=['c4:3','g3:1','f#','g','g#:3','g','r','b','c4']
|
||||||
|
PYTHON=['d5:1','b4','r','b','b','a#','b','g5','r','d','d','r','b4','c5','r','c','c','r','d','e:5','c:1','a4','r','a','a','g#','a','f#5','r','e','e','r','c','b4','r','b','b','r','c5','d:5','d:1','b4','r','b','b','a#','b','b5','r','g','g','r','d','c#','r','a','a','r','a','a:5','g:1','f#:2','a:1','a','g#','a','e:2','a:1','a','g#','a','d','r','c#','d','r','c#','d:2','r:3']
|
||||||
|
BADDY=['c3:3','r','d:2','d#','r','c','r','f#:8']
|
||||||
|
CHASE=['a4:1','b','c5','b4','a:2','r','a:1','b','c5','b4','a:2','r','a:2','e5','d#','e','f','e','d#','e','b4:1','c5','d','c','b4:2','r','b:1','c5','d','c','b4:2','r','b:2','e5','d#','e','f','e','d#','e']
|
||||||
|
BA_DING=['b5:1','e6:3']
|
||||||
|
WAWAWAWAA=['e3:3','r:1','d#:3','r:1','d:4','r:1','c#:8']
|
||||||
|
JUMP_UP=['c5:1','d','e','f','g']
|
||||||
|
JUMP_DOWN=['g5:1','f','e','d','c']
|
||||||
|
POWER_UP=['g4:1','c5','e4','g5:2','e5:1','g5:3']
|
||||||
|
POWER_DOWN=['g5:1','d#','c','g4:2','b:1','c5:3']
|
||||||
91
mixly/boards/default/micropython/build/lib/mxc6655xa.py
Normal file
91
mixly/boards/default/micropython/build/lib/mxc6655xa.py
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
"""
|
||||||
|
MXC6655XA
|
||||||
|
|
||||||
|
Micropython library for the MXC6655XA Accelerometer
|
||||||
|
=======================================================
|
||||||
|
#Changed from circuitpython to micropython 20220224
|
||||||
|
#Format unified 20220623
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from math import atan,sqrt,degrees
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
MXC6655XA_ADDRESS = const(0x15)
|
||||||
|
MXC6655XA_REG_DATA = const(0x03)
|
||||||
|
MXC6655XA_REG_CTRL = const(0x0D)
|
||||||
|
MXC6655XA_REG_DEVICE_ID = const(0x0E)
|
||||||
|
MXC6655XA_CMD_8G_POWER_ON = const(0x40)
|
||||||
|
MXC6655XA_CMD_4G_POWER_ON = const(0x20)
|
||||||
|
MXC6655XA_CMD_2G_POWER_ON = const(0x00)
|
||||||
|
|
||||||
|
_Range = (
|
||||||
|
MXC6655XA_CMD_2G_POWER_ON, # 2g
|
||||||
|
MXC6655XA_CMD_4G_POWER_ON, # 4g
|
||||||
|
MXC6655XA_CMD_8G_POWER_ON, # 8g
|
||||||
|
)
|
||||||
|
|
||||||
|
_Range_X = (
|
||||||
|
1024, # 2g
|
||||||
|
512, # 4g
|
||||||
|
256, # 8g
|
||||||
|
)
|
||||||
|
|
||||||
|
MXC6655XA_T_ZERO =25
|
||||||
|
MXC6655XA_T_SENSITIVITY =0.586
|
||||||
|
|
||||||
|
class MXC6655XA:
|
||||||
|
|
||||||
|
def __init__(self,i2c_bus,set_range=2, front=False):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = MXC6655XA_ADDRESS
|
||||||
|
self._range = set_range #default 8g range
|
||||||
|
self._front = front
|
||||||
|
|
||||||
|
if self._chip_id() != 0x02:
|
||||||
|
raise AttributeError("Cannot find a MXC6655XA")
|
||||||
|
self._Enable() #star
|
||||||
|
#time.sleep(0.3)
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg,nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
return self._rreg(MXC6655XA_REG_DEVICE_ID)
|
||||||
|
|
||||||
|
def _Enable(self):
|
||||||
|
self._wreg(MXC6655XA_REG_CTRL,_Range[self._range])
|
||||||
|
|
||||||
|
def u2s(self,n):
|
||||||
|
return n if n < (1 << 7) else n - (1 << 8)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def getdata(self):
|
||||||
|
data_reg=self._rreg(MXC6655XA_REG_DATA,7)
|
||||||
|
x_acc=float((self.u2s(data_reg[0])<<8|data_reg[1])>>4)/_Range_X[self._range]
|
||||||
|
y_acc=float((self.u2s(data_reg[2])<<8|data_reg[3])>>4)/_Range_X[self._range]
|
||||||
|
z_acc=float((self.u2s(data_reg[4])<<8|data_reg[5])>>4)/_Range_X[self._range]
|
||||||
|
t_acc=float(self.u2s(data_reg[6]))*MXC6655XA_T_SENSITIVITY + MXC6655XA_T_ZERO
|
||||||
|
return (-y_acc,-x_acc,z_acc,round(t_acc,1)) if self._front else (y_acc,-x_acc,z_acc,round(t_acc,1))
|
||||||
|
|
||||||
|
def acceleration(self):
|
||||||
|
return self.getdata[0:3]
|
||||||
|
|
||||||
|
def strength(self):
|
||||||
|
from math import sqrt
|
||||||
|
return sqrt(self.getdata[0]**2+self.getdata[1]**2+self.getdata[2]**2)
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
return self.getdata[3]
|
||||||
|
|
||||||
|
def eulerangles(self,upright=False):
|
||||||
|
x,y,z=self.acceleration()
|
||||||
|
pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2)))
|
||||||
|
roll = degrees(atan(x / sqrt(y ** 2 + z ** 2)))
|
||||||
|
return round(pitch,2),round(roll,2)
|
||||||
117
mixly/boards/default/micropython/build/lib/ns9300.py
Normal file
117
mixly/boards/default/micropython/build/lib/ns9300.py
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
"""
|
||||||
|
NS9300
|
||||||
|
|
||||||
|
Micropython library for the NS9300(Music Player)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_PLAY_CTRL = const(0x04)
|
||||||
|
_PLAY_VOL = const(0x06)
|
||||||
|
_PLAY_INS = const(0x09)
|
||||||
|
_PLAY_MODE = const(0x0B)
|
||||||
|
|
||||||
|
class NS9300:
|
||||||
|
def __init__(self, uart, delay=250):
|
||||||
|
self._uart = uart
|
||||||
|
self._delay = delay
|
||||||
|
self._uart.init(baudrate=9600, timeout_char=5)
|
||||||
|
if not self._chip_id():
|
||||||
|
raise AttributeError("Cannot find a NS930x")
|
||||||
|
|
||||||
|
def _wreg(self, cmd, data=b'\x00'):
|
||||||
|
'''Write memory address'''
|
||||||
|
_buf = bytearray([cmd, 255 - cmd, len(data)]) + data
|
||||||
|
eec = 0
|
||||||
|
for i in range(len(_buf)):
|
||||||
|
eec += _buf[i]
|
||||||
|
_buf.append(eec & 0xFF)
|
||||||
|
#print("TX:", bytes(_buf), len(_buf))
|
||||||
|
self._uart.write(_buf)
|
||||||
|
|
||||||
|
def _rreg(self, cmd):
|
||||||
|
'''read memory address'''
|
||||||
|
time.sleep_ms(self._delay)
|
||||||
|
if self._uart.any():
|
||||||
|
_buf = self._uart.read()
|
||||||
|
#print("RX:", _buf, len(_buf))
|
||||||
|
if _buf[0] == 0xAA and _buf[1] == 0x55:
|
||||||
|
raise OSError("Play Error", _buf[4])
|
||||||
|
elif _buf[0] == cmd and _buf[0] == (255 - _buf[1]):
|
||||||
|
#eec = 0
|
||||||
|
#for i in range(len(_buf) - 1):
|
||||||
|
#eec += _buf[i]
|
||||||
|
#if (eec & 0xFF) == _buf[-1]:
|
||||||
|
return _buf[3:3 + _buf[2]]
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
'''复位指令有问题,暂停止播放态处理'''
|
||||||
|
for _ in range(10):
|
||||||
|
self._wreg(_PLAY_CTRL, b'\x03')
|
||||||
|
if self._rreg(_PLAY_CTRL):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _ascll(self, data):
|
||||||
|
'''获取ASCLL字节,剔除中文'''
|
||||||
|
_strs=''
|
||||||
|
for char in data:
|
||||||
|
_strs += char if ord(char) <= 0xFF else "*"
|
||||||
|
return _strs.encode()
|
||||||
|
|
||||||
|
def status(self, value=1):
|
||||||
|
"""0已停止? 1播放中? 2已暂停?"""
|
||||||
|
return self.control(0) == value
|
||||||
|
|
||||||
|
def control(self, value=0):
|
||||||
|
"""0查询(0停止 1播放 2暂停) 1播放 2暂停 3停止 4上一曲 5下一曲 6总曲数 7当前曲"""
|
||||||
|
self._wreg(_PLAY_CTRL, (value if value <= 5 else value + 7).to_bytes(1, 'little'))
|
||||||
|
_dat = self._rreg(_PLAY_CTRL)
|
||||||
|
if _dat:
|
||||||
|
return _dat[1] if value <= 3 else _dat[1] << 8 | _dat[2]
|
||||||
|
|
||||||
|
def play(self, value='m*.mp3'):
|
||||||
|
"""int播放曲目 str播放文件(*省略,GBK编码MPY不支持)"""
|
||||||
|
if isinstance(value, int):
|
||||||
|
self._wreg(_PLAY_CTRL, b'\x06' + value.to_bytes(2, 'big'))
|
||||||
|
elif isinstance(value, str):
|
||||||
|
self._wreg(_PLAY_CTRL, b'\x07' + self._ascll(value))
|
||||||
|
else:
|
||||||
|
raise ValueError("Input format error")
|
||||||
|
_dat = self._rreg(_PLAY_CTRL)
|
||||||
|
if _dat:
|
||||||
|
return _dat[1] << 8 | _dat[2]
|
||||||
|
|
||||||
|
def insert(self, value='m*.mp3'):
|
||||||
|
"""int播放曲目 str播放文件(*省略,GBK编码MPY不支持)"""
|
||||||
|
if isinstance(value, int):
|
||||||
|
self._wreg(_PLAY_INS, b'\x00\x02' + value.to_bytes(2, 'big'))
|
||||||
|
elif isinstance(value, str):
|
||||||
|
self._wreg(_PLAY_INS, b'\x01\x02' + self._ascll(value))
|
||||||
|
else:
|
||||||
|
raise ValueError("Input format error")
|
||||||
|
time.sleep_ms(self._delay)
|
||||||
|
|
||||||
|
def volume(self, value=None):
|
||||||
|
"""None返回音量 int设置音量(0~30)"""
|
||||||
|
if value is None:
|
||||||
|
self._wreg(_PLAY_VOL, b'\x00')
|
||||||
|
_dat = self._rreg(_PLAY_VOL)
|
||||||
|
if _dat:
|
||||||
|
return _dat[1]
|
||||||
|
else:
|
||||||
|
value = min(30, max(0, value))
|
||||||
|
self._wreg(_PLAY_VOL, b'\x01' + value.to_bytes(1, 'little'))
|
||||||
|
time.sleep_ms(self._delay)
|
||||||
|
|
||||||
|
def mode(self, value=None):
|
||||||
|
"""0全部循环 1单曲循环 2目录循环 3随机播放 4单曲停止 5顺序播放"""
|
||||||
|
if value is None:
|
||||||
|
self._wreg(_PLAY_MODE, b'\x00')
|
||||||
|
_dat = self._rreg(_PLAY_MODE)
|
||||||
|
if _dat:
|
||||||
|
return _dat[1]
|
||||||
|
else:
|
||||||
|
self._wreg(_PLAY_MODE, b'\x01' + value.to_bytes(1, 'little'))
|
||||||
|
time.sleep_ms(self._delay)
|
||||||
46
mixly/boards/default/micropython/build/lib/ntptime.py
Normal file
46
mixly/boards/default/micropython/build/lib/ntptime.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import utime,gc
|
||||||
|
from machine import RTC
|
||||||
|
import usocket as socket
|
||||||
|
import ustruct as struct
|
||||||
|
|
||||||
|
# NTP_DELTA (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
|
||||||
|
NTP_DELTA=3155673600
|
||||||
|
|
||||||
|
def time(host="pool.ntp.org", utc=28800, times=5):
|
||||||
|
for _ in range(times):
|
||||||
|
try:
|
||||||
|
NTP_QUERY = bytearray(48)
|
||||||
|
NTP_QUERY[0] = 0x1B
|
||||||
|
addr = socket.getaddrinfo(host, 123)[0][-1]
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
try:
|
||||||
|
s.settimeout(1)
|
||||||
|
res = s.sendto(NTP_QUERY, addr)
|
||||||
|
msg = s.recv(48)
|
||||||
|
finally:
|
||||||
|
del addr
|
||||||
|
s.close()
|
||||||
|
gc.collect()
|
||||||
|
val = struct.unpack("!I", msg[40:44])[0]
|
||||||
|
return utime.gmtime(val - NTP_DELTA + utc)
|
||||||
|
except Exception as e:
|
||||||
|
error = e
|
||||||
|
utime.sleep(0.1)
|
||||||
|
raise OSError('Error fetching network time', error)
|
||||||
|
|
||||||
|
# There's currently no timezone support in MicroPython, and the RTC is set in UTC time.
|
||||||
|
def settime(times):
|
||||||
|
if isinstance(times, str):
|
||||||
|
try:
|
||||||
|
val = eval(times)
|
||||||
|
if len(val) >= 6:
|
||||||
|
times=(val[0], val[1], val[2], val[3], val[4], val[5], 0)
|
||||||
|
else:
|
||||||
|
raise ValueError("Clock information format error")
|
||||||
|
except:
|
||||||
|
raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values")
|
||||||
|
if type(times) in (tuple, list):
|
||||||
|
if 6 <= len(times) <= 8:
|
||||||
|
RTC().datetime((times[0], times[1], times[2], 0, times[3], times[4], times[5], 0))
|
||||||
|
else:
|
||||||
|
raise ValueError("Settime needs a tuple of length 6~8")
|
||||||
18
mixly/boards/default/micropython/build/lib/object_picture.py
Normal file
18
mixly/boards/default/micropython/build/lib/object_picture.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#Take the picture bytes in object_picture.py
|
||||||
|
#--dahanzimin From the Mixly Team
|
||||||
|
|
||||||
|
Bomb=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x0e\x00\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x02\x00\x80\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x03\x00\x80\x18\x00\x00\x00\x00\x00\x7f\x00\x00\x01\x80\x800\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x80\x80`\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x80\x80\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00A\x01\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00 \x02\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00 \x04\x00\x00\x00\x00\x00\x00\x7f\x00\x00@\x11\x18\x00\x00\x00\x00\x00\x00\x7f\x00\x00p\x000\x00\x00\x00\x00\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x02\x80\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00#\xfe\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xe0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x008\x00\x00\x00\x00\x00\x7f\x00\x00\x00@\x00\x06\x00\x00\x00\x00\x00\x7f\x00\x00\x01\x00\x00\x03\xf8\x00\x00\x00\x00\x7f\x00\x00\x06\x00\x00\x01\xf8\x00\x00\x00\x00\x7f\x00\x000\x08\x00\x03\xfc\x00\x00\x00\x00\x7f\x00\x01\xe0\x10\x00\x07\xfc\x00\x00\x00\x00\x7f\x00\x03\x00\x00\x80\x03\xff\xfe\x00\x00\x00\x7f\x00\x00\x000\x00\x03\xff\xff\xc0\x00\x00\x7f\x00\x00\x00 @\x01\xff\xfcp\x00\x00\x7f\x00\x00\x00@@\x03\xff\xff\x18\x00\x00\x7f\x00\x00\x00@@\x03\xff\xff\xcc\x00\x00\x7f\x00\x00\x00\xc0@\x07\xff\xff\xe6\x00\x00\x7f\x00\x00\x00\x00`\x0f\xff\xff\xf3\x00\x00\x7f\x00\x00\x00\x00 \x1f\xff\xff\xf1\x80\x00\x7f\x00\x00\x00\x00 ?\xff\xff\xf9\x80\x00\x7f\x00\x00\x00\x000?\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x000\x7f\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x10\x7f\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xf0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\xff\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xe0\x00\x7f\x00\x00\x00\x00\x00\x7f\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x00?\xff\xff\xff\xc0\x00\x7f\x00\x00\x00\x00\x00?\xff\xff\xff\x80\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xff\xff\x80\x00\x7f\x00\x00\x00\x00\x00\x1f\xff\xff\xff\x00\x00\x7f\x00\x00\x00\x00\x00\x0f\xff\xff\xfe\x00\x00\x7f\x00\x00\x00\x00\x00\x07\xff\xff\xfc\x00\x00\x7f\x00\x00\x00\x00\x00\x03\xff\xff\xf8\x00\x00\x7f\x00\x00\x00\x00\x00\x00\xff\xff\xe0\x00\x00\x7f\x00\x00\x00\x00\x00\x00?\xff\xc0\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0f\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Boom=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00`\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00p\x00\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00X\x00\x0e\x00\x00\x00\x00\x7f\x00\x00\x00\x00x\x00\x16\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\x00:\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xae\x00g\x00\x00\x00\x00\x7f\x00\x00\x80\x01\x96\x00k\x00\x00\x00\x00\x7f\x00\x00\xc0\x01\xab\x81\xd5\x00\x00\x00\x00\x7f\x00\x00|\x03U\xff\xa5\x80\x00\x00\x00\x7f\x00\x00v\x06\xaa\xffU\x80\x00\x00\x00\x7f\x00\x00;\xfe\xa9~\xaa\xc3\x02\x00\x00\x7f\x00\x005\xfdU\x02U`\x0c\x00\x00\x7f\x00\x00\x1a\xaa\xaa\xaa\xaa\xb8x\x00\x04\x7f\x01\x00\x15T\xaa\xaa\xa9_\xf0\x00\x04\x7f\x00\x00\x19URT\xa6\xa2\xb0\x00\x00\x7f\x00\x00\x1a\xaa\xa9J\x95\x15`\x00\x00\x7f\x00\x00\x1a\xaa^\xb5n\xea`\x00\x00\x7f\x00\x009U_\x85\x1e\x15\xc0\x00\x00\x7f\x00\x00:\xaa\xae\xf8{\xea\xc0\x00\x00\x7f\x00\x00z\xaa\xad\x7f\xea\xea\xc0\x00\x00\x7f\x00\x01\xf5U.\xaf\xd5u\x80\x00\x00\x7f\x00\x01\xea\xaa\xadj\xaa\xeb\x80\x00\x00\x7f\x00\x0f\xea\xaa\xae\x95UU\x80\x00\x00\x7f\x07\xff\xaaUUe\xaa\xd5\xc0\x00\x00\x7f\x01\xfe\xaa\xa0\x0e\x9auj\xc0\x00\x00\x7f\x00:\xa9_\xf5\xe3\xea\xd5\xc0\x00\x00\x7f\x00\x0e*\xaf\xea\xdeuU`\x00\x00\x7f\x00\x03\x95V\xaa\x80j\xea\xb0\x00\x00\x7f\x00\x01\xea\xabU\x80j\xb5x\x00\x00\x7f\x00\x00\xea\xa9\xaa\x80*\xba\x9c\x00\x00\x7f\x00\x009U\xd5\x00:\xadW\x00\x00\x7f\x00\x00\x1dT\xd5\x00\x1a\xadW\xe0\x00\x7f\x00\x00\x1c\xa5\xd7\x00\x0e\xb7T\x1e\x00\x7f\x00\x00\x0fU\xdd\xc3\xfdOU\xf8\x00\x7f\x00\x00\x06\xaa\xa2\xe5V\xba\xa5\x80\x00\x7f\x00\x00\x03\xa9\xbe\xba\xaa\xb2W\x00\x00\x7f\x00\x00\x03U\xc1ZUj\xac\x00\x00\x7f\x10\x0c\x03\xab\xbfU\xaaj\xac\x00\x00\x7f\x00\x08\x03\xa5\xfb\xaaU\xaa\xa8\x00\x00\x7f\x00\x00\x03\xd5\xd4\xd5\xaar\x98\x00\x00\x7f\x00\x00\x03\x97UtU\xfdX\x1c\x00\x7f\x00\x00\x03\xa8\xaa{\x97\x92\xa8\x0c\x00\x7f\x00\x00\x03UUW\xf5UX\x00\x00\x7f\x00\x00\x07\xaa\xaa\xbd>\xaaL\x00\x00\x7f\x00\x00\x06>\x95YOS\xec\x00\x00\x7f\x00\x00\r\xff\xca\xba\xaa\xaf\xfa\x00\x00\x7f\x00\x00\x1f\x81\xf5Z\xab_\x0e\x00\x00\x7f\x00\x00\x1e\x00uIT\x9c\x03\x00\x00\x7f\x00\xc00\x00:\xaa\xaa\xb8\x00\x00\x00\x7f\x00\x00@\x00\x1a\xaa\xa2\x98\x00\x00\x04\x7f\x00\x00\x00\x00\tH\xfc\x98\x00\x00\x00\x7f\x00\x00\x00\x10\x0e\xab\xffp\x000\x00\x7f\x00\x00\x00\x00\x05O\x83P@\x10\x00\x7f\x00\x00\x00\x80\x06\xbe\x00\xd0 \x00\x00\x7f\x00\x04\x00\x00\x06\xb8\x00p\x00\x00\x00\x7f\x00\x10\x00\x00\x03p\x000\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xe0\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
DOOR_CLOSE=b'BM>\x02\x00\x00\x00\x00\x00\x00>\x00\x00\x00(\x00\x00\x00@\x00\x00\x00@\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x02\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x18\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x08\x00\x00\x01\x80\x00\x00\x18\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x11\x8c\x00\x00\x10\x08\x00\x009\x9e\x00\x00\x10\x08\x00\x00y\x9e\x00\x00\x10\x08\x00\x001\x8c\x00\x00\x10\x08\x00\x00\x11\x88\x00\x00\x10\x08\x00\x00\x11\x88\x00\x00\x10\x08\x00\x00\x11\x88\x00\x00\x10\x08\x00\x001\x8c\x00\x00\x10\x08\x00\x00y\x9e\x00\x00\x10\x08\x00\x009\x9e\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x18\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x00\x00\x00\x01\x80\x00\x00\x00\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x08\x00\x00\x01\x80\x00\x00\x10\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
DOOR_OPEN=b'BM>\x02\x00\x00\x00\x00\x00\x00>\x00\x00\x00(\x00\x00\x00@\x00\x00\x00@\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x02\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xe0\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
DOOR_OPENING=b'BM>\x02\x00\x00\x00\x00\x00\x00>\x00\x00\x00(\x00\x00\x00@\x00\x00\x00@\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x02\x00\x00\xc4\x0e\x00\x00\xc4\x0e\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x08\xff\xff\xff\xff\xff\xff\x10\x08\x07\xff\xff\xff\xff\xe0\x10\x08\x00?\xff\xff\xfc\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x003\xff\xff\xcc\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x00\x00\x03\xff\xff\xc0\x00\x00\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00\x03\xff\xff\xc0\x00\x10\x08\x00?\xff\xff\xfc\x00\x10\x08\x07\xff\xff\xff\xff\xe0\x10\x08\xff\xff\xff\xff\xff\xff\x10\x0f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xf0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
|
Fire=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x7f\x00\x00\x01\x00\x00\x0f\x00\x00\x00\x00\x00\x7f\x00\x00\x03\x00\x00\x0f\x80\x00\x00\x01\x80\x7f\x00\x00\x03\x80\x00\x0f\x80\x00\x00\x03\x80\x7f\x00\x00\x03\xc0\x00\x0f\xc0\x00\x00\x07\x80\x7f\x00\x00\x07\xe0\x00\x1f\xc0\x00\x00\x07\x80\x7f\x00\x00\x07\xf0\x00\x1f\xc0\x00\x00\x07\xc0\x7f\x00\x00\x0f\xf0\x00?\xc0\x00\x00\x03\xc0\x7f\x00\x00\x0f\xf0\x00\x7f\xc0\x00\x00\x03\xe0\x7f\x00\x00\x1f\xf0\x00\xff\xc0\x00\x00\x03\xe0\x7f\x00\x00\x1f\xf0\x01\xff\xc0\x00\x00\x03\xf0\x7f\x00\x00\x1f\xf0\x07\xff\xc0\x00\x00\x03\xf8\x7f\x00\x00\x1f\xe0\x07\xff\xc0\x00\x00\x03\xfc\x7f\x00\x00\x1f\xe0\x0f\xff\xc0\x00\x00\x03\xfc\x7f\x00\x00\x1f\xe0\x0f\xff\xc0|\x00\x07\xfc\x7f\x00\x00\x0f\xe0\x1f\xff\xc3\xfe\x00\x07\xfc\x7f\x00\x00\x07\xc0\x1f\xff\x87\xfc\x00\x0f\xfc\x7f\x00\x00\x01\xc1\x1f\xff\x8f\xf8\x00?\xfc\x7f\x00\x00\x00\xe3\xbf\xef\x9f\xf8\x00\xff\xfc\x7f\x00\x00\x007\xbf\xef\xdf\xf8\x01\xff\xf8\x7f\x00\x00\x00\x0f\xbf\xdf\xff\xf0\x03\xff\xf8\x7f\x00\x00\x00\x1f\xdf\xdf\xfe\xf0\x07\xff\xf0\x7f\x10\x00\x00\x1f\xff\xdf\xff\xf0\x07\xff\x80\x7f\x18\x00\x00\x1f\xff\xaf\xfd\xf0\x0f\x80\x00\x7f\x1c\x00\x04\x1f\xff\xbf\xfb\xe0\x08\x00\x00\x7f\x1e\x00\x1e\x1f\xff\xdf\xfb\xe0\x00\x00\x00\x7f\x1f\x00>\x1f\xff\xaf\xfb\xe0\x00\x00\x00\x7f\x1f\x80~\x1f\xff\xaf\xf7\xe0\x00\x00\x00\x7f\x1f\xc0\x7f\x1f\xff\xaf\xeb\xe0~\x00\x00\x7f\x1f\xf0\x7f\x1f\xff\xd7\xf7\xe1\xfe\x00\x00\x7f\x1f\xf0\xff\x9f\xff\xab\xeb\xe7\xfc\x00\x00\x7f\x0f\xf8\xff\x8f\xbf\xab\xd7\xef\xf8\x00\x00\x7f\x0f\xf8\xff\xcf\xcf\xd5\xd7\xff\xf8\x0e\x00\x7f\x0f\xf8\xff\xef\xf5\xaa\xab\xffp\x7f\x00\x7f\x07\xfc\xff\xff\xf5UW\xfd\xf1\xfe\x00\x7f\x07\xfc\x7f\xff\xf5J\xab\xfe\xe3\xfc\x00\x7f\x03\xfc\x7f\xff\xfa\xf5U\xfd\xe7\xf8\x00\x7f\x01\xfc\x7f\xff\xfe\x9dU\xf5\xef\xf0\x00\x7f\x00\xfc\x7f\xff\xfdF\xaa\xea\xef\xf0\x00\x7f\x00<?\xff\xfdCUu\xff\xe0\x00\x7f\x00\x01?\xbf\xf5CUU\xfd\xe0\x00\x7f\x00\x01?\xab\xd5AUU\xfd\xc0\x00\x7f\x00\x01\x9f\xd5U`\xaa\xaa\xfb\xc0\x00\x7f\x00\x03\xcf\xea\xaa\xa0\xaa\xaa\xf7\x80\x00\x7f\x00\x03\xcf\xd5]`UU\xeb\x80\x00\x7f\x00\x03\xe7\xea\xb5@j\xd5w\x80\x00\x7f\x00\x03\xfb\xea\xa6\xc0+\xaa\xef\x80\x00\x7f\x00\x03\xff\xea\xa3@jUO\x80\x00\x7f\x00\x03\xff\xf5B\xc0J\xaa\xbf\x80\x00\x7f\x00\x03\xff\xfa\xa2\x804\xd5O\x80\x00\x7f\x00\x01\xff\xfda\x80,\xaa\xbf\x80\x00\x7f\x00\x01\xfe\xfa\xa1\x00(\xd5_\x80\x00\x7f\x00\x01\xfe\xad \x00p\xaa\xbf\x80\x00\x7f\x00\x00\xff\xaa\xe0\x00@\xd7_\x80\x00\x7f\x00\x00\x7fU \x00\x00\xaa\xbf\x00\x00\x7f\x00\x00\x7f\xd5\xf0\x00\x01\xb2\xbf\x00\x00\x7f\x00\x00?\xd5\xb8\x00\x01b\xbf\x00\x00\x7f\x00\x00\x0f\xf5@\x00\x03\x82\xbe\x00\x00\x7f\x00\x00\x03\xfa\xa0\x00\x00\x05~\x00\x00\x7f\x00\x00\x00\xfa\xb0\x00\x00\x06\xfc\x00\x00\x7f\x00\x00\x00}P\x00\x00\x05x\x00\x00\x7f'
|
||||||
|
Flowers=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x80\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x1f\xc0\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00?\xc3\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00?\xcf\xc0\x7f\x00\x00\x00\x00\x00\x00\x00\x0f\x7f\xdf\xc0\x7f\x00\x00\x00\x00\x00\x00\x00\x1f\xff\xdf\xe0\x7f\x00\x00\x00\x00\x00\x00\x00?\x7f\xff\xe0\x7f\x00\x00\x00\x00\x00\x00\x00\x7f\xff\xdf\xc0\x7f\x00\x00\x0c\x00\x00\x00\x00\x7f\x7f\xff\x90\x7f\x00\x00\x1c\x00\x00\x00\x00\xff\x7f\xfe|\x7f\x00\x06\x1c\x00\x00\x00\x00\xff\x7f\xbc\xfe\x7f\x00\x07\x1c\x00\x00\x00\x00\xffw9\xfe\x7f\x01\xc7\x1c\x18\x00\x00\x00\xffR{\xfe\x7f\x01\xe3\x9c\x1c\x00\x00\x00\x7f\x0co\xfe\x7f\x00\xf3\x9c8\x00\x00\x00}\x7f\x0f\xfc\x7f\x10y\x8cp\x00\x00\x00~\xff\x9f\xf0\x7f<<\xccq\x80\x00\x0f\xbc\xff\xc7\x80\x7f?\x1c\xcc\xe7\xc0\x00\x1f\xcc\xff\xc0\x00\x7f\x1f\xceH\xcf\x80\x00?\xe0\xff\xdf\x00\x7f\x07\xe6I\x9e\x00\x00?\xfc\xff\xaf\xf8\x7f\x00\xf9\t<\x00\x00?\xfb\x7f7\xfe\x7f<\x1c"p\x00\x00?\xff\x00\x1f\xfe\x7f?\xc0\xd1\x87\xe0\x00?\xfe\x01\x9f\xff\x7f?\xfd\xb8?\x80\x00\x1f\xfc)\xcf\xff\x7f\x00\x01\xf9\xfc\x00\x00\x07\xf1g\xef\xff\x7f\x00\x01\xec\x00\x00\x00\x00\x03\xdf\xf7\xfe\x7f\x07\xf0\xf8\x00\x00\x00\x00\x0f\xd7\xf3\xfc\x7f\x1f\xc20\xff\xe0\x00\x00\x7f\xef\xf9\xf8\x7f?\x07\x0b?\xe0\x00\x03\xff\xef\xf8@\x7f<\ri\x80\xc0\x00\x03\xff\xef\xf8\x00\x7f\x00\x1fm\xc0\x00\x00\x03\xff\xcf\xf8\x00\x7f\x00?l\xe0\x00\x00\x03\xff\x8f\xf8\x00\x7f\x00~\xeep\x00\x00\x01\xff\x0f\xf8\x00\x7f\x01\xee\xeex\x00\x00\x00\xfc\x0f\xf0\x00\x7f\x03\xde\xef<\x00\x00\x00\x00\x07\xf0\x00\x7f\x03\x9c\xe7\x1c\x06\x00\x00\x00\x07\xe4\x00\x7f\x00\x1d\xf7\x00\xce\x00\x00\x00\x03\xcc\x00\x7f\x00=\xd7\x04f \x00\x00\x00\x04\x00\x7f\x00\x19\xd6\x07fp\x00\x00\x00\x06\x00\x7f\x00\x00\x80\x03$`\x00\x00\x00\x02\x00\x7f\x00\x00 9\x94\xcc\x00\x0f\x00\x03\x00\x7f\x00\x00 <\xd4\x9c\x00?\x80\x01\x00\x7f\x00\x00 \x0fEp\x1e\x7f\x80\x01\x00\x7f\x03\x00 0\x81@?\xbb\xb0\x01\x80\x7f\x03`@\x7f\x9c>\x1d\x7f\xb8\x00\x80\x7f\x00\xe0@\x00<\xf0\x1e\xef\xf8\x00\x80\x7f\x00x@\x07=\x00\x1f\xd7\xdc\x00\xc0\x7f\x000\xc0<H\xfe\x1fw\xfc\x00@\x7f\x00\x1c\x80x\xd3\x0e\x1d\xef\xf8\x00@\x7f\x00\x1c\x80\x01\xd5\x80\x1f\xab\xb8\x00`\x7f\x00\x0c\x80\x03\xd6\xc0=\xef\xe0\x00 \x7f\x00\x05\x80\x07\xf6`\x7f}\xe0\x00 \x7f\x00\x01\x00\r\xbb0\x7f\xbf\xe0\x000\x7f\x00\x01\x01\xc1\xbb\x00\x87\xff\xc0\x000\x7f\x00\x01\x03\x81\xb3\x00\x03\xbf\x80\x00\x10\x7f\x00\x01\x0f\xc0\x00\x00\x01\xdb\x80\x00\x10\x7f\x00\x03\x0f\xe0\x08\x00\x00<\x00\x00\x18\x7f\x00\x02\x1f\x00\x08\x00\x00\x0c\x00\x00\x18\x7f\x00\x02?\x00\x10\x00\x00\x0c\x00\x00\x18\x7f\x00\x02>\x00\x10\x00\x00\x04\x00\x00\x08\x7f\x00\x02p\x00\x10\x00\x00\x04\x00\x00\x08\x7f'
|
||||||
|
Forest=b"P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00p\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x01\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00~\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00z\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x01\xfe\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x07\xff\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x0f\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\xff\xc0\x00\x00\x00\x00\x06\x00\x00\x7f\x00\x00\xfe\x00\x00\x00\x08\x00\x06\x00\x00\x7f\x00\x03\xff\x00\x00\x00\x0c\x89\x9d\x83\x00\x7f\x00\x0f\xff\x80\x00\x00\x07\x8d\x8b\x0e\x00\x7f\x00\x1f\xff\xc0\x00\x19a\xb0\x04\xc9\x80\x7f\x00?\xff\xf0\x00\x1b\x1aV\x1a\xb3\x90\x7f\x00\x7f\xff\xf0\x00\x06\xef\x84A\x14\x10\x7f\x00\xff\xff\xf8\x00\x1a`\xbb\x14\x8b\x10\x7f\x00\x01\xff\x04\x00P\x1b\x89d\xf4\x06\x7f\x00\x03\xff\x80\x00f\xe2\x91 d\x9e\x7f\x00\x0f\xff\xc0\x00\x018\xeb\xc7\xe0`\x7f\x00\x1f\xff\xf0\x00\xc4\xc1\xa8\xcc\xe1\xa8\x7f\x00?\xff\xf8\x04\xd6}\xb1\x15aL\x7f\x00\x7f\xff\xfe\x0e!/A\xe5`\xb0\x7f\x00\xff\xff\xff\x80\xd4'\x06 o0\x7f\x01\xfd\xff\xc1\xc35[\x06\xb0{\x00\x7f\x03\xe1\xff\xe0\x02\xb1\x13\xc1\xa0\xe10\x7f\x03\x87\xff\xf0\x01\xb0\x01\xe0\x03\xe6\xcc\x7f\x04\x1f\xff\xfc\x000\x03\xf8?\xc4Y\x7f\x00?\xff\xff\x80\x98\x07\xfc\xff\x81\x8b\xff\x00\x7f\xff\xff\xe3d\x1f\xfd\xfc\x01h\x7f\x01\xff\xff\xff\xc0\xe7\xfe?\xc0\x88L\x7f\x07\xff\xff\xfc\x0e\xa1\xf0\x0f\x84\x98\x0c\x7f\x1f\xf7\xff\xf0\x06X\xc0\x0f\x86\n\x00\x7f\x1f\xe7\xff\xf0\x03I\x80\x07\x81\x17\x00\x7f\x00\x07\xff\xf8\x03/@\x07\x81 0\x7f\x00\x0f\xff\xfc\x00\xb4@\x0f\x80\xcd\xe0\x7f\x00?\xff\xfe\x03\xe4\x80\x0f\x86\xc0(\x7f\x00\xff\xff\xff\x02c\x00?\x82\x87\xdc\x7f\x03\xff\xff\xff\x80\xc5\x07\xff\xfd\x8d@\x7f\x07\xe7\xff\xc7\xf0\x16?\xff\xff\xf9\xe0\x7f\x1c\x0f\xff\xe0x\x12\x7f\xfe\x0f\xf8\x80\x7f\x00?\xff\xf0\x00\x11\xff\xf8\x02\x84@\x7f\x00\x7f\xff\xfc\x00\x01\xff\xe0\x02D\xc0\x7f\x00\xff\xff\xfe\x00\x03\xff\x00\x02\xca\x80\x7f\x01\xff?\xff\x80\x07\xfe\x00\x00\x19p\x7f\x03\xfc;\xff\xe0\x07\xfc\x00\x00\x13 \x7f\x0f\xf08\xff\xf8\x0f\xf8\x00\x00\x02\xc0\x7f\x7f\x008\x0f\xff\x1f\xf8\x00\x00\x02\xc0\x7f\x00\x008\x00\x00\x1f\xf8\x00\x00\x00\x00\x7f\x00\x008\x00\x00?\xf8\x00\x00\x00\x00\x7f\x00\x008\x00\x0e\x7f\xf9\x00\x00\x00\x00\x7f\x00\x008\x00\xff\xff\xff\x80\x00\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f"
|
||||||
|
Lightning=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xf0\x18\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xff\x90\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xff\xa0\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xff@\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xfe\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xfe\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\xfd\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfb\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfa\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xe8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xff\x90\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff\xb0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xff`\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xfe\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xfc\x80\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xf9\x00\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xfa\x00\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xf4\x00\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xec\x00\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xd8\x00\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xf0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xfe\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xff\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xfe\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xfc\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xf8\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xf0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xe0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xc0\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\x80\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00~\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xfc\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xf8\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xf0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xe0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x03\xc0\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x03\x80\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Light_off=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xd5p\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07J\xb8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1c\xb5\\\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1bEV\x00\x00\x00\x00\x7f\x00\x00\x00\x004\n\xab\x00\x00\x00\x00\x7f\x00\x00\x00\x00tUU\x00\x00\x00\x00\x7f\x00\x00\x00\x00h\xaa\xab\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xd1UU\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xd2\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xa2\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xa5UU@\x00\x00\x00\x7f\x00\x00\x00\x01\xd2\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xa5UU@\x00\x00\x00\x7f\x00\x00\x00\x01\xaa\xaa\xaa\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UU\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UT\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UW\x80\x00\x00\x00\x7f\x00\x00\x00\x00j\xaa\xa9\x80\x00\x00\x00\x7f\x00\x00\x00\x00eUW\x00\x00\x00\x00\x7f\x00\x00\x00\x00=US\x00\x00\x00\x00\x7f\x00\x00\x00\x002\xaa\xae\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1dUV\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1a\xaa\xac\x00\x00\x00\x00\x7f\x00\x00\x00\x00\rU\\\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0e\xaa\xa8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x05UX\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\xb8\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\x90\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06Up\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xaa\xb0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xaa\xa0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x83\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Light_on=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xc0\x00\x0c\x00\x02\x00\x00\x00\x7f\x00\x00\x00`\x00\x00\x00\x06\x00\x00\x00\x7f\x00\x00\x000\x00\x00\x00\x0c\x00\x00\x00\x7f\x00\x00\x00\x18\x00\x00\x00\x18\x00\x00\x00\x7f\x00\x00\x00\x0c\x00\x1e\x000\x00\x00\x00\x7f\x00\x00\x00\x06\x00\xff\xc0`\x00\x00\x00\x7f\x00\x00\x00\x02\x03\x80p\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x00\x18\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x00\x0c\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x100\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x000\xe0\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x00a\x80\x01\x00\x00\x00\x00\x7f\x00\x00\x00\x00B\x00\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xc6\x00\x00\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x84\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x8c\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\x8c\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x01\x88\x00\x00@\x00\x00\x00\x7f\x00\x00\x00\x01\x80\x00\x00@\xfe\x00\x00\x7f\x00\x00\x7f\xc1\x80\x00\x00A\xfe\x00\x00\x7f\x00\x00\x00\x00\x80\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x00\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x00\x80\x00\x00\x00\x7f\x00\x00\x00\x00@\x00\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x00`\x00\x01\x00\x00\x00\x00\x7f\x00\x00\x00\x00 \x00\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x000\x00\x02\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x10\x00\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x00\x04\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x08\x00\x0c\x0c\x00\x00\x00\x7f\x00\x00\x00\x18\x0c\x00\x08\x06\x00\x00\x00\x7f\x00\x00\x000\x04\x00\x08\x03\x00\x00\x00\x7f\x00\x00\x00`\x04\x00\x18\x01\x80\x00\x00\x7f\x00\x00\x00\xc0\x06\x00\x10\x00\xc0\x00\x00\x7f\x00\x00\x01\x80\x06\x00\x10\x00`\x00\x00\x7f\x00\x00\x01\x00\x02\x000\x00 \x00\x00\x7f\x00\x00\x00\x00\x02\x00 \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x00 \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x00 \x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x7f\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x83\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00>\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Night=b'P4\n89 64\n\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfd\x7f\xff\xff\xff\xfe\x00\x7f\xff\xdf\xff\xff\xf7\xdf\xff\xff\xff\xe0\x00?\xff\xff\xff\xff\xef\xff\xff\xff\xff\x80\x01\xff\xff\xff\xff\x7f\xff\xef\xff\xff\xfe\x00\x07\xff\xff\xff\xff?\xdf\xff\xff\xff\xfc\x00\x0f\xff\xff\xff\xfe\x1f\xff\xff\xff\xff\xf8\x00?\xff\x87\xff\xfe?\xdf\xff\xff\xff\xf0\x00\x7f\xff\xcf\xff\xfe?\xff\xef\xff\xff\xe0\x00\xff\xff\xcf\xff\xff\xff\xef\xdf\xff\xff\xc0\x01\xff\xff\xff\xff\xff\xff\xfb\xbf\xff\xff\x80\x01\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x80\x03\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xfd\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xf9\xff\xff\xff\xff\xff\xfc\x00\x0f\xff\xff\xff\xe0?\xff\xcf\xff\xff\xfc\x00\x1f\xff\xff\xff\xe0?\xff\x87\xff\xff\xfc\x00\x1f\xff\xff\xff\xf0\x7f\xff\x8f\xff\xff\xfc\x00\x1f\xff\xff\xff\xf0\x7f\xff\xcf\xff\xff\xfc\x00\x1f\xff\xff\xff\xf2\x7f\xbf\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xbf\xff\xff\xff\xf8\x00?\xfd\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x1f\xff\xf5\xfb\xff\xff\xff\xf9\xff\xff\xfc\x00\x1f\xff\xee\xfb\xff\xff\xff\xff\xff\xff\xfc\x00\x1f\xff\xee\xff\xff\xff\xff\xff\xff\xff\xfc\x00\x1f\xff\xf5\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x1f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x00\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00\x07\xff\xff\xff\xff\xff\xff\xfd\xff\xff\xff\x80\x03\xff\xef\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x03\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x01\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xe0\x00\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xf0\x00\x7f\xff\xfc?\xff\xff\xff\xff\xff\xff\xf8\x00?\xff\xe0\x07\xff\xff\xff\xff\xff\xff\xfe\x00\x1f\xff\xc0\x03\xff\xff\xff\xff\xff\xff\xff\x00\x0f\xff\xe0\x07\xff\xff\xff\xbf\xff\xff\xff\xc0\x03\xff\xf0\x0f\xff\xf7\xff\x0f\xff\xff\xff\xf8\x00\x7f\xf8\x0f\xff\xff\xff\x1f\xff\xff\xff\xff\x83\xff\xf0\x0f\xff\xff\xff\x1f\xff\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf3\xcf\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x0f\xff\xff\xfd\x7f\xff\xf1\xff\xff\xff\xff\xf8\x1f\xff\xff\xfb\xbf\xff\xf9\xff\xff\xff\xff\xfc?\xff\xff\xfb\xbf?\xff\xff\xff\xff\xff\xfc\x1f\xff\xff\xfd\x7f?\xff\xff\xff\xff\xff\xfd\x9f\xff\xff\xff\xff?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
|
||||||
|
Pirate=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00?\xff\xfe\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xff\xfb\x80\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xff\xf8\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\xff\xff\xfe`\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xb8\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xff\xff\xd8\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xec\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xff\xff\xee\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf6\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xf6\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xff\xff\xff\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xf9\xff\xe7\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xc0\x7f\x80\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\xc0?\x00\xff\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00\x7f\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00?\x80\x1e\x00\x7f\x00\x00\x00\x7f\x00\x00\x00?\xc0?\x00\xff\x00\x00\x00\x7f\x00\x00\x00?\xe0s\x81\xfe\x00\x00\x00\x7f\x00\x00\x00\x1f\xf1\xf1\xe3\xfe\x00\x00\x00\x7f\x00\x00\x00\x1f\xff\xe1\xff\xfc\x00\x00\x00\x7f\x00\x00\x00\x0f\xff\xe0\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xc0\xff\xe0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xc0\x7f\xc0\x00\x00\x00\x7f\x00\x00\x00\x01\xff\xc0\x7f\xc0\x00\x00\x00\x7f\x00\x00\xf0\x00\xff\xff\xff\xc0\x00\x00\x00\x7f\x00\x00\xf0\x00\xff\xff\xff\x80\x00\xf0\x00\x7f\x00\x00\xf8\x00\x07\xff\xf8\x00\x01\xf0\x00\x7f\x00\x00\xf8\x00\x07\xff\xf8\x00\x03\xf0\x00\x7f\x00\x01\xff\x00\x07\xf7\xf8\x00\x07\xe0\x00\x7f\x00\x03\xff\xe0\x06s\x98\x00?\xf0\x00\x7f\x00\x03\xff\xfe\x00s\x98\x01\xff\xf8\x00\x7f\x00\x07\xff\xff\xc0!\x00\x1f\xff\xfc\x00\x7f\x00\x03\xf1\xff\xf8\x00\x01\xff\xf1\xfc\x00\x7f\x00\x03\xf0?\xff\x00\x0f\xff\x81\xf8\x00\x7f\x00\x01\xe0\x07\xff\xf0\x07\xfc\x01\xf8\x00\x7f\x00\x00\x00\x00\xff\xfe\x00`\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xfc\x00\x00\x00\x00\x7f\x00\x00p\x01\xc0\x7f\xff\xc0\x00\x00\x00\x7f\x00\x00\xfc\x1f\xf8\x0f\xff\xf8\x03\xe0\x00\x7f\x00\x01\xfd\xff\xfe\x01\xff\xff\x87\xf0\x00\x7f\x00\x03\xff\xff\xfe\x00?\xff\xff\xf0\x00\x7f\x00\x03\xff\xff\xf0\x00\x07\xff\xff\xf0\x00\x7f\x00\x01\xff\xff\x80\x00\x00\xff\xff\xf0\x00\x7f\x00\x00\xff\xfc\x00\x00\x00\x1f\xff\xf0\x00\x7f\x00\x00?\xc0\x00\x00\x00\x03\xff\xe0\x00\x7f\x00\x00?\x00\x00\x00\x00\x00\x7f\x80\x00\x7f\x00\x00?\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00?\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1f\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Snow=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\r\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x0c\xc0\x00\x02\x00\x7f\x00\x00\x00\x00\x00\x00\x13 \x00\x04\x00\x7f\x00\x00\x00\x00\x00\x00?\xf0\x00"`\x7f\x00\x10\x00\x00\x00\x00\x13`\x00\x1a\xc0\x7f\x00|\x00\x00\x00\x00\x04\x80\x00\x16\x00\x7f\x020\x80\x00\x01\x00\x0e\xc0\x00\x0f\x00\x7f\x02\xde\xc0\x00\x03\x00\x02\x80\x00\x1a\xc0\x7f\x0e\xba\xe0\x003\x18\x00\x00\x00$@\x7f\x07\xbb\xc0\x00;p\x00\x00\x00\x02\x00\x7f\t\xff0\x00\x1f\xe0\x00\x00\x00\x040\x7f\x03m\x80\x0c\x07\xc0@\x00\x00\x00x\x7f\x02\xee\xc0\x0c#\x10\xc0\x00\x00\x00p\x7f\r\xff\xb0\x0c{|\xc0\x00\x00\x00\x00\x7f\x07\xff\xc0l\xff\xfc\xcc\x00\x02\x00\x00\x7f\x0e\xba\xe0\xfc\xcf\xcc\xfc\x00\x1b`\x00\x7f\x02\xfe\x80<\xd3\xac\xf0\x00\x1f\xc0\x00\x7f\x02\x10\x80\x1f\xdbo\xf0\x00\x0f\xc0\x00\x7f\x00|\x00\x7f\xcf\xef\xfc\x08\x07\x00\x80\x7f\x00T\x00\xf1\xff\xff\x1e\x08\x03\x00\xc0\x7f\x00\x10\x00\x07\xff\xff\x80\x0c\x13 \x80\x7f\x00\x00\x00\x0f?\xf3\xe0<{y\xb0\x7f\x00\x00\x00\x1c\xfc\xfd\xe0<\x7f\xd9\xe0\x7f\x00\x00\x00\x0c\xfc~ ?g\x93\xe0\x7f\x00\x00\x00\x1e<\xf0\xe0\xff\xa77\xf8\x7f\x00\x80\x00\x07\xff\xfb\xc0\xe1\xe3>8\x7f\x00\x00\x00\xe3\xff\xff\x1e\x00\xfb|\x00\x7f\x02\xe0\x00\xff\xcf\xef\xbc\x03\xff\xff\x00\x7f\x01\x80\x00?\xdbo\xf0\x06\x0f\x83\x00\x7f\x00@\x00>\xd3,\xf8\x07\x9f\xc3\x00\x7f\x00\x80\x00|\xcf\xcc\xfc\x03\xff\xff\x00\x7f\x00\x00@\xec\xff\xfc\xce\x80\xf3<\x00\x7f\x00\x00\xc0\x0c\xfb|\xc0\xf9\xe3>x\x7f\x00\x00\xe0\x0c#\x10\xc0\x7f\'7\xf8\x7f\x00\x03\xf0\x0c\x07\xc0@>o\x91\xe0\x7f\x00\x03\xf0\x00\x1f\xe0\x00<{\xd9\xf0\x7f\x00\n\xd0\x00;\xf0\x00,{q\xa0\x7f\x00\x1e\xde\x0038\x00\x0c\x03\x00\xc0\x7f\x0e\x9c\xce|\x03\x00\x00\x08\x03\x00\xc0\x7f\x07\x87\xf8|\x01\x00\x00\x08\x07\x00\x80\x7f\x05\x8f\xdc|\x00\x00\x00\x00\x0f\xc0\x00\x7f\x03\xfe\xde\xf8\x00\x00\x00\x00\x1f\xe0\x00\x7f\x009\xf3\x10\x00\x00\x00\x00\x1b`\x00\x7f\x01\x9f\xff \x00\x00\x00\x00\x00\x00\x00\x7f\x00\xa7\xf9`\x00\x00\x00\x00\x10\x00\x00\x7f\x01\xff\xff\xe0\x00\x00\x00\x00\\\x00\x00\x7f\x01\xff\xff\xf0\x00\x00\x00\x008\x00\x00\x7f\x00\xa7\xfd`\x00\x00\x00\x02T\x80\x00\x7f\x01\x9d\xff \x00\x00\x00\x0e\xfe\xe0\x00\x7f\x033\xf3\x98\x00\x00\x00\x07\x9b\xc0\x00\x7f\x05\xde\xde\xe0\x00\x00\x00\r\xffp\x00\x7f\x07\x87\xd8|\x00\x02\x00\x03\x7f\x80\x00\x7f\x0f\xaf\xfd|\x00\x00\x00\x02\xee\xc0\x00\x7f\x02\x8c\xce0\x00\x12 \x03\xff\x80\x00\x7f\x00\x1e\xce\x00\x00\t\x80\r\xffp\x00\x7f\x00\x02\xc8\x00\x00\x07\x00\x07\xbb\xc0\x00\x7f\x00\x01\xf0\x00\x00\x0b\x80\x0e\xfe\xe0\x00\x7f\x00\x03\xd0\x00\x00\x19`\x02\xd4\x80\x00\x7f\x00\x01\xe0\x00\x00\x00\x00\x008\x80\x00\x7f\x00\x00\xe0\x00\x00\x03\x00\x00\\\x00\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x10\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Target=b"P4\n89 64\n\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xfb\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x03\xf8\x08\x1f\xe0\x00\x00\x00\x7f\x00\x00\x00\x07\xe1\x00\x01\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x10\x84 \xfc\x00\x00\x00\x7f\x00\x00\x00<\x00B\x10\x1e\x00\x00\x00\x7f\x00\x00\x00x\x84!\x08O\x00\x00\x00\x7f\x00\x00\x00\xe0B\x10\x84\x03\x80\x00\x00\x7f\x00\x00\x01\xe4!\x08B\x13\xc0\x00\x00\x7f\x00\x00\x03\x82\x10\x84!\x01\xe0\x00\x00\x7f\x00\x00\x07\xa1\x08B\x10\x84\xf0\x00\x00\x7f\x00\x00\x0e\x10\x84 \x08@x\x00\x00\x7f\x00\x00\x0e\x08B\x0c\x84!8\x00\x00\x7f\x00\x00\x1c\x84 \x08B\x10\x1c\x00\x00\x7f\x00\x008B\x10\xff\x01\x08N\x00\x00\x7f\x00\x008!\x03\xff\xe0\x84\x0e\x00\x00\x7f\x00\x00r\x10\x8f\x89\xf8B\x17\x00\x00\x7f\x00\x00q\x08\x1eU<!\x07\x00\x00\x7f\x00\x00p\x849UN\x10\x87\x00\x00\x7f\x00\x00\xe0BuUW\x08C\x80\x00\x7f\x00\x00\xe4 \xea\xaa\xab\x84#\x80\x00\x7f\x00\x00\xc2\x10\xca\xaa\xa9\x82\x03\x80\x00\x7f\x00\x01\xc1\t\xd5UU\xc1\t\xc0\x00\x7f\x00\x01\xc0\x81\x95R\xaa\xc0\x85\xc0\x00\x7f\x00\x01\xc8C\xaa\xadT\xe8A\xc0\x00\x7f\x00\x01\xc4#\xaa\xd2\xaa\xe0!\xc0\x00\x7f\x00\x01\xc2\x13U*\xaab\x11\xc0\x00\x7f\x00\x01\xc1\x03*\xc9Ui\x08\xc0\x00\x7f\x00\x07\xe0\x8f\xd5>\xaa\xf8\x83\xf0\x00\x7f\x00\x01\xc8\x0b\x15MUp@\xe0\x00\x7f\x00\x01\x84'j\xaa\x95d!\xc0\x00\x7f\x00\x01\xc2\x03\x95Ujb\x01\xc0\x00\x7f\x00\x01\xc1\x0b\xaa\xaa\x92\xe1\t\xc0\x00\x7f\x00\x01\xc0\x81\xaa\xb6n\xc0\x85\xc0\x00\x7f\x00\x01\xc8C\xd5I\x91\xc8A\xc0\x00\x7f\x00\x00\xe4 \xd56m\x84!\x80\x00\x7f\x00\x00\xe2\x10\xea\xc9\x93\x82\x13\x80\x00\x7f\x00\x00\xe1\x08u6w!\x03\x80\x00\x7f\x00\x00`\x849\xc9\x8e\x10\x87\x00\x00\x7f\x00\x00pB\x1e6<\x08G\x00\x00\x7f\x00\x00t!\x0f\x89\xf8\x84'\x00\x00\x7f\x00\x008\x10\x83\xff\xe0B\x0e\x00\x00\x7f\x00\x009\x08B\xff\x84!\x0e\x00\x00\x7f\x00\x00\x1c\x84 ,\x02\x10\x9c\x00\x00\x7f\x00\x00\x0eB\x10\x98!\x088\x00\x00\x7f\x00\x00\x0e\x01\x08B\x10\x848\x00\x00\x7f\x00\x00\x07\x90\x84!\x08Bp\x00\x00\x7f\x00\x00\x03\xc0B\x10\x84 \xe0\x00\x00\x7f\x00\x00\x01\xe4!\x08B\x13\xc0\x00\x00\x7f\x00\x00\x00\xe0\x10\x84!\x03\x80\x00\x00\x7f\x00\x00\x00y\x08B\x10\x8f\x00\x00\x00\x7f\x00\x00\x00<\x84!\x08\x1e\x00\x00\x00\x7f\x00\x00\x00\x1f\x02\x10\x84|\x00\x00\x00\x7f\x00\x00\x00\x07\xc1\x00A\xf0\x00\x00\x00\x7f\x00\x00\x00\x03\xf8\x08\x0f\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xeb\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x18\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f"
|
||||||
14
mixly/boards/default/micropython/build/lib/oled128x64.py
Normal file
14
mixly/boards/default/micropython/build/lib/oled128x64.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
"""
|
||||||
|
OLED Displays
|
||||||
|
|
||||||
|
Micropython library for the SSD1106_I2C OLED Displays
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from ssd1106 import SSD1106_I2C
|
||||||
|
|
||||||
|
class OLED(SSD1106_I2C):
|
||||||
|
"""A single matrix."""
|
||||||
|
def __init__(self, i2c, width=128, height=64, address=0x3c, font_address=0x700000, types=0):
|
||||||
|
super().__init__(width, height, i2c, address, l_offset=0 if types == 0 else -2)
|
||||||
|
self.font(font_address)
|
||||||
111
mixly/boards/default/micropython/build/lib/ollama.py
Normal file
111
mixly/boards/default/micropython/build/lib/ollama.py
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
import urequests
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class Ollama():
|
||||||
|
def __init__(self, url="", model="", max_history_num=0):
|
||||||
|
self._heads = {
|
||||||
|
"Accept": "text/event-stream",
|
||||||
|
# "Cache-Control": "no-cache",
|
||||||
|
# "Connection": "keep-alive",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
self._url = url
|
||||||
|
self._chat_url = "{}/api/chat".format(self._url)
|
||||||
|
self._max_retries = 1
|
||||||
|
self._max_history_num = max_history_num
|
||||||
|
self._timeout = 10000
|
||||||
|
self._messages = []
|
||||||
|
self._data = {
|
||||||
|
"stream": True,
|
||||||
|
"model": model,
|
||||||
|
"messages": self._messages
|
||||||
|
}
|
||||||
|
|
||||||
|
def set_timeout(self, timeout):
|
||||||
|
self._timeout = timeout
|
||||||
|
|
||||||
|
def set_max_retries(self, max_retries):
|
||||||
|
self._max_retries = max_retries
|
||||||
|
|
||||||
|
def set_custom_url(self, url):
|
||||||
|
self._url = url
|
||||||
|
self._chat_url = "{}/api/chat".format(self._url)
|
||||||
|
|
||||||
|
def select_model(self, model_name):
|
||||||
|
self._data["model"] = model_name
|
||||||
|
|
||||||
|
def set_max_history_num(self, num):
|
||||||
|
self._max_history_num = num
|
||||||
|
|
||||||
|
def empty_history(self):
|
||||||
|
self._messages = []
|
||||||
|
|
||||||
|
def add_history(self, role, content):
|
||||||
|
self._messages.append({
|
||||||
|
"role": role,
|
||||||
|
"content": content
|
||||||
|
})
|
||||||
|
|
||||||
|
def clear_user_history(self):
|
||||||
|
if len(self._messages) < 2:
|
||||||
|
return
|
||||||
|
for i in range(1, len(self._messages)):
|
||||||
|
del self._messages[i]
|
||||||
|
|
||||||
|
def _post(self, content_callback=None):
|
||||||
|
response = None
|
||||||
|
data = json.dumps(self._data).encode('utf-8')
|
||||||
|
for i in range(0, self._max_retries):
|
||||||
|
response = urequests.post(
|
||||||
|
self._chat_url, headers=self._heads, data=data)
|
||||||
|
if response.status_code == 200:
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
output = response.text
|
||||||
|
if content_callback:
|
||||||
|
content_callback(output)
|
||||||
|
return output
|
||||||
|
|
||||||
|
if not content_callback:
|
||||||
|
output = json.loads(response.text)["message"]["content"]
|
||||||
|
response.close()
|
||||||
|
return output
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
line = response.raw.readline()
|
||||||
|
if line:
|
||||||
|
line = line.decode('utf-8').strip()
|
||||||
|
data = json.loads(line)
|
||||||
|
if data["done"]:
|
||||||
|
break
|
||||||
|
content = data["message"]["content"]
|
||||||
|
content_callback(content)
|
||||||
|
output += content
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
finally:
|
||||||
|
response.close()
|
||||||
|
return output
|
||||||
|
|
||||||
|
def chat(self, message, content_callback=None):
|
||||||
|
self.add_history("user", message)
|
||||||
|
self._data["stream"] = bool(content_callback)
|
||||||
|
self._heads["Accept"] = "text/event-stream" if content_callback else "application/json"
|
||||||
|
content = self._post(content_callback)
|
||||||
|
if self._max_history_num:
|
||||||
|
self.add_history("assistant", content)
|
||||||
|
messages_len = len(self._messages)
|
||||||
|
history_num = 2 * self._max_history_num
|
||||||
|
while history_num < messages_len:
|
||||||
|
del self._messages[0]
|
||||||
|
else:
|
||||||
|
self.clear_user_history()
|
||||||
|
|
||||||
|
return content
|
||||||
34
mixly/boards/default/micropython/build/lib/onenet.py
Normal file
34
mixly/boards/default/micropython/build/lib/onenet.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import ujson as json
|
||||||
|
from umqtt import MQTTClient,str_len
|
||||||
|
|
||||||
|
def get_data_dict(d):
|
||||||
|
result = {"datastreams":[]}
|
||||||
|
for x in d:
|
||||||
|
result["datastreams"].append({"id":x,"datapoints":[{"value":d[x]}]})
|
||||||
|
return result
|
||||||
|
|
||||||
|
def pubData(value, state):
|
||||||
|
value = get_data_dict(value)
|
||||||
|
jdata = json.dumps(value)
|
||||||
|
jlen = str_len(jdata)
|
||||||
|
bdata = bytearray(jlen+3)
|
||||||
|
bdata[0] = 1 #publish data in type of json
|
||||||
|
bdata[1] = int(jlen / 256) # data lenght
|
||||||
|
bdata[2] = jlen % 256 # data lenght
|
||||||
|
bdata[3:jlen+4] = jdata.encode('ascii') # json data
|
||||||
|
if state:
|
||||||
|
print(value)
|
||||||
|
#print(bdata)
|
||||||
|
return bdata
|
||||||
|
|
||||||
|
def init_MQTT_client(sid, address, cid, api, topic, callback):
|
||||||
|
client = MQTT_Client(sid, address, 6002, cid, api)
|
||||||
|
client.set_callback(callback)
|
||||||
|
client.connect()
|
||||||
|
client.subscribe(bytes(topic, 'utf-8'))
|
||||||
|
return client
|
||||||
|
|
||||||
|
#inherit
|
||||||
|
class MQTT_Client(MQTTClient):
|
||||||
|
def publish(self, msg, is_print=False, topic='$dp', retain=False, qos=0):
|
||||||
|
super().publish('$dp',pubData(msg, is_print))
|
||||||
53
mixly/boards/default/micropython/build/lib/openai.py
Normal file
53
mixly/boards/default/micropython/build/lib/openai.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import urequests
|
||||||
|
import time
|
||||||
|
import json
|
||||||
|
import ollama
|
||||||
|
|
||||||
|
|
||||||
|
class OpenAI(ollama.Ollama):
|
||||||
|
def __init__(self, url="", api_key="", model="", max_history_num=0, max_tokens=1024):
|
||||||
|
super().__init__(url, model, max_history_num)
|
||||||
|
self._heads["Authorization"] = "Bearer {}".format(api_key)
|
||||||
|
self._data["max_tokens"] = max_tokens
|
||||||
|
self._chat_url = "{}/chat/completions".format(self._url)
|
||||||
|
|
||||||
|
def _post(self, content_callback=None):
|
||||||
|
response = None
|
||||||
|
data = json.dumps(self._data).encode('utf-8')
|
||||||
|
for i in range(0, self._max_retries):
|
||||||
|
response = urequests.post(
|
||||||
|
self._chat_url, headers=self._heads, data=data)
|
||||||
|
if response.status_code == 200:
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
output = ""
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
output = response.text
|
||||||
|
if content_callback:
|
||||||
|
content_callback(output)
|
||||||
|
return output
|
||||||
|
|
||||||
|
if not content_callback:
|
||||||
|
output = json.loads(response.text)[
|
||||||
|
"choices"][0]["message"]["content"]
|
||||||
|
response.close()
|
||||||
|
return output
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
line = response.raw.readline()
|
||||||
|
if line[:5] != b"data:":
|
||||||
|
continue
|
||||||
|
if line[-7:-1] == b"[DONE]":
|
||||||
|
break
|
||||||
|
line = line[6:-1]
|
||||||
|
line = line.decode('utf-8').strip()
|
||||||
|
data = json.loads(line)
|
||||||
|
content = data["choices"][0]["delta"]["content"]
|
||||||
|
content_callback(content)
|
||||||
|
output += content
|
||||||
|
finally:
|
||||||
|
response.close()
|
||||||
|
return output
|
||||||
126
mixly/boards/default/micropython/build/lib/pe_g1.py
Normal file
126
mixly/boards/default/micropython/build/lib/pe_g1.py
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
"""
|
||||||
|
Micropython library for
|
||||||
|
PE_G1 (Motor*5*2 & Servo*4)
|
||||||
|
MDB (Motor*4*2 & Servo*6)
|
||||||
|
===============================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from time import sleep_ms
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_PE_GX_ADDRESS = const(0x25)
|
||||||
|
_PE_GX_ID = const(0x00)
|
||||||
|
_PE_GX_VBAT = const(0x01)
|
||||||
|
_PE_GX_MOTOR = const(0x03)
|
||||||
|
|
||||||
|
class PE_G1:
|
||||||
|
def __init__(self, i2c_bus, addr=_PE_GX_ADDRESS):
|
||||||
|
self._i2c = i2c_bus
|
||||||
|
self._addr = addr
|
||||||
|
sleep_ms(500)
|
||||||
|
if self._rreg(_PE_GX_ID) == 0x25:
|
||||||
|
self._PE_GX_SERVO = 0x0D
|
||||||
|
self._type = 1 #PE_G1
|
||||||
|
elif self._rreg(_PE_GX_ID) == 0x26:
|
||||||
|
self._PE_GX_SERVO = 0x0B
|
||||||
|
self._type = 2 #MDB
|
||||||
|
else:
|
||||||
|
raise AttributeError("Cannot find a PE_G1 or MDB")
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
try:
|
||||||
|
self._i2c.writeto_mem(self._addr, reg, val.to_bytes(1, 'little'))
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def _rreg(self, reg, nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
try:
|
||||||
|
self._i2c.writeto(self._addr, reg.to_bytes(1, 'little'))
|
||||||
|
return self._i2c.readfrom(self._addr, nbytes)[0] if nbytes <= 1 else self._i2c.readfrom(self._addr, nbytes)
|
||||||
|
except:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Reset all registers to default state"""
|
||||||
|
if self._type == 1:
|
||||||
|
self._i2c.writeto_mem(self._addr, _PE_GX_MOTOR, bytes(18))
|
||||||
|
if self._type == 2:
|
||||||
|
self._i2c.writeto_mem(self._addr, _PE_GX_MOTOR, bytes(20))
|
||||||
|
|
||||||
|
def read_bat(self, ratio=1):
|
||||||
|
'''Read battery power'''
|
||||||
|
vbat = self._rreg(_PE_GX_VBAT) << 2 | self._rreg(_PE_GX_VBAT+1) >> 6
|
||||||
|
if self._type == 1:
|
||||||
|
return round(vbat * ratio * 0.00968, 2)
|
||||||
|
if self._type == 2:
|
||||||
|
return round(vbat * ratio * 0.01398, 2)
|
||||||
|
|
||||||
|
def m_pwm(self, index, duty=None):
|
||||||
|
"""Motor PWM duty cycle data register"""
|
||||||
|
if self._type == 1: # Motor*5*2
|
||||||
|
if not 0 <= index <= 9:
|
||||||
|
raise ValueError("Motor port must be a number in the range: 0~4")
|
||||||
|
if self._type == 2: # Motor*4*2
|
||||||
|
if not 0 <= index <= 7:
|
||||||
|
raise ValueError("Motor port must be a number in the range: 0~3")
|
||||||
|
if duty is None:
|
||||||
|
return self._rreg(_PE_GX_MOTOR + index)
|
||||||
|
else:
|
||||||
|
if not 0 <= duty <= 255:
|
||||||
|
raise ValueError("Duty must be a number in the range: 0~255")
|
||||||
|
self._wreg(_PE_GX_MOTOR + index, duty)
|
||||||
|
|
||||||
|
def s_pwm(self, index, duty=None):
|
||||||
|
"""Servo PWM duty cycle data register"""
|
||||||
|
if self._type == 1: # Servo*4
|
||||||
|
if not 0 <= index <= 3:
|
||||||
|
raise ValueError("Servo port must be a number in the range: 0~3")
|
||||||
|
if self._type == 2: # Servo*6
|
||||||
|
if not 0 <= index <= 5:
|
||||||
|
raise ValueError("Servo port must be a number in the range: 0~5")
|
||||||
|
if duty is None:
|
||||||
|
return self._rreg(self._PE_GX_SERVO + index * 2) << 8 | self._rreg(self._PE_GX_SERVO + index * 2 + 1)
|
||||||
|
else:
|
||||||
|
if not 0 <= duty <= 4095:
|
||||||
|
raise ValueError("Duty must be a number in the range: 0~4095")
|
||||||
|
self._wreg(self._PE_GX_SERVO + index * 2,duty >> 8)
|
||||||
|
self._wreg(self._PE_GX_SERVO + index * 2 + 1,duty & 0xff)
|
||||||
|
|
||||||
|
def motor(self, index, action="NC", speed=0):
|
||||||
|
if not 0 <= speed <= 100:
|
||||||
|
raise ValueError("Speed parameters must be a number in the range: 0~100")
|
||||||
|
if action == "N":
|
||||||
|
self.m_pwm(index * 2, 0)
|
||||||
|
self.m_pwm(index * 2 + 1, 0)
|
||||||
|
elif action == "P":
|
||||||
|
self.m_pwm(index * 2, 255)
|
||||||
|
self.m_pwm(index * 2 + 1, 255)
|
||||||
|
elif action == "CW":
|
||||||
|
self.m_pwm(index * 2, 0)
|
||||||
|
self.m_pwm(index * 2 + 1, speed * 255 // 100)
|
||||||
|
elif action == "CCW":
|
||||||
|
self.m_pwm(index * 2, speed * 255 // 100)
|
||||||
|
self.m_pwm(index * 2 + 1, 0)
|
||||||
|
elif action == "NC":
|
||||||
|
return round(self.m_pwm(index * 2) * 100 / 255), round(self.m_pwm(index * 2 + 1) * 100 / 255)
|
||||||
|
else:
|
||||||
|
raise ValueError('Invalid input, valid are "N","P","CW","CCW"')
|
||||||
|
|
||||||
|
def servo180(self, index, angle=None):
|
||||||
|
if angle is None:
|
||||||
|
return round((self.s_pwm(index) - 102.375) * 180 / 409.5)
|
||||||
|
else:
|
||||||
|
if not 0 <= angle <= 180:
|
||||||
|
raise ValueError("Servo(180) angle must be a number in the range: 0~180")
|
||||||
|
self.s_pwm(index,round(102.375 + 409.5 / 180 * angle))
|
||||||
|
|
||||||
|
def servo360(self, index, speed=None):
|
||||||
|
if speed is None:
|
||||||
|
return round((self.s_pwm(index) - 102.375) * 200 / 409.5 - 100)
|
||||||
|
else:
|
||||||
|
if not -100 <= speed <= 100:
|
||||||
|
raise ValueError("Servo(360) speed must be a number in the range: -100~100")
|
||||||
|
self.s_pwm(index,round(102.375 + 409.5 / 200 * (speed + 100)))
|
||||||
41
mixly/boards/default/micropython/build/lib/pm2_5.py
Normal file
41
mixly/boards/default/micropython/build/lib/pm2_5.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
"""
|
||||||
|
PM2.5
|
||||||
|
|
||||||
|
Micropython library for the PM2.5(UART)
|
||||||
|
=======================================================
|
||||||
|
#Preliminary composition 20220908
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
|
||||||
|
class PM2_5:
|
||||||
|
def __init__(self, uart):
|
||||||
|
self._uart=uart
|
||||||
|
self._uart.init(baudrate=9600)
|
||||||
|
self._pm=(0,0)
|
||||||
|
self._flag=False
|
||||||
|
if not self._chip_id():
|
||||||
|
raise AttributeError("Cannot find a PM2.5")
|
||||||
|
|
||||||
|
def _rreg(self):
|
||||||
|
'''Read data'''
|
||||||
|
if self._uart.any():
|
||||||
|
eec=0
|
||||||
|
buf=self._uart.read(7)
|
||||||
|
for i in buf[1:5]:
|
||||||
|
eec+=i
|
||||||
|
if (eec & 0xff) == buf[5] and buf[0] == 0xAA and buf[6] == 0xFF:
|
||||||
|
self._pm=(buf[1] << 8 | buf[2] , buf[3] << 8 | buf[4] )
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
for _ in range(5):
|
||||||
|
if self._rreg():
|
||||||
|
return True
|
||||||
|
time.sleep(1)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def concentration(self):
|
||||||
|
self._rreg()
|
||||||
|
return self._pm
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
#Take the picture bytes in progres_picture.py
|
||||||
|
#--dahanzimin From the Mixly Team
|
||||||
|
|
||||||
|
Bar_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1ca\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x16\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x002w@\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Bar_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\x1ea\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x05\x90\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x9c\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x86w@\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x02\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x07\xbe\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xea\xaa\xaa\xaa\xc0\x00\x00\x00\x00\x00\x00\xff\xd5RIU\x80\x00\x00\x00\x00\x00\x00\xff\xea\xad\xb6\xab\x00\x00\x00\x00\x00\x00\x00\xff\xd5RIV\x00\x00\x00\x00\x00\x00\x00\xff\xea\xad\xb6\xac\x00\x00\x00\x00\x00\x00\x00\xff\xd5RIX\x00\x00\x00\x00\x00\x00\x00\xff\xd5m\xb6\xb0\x00\x00\x00\x00\x00\x00\x00\xff\xea\x92I`\x00\x00\x00\x00\x00\x00\x00\xff\xd5m\xb6\xc0\x00\x00\x00\x00\x00\x00\x00\xff\xca\x92I\x80\x00\x00\x00\x00\x00\x00\x00\xff\xfbm\xb7\x00\x00\x00\x00\x00\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Bar_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x07\x9ca\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x04\x16\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x072\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xb2w@\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xb2\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\x9e\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xea\xaa\xaa\xaa\xaa\xaa\xac\x00\x00\x00\x00\xff\xd5$\x92I$\x95X\x00\x00\x00\x00\xff\xea\xdbm\xb6\xdbj\xb0\x00\x00\x00\x00\xff\xd5$\x92I$\x95`\x00\x00\x00\x00\xff\xd6\xdbm\xb6\xdbj\xc0\x00\x00\x00\x00\xff\xe9$\x92I$\x95\x80\x00\x00\x00\x00\xff\xd6\xdbm\xb6\xdbk\x00\x00\x00\x00\x00\xff\xc9$\x92I$\x96\x00\x00\x00\x00\x00\xff\xf6\xdbm\xb6\xdbl\x00\x00\x00\x00\x00\xff\xc9$\x92I$\x98\x00\x00\x00\x00\x00\xff\xf6\xdbm\xb6\xdbp\x00\x00\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Bar_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0f\x9ea\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x90\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x9c\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x06w@\x00\x00\x00\x7f\x00\x00\x00\x00\x02\x02\x0b@\x00\x00\x00\x7f\x00\x00\x00\x00\x06>\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd5UUUUUUUU\x80\x00\xff\xd5RI$\x92I$\x92\xab\x00\x00\xff\xea\xad\xb6\xdbm\xb6\xdbmV\x00\x00\xff\xd5RI$\x92I$\x92\xac\x00\x00\xff\xea\xad\xb6\xdbm\xb6\xdbmX\x00\x00\xff\xd5RI$\x92I$\x92\xb0\x00\x00\xff\xd5m\xb6\xdbm\xb6\xdbm`\x00\x00\xff\xea\x92I$\x92I$\x92\xc0\x00\x00\xff\xd5m\xb6\xdbm\xb6\xdbm\x80\x00\x00\xff\xca\x92I$\x92I$\x93\x00\x00\x00\xff\xfbm\xb6\xdbm\xb6\xdbn\x00\x00\x01\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Bar_4=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x87\x1ca\x00\x00\x00\x00\x7f\x00\x00\x00\x01\xc5\x96\xd2\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\xb2\xd5\x80\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\xb2w@\x00\x00\x00\x7f\x00\x00\x00\x00\xcc\xb2\x0b@\x00\x00\x00\x7f\x00\x00\x00\x01\xe7\x9e\x19\xc0\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xd5UUUUUUUUUU\xff\xd5$\x92I$\x92I$\x92I*\xff\xea\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xd5$\x92I$\x92I$\x92I+\xff\xd6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xe9$\x92I$\x92I$\x92I+\xff\xd6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xc9$\x92I$\x92I$\x92I+\xff\xf6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xd5\xff\xc9$\x92I$\x92I$\x92I%\xff\xf6\xdbm\xb6\xdbm\xb6\xdbm\xb6\xdb\xff\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Dial_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x03`\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x00\x00\x00\x00\xb8\x00\x7f\x00\x0e\x80\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x7f\x008\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x002\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x000\x00\x00\x00\x00\x00\x00\x00\x17\x00\x7f\x00t\x00\x00\x00\x00\x00\x00\x00\x03\x00\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x03\x80\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x01\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x0c\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x00w@\x00\x00\x02\xc0\x7f\x00\x80\x00?\xff\xf9\x00\x00\x00\x00@\x7f\x07\xe1\x7f\xff\xff\xfd\xa0\x00\x00\x0b\xf8\x7f\x0f\xf0\xff\xff\xff\xfc\x80\x00\x00\x03\xf8\x7f\x00\x00\x00?\xff\xfd\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xfb\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Dial_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x03`\x00\x7f\x00\x03\x88\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x02\x80\x00\x00\x00\x00\x00\xb8\x00\x7f\x00\x0e\x83\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x1c\x01\x80\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\xc0\x00\x00\x00\x00\x00\x0e\x00\x7f\x008\x00`\x00\x00\x00\x00\x00\x06\x00\x7f\x002\x010\x00\x00\x00\x00\x00\x06\x00\x7f\x000\x00\x1c\x80\x00\x00\x00\x00\x17\x00\x7f\x00t\x00N@\x00\x00\x00\x00\x03\x00\x7f\x00`\x00\x0f \x00\x00\x00\x00\x03\x80\x7f\x00`\x00\x17\x80\x00\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x03\xc0\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x05\xf0\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\xf8\x00\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00|\x00\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00>@\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x1f\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x0f\xd0\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x0f\xe0\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x07\xf1\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x13\xfc\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x01\xff@\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x04\xf9\x00\x00\x00\x00@\x7f\x07\xe4\x00\x00\x02}\xa0\x00\x00\x0b\xf8\x7f\x0f\xf0\x00\x00\x00\xfc\x80\x00\x00\x03\xf8\x7f\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Dial_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x02\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x08\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00$\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x0c\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x0c\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x0c\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x0c\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x0c\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x0c\x00\x00\x03`\x00\x7f\x00\x03\x80\x00\x00\x0c\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x0c\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x0c\x00\x00\x00\xb8\x00\x7f\x00\x0e\x80\x00\x00\x0c\x00\x00\x00\x1c\x00\x7f\x00\x1c\x00\x00\x00N\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\x00\x00\x1e\x80\x00\x00\x0e\x00\x7f\x008\x00\x00\x00\x1e\x00\x00\x00\x06\x00\x7f\x002\x00\x00\x00\x1e\x00\x00\x00\x06\x00\x7f\x000\x00\x00\x00\x1e\x00\x00\x00\x17\x00\x7f\x00t\x00\x00\x00\x1e\x00\x00\x00\x03\x00\x7f\x00`\x00\x00\x00\x1e\x00\x00\x00\x03\x80\x7f\x00`\x00\x00\x00\x1e\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x1e\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x1e\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x1e\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x1e\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00?\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x00?\x00\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x01\x7f\x00\x00\x00\x00@\x7f\x07\xe4\x00\x00\x00\x7f\xa0\x00\x00\x0b\xf8\x7f\x0f\xf0\x00\x00\x00\xde\x80\x00\x00\x03\xf8\x7f\x00\x00\x00\x00\x00A\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Dial_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x0b`\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x00\x00\x00\x10\xb8\x00\x7f\x00\x0e\x80\x00\x00\x00\x00\x00 \x1c\x00\x7f\x00\x1c\x00\x00\x00\x00\x00\x02H\x1c\x00\x7f\x00\x19\x00\x00\x00\x00\x00\x00\xd0\x0e\x00\x7f\x008\x00\x00\x00\x00\x00\x03\x80\x06\x00\x7f\x002\x00\x00\x00\x00\x00\x07\x00\x06\x00\x7f\x000\x00\x00\x00\x00\x00N\x00\x17\x00\x7f\x00t\x00\x00\x00\x00\x00\x1c\x00\x03\x00\x7f\x00`\x00\x00\x00\x00\x008\x00\x03\x80\x7f\x00`\x00\x00\x00\x00\x00\xf0\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x00\t\xe4\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x03\xc0\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x07\xd0\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x00\x1f\x80\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00\x00?\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00\x00~\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x04\xfc\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x01\xf8\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x03\xf2\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x0f\xe0\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x00?\xc0\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x01o\xd0\x00\x00\x00@\x7f\x07\xe4\x00\x00\x00O\x80\x00\x00\x0b\xf8\x7f\x0f\xf0\x00\x00\x00\xcf\x80\x00\x00\x03\xf8\x7f\x00\x00\x00\x00\x00a\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00#\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Dial_4=b"P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x0c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00m\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xff\xcc\xff\xc0\x00\x00\x00\x7f\x00\x00\x00\x07\xf8\x0c\x07\xf0\x00\x00\x00\x7f\x00\x00\x00\x1f\x80\x01\x00\xfc\x00\x00\x00\x7f\x00\x00\x00<\x00\x00\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\xf0\x00\x00\x00\x07\xc0\x00\x00\x7f\x00\x00\x01\xe0\x00\x00\x00\x11\xe0\x00\x00\x7f\x00\x00\x07\x80\x00\x00\x00\x00p\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x018\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x039\x00\x00\x00\x00\x00\x0f \x00\x7f\x00\x01\xb0\x00\x00\x00\x00\x00\x07`\x00\x7f\x00\x00\xc0\x00\x00\x00\x00\x00\x02\xc0\x00\x7f\x00\x00`\x00\x00\x00\x00\x00\x01\x80\x00\x7f\x00\x01\xa0\x00\x00\x00\x00\x00\x03`\x00\x7f\x00\x03\x80\x00\x00\x00\x00\x00\x00p\x00\x7f\x00\x07 \x00\x00\x00\x00\x00\x000\x00\x7f\x00\x06\x00\x00\x00\x00\x00\x00\x00\xb8\x00\x7f\x00\x0e\x80\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x7f\x00\x19\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x7f\x008\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x002\x00\x00\x00\x00\x00\x00\x00\x06\x00\x7f\x000\x00\x00\x00\x00\x00\x00\x00\x17\x00\x7f\x00t\x00\x00\x00\x00\x00\x00\x00\x03\x00\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x03\x80\x7f\x00`\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xe0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\x80\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x01\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x00\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x00\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x01\x00\x00\x00\x00\xc0\x7f\x01\x80\x00\x00\x00\x1c\x00\x00\x00\x00\xc0\x7f\x01\x90\x00\x00\x007\x00\x00\x00\x02\xc0\x7f\x00\x80\x00\x00\x01o\xff\xf0\x00\x00@\x7f\x07\xe4\x00\x00\x00O\xff\xff\xff\xab\xf8\x7f\x0f\xf0\x00\x00\x00\xcf\xff\xff\xff\x83\xf8\x7f\x00\x00\x00\x00\x00O\xff\xf8\x00\x00\x00\x7f\x00\x00\x00\x00\x00'\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x1e\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f"
|
||||||
|
Dots_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00 \x01\x02\x00\x10 \x01\x00\x00\x7f\x00\x00\x10\x02\x01\x00 \x10\x02\x00\x00\x7f\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xfc\x00\x0f\xc0\x00\x80\x00\x7f\x00\x00@\x00\xfc\x00\x0f\xc0\x00\x00\x00\x7f\x00\x00@\x00\x84\x00\x08@\x00\x80\x00\x7f\x00\x00\x00\x02\x00\x00 \x00\x02\x00\x00\x7f\x00\x00(\x01\x02\x80\x10(\x01\x00\x00\x7f\x00\x00\x00\x08\x00\x00\x80\x00\x08\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Dots_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x03\xf0\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x07\xf8\x00@\x80\x04\x08\x00\x00\x7f\x00\x00/\xfd\x02\x00\x10 \x01\x00\x00\x7f\x00\x00\x1f\xfe\x01\x00 \x10\x02\x00\x00\x7f\x00\x00\x1f\xfe\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00_\xfe\xfc\x00\x0f\xc0\x00\x80\x00\x7f\x00\x00\x1f\xfe\xfc\x00\x0f\xc0\x00\x00\x00\x7f\x00\x00_\xfe\x84\x00\x08@\x00\x80\x00\x7f\x00\x00\x1f\xfe\x00\x00 \x00\x02\x00\x00\x7f\x00\x00/\xfd\x02\x80\x10(\x01\x00\x00\x7f\x00\x00\x07\xf8\x00\x00\x80\x00\x08\x00\x00\x7f\x00\x00\x03\xf0\x00!\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Dots_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x02\x10\x00?\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00\x7f\x80\x04\x08\x00\x00\x7f\x00\x00 \x01\x02\xff\xd0 \x01\x00\x00\x7f\x00\x00\x10\x02\x01\xff\xe0\x10\x02\x00\x00\x7f\x00\x00@\x00\x01\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xfd\xff\xef\xc0\x00\x80\x00\x7f\x00\x00@\x00\xfd\xff\xef\xc0\x00\x00\x00\x7f\x00\x00@\x00\x85\xff\xe8@\x00\x80\x00\x7f\x00\x00\x00\x02\x01\xff\xe0\x00\x02\x00\x00\x7f\x00\x00(\x01\x02\xff\xd0(\x01\x00\x00\x7f\x00\x00\x00\x08\x00\x7f\x80\x00\x08\x00\x00\x7f\x00\x00\x02\x10\x00?\x00\x02\x10\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Dots_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\xa0\x00\n\x00\x00\xa0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x03\xf0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x07\xf8\x00\x00\x7f\x00\x00 \x01\x02\x00\x10/\xfd\x00\x00\x7f\x00\x00\x10\x02\x01\x00 \x1f\xfe\x00\x00\x7f\x00\x00@\x00\x00\x00\x00\x1f\xfe\x00\x00\x7f\x00\x00\x00\x00\xfc\x00\x0f\xdf\xfe\x80\x00\x7f\x00\x00@\x00\xfc\x00\x0f\xdf\xfe\x00\x00\x7f\x00\x00@\x00\x84\x00\x08_\xfe\x80\x00\x7f\x00\x00\x00\x02\x00\x00 \x1f\xfe\x00\x00\x7f\x00\x00(\x01\x02\x80\x10/\xfd\x00\x00\x7f\x00\x00\x00\x08\x00\x00\x80\x07\xf8\x00\x00\x7f\x00\x00\x02\x10\x00!\x00\x03\xf0\x00\x00\x7f\x00\x00\x04\x08\x00@\x80\x04\x08\x00\x00\x7f\x00\x00\x01@\x00\x14\x00\x01@\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Hourglass_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf0\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06UUUP\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00\x02UUU0\x00\x00\x00\x7f\x00\x00\x00\x03UUU \x00\x00\x00\x7f\x00\x00\x00\x01\xaa\xaa\xaa`\x00\x00\x00\x7f\x00\x00\x00\x00\xd5UT\xc0\x00\x00\x00\x7f\x00\x00\x00\x00j\xaa\xa9\x80\x00\x00\x00\x7f\x00\x00\x00\x005US\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1a\xaa\xa6\x00\x00\x00\x00\x7f\x00\x00\x00\x00\rUL\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\x98\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xaa`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xd4\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00i\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x003\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x006\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc1\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x88\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x00`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x080\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0c\x00\x18\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x08\x0c\x00\x00\x00\x00\x7f\x00\x00\x00\x000\x00\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00`\x08\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x01\x80\x08\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\x00\x00\x00`\x00\x00\x00\x7f\x00\x00\x00\x03\x00\x08\x000\x00\x00\x00\x7f\x00\x00\x00\x02\x00\x00\x000\x00\x00\x00\x7f\x00\x00\x00\x06\x00\n\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00*\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00U@\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x01U@\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x02\xaa\xa8\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x05UT\x10\x00\x00\x00\x7f\x00\x00\x00\x06]\xb6\xdb\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf8\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Hourglass_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf0\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x000\x00\x00\x00\x7f\x00\x00\x00\x02\x00\x00\x000\x00\x00\x00\x7f\x00\x00\x00\x03\x00\x00\x00 \x00\x00\x00\x7f\x00\x00\x00\x01\x80\x00\x00`\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x00\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x00`*\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x002\xaa\x83\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x1a\xaa\xa6\x00\x00\x00\x00\x7f\x00\x00\x00\x00\rUL\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\xaa\x98\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03U0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\xaa`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xd4\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00i\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x003\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x006\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00c\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc9\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x01\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\x08`\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x06\x000\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x0c\x08\x18\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x18\x00\x0c\x00\x00\x00\x00\x7f\x00\x00\x00\x000\x08\x06\x00\x00\x00\x00\x7f\x00\x00\x00\x00`\x00\x03\x00\x00\x00\x00\x7f\x00\x00\x00\x00\xc0\x08\x01\x80\x00\x00\x00\x7f\x00\x00\x00\x01\x80\x14\x00\xc0\x00\x00\x00\x7f\x00\x00\x00\x03\x00U\x00`\x00\x00\x00\x7f\x00\x00\x00\x03\x00\xaa\x800\x00\x00\x00\x7f\x00\x00\x00\x02\x05U@0\x00\x00\x00\x7f\x00\x00\x00\x06\x15UT\x10\x00\x00\x00\x7f\x00\x00\x00\x06UUU\x10\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06UUUP\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\x90\x00\x00\x00\x7f\x00\x00\x00\x06\xdbm\xb6\xd0\x00\x00\x00\x7f\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x7f\x00\x00\x00\x07\xff\xff\xff\xf0\x00\x00\x00\x7f\x00\x00\x00\x06\xaa\xaa\xaa\xb0\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00?\xff\xf8\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xfc\x00\x02\x00\x00\x00\x7f\x00\x00\x00?\xff\xff\xff\xfe\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Hourglass_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00p\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\x90\x00\x00\x00\x00\x00\x05\x80\x00\x7f\x00\x00\x9f\xfc\x00\x00\x00\x1f\xfc\x80\x00\x7f\x00\x00\x9f\xff\x80\x00\x00\x7f\xfc\x80\x00\x7f\x00\x00\x94\x01\xc0\x00\x00\xc0\x14\x80\x00\x7f\x00\x00\x9c\x00`\x00\x01\x80\x1c\x80\x00\x7f\x00\x00\x94\x000\x00\x03\x00\x14\x80\x00\x7f\x00\x00\x9c\x00\x18\x00\x06\x00\x1c\x80\x00\x7f\x00\x00\x94\x00\x0c\x00\x0c\x00\x14\x80\x00\x7f\x00\x00\x9c\x00\x06\x00\x18\x00\x1c\x80\x00\x7f\x00\x00\x94\x00\x03\x000\x00\x14\x80\x00\x7f\x00\x00\x9c\x00\x01\x80`\x00\x1c\x80\x00\x7f\x00\x00\x94\x00\x00\xc0\xc0\x00\x14\x80\x00\x7f\x00\x00\x9d\x00\x00a\x80\x00\x1c\x80\x00\x7f\x00\x00\x95@\x003\x00\x00\x14\x80\x00\x7f\x00\x00\x9dP\x00\x1e\x00\x00\x1c\x80\x00\x7f\x00\x00\x94\xb4\x00\x0c\x00\x00\x14\x80\x00\x7f\x00\x00\xbdJ@\x00\x00\x00\x1d\x80\x00\x7f\x00\x00\xf4\xb5\xa9\x00\x00\x00\x15\x80\x00\x7f\x00\x00\xfdJU\\\x00\x00\x1f\x80\x00\x7f\x00\x00\xf4\xb5\xaa\xb6\x00\x00\x17\x80\x00\x7f\x00\x00\xfdJUc\x00\x00\x1f\x80\x00\x7f\x00\x00\xf4\xb5\xaa\xc1\x85\x00\x17\x80\x00\x7f\x00\x00\xfdJU\x80\xca\xc0\x1f\x80\x00\x7f\x00\x00\xf4\xb5\xab\x00e*W\x80\x00\x7f\x00\x00\xfdJV\x002\xda\x9f\x80\x00\x7f\x00\x00\xf4\xb5\xac\x00\x19%W\x80\x00\x7f\x00\x00\xfdJX\x00\x0c\xda\x9f\x80\x00\x7f\x00\x00\xf5u\xb0\x00\x06%W\x80\x00\x7f\x00\x00\xfd\n`\x00\x039_\x80\x00\x7f\x00\x00\xf5\xf8\xc0\x00\x01\x87W\x80\x00\x7f\x00\x00\xfc\x03\x80\x00\x00\xf0_\x80\x00\x7f\x00\x00\xff\xff\x00\x00\x00?\xff\x80\x00\x7f\x00\x00\xf8\x00\x00\x00\x00\x00\x0f\x80\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\xf0\x00\x00\x00\x00\x00\x07\x80\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Timer_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80/\x00|p\x00\x00\x7f\x00\x00\x01\xbe\x00!\x00>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!\x00\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00#\x00\x07\x80\x00\x00\x7f\x00\x00\x01\xe0\x00.\x00\x03\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(\x00\x01\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(\x00\x00\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/\x00\x00p\x00\x00\x7f\x00\x00\x07\x00\x00\x00\x00\x00x\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x008\x00\x00\x7f\x00\x00\x0e\x00\x00\x00\x00\x00<\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0f\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x00y\xe0\x00\x00\x00\x03\xc7\x00\x00\x7f\x00\x00q \x00\x00\x00\x00G\x00\x00\x7f\x00\x00q \x00\x00\x00\x00G\x00\x00\x7f\x00\x00q\xe0\x00\x00\x00\x01\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00G\x00\x00\x7f\x00\x00x \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x009\xe0\x00\x00\x00\x03\xc7\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0f\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x0e\x00\x00\x00\x00\x00<\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x008\x00\x00\x7f\x00\x00\x07\x80\x00\x1e\x00\x00x\x00\x00\x7f\x00\x00\x03\x80\x00\x10\x00\x00\xf0\x00\x00\x7f\x00\x00\x03\xc0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x01\xe0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x00\xf0\x00\x1e\x00\x03\xc0\x00\x00\x7f\x00\x00\x00x\x00\x12\x00\x0f\x80\x00\x00\x7f\x00\x00\x00<\x00\x12\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x1e\x00>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x00\x00\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Timer_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80.@|p\x00\x00\x7f\x00\x00\x01\xbe\x00#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!U\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00!*\x87\x80\x00\x00\x7f\x00\x00\x01\xe0\x00/U\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(*Q\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(U\xa8\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/*Tp\x00\x00\x7f\x00\x00\x07\x00\x00\x00U\xa8x\x00\x00\x7f\x00\x00\x0f\x00\x00\x00RV8\x00\x00\x7f\x00\x00\x0e\x00\x00\x05m\xa9<\x00\x00\x7f\x00\x00\x1e\x00\x00\n\x92V\x9c\x00\x00\x7f\x00\x00\x1c\x00\x00\x05m\xa9\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\n\x92V\x8e\x00\x00\x7f\x00\x008\x00\x00\x05m\xa8\x8e\x00\x00\x7f\x00\x008\x00\x00\n\x92W\xcf\x00\x00\x7f\x00\x008\x00\x00\x05m\xa8\x0f\x00\x00\x7f\x00\x008\x00\x00\n\x92P\x07\x00\x00\x7f\x00\x00y\xe0\x00\x05m\xb3\xc7\x00\x00\x7f\x00\x00q \x00\n\x92HG\x00\x00\x7f\x00\x00q \x00\x05m\xb4G\x00\x00\x7f\x00\x00q\xe0\x00\x04\x92I\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x00p \x00\x00\x00\x00G\x00\x00\x7f\x00\x00x \x00\x00\x00\x00\xc7\x00\x00\x7f\x00\x009\xe0\x00\x00\x00\x03\xc7\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x07\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0f\x00\x00\x7f\x00\x008\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00<\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x0e\x00\x00\x7f\x00\x00\x1c\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x1e\x00\x00\x00\x00\x00\x1c\x00\x00\x7f\x00\x00\x0e\x00\x00\x00\x00\x00<\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\x00\x008\x00\x00\x7f\x00\x00\x07\x80\x00\x1e\x00\x00x\x00\x00\x7f\x00\x00\x03\x80\x00\x10\x00\x00\xf0\x00\x00\x7f\x00\x00\x03\xc0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x01\xe0\x00\x10\x00\x01\xe0\x00\x00\x7f\x00\x00\x00\xf0\x00\x1e\x00\x03\xc0\x00\x00\x7f\x00\x00\x00x\x00\x12\x00\x0f\x80\x00\x00\x7f\x00\x00\x00<\x00\x12\x00\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x1e\x00>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x00\x00\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Timer_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80.@|p\x00\x00\x7f\x00\x00\x01\xbe\x00#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!*\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00!UG\x80\x00\x00\x7f\x00\x00\x01\xe0\x00/*\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(UQ\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(*\xa8\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/UTp\x00\x00\x7f\x00\x00\x07\x00\x00\x00UTx\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\xaa\xaa8\x00\x00\x7f\x00\x00\x0e\x00\x00\x05UU<\x00\x00\x7f\x00\x00\x1e\x00\x00\n\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UU\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UV\x8e\x00\x00\x7f\x00\x008\x00\x00\x05UP\x8e\x00\x00\x7f\x00\x008\x00\x00\n\xaa\xaf\xcf\x00\x00\x7f\x00\x008\x00\x00\x05UP\x0f\x00\x00\x7f\x00\x008\x00\x00\x05UP\x07\x00\x00\x7f\x00\x00y\xe0\x00\x05US\xc7\x00\x00\x7f\x00\x00q \x00\n\xaa\xa8G\x00\x00\x7f\x00\x00q \x00\x05UTG\x00\x00\x7f\x00\x00q\xe0\x00\n\xaa\xa9\xc7\x00\x00\x7f\x00\x00p \x00\x05UT\xc7\x00\x00\x7f\x00\x00p \x00\n\xaa\xa8G\x00\x00\x7f\x00\x00x \x00\x05UP\xc7\x00\x00\x7f\x00\x009\xe0\x00\x05US\xc7\x00\x00\x7f\x00\x008\x00\x00\x05UP\x07\x00\x00\x7f\x00\x008\x00\x00\x05UUO\x00\x00\x7f\x00\x008\x00\x00\x05UUN\x00\x00\x7f\x00\x00<\x00\x00\n\xaa\xaa\x8e\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UUN\x00\x00\x7f\x00\x00\x1c\x00\x00\n\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1e\x00\x00\x05UU\x1c\x00\x00\x7f\x00\x00\x0e\x00\x00\x05UU<\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\xaa\xaa8\x00\x00\x7f\x00\x00\x07\x80\x00\x1eUTx\x00\x00\x7f\x00\x00\x03\x80\x00\x10\xb5T\xf0\x00\x00\x7f\x00\x00\x03\xc0\x00\x11J\xa9\xe0\x00\x00\x7f\x00\x00\x01\xe0\x00\x10\xb5!\xe0\x00\x00\x7f\x00\x00\x00\xf0\x00\x1eJ\xc3\xc0\x00\x00\x7f\x00\x00\x00x\x00\x12\xb5\x0f\x80\x00\x00\x7f\x00\x00\x00<\x00\x12J\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x00\x1e\xb4>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x00@\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Timer_3=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x80.@|p\x00\x00\x7f\x00\x00\x01\xbe\x00#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc\x00!*\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0\x00!UG\x80\x00\x00\x7f\x00\x00\x01\xe0\x00/*\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc0\x00(UQ\xe0\x00\x00\x7f\x00\x00\x03\xc0\x00(*\xa8\xf0\x00\x00\x7f\x00\x00\x07\x80\x00/UTp\x00\x00\x7f\x00\x00\x07\x00\x00\x00UTx\x00\x00\x7f\x00\x00\x0f\x00\x00\x00\xaa\xaa8\x00\x00\x7f\x00\x00\x0e\x00\x00\x05UU<\x00\x00\x7f\x00\x00\x1e\x00\x00\n\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UU\x1e\x00\x00\x7f\x00\x00\x1c\x00\x00\x05UV\x8e\x00\x00\x7f\x00\x008\x00\x00\x05UP\x8e\x00\x00\x7f\x00\x008\x00\x00\n\xaa\xaf\xcf\x00\x00\x7f\x00\x008\x00\x00\x05UP\x0f\x00\x00\x7f\x00\x008\x00\x00\x05UP\x07\x00\x00\x7f\x00\x00y\xe0\x00\x05US\xc7\x00\x00\x7f\x00\x00q \x00\n\xaa\xa8G\x00\x00\x7f\x00\x00q \x00\x05UTG\x00\x00\x7f\x00\x00q\xe0\x00\n\xaa\xa9\xc7\x00\x00\x7f\x00\x00p%UUUT\xc7\x00\x00\x7f\x00\x00p"\xaa\xaa\xaa\xa8G\x00\x00\x7f\x00\x00x%UUUP\xc7\x00\x00\x7f\x00\x009\xe5UUUS\xc7\x00\x00\x7f\x00\x008\n\xaa\xaa\xaa\xa8\x07\x00\x00\x7f\x00\x008\xd5UUUUO\x00\x00\x7f\x00\x008UUUUUN\x00\x00\x7f\x00\x00<\xaa\xaa\xaa\xaa\xaa\x8e\x00\x00\x7f\x00\x00\x1cUUUUUN\x00\x00\x7f\x00\x00\x1cUUUUU\x9c\x00\x00\x7f\x00\x00\x1e*\xaa\xaa\xaa\xaa\x1c\x00\x00\x7f\x00\x00\x0e\x15UUUU<\x00\x00\x7f\x00\x00\x0f\x15U@\xaa\xaa8\x00\x00\x7f\x00\x00\x07\x8a\xaa\x9eUTx\x00\x00\x7f\x00\x00\x03\x8a\xaa\x90\xb5T\xf0\x00\x00\x7f\x00\x00\x03\xc2\xaa\x91J\xa9\xe0\x00\x00\x7f\x00\x00\x01\xe2\xaa\x90\xb5!\xe0\x00\x00\x7f\x00\x00\x00\xf0\xaa\x9eJ\xc3\xc0\x00\x00\x7f\x00\x00\x00x*\x92\xb5\x0f\x80\x00\x00\x7f\x00\x00\x00<*\x92J\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x05\x1e\xb4>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x80@\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Timer_4=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xff\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x80\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xc0\xc0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\xf3\x80\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x002\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x10\x00\x7f\x00\x06\x00\x00\x00\x7f\x00\x00\x008\x07\xff\xf8\x0f\x00\x00\x00\x7f\x00\x00\x00|?\xff\xff\x1f\x80\x00\x00\x7f\x00\x00\x00\xc6\xff\xc1\xff\xb9\xc0\x00\x00\x7f\x00\x00\x01\x87\xf8\x00\x0f\xf0\xe0\x00\x00\x7f\x00\x00\x03\x07\xe0\x00\x01\xf8p\x00\x00\x7f\x00\x00\x03\x1f\x81.@|p\x00\x00\x7f\x00\x00\x01\xbe\x15#T>\xe0\x00\x00\x7f\x00\x00\x00\xfc*!*\x0f\xc0\x00\x00\x7f\x00\x00\x00\xf0U!UG\x80\x00\x00\x7f\x00\x00\x01\xe1U/*\xa3\xc0\x00\x00\x7f\x00\x00\x01\xc1U(UQ\xe0\x00\x00\x7f\x00\x00\x03\xc5U(*\xa8\xf0\x00\x00\x7f\x00\x00\x07\x85U/UTp\x00\x00\x7f\x00\x00\x07\x15U\x00UTx\x00\x00\x7f\x00\x00\x0f\n\xaa\x80\xaa\xaa8\x00\x00\x7f\x00\x00\x0e*\xaa\xaa\xaa\xaa<\x00\x00\x7f\x00\x00\x1e*\xaa\xaa\xaa\xaa\x9c\x00\x00\x7f\x00\x00\x1cUUUUU\x1e\x00\x00\x7f\x00\x00\x1cUUUUU\x8e\x00\x00\x7f\x00\x008\x15UUUTN\x00\x00\x7f\x00\x008\xf5UUUW\xcf\x00\x00\x7f\x00\x008\n\xaa\xaa\xaa\xa8\x0f\x00\x00\x7f\x00\x008\x05UUUP\x07\x00\x00\x7f\x00\x00y\xe5UUUS\xc7\x00\x00\x7f\x00\x00q"\xaa\xaa\xaa\xa8G\x00\x00\x7f\x00\x00q%UUUTG\x00\x00\x7f\x00\x00q\xe2\xaa\xaa\xaa\xa9\xc7\x00\x00\x7f\x00\x00p%UUUT\xc7\x00\x00\x7f\x00\x00p"\xaa\xaa\xaa\xa8G\x00\x00\x7f\x00\x00x%UUUP\xc7\x00\x00\x7f\x00\x009\xe5UUUS\xc7\x00\x00\x7f\x00\x008\n\xaa\xaa\xaa\xa8\x07\x00\x00\x7f\x00\x008\xd5UUUUO\x00\x00\x7f\x00\x008UUUUUN\x00\x00\x7f\x00\x00<\xaa\xaa\xaa\xaa\xaa\x8e\x00\x00\x7f\x00\x00\x1cUUUUUN\x00\x00\x7f\x00\x00\x1cUUUUU\x9c\x00\x00\x7f\x00\x00\x1e*\xaa\xaa\xaa\xaa\x1c\x00\x00\x7f\x00\x00\x0e\x15UUUU<\x00\x00\x7f\x00\x00\x0f\x15U@\xaa\xaa8\x00\x00\x7f\x00\x00\x07\x8a\xaa\x9eUTx\x00\x00\x7f\x00\x00\x03\x8a\xaa\x90\xb5T\xf0\x00\x00\x7f\x00\x00\x03\xc2\xaa\x91J\xa9\xe0\x00\x00\x7f\x00\x00\x01\xe2\xaa\x90\xb5!\xe0\x00\x00\x7f\x00\x00\x00\xf0\xaa\x9eJ\xc3\xc0\x00\x00\x7f\x00\x00\x00x*\x92\xb5\x0f\x80\x00\x00\x7f\x00\x00\x00<*\x92J\x1f\x00\x00\x00\x7f\x00\x00\x00\x1f\x05\x1e\xb4>\x00\x00\x00\x7f\x00\x00\x00\x0f\xc0\x80@\xfc\x00\x00\x00\x7f\x00\x00\x00\x07\xf0\x00\x03\xf0\x00\x00\x00\x7f\x00\x00\x00\x01\xfe\x00?\xe0\x00\x00\x00\x7f\x00\x00\x00\x00\x7f\xff\xff\x80\x00\x00\x00\x7f\x00\x00\x00\x00\x1f\xff\xfc\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x03\xff\xe0\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f'
|
||||||
|
Water_level_0=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff>?\xcf\xff\xff\xff\xff\xfd\xff\xff\xbf\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
|
||||||
|
Water_level_1=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff>?\xcf\xff\xff\xff\xff\xfd\xff\xff\xbf\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
|
||||||
|
Water_level_2=b'P4\n89 64\n\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff\x1e?\xcf\xff\xff\xff\xff\xfd\xff\xff?\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
|
||||||
|
Water_level_3=b'P4\n89 64\n\x01\x00\x00`\x00\x08\x00\x03\x00\x00@\x7f\x03\x80\x00\xf0\x00\x1c\x00\x07\x80\x00\xe0\x7f\x0e\xc0\x01\xd8\x00s\x00\x0e\xc0\x01\xf8\x7f\x1ep\x03\xde\x00\xfb\x80\x1ep\x07\x9c\x7f\xff\x1e?\xe7\xc7\xfc\xf1\xff\x1e?\xcf\xff\xff\xff\xff\xfd\xff\xff?\xff\xef\xff\xf7\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdc\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe1\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf0?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xdf\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xbf\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfc?\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8o\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xe0O\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xf8\x1f\xff\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xe0\x1f\xff\xff\xff\xff\x17\xff\xff\xff\xff\xff\xf0\x0f\xff\xff\xff\xff\x07\xff\xff\xff\xff\xff\xfco\xff\xff\xff\xff\x07\xff\xff\xff\xff\xff\xfe\x7f\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
|
||||||
115
mixly/boards/default/micropython/build/lib/ps2.py
Normal file
115
mixly/boards/default/micropython/build/lib/ps2.py
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
"""
|
||||||
|
PS2Controller
|
||||||
|
|
||||||
|
MicroPython library for the PS2Controller
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Perform upgrade repair 20220819
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
|
from machine import Pin
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
PSB_SELECT = const(0x0001)
|
||||||
|
PSB_L3 = const(0x0002)
|
||||||
|
PSB_R3 = const(0x0004)
|
||||||
|
PSB_START = const(0x0008)
|
||||||
|
PSB_PAD_UP = const(0x0010)
|
||||||
|
PSB_PAD_RIGHT = const(0x0020)
|
||||||
|
PSB_PAD_DOWN = const(0x0040)
|
||||||
|
PSB_PAD_LEFT = const(0x0080)
|
||||||
|
PSB_L2 = const(0x0100)
|
||||||
|
PSB_R2 = const(0x0200)
|
||||||
|
PSB_L1 = const(0x0400)
|
||||||
|
PSB_R1 = const(0x0800)
|
||||||
|
PSB_GREEN = const(0x1000)
|
||||||
|
PSB_RED = const(0x2000)
|
||||||
|
PSB_BLUE = const(0x4000)
|
||||||
|
PSB_PINK = const(0x8000)
|
||||||
|
PSB_TRIANGLE = const(0x1000)
|
||||||
|
PSB_CIRCLE = const(0x2000)
|
||||||
|
PSB_CROSS = const(0x4000)
|
||||||
|
PSB_SQUARE = const(0x8000)
|
||||||
|
|
||||||
|
PSS_RX = const(0)
|
||||||
|
PSS_RY = const(1)
|
||||||
|
PSS_LX = const(2)
|
||||||
|
PSS_LY = const(3)
|
||||||
|
|
||||||
|
class PS2Controller:
|
||||||
|
def __init__(self,clk_pin,do_pin,di_pin,cs_pin,mode=1,timeout=1000): #mode: 0 red; 1 green
|
||||||
|
self.di =Pin(di_pin,Pin.IN)
|
||||||
|
self.do =Pin(do_pin,Pin.OUT)
|
||||||
|
self.cs =Pin(cs_pin,Pin.OUT)
|
||||||
|
self.clk=Pin(clk_pin,Pin.OUT)
|
||||||
|
|
||||||
|
self.buttons=0
|
||||||
|
self.last_buttons=0
|
||||||
|
self.rods=(128,128,128,128)
|
||||||
|
self.motor1=0
|
||||||
|
self.motor2=0
|
||||||
|
|
||||||
|
timestamp = time.ticks_ms()
|
||||||
|
while not (self._cmds([0x01,0x42])[1] in [0x41,0x73,0x79,0xF3]):
|
||||||
|
if time.ticks_diff(time.ticks_ms(), timestamp) > timeout:
|
||||||
|
raise AttributeError("Cannot find a PS2Controller",self._cmds([0x01,0x42])[1])
|
||||||
|
|
||||||
|
self._cmds([0x01,0x43,0x00,0x01,0x00]) # 进入配置模式
|
||||||
|
time.sleep_ms(10)
|
||||||
|
self._cmds([0x01,0x44,0x00,mode,0x03,0x00,0x00,0x00,0x00]) # “红绿灯”配置模式
|
||||||
|
time.sleep_ms(10)
|
||||||
|
self._cmds([0x01,0x4D,0x00,0x00,0x01]) # 开启震动模式
|
||||||
|
time.sleep_ms(10)
|
||||||
|
self._cmds([0x01,0x43,0x00,0x00,0x5A,0x5A,0x5A,0x5A,0x5A]) # 完成并保存配置
|
||||||
|
time.sleep_ms(10)
|
||||||
|
|
||||||
|
def _cmd(self,cmd):
|
||||||
|
'''Single byte command sending and receiving'''
|
||||||
|
ret = 0
|
||||||
|
for i in range(8):
|
||||||
|
if cmd & 1 << i:
|
||||||
|
self.do.value(1)
|
||||||
|
else:
|
||||||
|
self.do.value(0)
|
||||||
|
self.clk.value(0)
|
||||||
|
time.sleep_us(10)
|
||||||
|
if self.di.value():
|
||||||
|
ret |= 1 << i
|
||||||
|
self.clk.value(1)
|
||||||
|
self.do.value(1)
|
||||||
|
time.sleep_us(10)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
def _cmds(self,cmds):
|
||||||
|
'''Multi byte command sending and receiving'''
|
||||||
|
self.cs.value(0)
|
||||||
|
buffer=bytearray(9)
|
||||||
|
for i, cmd in enumerate(cmds):
|
||||||
|
buffer[i]=self._cmd(cmd)
|
||||||
|
self.cs.value(1)
|
||||||
|
time.sleep_ms(10)
|
||||||
|
return buffer
|
||||||
|
|
||||||
|
def keydata(self):
|
||||||
|
"""Read the value of the key"""
|
||||||
|
_buffer=self._cmds([0X01, 0X42, 0X00, self.motor1, self.motor2, 0X00, 0X00, 0X00, 0X00])
|
||||||
|
if _buffer[2]==0x5A:
|
||||||
|
handkey=(_buffer[4]<<8)| _buffer[3]
|
||||||
|
self.buttons=-handkey-1 & 0xffff
|
||||||
|
self.rods=(_buffer[5],_buffer[6],_buffer[7],_buffer[8])
|
||||||
|
return self.buttons,self.rods
|
||||||
|
|
||||||
|
def vibration(self,motor1=0,motor2=0):
|
||||||
|
"""Vibration settings"""
|
||||||
|
self.motor1=motor1 #motor1:小电机,只有震和不振
|
||||||
|
self.motor2=0 if motor2<1 else motor2*0xBF//100+0X40 #motor2:大电机,范围0x40-0xff,映射0-100
|
||||||
|
self._cmds([0X01, 0X42, 0X00, self.motor1, self.motor2, 0X00, 0X00, 0X00, 0X00])
|
||||||
|
|
||||||
|
def button(self,psb):
|
||||||
|
return (self.keydata()[0] & psb) > 0
|
||||||
|
|
||||||
|
def analog(self,pss):
|
||||||
|
return self.keydata()[1][pss]
|
||||||
215
mixly/boards/default/micropython/build/lib/qmc5883l.py
Normal file
215
mixly/boards/default/micropython/build/lib/qmc5883l.py
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
"""
|
||||||
|
QMC5883L
|
||||||
|
|
||||||
|
MicroPython library for the QMC5883L 3-Axis Magnetic Sensor
|
||||||
|
=======================================================
|
||||||
|
#Preliminary composition 20220217
|
||||||
|
|
||||||
|
by https://github.com/RigacciOrg/py-qmc5883l.git
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import math
|
||||||
|
import time
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
I2CADDR_DEFAULT = const(0x0D) # Default I2C address
|
||||||
|
|
||||||
|
REG_XOUT_LSB = const(0x00) # Output Data Registers for magnetic sensor.
|
||||||
|
REG_YOUT_LSB = const(0x02) # Output Data Registers for magnetic sensor.
|
||||||
|
REG_ZOUT_LSB = const(0x04) # Output Data Registers for magnetic sensor.
|
||||||
|
REG_STATUS_1 = const(0x06) # Status Register.
|
||||||
|
REG_TOUT_LSB = const(0x07) # Output Data Registers for temperature.
|
||||||
|
|
||||||
|
REG_CONTROL_1 = const(0x09) # Reg to control mode of compass.
|
||||||
|
REG_CONTROL_2 = const(0x0A) # Reg to contro2 mode of compass.
|
||||||
|
REG_RST_PERIOD = const(0x0B) # SET/RESET Period Register.
|
||||||
|
REG_CHIP_ID = const(0x0D) # Chip ID register.
|
||||||
|
|
||||||
|
# Flags for Status Register #1.
|
||||||
|
STAT_DRDY = const(0b00000001) # Data Ready.
|
||||||
|
STAT_OVL = const(0b00000010) # Overflow flag.
|
||||||
|
STAT_DOR = const(0b00000100) # Data skipped for reading.
|
||||||
|
# Flags for Status Register #2.
|
||||||
|
INT_ENB = const(0b00000001) # Interrupt Pin Enabling.
|
||||||
|
SOFT_RST = const(0b10000000) # Soft Reset.
|
||||||
|
# Flags for Control Register 1.
|
||||||
|
MODE_STBY = const(0b00000000) # Standby mode.
|
||||||
|
MODE_CONT = const(0b00000001) # Continuous read mode.
|
||||||
|
ODR_10HZ = const(0b00000000) # Output Data Rate Hz.
|
||||||
|
ODR_50HZ = const(0b00000100)
|
||||||
|
ODR_100HZ = const(0b00001000)
|
||||||
|
ODR_200HZ = const(0b00001100)
|
||||||
|
RNG_2G = const(0b00000000) # Range 2 Gauss: for magnetic-clean environments.
|
||||||
|
RNG_8G = const(0b00010000) # Range 8 Gauss: for strong magnetic fields.
|
||||||
|
OSR_512 = const(0b00000000) # Over Sample Rate 512: less noise, more power.
|
||||||
|
OSR_256 = const(0b01000000)
|
||||||
|
OSR_128 = const(0b10000000)
|
||||||
|
OSR_64 = const(0b11000000)
|
||||||
|
|
||||||
|
class Compass:
|
||||||
|
|
||||||
|
def __init__(self,i2c_bus,ODR=ODR_200HZ,RNG=RNG_8G,OSR=OSR_512):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = I2CADDR_DEFAULT
|
||||||
|
self.output_range = RNG
|
||||||
|
self._declination = 0.0
|
||||||
|
self._calibration = [[1.0, 0.0, 0.0],
|
||||||
|
[0.0, 1.0, 0.0],
|
||||||
|
[0.0, 0.0, 1.0]]
|
||||||
|
self._device.scan()
|
||||||
|
time.sleep(0.1)
|
||||||
|
if self._read_byte(REG_CHIP_ID) != 0xFF:
|
||||||
|
raise AttributeError("Cannot find a QMC5883L")
|
||||||
|
|
||||||
|
self.mode_cont = (MODE_CONT | ODR | RNG | OSR)
|
||||||
|
self.mode_stby = (MODE_STBY | ODR_10HZ | RNG_2G | OSR_64)
|
||||||
|
self.mode_continuous()
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
"""Once finished using the sensor, switch to standby mode."""
|
||||||
|
self.mode_standby()
|
||||||
|
|
||||||
|
def _write_byte(self, reg, val):
|
||||||
|
"""Write memory address"""
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _read_byte(self, reg,nbytes=1):
|
||||||
|
"""Read memory address"""
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def mode_continuous(self):
|
||||||
|
"""Set the device in continuous read mode."""
|
||||||
|
self._write_byte(REG_CONTROL_2, SOFT_RST) # Soft reset.
|
||||||
|
self._write_byte(REG_CONTROL_2, INT_ENB) # Disable interrupt.
|
||||||
|
self._write_byte(REG_RST_PERIOD, 0x01) # Define SET/RESET period.
|
||||||
|
self._write_byte(REG_CONTROL_1, self.mode_cont) # Set operation mode.
|
||||||
|
|
||||||
|
def mode_standby(self):
|
||||||
|
"""Set the device in standby mode."""
|
||||||
|
self._write_byte(REG_CONTROL_2, SOFT_RST)
|
||||||
|
self._write_byte(REG_CONTROL_2, INT_ENB)
|
||||||
|
self._write_byte(REG_RST_PERIOD, 0x01)
|
||||||
|
self._write_byte(REG_CONTROL_1, self.mode_stby) # Set operation mode.
|
||||||
|
|
||||||
|
def _read_word_2c(self, registry):
|
||||||
|
"""Calculate the 2's complement of a two bytes value."""
|
||||||
|
data=self._read_byte(registry,2)
|
||||||
|
val = (data[1] << 8) | data[0]
|
||||||
|
if val >= 0x8000: # 32768
|
||||||
|
return val - 0x10000 # 65536
|
||||||
|
else:
|
||||||
|
return val
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
return self._read_byte(REG_STATUS_1)
|
||||||
|
|
||||||
|
def get_data(self):
|
||||||
|
"""Read data from magnetic and temperature data registers."""
|
||||||
|
i = 0
|
||||||
|
[x, y, z, t] = [None, None, None, 0]
|
||||||
|
while i < 20: # Timeout after about 0.20 seconds.
|
||||||
|
status = self.ready()
|
||||||
|
if status & STAT_OVL:
|
||||||
|
# Some values have reached an overflow.
|
||||||
|
if self.output_range == RNG_2G:
|
||||||
|
raise AttributeError("Consider switching to RNG_8G output range")
|
||||||
|
else:
|
||||||
|
raise AttributeError("Magnetic sensor overflow")
|
||||||
|
if status & STAT_DOR:
|
||||||
|
# Previous measure was read partially, sensor in Data Lock.
|
||||||
|
x = self._read_word_2c(REG_XOUT_LSB)
|
||||||
|
y = self._read_word_2c(REG_YOUT_LSB)
|
||||||
|
z = self._read_word_2c(REG_ZOUT_LSB)
|
||||||
|
continue
|
||||||
|
if status & STAT_DRDY:
|
||||||
|
# Data is ready to read.
|
||||||
|
x = self._read_word_2c(REG_XOUT_LSB)
|
||||||
|
y = self._read_word_2c(REG_YOUT_LSB)
|
||||||
|
z = self._read_word_2c(REG_ZOUT_LSB)
|
||||||
|
t = self._read_word_2c(REG_TOUT_LSB)
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# Waiting for DRDY.
|
||||||
|
time.sleep(0.01)
|
||||||
|
i += 1
|
||||||
|
return [x, y, z, t/100+20]
|
||||||
|
|
||||||
|
def get_magnet_raw(self):
|
||||||
|
"""Get the 3 axis values from magnetic sensor."""
|
||||||
|
[x, y, z, t] = self.get_data()
|
||||||
|
return [x, y, z]
|
||||||
|
|
||||||
|
def get_magnet(self):
|
||||||
|
"""Return the horizontal magnetic sensor vector with (x, y) calibration applied."""
|
||||||
|
[x, y, z] = self.get_magnet_raw()
|
||||||
|
if x is None or y is None:
|
||||||
|
[x1, y1] = [x, y]
|
||||||
|
else:
|
||||||
|
c = self._calibration
|
||||||
|
x1 = x * c[0][0] + y * c[0][1] + c[0][2]
|
||||||
|
y1 = x * c[1][0] + y * c[1][1] + c[1][2]
|
||||||
|
return [x1, y1]
|
||||||
|
|
||||||
|
def get_bearing_raw(self):
|
||||||
|
"""Horizontal bearing (in degrees) from magnetic value X and Y."""
|
||||||
|
[x, y, z] = self.get_magnet_raw()
|
||||||
|
if x is None or y is None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
b = math.degrees(math.atan2(y, x))
|
||||||
|
if b < 0:
|
||||||
|
b += 360.0
|
||||||
|
return b
|
||||||
|
|
||||||
|
def get_bearing(self):
|
||||||
|
"""Horizontal bearing, adjusted by calibration and declination."""
|
||||||
|
[x, y] = self.get_magnet()
|
||||||
|
if x is None or y is None:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
b = math.degrees(math.atan2(y, x))
|
||||||
|
if b < 0:
|
||||||
|
b += 360.0
|
||||||
|
b += self._declination
|
||||||
|
if b < 0.0:
|
||||||
|
b += 360.0
|
||||||
|
elif b >= 360.0:
|
||||||
|
b -= 360.0
|
||||||
|
return round(b,2)
|
||||||
|
|
||||||
|
def get_temp(self):
|
||||||
|
"""Raw (uncalibrated) data from temperature sensor."""
|
||||||
|
[x, y, z, t] = self.get_data()
|
||||||
|
return t
|
||||||
|
|
||||||
|
def set_declination(self, value):
|
||||||
|
"""Set the magnetic declination, in degrees."""
|
||||||
|
try:
|
||||||
|
d = float(value)
|
||||||
|
if d < -180.0 or d > 180.0:
|
||||||
|
raise AttributeError('Declination must be >= -180 and <= 180')
|
||||||
|
else:
|
||||||
|
self._declination = d
|
||||||
|
except:
|
||||||
|
raise AttributeError('Declination must be a float value')
|
||||||
|
|
||||||
|
def get_declination(self):
|
||||||
|
"""Return the current set value of magnetic declination."""
|
||||||
|
return self._declination
|
||||||
|
|
||||||
|
def set_calibration(self, value):
|
||||||
|
"""Set the 3x3 matrix for horizontal (x, y) magnetic vector calibration."""
|
||||||
|
c = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]
|
||||||
|
try:
|
||||||
|
for i in range(0, 3):
|
||||||
|
for j in range(0, 3):
|
||||||
|
c[i][j] = float(value[i][j])
|
||||||
|
self._calibration = c
|
||||||
|
except:
|
||||||
|
logging.error(u'Calibration must be a 3x3 float matrix.')
|
||||||
|
|
||||||
|
def get_calibration(self):
|
||||||
|
"""Return the current set value of the calibration matrix."""
|
||||||
|
return self._calibration
|
||||||
111
mixly/boards/default/micropython/build/lib/qmi8658.py
Normal file
111
mixly/boards/default/micropython/build/lib/qmi8658.py
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
"""
|
||||||
|
QMI8658
|
||||||
|
|
||||||
|
Micropython library for the QMI8658(Accelerometer+Gyroscope)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from math import atan, sqrt, degrees
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
QMI8658_REG_DEVICE_ID = const(0x00)
|
||||||
|
|
||||||
|
QMI8658_REG_Ctrl1 = const(0x02) #Serial Interface and Sensor Enable
|
||||||
|
QMI8658_REG_Ctrl2 = const(0x03) #Accelerometer Settings
|
||||||
|
QMI8658_REG_Ctrl3 = const(0x04) #Gyroscope Settings
|
||||||
|
QMI8658_REG_Ctrl5 = const(0x06) #Sensor Data Processing Settings
|
||||||
|
QMI8658_REG_Ctrl7 = const(0x08) #Sensor Data Processing Settings
|
||||||
|
QMI8658_REG_Ctrl9 = const(0x0A) #Host Commands
|
||||||
|
QMI8658_REG_StatusInt = const(0x2D) #Sensor Data Available and Lock Register Address
|
||||||
|
QMI8658_REG_DATA = const(0x33)
|
||||||
|
|
||||||
|
Qmi8658AccRange_2g = 0 #/* +/- 2g range */
|
||||||
|
Qmi8658AccRange_4g = 1 #/* +/- 4g range */
|
||||||
|
Qmi8658AccRange_8g = 2 #/* +/- 8g range */
|
||||||
|
Qmi8658AccRange_16g = 3 #/* +/- 16g range */
|
||||||
|
|
||||||
|
Qmi8658GyrRange_16dps = 0 #/* +-16 degrees per second. */
|
||||||
|
Qmi8658GyrRange_32dps = 1 #/* +-32 degrees per second. */
|
||||||
|
Qmi8658GyrRange_64dps = 2 #/* +-64 degrees per second. */
|
||||||
|
Qmi8658GyrRange_128dps = 3 #/* +-128 degrees per second. */
|
||||||
|
Qmi8658GyrRange_256dps = 4 #/* +-256 degrees per second. */
|
||||||
|
Qmi8658GyrRange_512dps = 5 #/* +-512 degrees per second. */
|
||||||
|
Qmi8658GyrRange_1024dps = 6 #/* +-1024 degrees per second. */
|
||||||
|
Qmi8658GyrRange_2048dps = 7 #/* +-2048 degrees per second. */
|
||||||
|
|
||||||
|
Qmi8658Acc_Gyr_Odr_8000Hz = 0x00 #/* High resolution 8000Hz output rate. */
|
||||||
|
Qmi8658Acc_Gyr_Odr_4000Hz = 0x01 #/* High resolution 4000Hz output rate. */
|
||||||
|
Qmi8658Acc_Gyr_Odr_2000Hz = 0x02 #/* High resolution 2000Hz output rate. */
|
||||||
|
Qmi8658Acc_Gyr_Odr_1000Hz = 0x03 #/* High resolution 1000Hz output rate. */
|
||||||
|
Qmi8658Acc_Gyr_Odr_500Hz = 0x04 #/* High resolution 500Hz output rate. */
|
||||||
|
Qmi8658Acc_Gyr_Odr_250Hz = 0x05 #/* High resolution 250Hz output rate. */
|
||||||
|
Qmi8658Acc_Gyr_Odr_125Hz = 0x06 #/* High resolution 125Hz output rate. */
|
||||||
|
Qmi8658Acc_Gyr_Odr_62_5Hz = 0x07 #/* High resolution 62.5Hz output rate. */
|
||||||
|
Qmi8658Acc_Gyr_Odr_31_25Hz= 0x08 #/* High resolution 31.25Hz output rate. */
|
||||||
|
|
||||||
|
class QMI8658:
|
||||||
|
def __init__(self, i2c_bus,addr=0x6B,AccRange=Qmi8658AccRange_8g,GyrRange=Qmi8658GyrRange_2048dps,Acc_Gyr_Odr=Qmi8658Acc_Gyr_Odr_500Hz):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
if self._chip_id() != 0x05:
|
||||||
|
raise AttributeError("Cannot find a QMI8658")
|
||||||
|
|
||||||
|
self._wreg(QMI8658_REG_Ctrl9,0xA2) #做selftest,提高精度
|
||||||
|
time.sleep(0.1)
|
||||||
|
self._wreg(QMI8658_REG_Ctrl1,0x60)
|
||||||
|
self._wreg(QMI8658_REG_Ctrl7,0x03) #启动
|
||||||
|
self._wreg(QMI8658_REG_Ctrl2,(AccRange<< 4)|Acc_Gyr_Odr) #ACC-500HZ/8G
|
||||||
|
self._wreg(QMI8658_REG_Ctrl3,(GyrRange<< 4)|Acc_Gyr_Odr) #Gyr-500HZ/2048dps
|
||||||
|
self._wreg(QMI8658_REG_Ctrl5,0x75) #Gyr-14%,ACC-5.32%
|
||||||
|
self.gyr_lsb_div= 2**(11-GyrRange)
|
||||||
|
self.acc_lsb_div= 1<<(14-AccRange)
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg,nbytes=1):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, nbytes)[0] if nbytes<=1 else self._device.readfrom_mem(self._address, reg, nbytes)[0:nbytes]
|
||||||
|
|
||||||
|
def _chip_id(self):
|
||||||
|
return self._rreg(QMI8658_REG_DEVICE_ID)
|
||||||
|
|
||||||
|
def status(self):
|
||||||
|
return self._rreg(QMI8658_REG_StatusInt)
|
||||||
|
|
||||||
|
def u2s(self,n):
|
||||||
|
return n if n < (1 << 15) else n - (1 << 16)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def getdata(self):
|
||||||
|
while self.status() == 0x81:
|
||||||
|
time.sleep(0.001)
|
||||||
|
_buffer=self._rreg(QMI8658_REG_DATA,14)
|
||||||
|
tmp= float(self.u2s(_buffer[1]<<8|_buffer[0]))/256.0
|
||||||
|
acc_x=float(self.u2s(_buffer[3]<<8|_buffer[2]))/self.acc_lsb_div
|
||||||
|
acc_y=float(self.u2s(_buffer[5]<<8|_buffer[4]))/self.acc_lsb_div
|
||||||
|
acc_z=float(self.u2s(_buffer[7]<<8|_buffer[6]))/self.acc_lsb_div
|
||||||
|
gyr_x=float(self.u2s(_buffer[9]<<8|_buffer[8]))/self.gyr_lsb_div
|
||||||
|
gyr_y=float(self.u2s(_buffer[11]<<8|_buffer[10]))/self.gyr_lsb_div
|
||||||
|
gyr_z=float(self.u2s(_buffer[13]<<8|_buffer[12]))/self.gyr_lsb_div
|
||||||
|
return (acc_x,acc_y,acc_z),(gyr_x,gyr_y,gyr_z),round(tmp,2)
|
||||||
|
|
||||||
|
def acceleration(self):
|
||||||
|
return self.getdata[0]
|
||||||
|
|
||||||
|
def strength(self):
|
||||||
|
return sqrt(self.getdata[0][0]**2+self.getdata[0][1]**2+self.getdata[0][2]**2)
|
||||||
|
|
||||||
|
def gyroscope(self):
|
||||||
|
return self.getdata[1]
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
return self.getdata[2]
|
||||||
|
|
||||||
|
def eulerangles(self,upright=False):
|
||||||
|
x,y,z = self.acceleration()
|
||||||
|
pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2)))
|
||||||
|
roll = degrees(atan(x / sqrt(y ** 2 + z ** 2)))
|
||||||
|
return round(pitch,2),round(roll,2)
|
||||||
145
mixly/boards/default/micropython/build/lib/radio.py
Normal file
145
mixly/boards/default/micropython/build/lib/radio.py
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
"""
|
||||||
|
Radio-ESP-NOW
|
||||||
|
|
||||||
|
Micropython library for the Radio-ESP-NOW
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
from esp import espnow
|
||||||
|
version = 0
|
||||||
|
except:
|
||||||
|
import espnow
|
||||||
|
version = 1
|
||||||
|
from ubinascii import hexlify, unhexlify
|
||||||
|
import network
|
||||||
|
|
||||||
|
class ESPNow(espnow.ESPNow):
|
||||||
|
def __init__(self, channel=None, txpower=20):
|
||||||
|
self._on_handle = {}
|
||||||
|
self._once_irq = True
|
||||||
|
self._nic = network.WLAN(network.STA_IF) #if version else network.WLAN(network.AP_IF)
|
||||||
|
self._nic.active(True)
|
||||||
|
if channel is not None:
|
||||||
|
self.set_channel(channel, txpower)
|
||||||
|
super().__init__()
|
||||||
|
self.active(True)
|
||||||
|
|
||||||
|
def encrypt(self, peer, pmk, add_peer=True):
|
||||||
|
super().set_pmk((pmk + "0" *16)[:16].encode())
|
||||||
|
if add_peer:
|
||||||
|
super().add_peer(unhexlify(peer), encrypt=True)
|
||||||
|
else:
|
||||||
|
super().del_peer(unhexlify(peer))
|
||||||
|
|
||||||
|
def send(self, peer='ffffffffffff', msg=''):
|
||||||
|
'''Send data after error reporting and effective processing'''
|
||||||
|
try:
|
||||||
|
_peer = unhexlify(peer)
|
||||||
|
return super().send(_peer, str(msg))
|
||||||
|
except OSError as err:
|
||||||
|
if len(err.args) < 2:
|
||||||
|
raise err
|
||||||
|
if err.args[1] == 'ESP_ERR_ESPNOW_NOT_INIT':
|
||||||
|
raise OSError("Radio(ESPNOW) is not activated, unable to transmit data")
|
||||||
|
elif err.args[1] == 'ESP_ERR_ESPNOW_IF':
|
||||||
|
self._nic.active(True)
|
||||||
|
elif err.args[1] == 'ESP_ERR_ESPNOW_NOT_FOUND':
|
||||||
|
super().add_peer(_peer, channel=self.channel)
|
||||||
|
return super().send(_peer, str(msg))
|
||||||
|
elif err.args[1] == 'ESP_ERR_ESPNOW_NO_MEM':
|
||||||
|
raise OSError("internal ESP-NOW buffers are full")
|
||||||
|
elif err.args[1] == 'ESP_ERR_ESPNOW_ARG':
|
||||||
|
raise OSError("invalid argument")
|
||||||
|
else:
|
||||||
|
raise err
|
||||||
|
|
||||||
|
def recv(self):
|
||||||
|
'''Receive data'''
|
||||||
|
if self.any():
|
||||||
|
host, msg = super().recv()
|
||||||
|
return hexlify(host).decode(),msg.decode()
|
||||||
|
else :
|
||||||
|
return None,None
|
||||||
|
|
||||||
|
def set_channel(self, channel=1, txpower=20):
|
||||||
|
if not self._nic.isconnected():
|
||||||
|
self._nic.config(channel=channel, txpower=txpower)
|
||||||
|
else:
|
||||||
|
print("Warning: WiFi is connected, the actual espnow channel is {}".format(self.channel))
|
||||||
|
|
||||||
|
def _cb_handle0(self, event_code, data):
|
||||||
|
'''Callback processing conversion'''
|
||||||
|
if self._on_handle:
|
||||||
|
if isinstance(self._on_handle, list):
|
||||||
|
for func in self._on_handle:
|
||||||
|
cmd = func.__name__.rfind('__')
|
||||||
|
if cmd != -1:
|
||||||
|
cmd=func.__name__[cmd+2:]
|
||||||
|
if cmd == str(data[1].decode()):
|
||||||
|
func(hexlify(data[0]).decode(), data[1].decode())
|
||||||
|
else:
|
||||||
|
func(hexlify(data[0]).decode(), data[1].decode())
|
||||||
|
elif isinstance(self._on_handle, dict):
|
||||||
|
mac = hexlify(data[0]).decode()
|
||||||
|
decoded_msg = str(data[1].decode())
|
||||||
|
if '__all__' in self._on_handle:
|
||||||
|
self._on_handle['__all__'](mac, decoded_msg)
|
||||||
|
if decoded_msg in self._on_handle:
|
||||||
|
self._on_handle[decoded_msg](mac, decoded_msg)
|
||||||
|
else:
|
||||||
|
self._on_handle(hexlify(data[0]).decode(), data[1].decode())
|
||||||
|
|
||||||
|
def _cb_handle1(self, ee):
|
||||||
|
'''Callback processing conversion'''
|
||||||
|
host, msg = super().recv()
|
||||||
|
if self._on_handle:
|
||||||
|
if isinstance(self._on_handle, list):
|
||||||
|
for func in self._on_handle:
|
||||||
|
cmd = func.__name__.rfind('__')
|
||||||
|
if cmd != -1:
|
||||||
|
cmd=func.__name__[cmd+2:]
|
||||||
|
if cmd == str(msg.decode()):
|
||||||
|
func(hexlify(host).decode(), msg.decode())
|
||||||
|
else:
|
||||||
|
func(hexlify(host).decode(), msg.decode())
|
||||||
|
elif isinstance(self._on_handle, dict):
|
||||||
|
mac = hexlify(host).decode()
|
||||||
|
decoded_msg = str(msg.decode())
|
||||||
|
if '__all__' in self._on_handle:
|
||||||
|
self._on_handle['__all__'](mac, decoded_msg)
|
||||||
|
if decoded_msg in self._on_handle:
|
||||||
|
self._on_handle[decoded_msg](mac, decoded_msg)
|
||||||
|
else:
|
||||||
|
self._on_handle(hexlify(host).decode(), msg.decode())
|
||||||
|
|
||||||
|
def recv_cb(self, *args):
|
||||||
|
'''Receive callback (single dictionary or lists)'''
|
||||||
|
if len(args) >= 2:
|
||||||
|
self._on_handle.update({args[0]: args[1]})
|
||||||
|
else:
|
||||||
|
self._on_handle = args[0]
|
||||||
|
|
||||||
|
if self._once_irq:
|
||||||
|
self._once_irq = False
|
||||||
|
if version == 0:
|
||||||
|
self.irq(self._cb_handle0)
|
||||||
|
else:
|
||||||
|
self.irq(self._cb_handle1)
|
||||||
|
|
||||||
|
def info(self):
|
||||||
|
'''Get the paired Mac and rssi'''
|
||||||
|
_info=[]
|
||||||
|
for i in self.peers_table:
|
||||||
|
_info.append((hexlify(i).decode(), self.peers_table[i][0]))
|
||||||
|
return _info
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mac(self):
|
||||||
|
'''Get mac address'''
|
||||||
|
return hexlify(self._nic.config('mac')).decode()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def channel(self):
|
||||||
|
'''Get channel address'''
|
||||||
|
return self._nic.config('channel')
|
||||||
279
mixly/boards/default/micropython/build/lib/rc522.py
Normal file
279
mixly/boards/default/micropython/build/lib/rc522.py
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
"""
|
||||||
|
RC522
|
||||||
|
|
||||||
|
Micropython library for the RC522 RFID (I2C&SPI)
|
||||||
|
=======================================================
|
||||||
|
#Preliminary composition 20231204
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import machine
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
RC_OK = True
|
||||||
|
RC_NOTAGERR = None
|
||||||
|
RC_ERR = False
|
||||||
|
RC_REQIDL = const(0x26)
|
||||||
|
RC_REQALL = const(0x52)
|
||||||
|
RC_AUTHENT1A = const(0x60)
|
||||||
|
RC_AUTHENT1B = const(0x61)
|
||||||
|
RC_Version = const(0x37)
|
||||||
|
|
||||||
|
class RC522:
|
||||||
|
def __init__(self, drive_bus,cs_pin=None,addr=0x28):
|
||||||
|
self._device= drive_bus
|
||||||
|
if type(drive_bus) in [machine.I2C,machine.SoftI2C]:
|
||||||
|
self._type=True
|
||||||
|
self._address = addr
|
||||||
|
elif type(drive_bus) in [machine.SPI,machine.SoftSPI]:
|
||||||
|
self._type=False
|
||||||
|
self._cs = machine.Pin(cs_pin, machine.Pin.OUT)
|
||||||
|
else:
|
||||||
|
raise ValueError("RC522 only supports I2C and SPI")
|
||||||
|
|
||||||
|
self.init()
|
||||||
|
self.add_list=[1,2,4,5,6,8,9,10,12,13,14,16,17,18,20,21,22,24,25,26,28,29,30,32,33,34,36,37,38,40,41,42,44,45,46,48,49,50,52,53,54,56,57,58,60,61,62]
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
if self._type:
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
else:
|
||||||
|
self._cs.value(0)
|
||||||
|
self._device.write(b'%c' % int(0xff & ((reg << 1) & 0x7e)))
|
||||||
|
self._device.write(b'%c' % int(0xff & val))
|
||||||
|
self._cs.value(1)
|
||||||
|
|
||||||
|
def _rreg(self, reg):
|
||||||
|
'''Read memory address'''
|
||||||
|
if self._type:
|
||||||
|
return self._device.readfrom_mem(self._address, reg, 1)[0]
|
||||||
|
else:
|
||||||
|
self._cs.value(0)
|
||||||
|
self._device.write(b'%c' % int(0xff & (((reg << 1) & 0x7e) | 0x80)))
|
||||||
|
val = self._device.read(1)
|
||||||
|
self._cs.value(1)
|
||||||
|
return val[0]
|
||||||
|
|
||||||
|
def _sflags(self, reg, mask):
|
||||||
|
self._wreg(reg, self._rreg(reg) | mask)
|
||||||
|
|
||||||
|
def _cflags(self, reg, mask):
|
||||||
|
self._wreg(reg, self._rreg(reg) & (~mask))
|
||||||
|
|
||||||
|
def _tocard(self, cmd, send):
|
||||||
|
recv = []
|
||||||
|
bits = 0
|
||||||
|
irq_en = 0
|
||||||
|
wait_irq =0
|
||||||
|
n = 0
|
||||||
|
stat = RC_ERR
|
||||||
|
if cmd == 0x0E:
|
||||||
|
irq_en = 0x12
|
||||||
|
wait_irq = 0x10
|
||||||
|
elif cmd == 0x0C:
|
||||||
|
irq_en = 0x77
|
||||||
|
wait_irq = 0x30
|
||||||
|
self._wreg(0x02, irq_en)
|
||||||
|
self._cflags(0x04, 0x80)
|
||||||
|
self._sflags(0x0A, 0x80)
|
||||||
|
self._wreg(0x01, 0x00)
|
||||||
|
for c in send:
|
||||||
|
self._wreg(0x09, c)
|
||||||
|
self._wreg(0x01, cmd)
|
||||||
|
|
||||||
|
if cmd == 0x0C:
|
||||||
|
self._sflags(0x0D, 0x80)
|
||||||
|
|
||||||
|
i = 100
|
||||||
|
while True:
|
||||||
|
n = self._rreg(0x04)
|
||||||
|
i -= 1
|
||||||
|
if ~((i != 0) and ~(n & 0x01) and ~(n & wait_irq)):
|
||||||
|
break
|
||||||
|
|
||||||
|
self._cflags(0x0D, 0x80)
|
||||||
|
if i:
|
||||||
|
if (self._rreg(0x06) & 0x1B) == 0x00:
|
||||||
|
stat = RC_OK
|
||||||
|
|
||||||
|
if n & irq_en & 0x01:
|
||||||
|
stat = RC_NOTAGERR
|
||||||
|
elif cmd == 0x0C:
|
||||||
|
n = self._rreg(0x0A)
|
||||||
|
lbits = self._rreg(0x0C) & 0x07
|
||||||
|
if lbits != 0:
|
||||||
|
bits = (n - 1) * 8 + lbits
|
||||||
|
else:
|
||||||
|
bits = n * 8
|
||||||
|
if n == 0:
|
||||||
|
n = 1
|
||||||
|
elif n > 16:
|
||||||
|
n = 16
|
||||||
|
for _ in range(n):
|
||||||
|
recv.append(self._rreg(0x09))
|
||||||
|
else:
|
||||||
|
stat = RC_ERR
|
||||||
|
return stat, recv, bits
|
||||||
|
|
||||||
|
def _crc(self, data):
|
||||||
|
self._cflags(0x05, 0x04)
|
||||||
|
self._sflags(0x0A, 0x80)
|
||||||
|
for c in data:
|
||||||
|
self._wreg(0x09, c)
|
||||||
|
self._wreg(0x01, 0x03)
|
||||||
|
i = 0xFF
|
||||||
|
while True:
|
||||||
|
n = self._rreg(0x05)
|
||||||
|
i -= 1
|
||||||
|
if not ((i != 0) and not (n & 0x04)):
|
||||||
|
break
|
||||||
|
return [self._rreg(0x22), self._rreg(0x21)]
|
||||||
|
|
||||||
|
def init(self):
|
||||||
|
self.reset()
|
||||||
|
self._wreg(0x2A, 0x8D)
|
||||||
|
self._wreg(0x2B, 0x3E)
|
||||||
|
self._wreg(0x2D, 30)
|
||||||
|
self._wreg(0x2C, 0)
|
||||||
|
self._wreg(0x15, 0x40)
|
||||||
|
self._wreg(0x11, 0x3D)
|
||||||
|
self._wreg(0x26, 0x68)
|
||||||
|
#A32NQ32C3 Additional Register Configuration
|
||||||
|
if self._rreg(RC_Version) == 0x82:
|
||||||
|
self._wreg(0x12, 0x0)
|
||||||
|
self._wreg(0x13, 0x0)
|
||||||
|
self._wreg(0x14, 0x84)
|
||||||
|
self._wreg(0x18, 0x33)
|
||||||
|
self._wreg(0x0c, 0x10)
|
||||||
|
self.antenna_on()
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self._wreg(0x01, 0x0F)
|
||||||
|
|
||||||
|
def antenna_on(self, on=True):
|
||||||
|
if on and ~(self._rreg(0x14) & 0x03):
|
||||||
|
self._sflags(0x14, 0x03)
|
||||||
|
else:
|
||||||
|
self._cflags(0x14, 0x03)
|
||||||
|
|
||||||
|
def request(self, mode):
|
||||||
|
self._wreg(0x0D, 0x07)
|
||||||
|
stat, recv, bits = self._tocard(0x0C, [mode])
|
||||||
|
if (stat != RC_OK) | (bits != 0x10):
|
||||||
|
stat = RC_ERR
|
||||||
|
return stat, bits
|
||||||
|
|
||||||
|
def anticoll(self):
|
||||||
|
ser_chk = 0
|
||||||
|
ser = [0x93, 0x20]
|
||||||
|
self._wreg(0x0D, 0x00)
|
||||||
|
(stat, recv, bits) = self._tocard(0x0C, ser)
|
||||||
|
|
||||||
|
if stat == RC_OK:
|
||||||
|
if len(recv) == 5:
|
||||||
|
for i in range(4):
|
||||||
|
ser_chk = ser_chk ^ recv[i]
|
||||||
|
if ser_chk != recv[4]:
|
||||||
|
stat = RC_ERR
|
||||||
|
else:
|
||||||
|
stat = RC_ERR
|
||||||
|
return stat, recv
|
||||||
|
|
||||||
|
def select_tag(self, ser):
|
||||||
|
buf = [0x93, 0x70] + ser[:5]
|
||||||
|
buf += self._crc(buf)
|
||||||
|
(stat, recv, bits) = self._tocard(0x0C, buf)
|
||||||
|
return RC_OK if (stat == RC_OK) and (bits == 0x18) else RC_ERR
|
||||||
|
|
||||||
|
def auth(self, mode, addr, sect, ser):
|
||||||
|
return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0]
|
||||||
|
|
||||||
|
def stop_crypto1(self):
|
||||||
|
self._cflags(0x08, 0x08)
|
||||||
|
|
||||||
|
def read(self, addr):
|
||||||
|
data = [0x30, addr]
|
||||||
|
data += self._crc(data)
|
||||||
|
(stat, recv, _) = self._tocard(0x0C, data)
|
||||||
|
return recv if stat == RC_OK else None
|
||||||
|
|
||||||
|
def write(self, addr, data):
|
||||||
|
buf = [0xA0, addr]
|
||||||
|
buf += self._crc(buf)
|
||||||
|
(stat, recv, bits) = self._tocard(0x0C, buf)
|
||||||
|
|
||||||
|
if not (stat == RC_OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A):
|
||||||
|
stat = RC_ERR
|
||||||
|
else:
|
||||||
|
buf = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||||
|
for i in range(len(data)):
|
||||||
|
buf[i]=data[i]
|
||||||
|
buf += self._crc(buf)
|
||||||
|
(stat, recv, bits) = self._tocard(0x0C, buf)
|
||||||
|
if not (stat == RC_OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A):
|
||||||
|
stat = RC_ERR
|
||||||
|
return stat
|
||||||
|
|
||||||
|
def read_card(self,add,x='ALL'):#0:all,i:id,2:content
|
||||||
|
if add>=47:
|
||||||
|
raise AttributeError("Out of address range")
|
||||||
|
stat, tag_type = self.request(RC_REQALL)
|
||||||
|
if stat !=RC_OK:
|
||||||
|
stat, tag_type = self.request(RC_REQALL)
|
||||||
|
if stat == RC_OK:
|
||||||
|
(stat, raw_uid) = self.anticoll()
|
||||||
|
if stat == RC_OK:
|
||||||
|
if self.select_tag(raw_uid) == RC_OK:
|
||||||
|
key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]
|
||||||
|
if self.auth(RC_AUTHENT1A, self.add_list[add], key, raw_uid) == RC_OK:
|
||||||
|
card = self.read(self.add_list[add])
|
||||||
|
try:
|
||||||
|
card = bytes(card).decode().replace("\x00", '') if card else None
|
||||||
|
except:
|
||||||
|
card = bytes(card) if card else None
|
||||||
|
self.stop_crypto1()
|
||||||
|
if x == "ALL":
|
||||||
|
return int('{}{}{}{}'.format(raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])), card
|
||||||
|
elif x == "id":
|
||||||
|
return int('{}{}{}{}'.format(raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3]))
|
||||||
|
elif x == "content":
|
||||||
|
return card
|
||||||
|
|
||||||
|
def write_card(self, data,add):
|
||||||
|
if add>=47:
|
||||||
|
raise AttributeError("Out of address range")
|
||||||
|
stat, tag_type = self.request(RC_REQALL)
|
||||||
|
if stat !=RC_OK:
|
||||||
|
stat, tag_type = self.request(RC_REQALL)
|
||||||
|
if stat == RC_OK:
|
||||||
|
(stat, raw_uid) = self.anticoll()
|
||||||
|
if stat == RC_OK:
|
||||||
|
if self.select_tag(raw_uid) == RC_OK:
|
||||||
|
key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF]
|
||||||
|
if self.auth(RC_AUTHENT1A, self.add_list[add], key, raw_uid) == RC_OK:
|
||||||
|
try:
|
||||||
|
data =list(data.encode())
|
||||||
|
except:
|
||||||
|
data =list(data)
|
||||||
|
if len(data)>16:
|
||||||
|
raise AttributeError("Input must be less than 16 bytes")
|
||||||
|
stat = self.write(self.add_list[add], data)
|
||||||
|
self.stop_crypto1()
|
||||||
|
if stat == RC_OK:
|
||||||
|
print('Data written to card')
|
||||||
|
return RC_OK
|
||||||
|
else:
|
||||||
|
print('Failed to write data to card')
|
||||||
|
return RC_ERR
|
||||||
|
else:
|
||||||
|
print('Authentication error')
|
||||||
|
return RC_ERR
|
||||||
|
else:
|
||||||
|
print('Failed to select tag')
|
||||||
|
return RC_ERR
|
||||||
|
else:
|
||||||
|
return RC_ERR
|
||||||
|
|
||||||
|
def scan_card(self,stat=RC_REQIDL):
|
||||||
|
return self.request(stat)[0]
|
||||||
239
mixly/boards/default/micropython/build/lib/rfm98.py
Normal file
239
mixly/boards/default/micropython/build/lib/rfm98.py
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
"""
|
||||||
|
RFM98
|
||||||
|
|
||||||
|
Micropython library for the RFM98 LoRa
|
||||||
|
=======================================================
|
||||||
|
#Preliminary composition 20220406
|
||||||
|
#Rebuild and optimize execution 20220412
|
||||||
|
#Repair receive mode 20220428
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import gc
|
||||||
|
import time
|
||||||
|
from machine import Pin
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_REG_FIFO = const(0x00)
|
||||||
|
_REG_OP_MODE = const(0x01)
|
||||||
|
_REG_FRF_MSB = const(0x06)
|
||||||
|
_REG_FRF_MID = const(0x07)
|
||||||
|
_REG_FRF_LSB = const(0x08)
|
||||||
|
_REG_PA_CONFIG = const(0x09)
|
||||||
|
_REG_LNA = const(0x0C)
|
||||||
|
_REG_FIFO_ADDR_PTR = const(0x0D)
|
||||||
|
_REG_FIFO_TX_BASE_ADDR = const(0x0E)
|
||||||
|
_REG_FIFO_RX_BASE_ADDR = const(0x0F)
|
||||||
|
_REG_FIFO_RX_CURRENT_ADDR = const(0x10)
|
||||||
|
_REG_IRQ_FLAGS = const(0x12)
|
||||||
|
_REG_RX_NB_BYTES = const(0x13)
|
||||||
|
_REG_PKT_SNR_VALUE = const(0x19)
|
||||||
|
_REG_PKT_RSSI_VALUE = const(0x1A)
|
||||||
|
_REG_MODEM_CONFIG1 = const(0x1D)
|
||||||
|
_REG_MODEM_CONFIG2 = const(0x1E)
|
||||||
|
_REG_PREAMBLE_MSB = const(0x20)
|
||||||
|
_REG_PREAMBLE_LSB = const(0x21)
|
||||||
|
_REG_PAYLOAD_LENGTH = const(0x22)
|
||||||
|
_REG_MODEM_CONFIG3 = const(0x26)
|
||||||
|
_REG_DIO_MAPPING1 = const(0x40)
|
||||||
|
_REG_DIO_MAPPING2 = const(0x41)
|
||||||
|
_REG_VERSION = const(0x42)
|
||||||
|
_REG_PA_DAC = const(0x4D)
|
||||||
|
_DETECTION_OPTIMIZE = const(0x31)
|
||||||
|
_DETECTION_THRESHOLD = const(0x37)
|
||||||
|
|
||||||
|
_MODE_LONG_RANGE_MODE = const(0x88)
|
||||||
|
_MODE_SLEEP = const(0x00)
|
||||||
|
_MODE_STDBY = const(0x01)
|
||||||
|
_MODE_TX = const(0x03)
|
||||||
|
_MODE_RX = const(0x05)
|
||||||
|
|
||||||
|
class RFM98:
|
||||||
|
def __init__(self,spi,cs_pin,frequency_mhz=433.0,signal_bandwidth=125E3,coding_rate=5,spreading_factor=7,**kw):
|
||||||
|
self._spi = spi
|
||||||
|
self._pin_ss = Pin(cs_pin, Pin.OUT)
|
||||||
|
self._frequency_mhz=frequency_mhz
|
||||||
|
self._signal_bandwidth=signal_bandwidth
|
||||||
|
self._coding_rate=coding_rate
|
||||||
|
self._spreading_factor=spreading_factor
|
||||||
|
self._kw=kw
|
||||||
|
self.init()
|
||||||
|
|
||||||
|
def init(self):
|
||||||
|
for i in range(6):
|
||||||
|
if self._read_u8(_REG_VERSION) == 18: # No device type check!
|
||||||
|
break
|
||||||
|
if i >=5:
|
||||||
|
raise AttributeError("Cannot find a RFM9x")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
self.sleep()
|
||||||
|
time.sleep(0.01)
|
||||||
|
if self._read_u8(_REG_OP_MODE) != (_MODE_LONG_RANGE_MODE | _MODE_SLEEP):
|
||||||
|
raise RuntimeError("Failed to configure radio for LoRa mode, check wiring!")
|
||||||
|
self._write_u8(_REG_FIFO_TX_BASE_ADDR, 0x00) # Setup entire 256 byte FIFO
|
||||||
|
self._write_u8(_REG_FIFO_RX_BASE_ADDR, 0x00)
|
||||||
|
|
||||||
|
self.idle()
|
||||||
|
self.coding_rate(self._coding_rate) # CR: 5...8
|
||||||
|
self.frequency_mhz(self._frequency_mhz) # Set frequency_mhz 433±10.00
|
||||||
|
self.signal_bandwidth(self._signal_bandwidth) # BW: 7.8...500 kHz
|
||||||
|
self.spreading_factor(self._spreading_factor) # SF: 6..12
|
||||||
|
self.enable_crc(self._kw.get('enable_crc', True)) # Set enable_crc
|
||||||
|
self.preamble_length(self._kw.get('preamble_length', 6))
|
||||||
|
self.tx_power(self._kw.get('tx_power', 16),self._kw.get('high_power', True))
|
||||||
|
|
||||||
|
self._write_u8(_REG_MODEM_CONFIG3, 0x04) #set AGC - True
|
||||||
|
if 1000 /(self._signal_bandwidth / 2**self._spreading_factor) > 16:
|
||||||
|
self._write_u8(_REG_MODEM_CONFIG3, self._read_u8(_REG_MODEM_CONFIG3) | 0x08)
|
||||||
|
|
||||||
|
def transfer(self, address, value = 0x00):
|
||||||
|
response = bytearray(1)
|
||||||
|
self._pin_ss.value(0)
|
||||||
|
self._spi.write(bytes([address]))
|
||||||
|
self._spi.write_readinto(bytes([value]), response)
|
||||||
|
self._pin_ss.value(1)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def _read_u8(self, address):
|
||||||
|
response = self.transfer(address & 0x7f)
|
||||||
|
return int.from_bytes(response, 'big')
|
||||||
|
|
||||||
|
def _write_u8(self, address, value):
|
||||||
|
self.transfer(address | 0x80, value)
|
||||||
|
|
||||||
|
def idle(self):
|
||||||
|
self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_STDBY)
|
||||||
|
|
||||||
|
def sleep(self):
|
||||||
|
self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_SLEEP)
|
||||||
|
|
||||||
|
def listen(self):
|
||||||
|
self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_RX)
|
||||||
|
self._write_u8(_REG_DIO_MAPPING1, 0x00)
|
||||||
|
self._write_u8(_REG_DIO_MAPPING2, 0x40)
|
||||||
|
|
||||||
|
def transmit(self):
|
||||||
|
self._write_u8(_REG_OP_MODE, _MODE_LONG_RANGE_MODE | _MODE_TX)
|
||||||
|
self._write_u8(_REG_DIO_MAPPING1, 0x01)
|
||||||
|
self._write_u8(_REG_DIO_MAPPING2, 0x00)
|
||||||
|
|
||||||
|
def preamble_length(self, val):
|
||||||
|
self._write_u8(_REG_PREAMBLE_MSB, (val >> 8) & 0xFF)
|
||||||
|
self._write_u8(_REG_PREAMBLE_LSB, val & 0xFF)
|
||||||
|
|
||||||
|
def frequency_mhz(self, val):
|
||||||
|
if val < 410 or val > 525:
|
||||||
|
raise RuntimeError("frequency_mhz must be between 410 and 525")
|
||||||
|
frf = int((val * 1000000.0) /(32000000.0 / 524288)) & 0xFFFFFF
|
||||||
|
self._write_u8(_REG_FRF_MSB, frf >> 16)
|
||||||
|
self._write_u8(_REG_FRF_MID, (frf >> 8) & 0xFF)
|
||||||
|
self._write_u8(_REG_FRF_LSB, frf & 0xFF)
|
||||||
|
|
||||||
|
def tx_power(self, val,high_power=True):
|
||||||
|
if high_power:
|
||||||
|
assert 5 <= val <= 23
|
||||||
|
if val > 20:
|
||||||
|
self._write_u8(_REG_PA_DAC, 0x07)
|
||||||
|
val -= 3
|
||||||
|
else:
|
||||||
|
self._write_u8(_REG_PA_DAC, 0x04)
|
||||||
|
self._write_u8(_REG_PA_CONFIG, 0x80 | (val - 5))
|
||||||
|
else:
|
||||||
|
assert -1 <= val <= 14
|
||||||
|
self._write_u8(_REG_PA_CONFIG, 0x70 | (val +1))
|
||||||
|
|
||||||
|
def packet_rssi(self): #last RSSI reading
|
||||||
|
return self._read_u8(_REG_PKT_RSSI_VALUE)-157
|
||||||
|
|
||||||
|
def packet_snr(self): #last SNR reading
|
||||||
|
snr_byte = self._read_u8(_REG_PKT_SNR_VALUE)
|
||||||
|
return snr_byte/4 if snr_byte<=127 else (snr_byte -256 )/4
|
||||||
|
|
||||||
|
def signal_bandwidth(self, val):
|
||||||
|
bw_bins = (7800, 10400, 15600, 20800, 31250, 41700, 62500, 125000, 250000)
|
||||||
|
for bw_id, cutoff in enumerate(bw_bins):
|
||||||
|
if val <= cutoff:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
bw_id = 9
|
||||||
|
self._write_u8(_REG_MODEM_CONFIG1,(self._read_u8(_REG_MODEM_CONFIG1) & 0x0F) | (bw_id << 4))
|
||||||
|
if val >= 500000:
|
||||||
|
self._write_u8(_DETECTION_OPTIMIZE,(self._read_u8(_DETECTION_OPTIMIZE) | 0x80))
|
||||||
|
self._write_u8(0x36, 0x02)
|
||||||
|
self._write_u8(0x3A, 0x7F)
|
||||||
|
else:
|
||||||
|
self._write_u8(_DETECTION_OPTIMIZE,(self._read_u8(_DETECTION_OPTIMIZE) & 0x7F))
|
||||||
|
self._write_u8(0x36, 0x03)
|
||||||
|
if val == 7800:
|
||||||
|
self._write_u8(0x2F, 0x48)
|
||||||
|
elif val >= 62500:
|
||||||
|
self._write_u8(0x2F, 0x40)
|
||||||
|
else:
|
||||||
|
self._write_u8(0x2F, 0x44)
|
||||||
|
self._write_u8(0x30, 0)
|
||||||
|
|
||||||
|
def coding_rate(self, val):
|
||||||
|
denominator = min(max(val, 5), 8)
|
||||||
|
cr_id = denominator - 4
|
||||||
|
self._write_u8(_REG_MODEM_CONFIG1,(self._read_u8(_REG_MODEM_CONFIG1) & 0xF1) | (cr_id << 1))
|
||||||
|
|
||||||
|
def spreading_factor(self, val):
|
||||||
|
val = min(max(val, 6), 12)
|
||||||
|
self._write_u8(_DETECTION_OPTIMIZE,self._read_u8(_DETECTION_OPTIMIZE)|0x05 if val == 6 else self._read_u8(_DETECTION_OPTIMIZE)|0x03)
|
||||||
|
self._write_u8(_DETECTION_THRESHOLD, 0x0C if val == 6 else 0x0A)
|
||||||
|
self._write_u8(_REG_MODEM_CONFIG2,((self._read_u8(_REG_MODEM_CONFIG2) & 0x0F)| ((val << 4) & 0xF0)))
|
||||||
|
|
||||||
|
def enable_crc(self, val):
|
||||||
|
if val:
|
||||||
|
self._write_u8(_REG_MODEM_CONFIG2,self._read_u8(_REG_MODEM_CONFIG2) | 0x04)
|
||||||
|
else:
|
||||||
|
self._write_u8(_REG_MODEM_CONFIG2,self._read_u8(_REG_MODEM_CONFIG2) & 0xFB)
|
||||||
|
|
||||||
|
def irq_done(self): #irq status
|
||||||
|
return self._read_u8(_REG_IRQ_FLAGS)
|
||||||
|
|
||||||
|
def send(self,msg,timeout=2):
|
||||||
|
self.idle() # Stop receiving to clear FIFO and keep it clear.
|
||||||
|
self._write_u8(_REG_FIFO_ADDR_PTR, 0x00) # FIFO starts at 0.
|
||||||
|
if isinstance(msg, str):
|
||||||
|
msg = msg.encode()
|
||||||
|
size = min(len(msg), 255)
|
||||||
|
for i in range(size): # write data
|
||||||
|
self._write_u8(_REG_FIFO, msg[i]) # Write payload.
|
||||||
|
self._write_u8(_REG_PAYLOAD_LENGTH, size) # Write payload and header length.
|
||||||
|
self.transmit() # Turn on transmit mode to send out the packet.
|
||||||
|
|
||||||
|
timed_out = False
|
||||||
|
start = time.ticks_ms()
|
||||||
|
while not timed_out and not((self._read_u8(_REG_IRQ_FLAGS) & 0x8) >> 3):
|
||||||
|
if time.ticks_diff(time.ticks_ms(), start) >= timeout * 1000:
|
||||||
|
timed_out = True
|
||||||
|
|
||||||
|
self.idle() # Enter idle mode to stop receiving other packets.
|
||||||
|
gc.collect()
|
||||||
|
self._write_u8(_REG_IRQ_FLAGS, 0xFF) # Clear interrupt.
|
||||||
|
return not timed_out
|
||||||
|
|
||||||
|
def recv(self):
|
||||||
|
if self._read_u8(_REG_OP_MODE) != (_MODE_LONG_RANGE_MODE | _MODE_RX):
|
||||||
|
self.listen() # Enter receive mode
|
||||||
|
|
||||||
|
flags=self.irq_done()
|
||||||
|
if flags & 0x40:
|
||||||
|
self.idle() # Enter idle mode to stop receiving other packets.
|
||||||
|
fifo_length = self._read_u8(_REG_RX_NB_BYTES) # Read the length of the FIFO.
|
||||||
|
if fifo_length > 0: # Read the data from the FIFO.
|
||||||
|
self._write_u8(_REG_FIFO_ADDR_PTR, self._read_u8(_REG_FIFO_RX_CURRENT_ADDR))
|
||||||
|
packet = bytearray()
|
||||||
|
for i in range(fifo_length):
|
||||||
|
packet.append(self._read_u8(_REG_FIFO)) # Read the packet.
|
||||||
|
self._write_u8(_REG_IRQ_FLAGS, 0xFF) # Clear interrupt.
|
||||||
|
gc.collect()
|
||||||
|
try :
|
||||||
|
return bytes(packet).decode()
|
||||||
|
except:
|
||||||
|
return bytes(packet)
|
||||||
|
elif flags== 0x15:
|
||||||
|
print("Timeout not handled , overflow error,will restart!")
|
||||||
|
self.init()
|
||||||
69
mixly/boards/default/micropython/build/lib/rtctime.py
Normal file
69
mixly/boards/default/micropython/build/lib/rtctime.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
"""RTC Time"""
|
||||||
|
import gc
|
||||||
|
from time import *
|
||||||
|
from machine import RTC
|
||||||
|
import usocket as socket
|
||||||
|
import ustruct as struct
|
||||||
|
|
||||||
|
# NTP_DELTA (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
|
||||||
|
NTP_DELTA = 3155673600
|
||||||
|
_weekdayname = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun")
|
||||||
|
_monthname = (None, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",)
|
||||||
|
|
||||||
|
def ntptime(host="pool.ntp.org", utc=28800):
|
||||||
|
NTP_QUERY = bytearray(48)
|
||||||
|
NTP_QUERY[0] = 0x1B
|
||||||
|
addr = socket.getaddrinfo(host, 123)[0][-1]
|
||||||
|
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
try:
|
||||||
|
s.settimeout(1)
|
||||||
|
res = s.sendto(NTP_QUERY, addr)
|
||||||
|
msg = s.recv(48)
|
||||||
|
finally:
|
||||||
|
del addr
|
||||||
|
s.close()
|
||||||
|
gc.collect()
|
||||||
|
val = struct.unpack("!I", msg[40:44])[0]
|
||||||
|
return gmtime(val - NTP_DELTA + utc)
|
||||||
|
|
||||||
|
# There's currently no timezone support in MicroPython, and the RTC is set in UTC time.
|
||||||
|
def settime(times):
|
||||||
|
if isinstance(times, str):
|
||||||
|
try:
|
||||||
|
times = eval(times)
|
||||||
|
except:
|
||||||
|
raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values")
|
||||||
|
if type(times) in (tuple, list):
|
||||||
|
if 6 <= len(times) <= 8:
|
||||||
|
RTC().datetime((times[0], times[1], times[2], 0, times[3], times[4], times[5], 0))
|
||||||
|
else:
|
||||||
|
raise ValueError("Settime needs a type of length 6~8")
|
||||||
|
|
||||||
|
def strtime(times=None):
|
||||||
|
if times is None:
|
||||||
|
times = localtime()
|
||||||
|
if isinstance(times, str):
|
||||||
|
try:
|
||||||
|
times = eval(times)
|
||||||
|
except:
|
||||||
|
raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values")
|
||||||
|
if type(times) in (tuple, list):
|
||||||
|
if 6 <= len(times) <= 8:
|
||||||
|
return '{0:04d}-{1:02d}-{2:02d} {3:02d}:{4:02d}:{5:02d}'.format(*times)
|
||||||
|
else:
|
||||||
|
raise ValueError("Settime needs a type of length 6~8")
|
||||||
|
|
||||||
|
def rfc1123_time(times=None, utc=28800):
|
||||||
|
if times is None:
|
||||||
|
times = localtime()
|
||||||
|
if isinstance(times, str):
|
||||||
|
try:
|
||||||
|
times = eval(times)
|
||||||
|
except:
|
||||||
|
raise ValueError("Clock information format error, use ',' to separate at least 6 numerical values")
|
||||||
|
if type(times) in (tuple, list):
|
||||||
|
if 6 <= len(times) <= 8:
|
||||||
|
times = localtime(mktime(times) - utc)
|
||||||
|
return '{0}, {1:02d} {2} {3:04d} {4:02d}:{5:02d}:{6:02d} GMT'.format(_weekdayname[times[6]], times[2], _monthname[times[1]], times[0], times[3], times[4], times[5])
|
||||||
|
else:
|
||||||
|
raise ValueError("Settime needs a type of length 6~8")
|
||||||
72
mixly/boards/default/micropython/build/lib/sc7a20.py
Normal file
72
mixly/boards/default/micropython/build/lib/sc7a20.py
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
"""
|
||||||
|
SC7A20
|
||||||
|
|
||||||
|
Micropython library for the SC7A20 Accelerometer
|
||||||
|
=================================================
|
||||||
|
#Preliminary composition 20240312
|
||||||
|
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from math import atan,sqrt,degrees
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
SC7A20_ADDRESS = const(0x19)
|
||||||
|
SC7A20_REG_ID = const(0x0F)
|
||||||
|
SC7A20_REG_CTRL1 = const(0x20)
|
||||||
|
SC7A20_REG_CTRL2 = const(0x21)
|
||||||
|
SC7A20_REG_CTRL3 = const(0x22)
|
||||||
|
SC7A20_REG_CTRL4 = const(0x23)
|
||||||
|
SC7A20_REG_DATA = const(0x28)
|
||||||
|
|
||||||
|
#2g 4g 8g 16g
|
||||||
|
_Range_X = (1024,512,256,128)
|
||||||
|
|
||||||
|
class SC7A20:
|
||||||
|
|
||||||
|
def __init__(self, i2c_bus, set_range=2, front=False):
|
||||||
|
self._device = i2c_bus
|
||||||
|
self._address = SC7A20_ADDRESS
|
||||||
|
self._range = set_range #default 8g range
|
||||||
|
self._front = front
|
||||||
|
|
||||||
|
if self._rreg(SC7A20_REG_ID) != 0x11:
|
||||||
|
raise AttributeError("Cannot find a SC7A20")
|
||||||
|
self._wreg(SC7A20_REG_CTRL1, 0X77) #400HZ,xyz使能
|
||||||
|
self._wreg(SC7A20_REG_CTRL2, 0X00) #禁止高通滤波模式
|
||||||
|
self._wreg(SC7A20_REG_CTRL3, 0X00) #禁止中断
|
||||||
|
self._wreg(SC7A20_REG_CTRL4, 0X00 | set_range << 4) #连续更新,设置量程
|
||||||
|
|
||||||
|
def _wreg(self, reg, val):
|
||||||
|
'''Write memory address'''
|
||||||
|
self._device.writeto_mem(self._address,reg,val.to_bytes(1, 'little'))
|
||||||
|
|
||||||
|
def _rreg(self, reg):
|
||||||
|
'''Read memory address'''
|
||||||
|
return self._device.readfrom_mem(self._address, reg, 1)[0]
|
||||||
|
|
||||||
|
def u2s(self, n):
|
||||||
|
return n if n < (1 << 7) else n - (1 << 8)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def getdata(self):
|
||||||
|
x_acc = ((self.u2s(self._rreg(SC7A20_REG_DATA + 1)) << 8 | self._rreg(SC7A20_REG_DATA + 0)) >> 4) / _Range_X[self._range]
|
||||||
|
y_acc = ((self.u2s(self._rreg(SC7A20_REG_DATA + 3)) << 8 | self._rreg(SC7A20_REG_DATA + 2)) >> 4) / _Range_X[self._range]
|
||||||
|
z_acc = ((self.u2s(self._rreg(SC7A20_REG_DATA + 5)) << 8 | self._rreg(SC7A20_REG_DATA + 4)) >> 4) / _Range_X[self._range]
|
||||||
|
return (-x_acc, y_acc, z_acc, None) if self._front else (x_acc, y_acc, z_acc, None)
|
||||||
|
|
||||||
|
def acceleration(self):
|
||||||
|
return self.getdata[0:3]
|
||||||
|
|
||||||
|
def strength(self):
|
||||||
|
from math import sqrt
|
||||||
|
return sqrt(self.getdata[0]**2+self.getdata[1]**2+self.getdata[2]**2)
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
return self.getdata[3]
|
||||||
|
|
||||||
|
def eulerangles(self,upright=False):
|
||||||
|
x, y, z = self.acceleration()
|
||||||
|
pitch = degrees(atan(z / sqrt(x ** 2 + y ** 2))) if upright else degrees(atan(y / sqrt(x ** 2 + z ** 2)))
|
||||||
|
roll = degrees(atan(x / sqrt(y ** 2 + z ** 2)))
|
||||||
|
return round(pitch,2),round(roll,2)
|
||||||
231
mixly/boards/default/micropython/build/lib/sdcard.py
Normal file
231
mixly/boards/default/micropython/build/lib/sdcard.py
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
"""
|
||||||
|
MicroPython driver for SD cards using SPI bus.
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
from machine import Pin
|
||||||
|
from micropython import const
|
||||||
|
|
||||||
|
_CMD_TIMEOUT = const(100)
|
||||||
|
_R1_IDLE_STATE = const(1 << 0)
|
||||||
|
_R1_ILLEGAL_COMMAND = const(1 << 2)
|
||||||
|
_TOKEN_CMD25 = const(0xFC)
|
||||||
|
_TOKEN_STOP_TRAN = const(0xFD)
|
||||||
|
_TOKEN_DATA = const(0xFE)
|
||||||
|
|
||||||
|
class SDCard:
|
||||||
|
def __init__(self, spi, cs_pin=None, baudrate=50000000):
|
||||||
|
self.spi = spi
|
||||||
|
self.cs = Pin(cs_pin, Pin.OUT, value=1) if cs_pin else None
|
||||||
|
self.cmdbuf = bytearray(6)
|
||||||
|
self.dummybuf = bytearray(512)
|
||||||
|
self.tokenbuf = bytearray(1)
|
||||||
|
for i in range(512):
|
||||||
|
self.dummybuf[i] = 0xFF
|
||||||
|
self.dummybuf_memoryview = memoryview(self.dummybuf)
|
||||||
|
# initialise the card
|
||||||
|
self.init_card(baudrate)
|
||||||
|
|
||||||
|
def init_spi(self, baudrate):
|
||||||
|
self.spi.init(baudrate=baudrate, phase=0, polarity=0)
|
||||||
|
|
||||||
|
def init_card(self, baudrate):
|
||||||
|
# init SPI bus; use low data rate for initialisation
|
||||||
|
self.init_spi(100000)
|
||||||
|
# clock card at least 100 cycles with cs high
|
||||||
|
for i in range(16):
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
# CMD0: init card; should return _R1_IDLE_STATE (allow 5 attempts)
|
||||||
|
for _ in range(5):
|
||||||
|
if self.cmd(0, 0, 0x95) == _R1_IDLE_STATE:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise OSError("no SD card")
|
||||||
|
# CMD8: determine card version
|
||||||
|
r = self.cmd(8, 0x01AA, 0x87, 4)
|
||||||
|
if r == _R1_IDLE_STATE:
|
||||||
|
self.init_card_v2()
|
||||||
|
elif r == (_R1_IDLE_STATE | _R1_ILLEGAL_COMMAND):
|
||||||
|
self.init_card_v1()
|
||||||
|
else:
|
||||||
|
raise OSError("couldn't determine SD card version")
|
||||||
|
# CMD9: response R2 (R1 byte + 16-byte block read)
|
||||||
|
if self.cmd(9, 0, 0, 0, False) != 0:
|
||||||
|
raise OSError("no response from SD card")
|
||||||
|
csd = bytearray(16)
|
||||||
|
self.readinto(csd)
|
||||||
|
if csd[0] & 0xC0 == 0x40: # CSD version 2.0
|
||||||
|
self.sectors = ((csd[8] << 8 | csd[9]) + 1) * 1024
|
||||||
|
elif csd[0] & 0xC0 == 0x00: # CSD version 1.0 (old, <=2GB)
|
||||||
|
c_size = (csd[6] & 0b11) << 10 | csd[7] << 2 | csd[8] >> 6
|
||||||
|
c_size_mult = (csd[9] & 0b11) << 1 | csd[10] >> 7
|
||||||
|
read_bl_len = csd[5] & 0b1111
|
||||||
|
capacity = (c_size + 1) * (2 ** (c_size_mult + 2)) * (2**read_bl_len)
|
||||||
|
self.sectors = capacity // 512
|
||||||
|
else:
|
||||||
|
raise OSError("SD card CSD format not supported")
|
||||||
|
# CMD16: set block length to 512 bytes
|
||||||
|
if self.cmd(16, 512, 0) != 0:
|
||||||
|
raise OSError("can't set 512 block size")
|
||||||
|
# set to high data rate now that it's initialised
|
||||||
|
self.init_spi(baudrate)
|
||||||
|
|
||||||
|
def init_card_v1(self):
|
||||||
|
for i in range(_CMD_TIMEOUT):
|
||||||
|
time.sleep_ms(50)
|
||||||
|
self.cmd(55, 0, 0)
|
||||||
|
if self.cmd(41, 0, 0) == 0:
|
||||||
|
# SDSC card, uses byte addressing in read/write/erase commands
|
||||||
|
self.cdv = 512
|
||||||
|
# print("[SDCard] v1 card")
|
||||||
|
return
|
||||||
|
raise OSError("timeout waiting for v1 card")
|
||||||
|
|
||||||
|
def init_card_v2(self):
|
||||||
|
for i in range(_CMD_TIMEOUT):
|
||||||
|
time.sleep_ms(50)
|
||||||
|
self.cmd(58, 0, 0, 4)
|
||||||
|
self.cmd(55, 0, 0)
|
||||||
|
if self.cmd(41, 0x40000000, 0) == 0:
|
||||||
|
self.cmd(58, 0, 0, -4) # 4-byte response, negative means keep the first byte
|
||||||
|
ocr = self.tokenbuf[0] # get first byte of response, which is OCR
|
||||||
|
if not ocr & 0x40:
|
||||||
|
# SDSC card, uses byte addressing in read/write/erase commands
|
||||||
|
self.cdv = 512
|
||||||
|
else:
|
||||||
|
# SDHC/SDXC card, uses block addressing in read/write/erase commands
|
||||||
|
self.cdv = 1
|
||||||
|
# print("[SDCard] v2 card")
|
||||||
|
return
|
||||||
|
raise OSError("timeout waiting for v2 card")
|
||||||
|
|
||||||
|
def cmd(self, cmd, arg, crc, final=0, release=True, skip1=False):
|
||||||
|
if self.cs: self.cs(0)
|
||||||
|
|
||||||
|
# create and send the command
|
||||||
|
buf = self.cmdbuf
|
||||||
|
buf[0] = 0x40 | cmd
|
||||||
|
buf[1] = arg >> 24
|
||||||
|
buf[2] = arg >> 16
|
||||||
|
buf[3] = arg >> 8
|
||||||
|
buf[4] = arg
|
||||||
|
buf[5] = crc
|
||||||
|
self.spi.write(buf)
|
||||||
|
|
||||||
|
if skip1:
|
||||||
|
self.spi.readinto(self.tokenbuf, 0xFF)
|
||||||
|
# wait for the response (response[7] == 0)
|
||||||
|
for i in range(_CMD_TIMEOUT):
|
||||||
|
self.spi.readinto(self.tokenbuf, 0xFF)
|
||||||
|
response = self.tokenbuf[0]
|
||||||
|
if not (response & 0x80):
|
||||||
|
if final < 0:
|
||||||
|
self.spi.readinto(self.tokenbuf, 0xFF)
|
||||||
|
final = -1 - final
|
||||||
|
for j in range(final):
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
if release:
|
||||||
|
if self.cs: self.cs(1)
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
return response
|
||||||
|
if self.cs: self.cs(1)
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def readinto(self, buf):
|
||||||
|
if self.cs: self.cs(0)
|
||||||
|
for i in range(_CMD_TIMEOUT):
|
||||||
|
self.spi.readinto(self.tokenbuf, 0xFF)
|
||||||
|
if self.tokenbuf[0] == _TOKEN_DATA:
|
||||||
|
break
|
||||||
|
time.sleep_ms(1)
|
||||||
|
else:
|
||||||
|
if self.cs: self.cs(1)
|
||||||
|
raise OSError("timeout waiting for response")
|
||||||
|
mv = self.dummybuf_memoryview
|
||||||
|
if len(buf) != len(mv):
|
||||||
|
mv = mv[: len(buf)]
|
||||||
|
self.spi.write_readinto(mv, buf)
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
if self.cs: self.cs(1)
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
|
||||||
|
def write(self, token, buf):
|
||||||
|
if self.cs: self.cs(0)
|
||||||
|
self.spi.read(1, token)
|
||||||
|
self.spi.write(buf)
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
if (self.spi.read(1, 0xFF)[0] & 0x1F) != 0x05:
|
||||||
|
if self.cs: self.cs(1)
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
return
|
||||||
|
while self.spi.read(1, 0xFF)[0] == 0:
|
||||||
|
pass
|
||||||
|
if self.cs: self.cs(1)
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
|
||||||
|
def write_token(self, token):
|
||||||
|
if self.cs: self.cs(0)
|
||||||
|
self.spi.read(1, token)
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
while self.spi.read(1, 0xFF)[0] == 0x00:
|
||||||
|
pass
|
||||||
|
if self.cs: self.cs(1)
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
|
||||||
|
def readblocks(self, block_num, buf):
|
||||||
|
# workaround for shared bus, required for (at least) some Kingston
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
|
||||||
|
nblocks = len(buf) // 512
|
||||||
|
assert nblocks and not len(buf) % 512, "Buffer length is invalid"
|
||||||
|
if nblocks == 1:
|
||||||
|
# CMD17: set read address for single block
|
||||||
|
if self.cmd(17, block_num * self.cdv, 0, release=False) != 0:
|
||||||
|
# release the card
|
||||||
|
if self.cs: self.cs(1)
|
||||||
|
raise OSError(5) # EIO
|
||||||
|
# receive the data and release card
|
||||||
|
self.readinto(buf)
|
||||||
|
else:
|
||||||
|
# CMD18: set read address for multiple blocks
|
||||||
|
if self.cmd(18, block_num * self.cdv, 0, release=False) != 0:
|
||||||
|
if self.cs: self.cs(1)
|
||||||
|
raise OSError(5) # EIO
|
||||||
|
offset = 0
|
||||||
|
mv = memoryview(buf)
|
||||||
|
while nblocks:
|
||||||
|
self.readinto(mv[offset : offset + 512])
|
||||||
|
offset += 512
|
||||||
|
nblocks -= 1
|
||||||
|
if self.cmd(12, 0, 0xFF, skip1=True):
|
||||||
|
raise OSError(5) # EIO
|
||||||
|
|
||||||
|
def writeblocks(self, block_num, buf):
|
||||||
|
# workaround for shared bus, required for (at least) some Kingston
|
||||||
|
self.spi.write(b"\xff")
|
||||||
|
nblocks, err = divmod(len(buf), 512)
|
||||||
|
assert nblocks and not err, "Buffer length is invalid"
|
||||||
|
if nblocks == 1:
|
||||||
|
# CMD24: set write address for single block
|
||||||
|
if self.cmd(24, block_num * self.cdv, 0) != 0:
|
||||||
|
raise OSError(5) # EIO
|
||||||
|
self.write(_TOKEN_DATA, buf)
|
||||||
|
else:
|
||||||
|
# CMD25: set write address for first block
|
||||||
|
if self.cmd(25, block_num * self.cdv, 0) != 0:
|
||||||
|
raise OSError(5) # EIO
|
||||||
|
offset = 0
|
||||||
|
mv = memoryview(buf)
|
||||||
|
while nblocks:
|
||||||
|
self.write(_TOKEN_CMD25, mv[offset : offset + 512])
|
||||||
|
offset += 512
|
||||||
|
nblocks -= 1
|
||||||
|
self.write_token(_TOKEN_STOP_TRAN)
|
||||||
|
|
||||||
|
def ioctl(self, op, arg):
|
||||||
|
if op == 4: # get number of blocks
|
||||||
|
return self.sectors
|
||||||
|
if op == 5: # get block size in bytes
|
||||||
|
return 512
|
||||||
217
mixly/boards/default/micropython/build/lib/seniverse_api.py
Normal file
217
mixly/boards/default/micropython/build/lib/seniverse_api.py
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
"""
|
||||||
|
Seniverse Weather API
|
||||||
|
|
||||||
|
MicroPython library for Seniverse Weather API
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20220420
|
||||||
|
#https://www.seniverse.com/api
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import urequests
|
||||||
|
|
||||||
|
_weather_now="http://api.seniverse.com/v3/weather/now.json?" #天气实况
|
||||||
|
_weather_daily="http://api.seniverse.com/v3/weather/daily.json?" #逐日天气预报
|
||||||
|
_weather_hourly="http://api.seniverse.com/v3/weather/hourly.json?" #逐时天气预报
|
||||||
|
_weather_alarm="http://api.seniverse.com/v3/weather/alarm.json?" #气象灾害预警
|
||||||
|
_life_suggestion="http://api.seniverse.com/v3/life/suggestion.json?" #生活指数
|
||||||
|
_air_now="http://api.seniverse.com/v3/air/now.json?" #空气质量实况
|
||||||
|
_air_daily="http://api.seniverse.com/v3/air/daily.json?" #逐日空气质量预报
|
||||||
|
_air_hourly="http://api.seniverse.com/v3/air/hourly.json?" #逐时空气质量预报
|
||||||
|
_tide_daily="http://api.seniverse.com/v3/tide/daily.json?" #逐时潮汐预报
|
||||||
|
_geo_sun="http://api.seniverse.com/v3/geo/sun.json?" #日出日落
|
||||||
|
_geo_moon="http://api.seniverse.com/v3/geo/moon.json?" #月出月落和月相
|
||||||
|
_location_search="http://api.seniverse.com/v3/location/search.json?" #城市搜索
|
||||||
|
|
||||||
|
#数据请求
|
||||||
|
class API_BASE:
|
||||||
|
_results = None
|
||||||
|
def _urequests_api(self, url):
|
||||||
|
try:
|
||||||
|
results=json.loads(urequests.post(url).text)
|
||||||
|
except Exception as e:
|
||||||
|
raise RuntimeError("API request failed or WiFi is not connected",e)
|
||||||
|
|
||||||
|
if "status" in results.keys():
|
||||||
|
raise ValueError(results["status"])
|
||||||
|
if "results" in results.keys():
|
||||||
|
return results["results"]
|
||||||
|
|
||||||
|
#天气实况 https://docs.seniverse.com/api/weather/now.html
|
||||||
|
class Weather_now(API_BASE):
|
||||||
|
def request(self, key, location):
|
||||||
|
url = "{}key={}&location={}".format(_weather_now, key, location)
|
||||||
|
self._results = self._urequests_api(url)[0]['now']
|
||||||
|
|
||||||
|
def analysis(self, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results
|
||||||
|
else:
|
||||||
|
return self._results[key]
|
||||||
|
|
||||||
|
Weather_now = Weather_now()
|
||||||
|
|
||||||
|
#逐日天气预报 https://docs.seniverse.com/api/weather/daily.html
|
||||||
|
class Weather_daily(API_BASE):
|
||||||
|
def request(self, key, location, days=1):
|
||||||
|
url = "{}key={}&location={}&days={}".format(_weather_daily, key, location, days)
|
||||||
|
self._results = self._urequests_api(url)[0]['daily']
|
||||||
|
|
||||||
|
def analysis(self, days=1, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results[days]
|
||||||
|
else:
|
||||||
|
return self._results[days][key]
|
||||||
|
|
||||||
|
Weather_daily = Weather_daily()
|
||||||
|
|
||||||
|
#逐时天气预报 https://docs.seniverse.com/api/weather/hourly.html
|
||||||
|
class Weather_hourly(API_BASE):
|
||||||
|
def request(self, key, location, hours=1):
|
||||||
|
url = "{}key={}&location={}&hours={}".format(_weather_hourly, key, location, hours)
|
||||||
|
self._results = self._urequests_api(url)[0]['hourly']
|
||||||
|
|
||||||
|
def analysis(self, hours=1, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results[hours]
|
||||||
|
else:
|
||||||
|
return self._results[hours][key]
|
||||||
|
|
||||||
|
#Weather_hourly = Weather_hourly() #暂不开启
|
||||||
|
|
||||||
|
#空气质量实况 https://docs.seniverse.com/api/air/now.html
|
||||||
|
class Air_now(API_BASE):
|
||||||
|
def request(self, key, location):
|
||||||
|
url = "{}key={}&location={}&scope=city".format(_air_now, key, location)
|
||||||
|
self._results = self._urequests_api(url)[0]['air']['city']
|
||||||
|
|
||||||
|
def analysis(self, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results
|
||||||
|
else:
|
||||||
|
return self._results[key]
|
||||||
|
|
||||||
|
Air_now = Air_now()
|
||||||
|
|
||||||
|
#逐日空气质量预报 https://docs.seniverse.com/api/air/daily5d.html
|
||||||
|
class Air_daily(API_BASE):
|
||||||
|
def request(self, key, location, days=1):
|
||||||
|
url = "{}key={}&location={}&days={}".format(_air_daily, key, location, days)
|
||||||
|
self._results = self._urequests_api(url)[0]['daily']
|
||||||
|
|
||||||
|
def analysis(self, days=1, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results[days]
|
||||||
|
else:
|
||||||
|
return self._results[days][key]
|
||||||
|
|
||||||
|
Air_daily= Air_daily()
|
||||||
|
|
||||||
|
#逐时空气质量预报 https://docs.seniverse.com/api/air/hourly5d.html
|
||||||
|
class Air_hourly(API_BASE):
|
||||||
|
def request(self, key, location, hours=1):
|
||||||
|
url = "{}key={}&location={}&hours={}&days=1".format(_air_hourly, key, location, hours)
|
||||||
|
self._results = self._urequests_api(url)[0]['hourly']
|
||||||
|
|
||||||
|
def analysis(self, hours=1, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results[hours]
|
||||||
|
else:
|
||||||
|
return self._results[hours][key]
|
||||||
|
|
||||||
|
#Air_hourly = Air_hourly() #暂不开启
|
||||||
|
|
||||||
|
#气象灾害预警 https://docs.seniverse.com/api/weather/alarm.html
|
||||||
|
class Weather_alarm(API_BASE):
|
||||||
|
def request(self, key, location):
|
||||||
|
url = "{}key={}&location={}".format(_weather_alarm, key, location)
|
||||||
|
results = self._urequests_api(url)[0]['alarms']
|
||||||
|
self._results = results[0] if results else {}
|
||||||
|
|
||||||
|
def analysis(self, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results
|
||||||
|
if key in self._results.keys():
|
||||||
|
return self._results[key]
|
||||||
|
|
||||||
|
Weather_alarm = Weather_alarm()
|
||||||
|
|
||||||
|
#生活指数 https://docs.seniverse.com/api/life/suggestion.html
|
||||||
|
class Life_suggestion(API_BASE):
|
||||||
|
def request(self, key, location):
|
||||||
|
url = "{}key={}&location={}".format(_life_suggestion, key, location)
|
||||||
|
self._results = self._urequests_api(url)[0]['suggestion']
|
||||||
|
|
||||||
|
def analysis(self, key=None, brief=False):
|
||||||
|
if key is None:
|
||||||
|
return self._results
|
||||||
|
else:
|
||||||
|
return self._results[key]['brief'] if brief else self._results[key]['details']
|
||||||
|
|
||||||
|
Life_suggestion = Life_suggestion()
|
||||||
|
|
||||||
|
#24时潮汐预报 https://docs.seniverse.com/api/ocean/tide.html
|
||||||
|
class Tide_daily(API_BASE):
|
||||||
|
def request(self, key, location):
|
||||||
|
url = "{}key={}&location={}&days=1".format(_tide_daily, key, location)
|
||||||
|
self._results = self._urequests_api(url)[0]['ports'][0]['data'][0]
|
||||||
|
|
||||||
|
def analysis(self, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results
|
||||||
|
else:
|
||||||
|
key = key.split(',')
|
||||||
|
if len(key) == 1:
|
||||||
|
return self._results[key[0]]
|
||||||
|
if len(key) == 2:
|
||||||
|
return self._results['range'][int(key[0])][key[1]]
|
||||||
|
|
||||||
|
Tide_daily = Tide_daily()
|
||||||
|
|
||||||
|
#日出日落 https://docs.seniverse.com/api/geo/sun.html
|
||||||
|
class Geo_sun(API_BASE):
|
||||||
|
def request(self, key, location, days=1):
|
||||||
|
url = "{}key={}&location={}&days={}".format(_geo_sun, key, location, days)
|
||||||
|
self._results = self._urequests_api(url)[0]['sun']
|
||||||
|
|
||||||
|
def analysis(self, days=1, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results[days]
|
||||||
|
else:
|
||||||
|
return self._results[days][key]
|
||||||
|
|
||||||
|
Geo_sun = Geo_sun()
|
||||||
|
|
||||||
|
#月出月落和月相 https://docs.seniverse.com/api/geo/moon.html
|
||||||
|
class Geo_moon(API_BASE):
|
||||||
|
def request(self, key, location, days=1):
|
||||||
|
url = "{}key={}&location={}&days={}".format(_geo_moon, key, location, days)
|
||||||
|
self._results = self._urequests_api(url)[0]['moon']
|
||||||
|
|
||||||
|
def analysis(self, days=1, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results[days]
|
||||||
|
else:
|
||||||
|
return self._results[days][key]
|
||||||
|
|
||||||
|
Geo_moon = Geo_moon()
|
||||||
|
|
||||||
|
#城市搜索 https://docs.seniverse.com/api/fct/search.html
|
||||||
|
class Location_search(API_BASE):
|
||||||
|
def request(self, key, location):
|
||||||
|
url = "{}key={}&q={}&limit=50".format(_location_search, key, location)
|
||||||
|
results = self._urequests_api(url)
|
||||||
|
self._results = results[0] if results else {}
|
||||||
|
|
||||||
|
def analysis(self, key=None):
|
||||||
|
if key is None:
|
||||||
|
return self._results
|
||||||
|
else:
|
||||||
|
if key in self._results.keys():
|
||||||
|
return self._results[key]
|
||||||
|
|
||||||
|
Location_search = Location_search()
|
||||||
|
|
||||||
53
mixly/boards/default/micropython/build/lib/servo.py
Normal file
53
mixly/boards/default/micropython/build/lib/servo.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
"""
|
||||||
|
Servo
|
||||||
|
|
||||||
|
MicroPython library for the Servo(0~180°)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20220803
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from machine import Pin,PWM
|
||||||
|
|
||||||
|
class Servo:
|
||||||
|
__species = {}
|
||||||
|
__first_init = True
|
||||||
|
|
||||||
|
def __new__(cls, pin, *args, **kwargs):
|
||||||
|
if pin not in cls.__species.keys():
|
||||||
|
cls.__first_init = True
|
||||||
|
cls.__species[pin]=object.__new__(cls)
|
||||||
|
return cls.__species[pin]
|
||||||
|
|
||||||
|
def __init__(self,pin):
|
||||||
|
if self.__first_init:
|
||||||
|
self.__first_init = False
|
||||||
|
self._pulse=None
|
||||||
|
self.pwm = PWM(Pin(pin), duty=0, freq=50)
|
||||||
|
|
||||||
|
def servo_write(self,pulse):
|
||||||
|
self._pulse=pulse
|
||||||
|
self.pwm.duty_u16(int(1638.375 + 6553.5 * pulse))
|
||||||
|
|
||||||
|
def servo_read(self):
|
||||||
|
return self._pulse
|
||||||
|
|
||||||
|
#-------Method usage of class--------
|
||||||
|
|
||||||
|
def servo180_angle(pin,angle=None):
|
||||||
|
if angle is None:
|
||||||
|
return int(Servo(pin).servo_read()*180)
|
||||||
|
else:
|
||||||
|
if not 0<= angle <= 180:
|
||||||
|
raise ValueError("The effective range of the servo(180) angle is 0~180°")
|
||||||
|
Servo(pin).servo_write(angle/180)
|
||||||
|
|
||||||
|
|
||||||
|
def servo360_speed(pin,speed=None):
|
||||||
|
if speed is None:
|
||||||
|
return int(Servo(pin).servo_read()*200-100)
|
||||||
|
else:
|
||||||
|
if not -100<= speed <= 100:
|
||||||
|
raise ValueError("The effective range of the servo(360) speed is -100~100%")
|
||||||
|
Servo(pin).servo_write((speed+100)/200)
|
||||||
37
mixly/boards/default/micropython/build/lib/sht20.py
Normal file
37
mixly/boards/default/micropython/build/lib/sht20.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
from struct import unpack as unp
|
||||||
|
from time import sleep_ms
|
||||||
|
|
||||||
|
# SHT20 default address
|
||||||
|
SHT20_I2CADDR = 64
|
||||||
|
TRI_T_MEASURE_NO_HOLD = b'\xf3'
|
||||||
|
TRI_RH_MEASURE_NO_HOLD = b'\xf5'
|
||||||
|
READ_USER_REG = b'\xe7'
|
||||||
|
WRITE_USER_REG = b'\xe6'
|
||||||
|
SOFT_RESET = b'\xfe'
|
||||||
|
|
||||||
|
class SHT20(object):
|
||||||
|
def __init__(self, i2c_bus):
|
||||||
|
self._address = SHT20_I2CADDR
|
||||||
|
self._bus = i2c_bus
|
||||||
|
|
||||||
|
def get_SHT_temperature(self):
|
||||||
|
self._bus.writeto(self._address, TRI_T_MEASURE_NO_HOLD)
|
||||||
|
sleep_ms(150)
|
||||||
|
origin_data = self._bus.readfrom(self._address, 2)
|
||||||
|
origin_value = unp('>h', origin_data)[0]
|
||||||
|
value = -46.85 + 175.72 * (origin_value / 65536)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def get_SHT_relative_humidity(self):
|
||||||
|
self._bus.writeto(self._address, TRI_RH_MEASURE_NO_HOLD)
|
||||||
|
sleep_ms(150)
|
||||||
|
origin_data = self._bus.readfrom(self._address, 2)
|
||||||
|
origin_value = unp('>H', origin_data)[0]
|
||||||
|
value = -6 + 125 * (origin_value / 65536)
|
||||||
|
return value
|
||||||
|
|
||||||
|
def humidity(self):
|
||||||
|
return self.get_SHT_relative_humidity()
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
return self.get_SHT_temperature()
|
||||||
134
mixly/boards/default/micropython/build/lib/shtc3.py
Normal file
134
mixly/boards/default/micropython/build/lib/shtc3.py
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
"""
|
||||||
|
SHTC3
|
||||||
|
|
||||||
|
MicroPython library for the SHTC3(Humidity and Temperature)
|
||||||
|
=======================================================
|
||||||
|
|
||||||
|
#Preliminary composition 20220224
|
||||||
|
#https://github.com/adafruit/Adafruit_CircuitPython_SHTC3.git
|
||||||
|
|
||||||
|
dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
|
||||||
|
from time import sleep
|
||||||
|
from micropython import const
|
||||||
|
from struct import unpack_from
|
||||||
|
|
||||||
|
_SHTC3_DEFAULT_ADDR = const(0x70) # SHTC3 I2C Address
|
||||||
|
_SHTC3_READID = const(0xEFC8) # Read Out of ID Register
|
||||||
|
_SHTC3_SOFTRESET = const(0x805D) # Soft Reset
|
||||||
|
_SHTC3_SLEEP = const(0xB098) # Enter sleep mode
|
||||||
|
_SHTC3_WAKEUP = const(0x3517) # Wakeup mode
|
||||||
|
_SHTC3_CHIP_ID = const(0x807)
|
||||||
|
_SHTC3_NORMAL_MEAS = const(0x7866)
|
||||||
|
_SHTC3_LOWPOW_MEAS = const(0x609C)
|
||||||
|
|
||||||
|
class SHTC3:
|
||||||
|
def __init__(self, i2c_bus, addr = _SHTC3_DEFAULT_ADDR):
|
||||||
|
self._device= i2c_bus
|
||||||
|
self._address = addr
|
||||||
|
self._buffer = bytearray(6)
|
||||||
|
self.low_power = False
|
||||||
|
self.sleeping = False
|
||||||
|
self.reset()
|
||||||
|
if self._get_chip_id() != _SHTC3_CHIP_ID:
|
||||||
|
raise AttributeError("Cannot find a SHTC3")
|
||||||
|
|
||||||
|
def _write_command(self, command):
|
||||||
|
"""helper function to write a command to the i2c device"""
|
||||||
|
self._buffer[0] = command >> 8
|
||||||
|
self._buffer[1] = command & 0xFF
|
||||||
|
self._device.writeto(self._address,self._buffer[0:2])
|
||||||
|
|
||||||
|
def _get_chip_id(self): # readCommand(SHTC3_READID, data, 3);
|
||||||
|
"""Determines the chip id of the sensor"""
|
||||||
|
self._write_command(_SHTC3_READID)
|
||||||
|
sleep(0.001)
|
||||||
|
self._device.readfrom_into(self._address,self._buffer)
|
||||||
|
return unpack_from(">H", self._buffer)[0] & 0x083F
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
"""Perform a soft reset of the sensor, resetting all settings to their power-on defaults"""
|
||||||
|
self.sleeping = False
|
||||||
|
try:
|
||||||
|
self._write_command(_SHTC3_SOFTRESET)
|
||||||
|
|
||||||
|
except RuntimeError as run_err:
|
||||||
|
if run_err.args and run_err.args[0] != "I2C device address was NACK'd":
|
||||||
|
raise run_err
|
||||||
|
sleep(0.001)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def sleeping(self):
|
||||||
|
"""Determines the sleep state of the sensor"""
|
||||||
|
return self._cached_sleep
|
||||||
|
|
||||||
|
@sleeping.setter
|
||||||
|
def sleeping(self, sleep_enabled):
|
||||||
|
if sleep_enabled:
|
||||||
|
self._write_command(_SHTC3_SLEEP)
|
||||||
|
else:
|
||||||
|
self._write_command(_SHTC3_WAKEUP)
|
||||||
|
sleep(0.001)
|
||||||
|
self._cached_sleep = sleep_enabled
|
||||||
|
|
||||||
|
@property
|
||||||
|
def low_power(self):
|
||||||
|
"""Enables the less accurate low power mode, trading accuracy for power consumption"""
|
||||||
|
return self._low_power
|
||||||
|
|
||||||
|
@low_power.setter
|
||||||
|
def low_power(self, low_power_enabled):
|
||||||
|
self._low_power = low_power_enabled
|
||||||
|
|
||||||
|
@property
|
||||||
|
def measurements(self):
|
||||||
|
"""both `temperature` and `relative_humidity`, read simultaneously"""
|
||||||
|
self.sleeping = False
|
||||||
|
temperature = None
|
||||||
|
humidity = None
|
||||||
|
if self.low_power:
|
||||||
|
self._write_command(_SHTC3_LOWPOW_MEAS)
|
||||||
|
sleep(0.001)
|
||||||
|
else:
|
||||||
|
self._write_command(_SHTC3_NORMAL_MEAS)
|
||||||
|
sleep(0.013)
|
||||||
|
|
||||||
|
self._device.readfrom_into(self._address,self._buffer)
|
||||||
|
|
||||||
|
temp_data = self._buffer[0:2]
|
||||||
|
temp_crc = self._buffer[2]
|
||||||
|
humidity_data = self._buffer[3:5]
|
||||||
|
humidity_crc = self._buffer[5]
|
||||||
|
|
||||||
|
if temp_crc != self._crc8(temp_data) or humidity_crc != self._crc8(humidity_data):
|
||||||
|
return
|
||||||
|
|
||||||
|
raw_temp = unpack_from(">H", temp_data)[0]
|
||||||
|
raw_temp = ((4375 * raw_temp) >> 14) - 4500
|
||||||
|
temperature = raw_temp / 100.0
|
||||||
|
raw_humidity = unpack_from(">H", humidity_data)[0]
|
||||||
|
raw_humidity = (625 * raw_humidity) >> 12
|
||||||
|
humidity = raw_humidity / 100.0
|
||||||
|
|
||||||
|
self.sleeping = True
|
||||||
|
return (temperature, humidity)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _crc8(buffer):
|
||||||
|
"""verify the crc8 checksum"""
|
||||||
|
crc = 0xFF
|
||||||
|
for byte in buffer:
|
||||||
|
crc ^= byte
|
||||||
|
for _ in range(8):
|
||||||
|
if crc & 0x80:
|
||||||
|
crc = (crc << 1) ^ 0x31
|
||||||
|
else:
|
||||||
|
crc = crc << 1
|
||||||
|
return crc & 0xFF # return the bottom 8 bits
|
||||||
|
|
||||||
|
def humidity(self):
|
||||||
|
return self.measurements[1]
|
||||||
|
|
||||||
|
def temperature(self):
|
||||||
|
return self.measurements[0]
|
||||||
39
mixly/boards/default/micropython/build/lib/sonar.py
Normal file
39
mixly/boards/default/micropython/build/lib/sonar.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
"""
|
||||||
|
CS100/HC-SR04
|
||||||
|
|
||||||
|
Micropython library for the CS100/HC-SR04(Ultrasonic ranging)
|
||||||
|
=======================================================
|
||||||
|
@dahanzimin From the Mixly Team
|
||||||
|
"""
|
||||||
|
from time import sleep_us
|
||||||
|
from machine import Pin, time_pulse_us
|
||||||
|
|
||||||
|
class Sonar:
|
||||||
|
__species = {}
|
||||||
|
__first_init = True
|
||||||
|
|
||||||
|
def __new__(cls, trig, echo, *args, **kwargs):
|
||||||
|
if (trig, echo) not in cls.__species.keys():
|
||||||
|
cls.__first_init = True
|
||||||
|
cls.__species[(trig, echo) ] = object.__new__(cls)
|
||||||
|
return cls.__species[(trig, echo)]
|
||||||
|
|
||||||
|
def __init__(self, trig, echo, max_rang=400):
|
||||||
|
if self.__first_init:
|
||||||
|
self.__first_init = False
|
||||||
|
self.trig = Pin(trig, Pin.OUT, value=0)
|
||||||
|
self.echo = Pin(echo, Pin.IN)
|
||||||
|
self.timeout_us = int(max_rang * 2 * 29.1)
|
||||||
|
|
||||||
|
def checkdist(self):
|
||||||
|
self.trig.value(0)
|
||||||
|
sleep_us(5)
|
||||||
|
self.trig.value(1)
|
||||||
|
sleep_us(10)
|
||||||
|
self.trig.value(0)
|
||||||
|
try:
|
||||||
|
pulse_time = time_pulse_us(self.echo, 1, self.timeout_us)
|
||||||
|
pulse_time = pulse_time if pulse_time >= 0 else self.timeout_us
|
||||||
|
return round(pulse_time / 2 / 29.1, 2) # 1cm each 29.1us
|
||||||
|
except:
|
||||||
|
return None
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user