docs: 同步日常维护指南并补齐遗漏的板卡配置

This commit is contained in:
yczpf2019
2026-01-24 16:42:42 +08:00
parent a6cdad4b21
commit f166758ec5
373 changed files with 86311 additions and 1 deletions

View File

@@ -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
View 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
View 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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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

View 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]

View 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]

View 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

View 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]

View 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),
)

View 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()

View 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()

View File

@@ -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

View 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()

View 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

View 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()

View 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()

View 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()

View 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()

View File

@@ -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)

View 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)

View 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)

View 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

View 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

View 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)

View 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")

View 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')

View 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]))

View 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

View 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

View 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)

View File

@@ -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'

View 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'

View 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)

View 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)

View 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)

View 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)

View 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)

View 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)

View 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)

View 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)

View 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]

View 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()

View File

@@ -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

View 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)

View 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

View 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

View 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]

View 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])

View 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]

File diff suppressed because it is too large Load Diff

View 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)

View 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'

View 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'

View 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'

View 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

View 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')

View 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)

View 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'])

View 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]

View File

@@ -0,0 +1,149 @@
"""
MMC5603
Micropython library for the MMC5603NJMagnetic
=======================================================
#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

View 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")

View 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)

View 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

View 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)

View 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']

View 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)

View 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)

View 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")

View 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"

View 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)

View 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

View 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))

View 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

View 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)))

View 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

View File

@@ -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'

View 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]

View 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

View 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)

View 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')

View 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]

View 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 errorwill restart")
self.init()

View 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")

View 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)

View 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

View 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()

View 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)

View 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()

View 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]

View 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