first commit

This commit is contained in:
fanhuanji
2023-11-05 10:13:42 +00:00
commit 4a70ed45ad
39 changed files with 1788 additions and 0 deletions

38
.clang-format Normal file
View File

@@ -0,0 +1,38 @@
---
BasedOnStyle: Microsoft
Language: Cpp
###################################
# indent conf
###################################
UseTab: Never
IndentWidth: 4
TabWidth: 4
ColumnLimit: 0
AccessModifierOffset: -4
NamespaceIndentation: All
FixNamespaceComments: false
BreakBeforeBraces: Linux
###################################
# other styles
###################################
#
# for more conf, you can ref: https://clang.llvm.org/docs/ClangFormatStyleOptions.html
#
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AllowShortBlocksOnASingleLine: true
IndentCaseLabels: true
SortIncludes: false
AlignConsecutiveMacros: AcrossEmptyLines
AlignConsecutiveAssignments: Consecutive

View File

@@ -0,0 +1,31 @@
##########################################################################################
# Append Compiler Options For Source Files
#
# syntax:
# <your matcher expr>: <your compiler command>
#
# examples:
# 'main.cpp': --cpp11 -Og ...
# 'src/*.c': -gnu -O2 ...
# 'src/lib/**/*.cpp': --cpp11 -Os ...
# '!Application/*.c': -O0
# '**/*.c': -O2 -gnu ...
#
# For more syntax, please refer to: https://www.npmjs.com/package/micromatch
#
##########################################################################################
version: '1.0'
#
# for source files with filesystem paths
#
files:
# './test/**/*.c': --c99
#
# for source files with virtual paths
#
virtualPathFiles:
# 'virtual_folder/**/*.c': --c99

View File

@@ -0,0 +1,25 @@
{
"version": 3,
"beforeBuildTasks": [],
"afterBuildTasks": [
{
"name": "new postbuild task",
"disable": false,
"abortAfterFailed": true,
"command": "makebin.exe -p -s 32768 \"${OutDir}/${ProjectName}.ihx\" \"${OutDir}/cc.bin\"\necho \"${OutDir}/${ProjectName}.hex ->${OutDir}/cc.bin\""
}
],
"global": {
"device": "mcs51",
"optimize-type": "speed",
"misc-controls": "-pcc2510fx --iram-size 256 --xram-loc 0xF000 --xram-size 0xF00 --code-size 32768 --model-small"
},
"c/cpp-compiler": {
"language-c": "c11"
},
"asm-compiler": {},
"linker": {
"$mainFileName": "main",
"output-format": "hex"
}
}

44
.eide/eide.json Normal file
View File

@@ -0,0 +1,44 @@
{
"name": "VUSION_42_BWR_340",
"type": "C51",
"dependenceList": [],
"srcDirs": [
"src",
"inc"
],
"virtualFolder": {
"name": "<virtual_root>",
"files": [],
"folders": []
},
"outDir": "build",
"deviceName": null,
"packDir": null,
"miscInfo": {
"uid": "5b43a45b37334fd04652e2aa887d9e59"
},
"targets": {
"Debug": {
"excludeList": [],
"toolchain": "SDCC",
"compileConfig": {
"options": "null"
},
"uploader": "Custom",
"uploadConfig": {
"bin": "build\\Debug\\cc.bin",
"commandLine": "python \"D:\\esp\\proj\\serial_cc_debugger\\ctrl.py\" flash COM3 \"${hexFile}\"",
"eraseChipCommand": ""
},
"uploadConfigMap": {},
"custom_dep": {
"name": "default",
"incList": [],
"libList": [],
"sourceDirList": [],
"defineList": []
}
}
},
"version": "3.3"
}

68
.gitignore vendored Normal file
View File

@@ -0,0 +1,68 @@
# Prerequisites
*.d
# Object files
*.o
*.ko
*.obj
*.elf
# Linker output
*.ilk
*.map
*.exp
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
*.pdb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
# dot files
/.vscode/launch.json
/.settings
/.eide/log
/.eide.usr.ctx.json
# project out
/build
/bin
/obj
/out
# eide template
*.ept
*.eide-template

1
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1 @@
{}

40
.vscode/tasks.json vendored Normal file
View File

@@ -0,0 +1,40 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"type": "shell",
"command": "${command:eide.project.build}",
"group": "build",
"problemMatcher": []
},
{
"label": "flash",
"type": "shell",
"command": "${command:eide.project.uploadToDevice}",
"group": "build",
"problemMatcher": []
},
{
"label": "build and flash",
"type": "shell",
"command": "${command:eide.project.buildAndFlash}",
"group": "build",
"problemMatcher": []
},
{
"label": "rebuild",
"type": "shell",
"command": "${command:eide.project.rebuild}",
"group": "build",
"problemMatcher": []
},
{
"label": "clean",
"type": "shell",
"command": "${command:eide.project.clean}",
"group": "build",
"problemMatcher": []
}
]
}

21
LICENSE Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 fanhuanji
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

31
README.md Normal file
View File

@@ -0,0 +1,31 @@
# VUSION4.2BWR_GL340
A working NFC demo for EPD VUSION4.2BWR_GL340
## 大图警告
## 效果图
### 手机界面
界面入口:主界面左下角工具->MainEpdTool
![](img/Screenshot_20230905_011119_de.syss.NfcTool.jpg)
![](img/Screenshot_20230905_004955_de.syss.NfcTool.jpg)
### 墨水屏显示效果
![](img/IMG_20230903_034036.jpg)
![](img/IMG_20230903_123715.jpg)
![](img/IMG_20230903_124842.jpg)
![](img/IMG_20230905_011313.jpg)
![](img/IMG_20230905_004157.jpg)
![](img/IMG_20230816_010023.jpg)
## PCB图片
![](img/top_thumb.jpg)
![](img/bottom_thumb.jpg)
![](img/Rev.png)

View File

@@ -0,0 +1,48 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"EIDE.SourceTree.AutoSearchIncludePath": true,
"EIDE.SourceTree.AutoSearchObjFile": true,
"files.associations": {
"*.C": "c",
".eideignore": "ignore",
"stdio.h": "c",
"*.a51": "a51",
"*.h": "c",
"*.c": "c",
"*.hxx": "cpp",
"*.hpp": "cpp",
"*.c++": "cpp",
"*.cpp": "cpp",
"*.cxx": "cpp",
"*.cc": "cpp"
},
"files.autoGuessEncoding": true,
"EIDE.ARM.Option.AutoGenerateRTE_Components": false,
"C_Cpp.default.configurationProvider": "cl.eide",
"C_Cpp.errorSquiggles": "disabled",
"[yaml]": {
"editor.insertSpaces": true,
"editor.tabSize": 4,
"editor.autoIndent": "advanced"
}
},
"extensions": {
"recommendations": [
"cl.eide",
"keroc.hex-fmt",
"xiaoyongdong.srecord",
"hars.cppsnippets",
"zixuanwang.linkerscript",
"redhat.vscode-yaml",
"IBM.output-colorizer",
"cschlosser.doxdocgen",
"ms-vscode.vscode-serial-monitor",
"cl.stm8-debug"
]
}
}

BIN
binary/cc.bin Normal file

Binary file not shown.

BIN
img/IMG_20230816_010023.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

BIN
img/IMG_20230903_034036.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 MiB

BIN
img/IMG_20230903_123715.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 MiB

BIN
img/IMG_20230903_124842.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

BIN
img/IMG_20230905_004157.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 MiB

BIN
img/IMG_20230905_011313.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

BIN
img/Rev.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 840 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

BIN
img/bottom.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 MiB

BIN
img/bottom_thumb.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

BIN
img/top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 MiB

BIN
img/top_thumb.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

3
src/display/ASC16.c Normal file
View File

@@ -0,0 +1,3 @@
#include <stdint.h>

318
src/display/epd.c Normal file
View File

@@ -0,0 +1,318 @@
#include "epd.h"
#include "../util.h"
#include "../time/time.h"
#define PWR_ON EPD_PWR = 0
#define PWR_OFF EPD_PWR = 1
#define RESET_ON EPD_RESET = 0
#define RESET_OFF EPD_RESET = 1
// #define HRES 104
// #define VRES 212
#define HRES 400
#define VRES 300
#define BUFFER_SIZE (HRES / 8 * VRES)
static void inline Epd_SendCommand(uint8_t cmd);
static void inline Epd_SendData(uint8_t data);
static void inline Epd_WaitBusy()
{
do
{
// sendCommand(0x71);
} while (EPD_BUSY == 0);
delayMs(200);
}
#ifdef ASC_FONT_SUPPORT
extern __code const unsigned char ASC16[4096];
__code const unsigned char ASC16[4096]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x81,0xA5,0x81,0x81,0xBD,0x99,0x81,0x81,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0xFF,0xDB,0xFF,0xFF,0xC3,0xE7,0xFF,0xFF,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0xFE,0xFE,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x7C,0xFE,0x7C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0xE7,0xE7,0xE7,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x18,0x3C,0x7E,0xFF,0xFF,0x7E,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xC3,0xC3,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x42,0x42,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0x99,0xBD,0xBD,0x99,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x1E,0x0E,0x1A,0x32,0x78,0xCC,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,
0x3C,0x66,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x33,0x3F,0x30,0x30,0x30,0x30,0x70,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x63,0x7F,0x63,0x63,0x63,0x63,0x67,0xE7,0xE6,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0xDB,0x3C,0xE7,0x3C,0xDB,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x18,
0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x7E,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,
0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x60,0xFE,0x60,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x28,0x6C,0xFE,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,0x18,0x18,0x7C,0xC6,0xC2,0xC0,
0x7C,0x06,0x06,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x3C,
0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xD6,0xD6,
0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,
0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,
0x0C,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,
0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,
0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,
0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x7E,0x5A,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,
0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,
0x00,0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x60,0x60,0x78,0x6C,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00,0x00,0x00,0xE0,0x60,0x60,0x6C,0x76,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x78,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0xEC,0xFE,0xD6,0xD6,0xD6,0xD6,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x76,0x66,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x7C,0xC6,0x60,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xCC,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,
0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x0C,0x06,0x7C,0x00,0x00,0x00,0x00,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0x00,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x78,
0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x66,0x60,0x60,0x66,0x3C,0x0C,0x06,0x3C,0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x00,0x00,0x38,0x18,
0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0xC6,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x38,0x6C,0x38,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x18,0x30,0x60,0x00,0xFE,0x66,0x60,0x7C,0x60,0x60,0x66,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0x76,0x36,
0x7E,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,
0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00,0x00,0xC6,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0xC6,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x3C,0x66,0x60,0x60,0x60,0x66,0x3C,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0x64,0x60,0xF0,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,
0x18,0x18,0x00,0x00,0x00,0x00,0x00,0xF8,0xCC,0xCC,0xF8,0xC4,0xCC,0xDE,0xCC,0xCC,0xCC,0xC6,0x00,0x00,0x00,0x00,0x00,0x0E,0x1B,0x18,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x18,0xD8,0x70,0x00,0x00,0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,
0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00,0x3C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00,0x00,0xC0,0xC0,0xC2,0xC6,0xCC,0x18,0x30,0x66,0xCE,0x9E,0x3E,0x06,0x06,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,
0x00,0x00,0x00,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0x55,0xAA,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0xDD,0x77,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,
0x18,0x18,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,
0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x36,
0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,
0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x76,0xDC,0xD8,0xD8,0xD8,0xDC,0x76,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0xCC,0xCC,0xCC,0xD8,0xCC,0xC6,0xC6,0xC6,0xCC,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC6,0xC6,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xC6,0x60,0x30,0x18,0x30,0x60,0xC6,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0xD8,0xD8,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x66,
0x66,0x66,0x66,0x7C,0x60,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x18,0x3C,0x66,0x66,0x66,0x3C,0x18,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x6C,0x6C,0x6C,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x1E,0x30,0x18,0x0C,0x3E,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0xDB,
0xDB,0xDB,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x06,0x7E,0xDB,0xDB,0xF3,0x7E,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x30,0x60,0x60,0x7C,0x60,0x60,0x60,0x30,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x18,0x0C,0x06,0x0C,
0x18,0x30,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x1B,0x1B,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xD8,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x7E,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x0C,0x0C,0x0C,0x0C,0x0C,0xEC,0x6C,0x6C,0x3C,0x1C,0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x6C,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xD8,0x30,0x60,0xC8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x7C,0x7C,0x7C,0x7C,0x7C,
0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,};
__xdata char g_epdTextScrBuf[18][51] = {
"Designed to be the perfect enabler for NFC in home",
"-automation and consumer applications, this featur",
"e-packed, second-generation connected NFC tag is t",
"he fastest, least expensive way to add tap-and-go ",
"connectivity to just about any electronic device. ",
"NXP NTAG I2C plus is a family of connected NFC tag",
"s that combine a passive NFC interface with a cont",
"act I2C interface. As the second generation of NXP",
"'s industry leading connected-tag technology, thes",
"e devices maintain full backward compatibility wit",
"h firstgeneration NTAG I2C products, while adding ",
"new, advanced features for password protection, fu",
"ll memory-access configuration from both interface",
"s, and an originality signature for protection aga",
"inst cloning. ",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/", // 0
"BCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/A", // 1
"CDEFGHIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/AB", // 2
// "ABCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/", // 0
// "BCDEFGHIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/A", // 1
// "CDEFGHIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/AB", // 2
// "DEFGHIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/ABC", // 3
// "EFGHIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/ABCD", // 4
// "FGHIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/ABCDE", // 5
// "GHIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/ABCDEF", // 6
// "HIJKLMNOPQRSTUVWXYZ12345678901234567890+-*/ABCDEFG", // 7
// "IJKLMNOPQRSTUVWXYZ12345678901234567890+-*/ABCDEFGH", // 8
// "JKLMNOPQRSTUVWXYZ12345678901234567890+-*/ABCDEFGHI", // 9
// "KLMNOPQRSTUVWXYZ12345678901234567890+-*/ABCDEFGHIJ", // 10
// "LMNOPQRSTUVWXYZ12345678901234567890+-*/ABCDEFGHIJK", // 11
// "MNOPQRSTUVWXYZ12345678901234567890+-*/ABCDEFGHIJKL", // 12
// "NOPQRSTUVWXYZ12345678901234567890+-*/ABCDEFGHIJKLM", // 13
// "OPQRSTUVWXYZ12345678901234567890+-*/ABCDEFGHIJKLMN", // 14
// "PQRSTUVWXYZ12345678901234567890+-*/ABCDEFGHIJKLMNO", // 15
// "QRSTUVWXYZ12345678901234567890+-*/ABCDEFGHIJKLMNOP", // 16
// "RSTUVWXYZ12345678901234567890+-*/ABCDEFGHIJKLMNOPQ", // 17
};
uint8_t Epd_TextScrByte(uint16_t row, uint16_t col)
{
// 第row行像素的第几个字节
// 共18行字符 每个字符高16像素 每行50个字符
uint8_t charRow = row >> 4u; // 第r行
uint8_t pixRow = row & 0xFu; // 0~15 该行字符内第几行
uint8_t charCol = col >> 3u; // 第c列
if (charRow >= 18 || charCol >= 50) {
return 0;
}
uint8_t charAt = (uint8_t)g_epdTextScrBuf[charRow][charCol];
const uint8_t *pCode = &ASC16[(uint16_t)charAt << 4];
uint8_t ret = 0;
for(uint8_t j = 0; j < 8; j++){
if((pCode[pixRow] >> j) & 0x01){
ret |= 1 << j;
}
}
return ret;
}
void Epd_DisplayTextScreen(void)
{
Epd_SendCommand(0x10); //Transfer old data
for (uint16_t r = 0; r < VRES; r++) {
for (uint16_t c = 0; c < HRES; c += 8) {
uint8_t v = Epd_TextScrByte(r, c);
if (c > 150) {
v ^= 0xFF;
} else {
}
Epd_SendData(v);
}
}
Epd_SendCommand(0x13); //Transfer new data
for (uint16_t r = 0; r < VRES; r++) {
for (uint16_t c = 0; c < HRES; c += 8) {
uint8_t v = Epd_TextScrByte(r, c);
if (r > 200) {
v ^= 0xFF;
} else {
}
Epd_SendData(v);
}
}
}
#endif // ASC_FONT_SUPPORT
void Epd_ClearDisplay(uint8_t black, uint8_t red)
{
Epd_SendCommand(0x10); //Transfer old data
for (uint16_t i = 0; i < BUFFER_SIZE; i++) {
Epd_SendData(black);
}
Epd_SendCommand(0x13); //Transfer new data
for (uint16_t i = 0; i < BUFFER_SIZE; i++) {
Epd_SendData(red);
}
}
void Epd_TestPattern_ChessBoard(uint8_t pat)
{
if (pat > 8) {
return;
}
{
uint8_t v = 0;
for (uint8_t i = 0; i < pat; ++i) {
v |= 1 << i;
}
Epd_SendCommand(0x10); //Transfer old data
for (uint16_t row = 0; row < 300; row += pat) {
for (uint8_t srow = 0; (srow < pat) && (srow + row < 300); ++srow) {
for (uint16_t i = 0; i < 400 / 8; i++) {
Epd_SendData(v);
}
}
v ^= 0xFF;
}
}
{
uint8_t v = 0;
for (uint8_t i = 0; i < pat; ++i) {
v |= 1 << i;
}
Epd_SendCommand(0x13); //Transfer old data
for (uint16_t row = 0; row < 300; row += pat) {
for (uint8_t srow = 0; (srow < pat) && (srow + row < 300); ++srow) {
for (uint16_t i = 0; i < 400 / 8; i++) {
Epd_SendData(v);
}
}
v ^= 0xFF;
}
}
}
void Epd_BeginBlack(void)
{
Epd_SendCommand(0x10);
}
void Epd_BeginRed(void)
{
Epd_SendCommand(0x13);
}
void Epd_LoadBatch(const uint8_t *buf)
{
for (uint8_t i = 0; i < 60; ++i) {
Epd_SendData(buf[i]);
}
}
void Epd_Refresh(void)
{
Epd_SendCommand(0x12);
delayMs(100);
Epd_WaitBusy();
}
static void Epd_Sleep(void)
{
Epd_SendCommand(0x02); //power off
Epd_WaitBusy();
delayMs(1000);
Epd_SendCommand(0x07); //deep sleep
Epd_SendData(0xA5);
}
void Epd_Init(void)
{
PERCFG &= ~0x01; // USART0 alternative 1 location
U0CSR = 0; // SPI mode/master/clear flags
U0GCR = (1 << 5) | 17; // SCK-low idle, DATA-1st clock edge, MSB first + baud E
U0BAUD = 0; // baud M
U0CSR |= BV(6); // enable SPI
P0SEL |= BV(3) | BV(5); // MISO/MOSI/CLK peripheral functions
P0DIR |= BV(3) | BV(5) | BV(EPD_B_PWR) | BV(EPD_B_CS); // MOSI/CLK, PWR/CS output
P1DIR |= BV(EPD_B_DC);
P1DIR &= ~BV(EPD_B_BUSY);
P2DIR |= BV(EPD_B_RESET);
PWR_ON;
delayMs(1000);
RESET_ON;
delayMs(10);
RESET_OFF;
delayMs(10);
Epd_SendCommand(6); //boost soft start
Epd_SendData(0x17); //A
Epd_SendData(0x17); //B
Epd_SendData(0x17); //C
Epd_SendCommand(4);//Power on
Epd_WaitBusy();
Epd_SendCommand(0); //panel setting
Epd_SendData(0x0f); //LUT from OTP£¬400x300
Epd_SendData(0x0d); //VCOM to 0V fast
// sendCommand(0x61);
// sendData(HRES);
// sendData(VRES >> 8);
// sendData(VRES);
Epd_SendCommand(0x50);
Epd_SendData(0x77);
// delay(20e3);
// epd_image(gImage_black2, gImage_red2);
// epd_refresh();
}
void Epd_Deinit(void)
{
Epd_Sleep();
PWR_OFF;
}
static void inline Epd_SendData(uint8_t data)
{
EPD_CS = 0;
U0DBUF = data;
while (U0CSR & 0x01)
{
}
EPD_CS = 1;
}
static void inline Epd_SendCommand(uint8_t cmd)
{
EPD_DC = 0;
Epd_SendData(cmd);
EPD_DC = 1;
}

32
src/display/epd.h Normal file
View File

@@ -0,0 +1,32 @@
#ifndef _EPD_H_
#define _EPD_H_
#include <stdint.h>
#define EPD_B_PWR 0 //P0_0
#define EPD_B_CS 1 //P0_1
#define EPD_B_DC 2 //P1_2 - low command, high data
#define EPD_B_BUSY 3 //P1_3 - low busy
#define EPD_B_RESET 0 //P2_0 - low reset
#define EPD_PWR P0_0
#define EPD_CS P0_1
#define EPD_DC P1_2
#define EPD_BUSY P1_3
#define EPD_RESET P2_0
void Epd_Init(void);
void Epd_ClearDisplay(uint8_t black, uint8_t red);
void Epd_Refresh(void);
void Epd_Deinit(void);
void Epd_TestPattern_ChessBoard(uint8_t pat);
void Epd_BeginBlack(void);
void Epd_BeginRed(void);
void Epd_LoadBatch(const uint8_t *buf);
#endif

106
src/flash/flash.c Normal file
View File

@@ -0,0 +1,106 @@
#include "flash.h"
#include <cc2510fx.h>
#include <stdbool.h>
inline void Flash_Select(bool select)
{
FLASH_CS = !select;
}
static uint8_t Flash_ExchangeData(uint8_t data)
{
U1DBUF = data;
while (U1CSR & 0x01)
{
*(__xdata volatile uint8_t*)0xFE00 = U1CSR;
}
return U1DBUF;
}
bool Flash_CheckId(void)
{
Flash_Select(true);
Flash_ExchangeData(0x90u);
Flash_ExchangeData(0x00u); // 3 Byte dummy
Flash_ExchangeData(0x00u);
Flash_ExchangeData(0x00u);
uint8_t mid = Flash_ExchangeData(0xFFu); // 0xEF
uint8_t did = Flash_ExchangeData(0xFFu); // 0x11
Flash_Select(false);
return (mid == 0xEFu) && (did == 0x11u);
}
void Flash_EnterPowerDown(void)
{
Flash_Select(true);
Flash_ExchangeData(0xB9u);
Flash_Select(false);
}
/**
* @brief 释放复位并判断ChipId
*
* @return true
* @return false
*/
bool Flash_ReleasePowerDown(void)
{
Flash_Select(true);
Flash_ExchangeData(0xABu);
Flash_ExchangeData(0x00u); // 3 Byte dummy
Flash_ExchangeData(0x00u);
Flash_ExchangeData(0x00u);
uint8_t did = Flash_ExchangeData(0xFFu);
Flash_Select(false);
return (did == 0x11u);
}
/**
* @brief
*
* @param addr
* @param len 只有16位宽内存受限
*/
void Flash_FastRead(uint32_t addr, uint8_t *buf, uint16_t len)
{
Flash_Select(true);
Flash_ExchangeData(0x0Bu);
Flash_ExchangeData((addr & 0xFF0000u) >> 16u);
Flash_ExchangeData((addr & 0xFF00u) >> 8u);
Flash_ExchangeData((addr & 0xFFu) >> 0u);
Flash_ExchangeData(0xFFu); // dummy
for (uint16_t i = 0; i < len; ++i) {
buf[i] = Flash_ExchangeData(i & 0xFFu);
}
Flash_Select(false);
}
void NfcFlash_IoInit(void)
{
P1DIR |= BV(FLASH_B_CS);
FLASH_CS = 1; // Flas CS
NFCFLASH_PWR = 0;
P1DIR |= BV(NFCFLASH_B_PWR) // NFCPWR output
| BV(FLASH_B_SCK)
| BV(FLASH_B_MOSI)
| BV(FLASH_B_CS);
P1DIR &= ~(BV(FLASH_B_MISO));
PERCFG |= 0x02; // USART1 alternative 2 location SPI
U1CSR = 0; // SPI mode/master/clear flags
P1SEL |= BV(FLASH_B_SCK) | BV(FLASH_B_MOSI) | BV(FLASH_B_MISO); // MISO/MOSI/CLK peripheral functions // SS仅当从机使用时才配置为外设
U1BAUD = 0; // baud M
U1GCR = BV(5) | 17; // SCK-low idle, DATA-1st clock edge, MSB first
P1DIR &= ~BV(NFC_B_FD);
}
void NfcFlash_Pwr(bool enable)
{
P1_0 = enable ? 1 : 0;
}

34
src/flash/flash.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef FLASH_H
#define FLASH_H
#include <stdbool.h>
#include <stdint.h>
#include <cc2510fx.h>
#include "util.h"
void NfcFlash_IoInit(void);
void NfcFlash_Pwr(bool enable);
bool Flash_CheckId(void);
bool Flash_ReleasePowerDown(void);
void Flash_FastRead(uint32_t addr, uint8_t *buf, uint16_t len);
#define NFC_FD P1_1
#define NFCFLASH_PWR P1_0
#define FLASH_CS P1_4
#define FLASH_MOSI P1_6
#define FLASH_MISO P1_7
#define FLASH_SCK P1_5
#define NFC_B_FD 1
#define NFCFLASH_B_PWR 0
#define FLASH_B_CS 4
#define FLASH_B_MOSI 6
#define FLASH_B_MISO 7
#define FLASH_B_SCK 5
#define NFC_FD_ON() (!NFC_FD)
#define NFC_FD_OFF() (!!NFC_FD)
#endif // FLASH_H

26
src/hal_clock.c Normal file
View File

@@ -0,0 +1,26 @@
#include "hal_clock.h"
#include "util.h"
void halPowerClkMgmtSetMainClkSrc(uint8_t source)
{
// source can have the following values:
// CRYSTAL 0x00 /* High speed Crystal Oscillator Control */
// RC 0x01 /* Low power RC Oscillator */
SLEEP &= ~OSC_PD_BIT;
while (!HIGH_FREQUENCY_RC_OSC_STABLE);
CLKCON = 0xC9u;
CLKCON = 0x49u;
while (!XOSC_STABLE);
CLKCON = 0xC9u;
__asm__("NOP");
CLKCON = 0x89u;
(void)source;
}

62
src/hal_clock.h Normal file
View File

@@ -0,0 +1,62 @@
#ifndef HAL_CLOCK_H
#define HAL_CLOCK_H
#include <stdint.h>
#include <cc2510fx.h>
/* Pre defined values for source, as used in halPowerClkMgmtSetMainClkSrc() */
#define CRYSTAL 0x00 /* High speed Crystal Oscillator Control */
#define RC 0x01 /* Low power RC Oscillator */
// Bit masks to check CLKCON register
#define OSC_BIT 0x40 // bit mask used to select/check the system clock oscillator
#define TICKSPD_BITS 0x38 // bit mask used to check the timer ticks output setting
#define CLKSPD_BIT 0x03 // bit maks used to check the clock speed
#define MAIN_OSC_BITS 0x7F // bit mask used to control the system clock oscillator
// e.g. ~MAIN_OSC_BITS can be used to start Crystal OSC
// Bit masks to check SLEEP register
#define XOSC_STABLE_BIT 0x40 // bit mask used to check the stability of XOSC
#define HFRC_STB_BIT 0x20 // bit maks used to check the stability of the High-frequency RC oscillator
#define OSC_PD_BIT 0x04 // bit maks used to power down system clock oscillators
/*==== TYPES =================================================================*/
/*==== EXPORTS ===============================================================*/
/*==== MACROS=================================================================*/
// Macro for checking status of the high frequency RC oscillator.
#define HIGH_FREQUENCY_RC_OSC_STABLE (SLEEP & HFRC_STB_BIT)
// Macro for getting the clock division factor
#define CLKSPD (CLKCON & CLKSPD_BIT)
// Macro for getting the timer tick division factor.
#define TICKSPD ((CLKCON & TICKSPD_BITS) >> 3)
// Macro for checking status of the crystal oscillator
#define XOSC_STABLE (SLEEP & XOSC_STABLE_BIT)
/*==== FUNCTIONS =============================================================*/
/******************************************************************************
* @fn halPowerClkMgmtSetMainClkSrc
*
* @brief
* Function for setting the main clock oscillator source, turns off the
* clock source not used changing to XOSC will take approx 150 us
* Settings TICKSPD equal CLKSPD
*
* Parameters:
*
* @param UINT8 source
*
* @return void
*
******************************************************************************/
void halPowerClkMgmtSetMainClkSrc(uint8_t source);
#endif // HAL_CLOCK_H

8
src/isr.h Normal file
View File

@@ -0,0 +1,8 @@
#ifndef ISR_H
#define ISR_H
#include <cc2510fx.h>
void time_isr(void) __interrupt(WDT_VECTOR);
#endif // ISR_H

390
src/main.c Normal file
View File

@@ -0,0 +1,390 @@
#include "display/epd.h"
#include "isr.h"
#include "time/time.h"
#include "util.h"
#include "flash/flash.h"
#include "hal_clock.h"
#include "nfc/i2c.h"
#define MANAGED_XRAM_START 0xF000
void blink(void)
{
LED_ON();
delayMs(5);
LED_OFF();
}
void EPD_Test(void)
{
Epd_ClearDisplay(0, 0);
Epd_Refresh();
// Epd_DisplayTextScreen();
// Epd_Refresh();
for (int i = 0; i < 0; ++i) {
Epd_ClearDisplay(0x0Fu, 0xF0u);
Epd_Refresh();
//blink();
delayMs(5000);
Epd_ClearDisplay(0xF0u, 0x0Fu);
Epd_Refresh();
//blink();
delayMs(5000);
}
// FF00 红色
// 00FF 黑色
// FFFF 白色
// Epd_ClearDisplay(0xFFu, 0xFFu);
// Epd_Refresh();
Epd_Deinit();
}
#define XRAM_BEGIN (void *)0xF000
#define XRAM_END (void *)0xFEFF
__code static const unsigned char crc_table[] =
{
0x00,0x31,0x62,0x53,0xc4,0xf5,0xa6,0x97,0xb9,0x88,0xdb,0xea,0x7d,0x4c,0x1f,0x2e,
0x43,0x72,0x21,0x10,0x87,0xb6,0xe5,0xd4,0xfa,0xcb,0x98,0xa9,0x3e,0x0f,0x5c,0x6d,
0x86,0xb7,0xe4,0xd5,0x42,0x73,0x20,0x11,0x3f,0x0e,0x5d,0x6c,0xfb,0xca,0x99,0xa8,
0xc5,0xf4,0xa7,0x96,0x01,0x30,0x63,0x52,0x7c,0x4d,0x1e,0x2f,0xb8,0x89,0xda,0xeb,
0x3d,0x0c,0x5f,0x6e,0xf9,0xc8,0x9b,0xaa,0x84,0xb5,0xe6,0xd7,0x40,0x71,0x22,0x13,
0x7e,0x4f,0x1c,0x2d,0xba,0x8b,0xd8,0xe9,0xc7,0xf6,0xa5,0x94,0x03,0x32,0x61,0x50,
0xbb,0x8a,0xd9,0xe8,0x7f,0x4e,0x1d,0x2c,0x02,0x33,0x60,0x51,0xc6,0xf7,0xa4,0x95,
0xf8,0xc9,0x9a,0xab,0x3c,0x0d,0x5e,0x6f,0x41,0x70,0x23,0x12,0x85,0xb4,0xe7,0xd6,
0x7a,0x4b,0x18,0x29,0xbe,0x8f,0xdc,0xed,0xc3,0xf2,0xa1,0x90,0x07,0x36,0x65,0x54,
0x39,0x08,0x5b,0x6a,0xfd,0xcc,0x9f,0xae,0x80,0xb1,0xe2,0xd3,0x44,0x75,0x26,0x17,
0xfc,0xcd,0x9e,0xaf,0x38,0x09,0x5a,0x6b,0x45,0x74,0x27,0x16,0x81,0xb0,0xe3,0xd2,
0xbf,0x8e,0xdd,0xec,0x7b,0x4a,0x19,0x28,0x06,0x37,0x64,0x55,0xc2,0xf3,0xa0,0x91,
0x47,0x76,0x25,0x14,0x83,0xb2,0xe1,0xd0,0xfe,0xcf,0x9c,0xad,0x3a,0x0b,0x58,0x69,
0x04,0x35,0x66,0x57,0xc0,0xf1,0xa2,0x93,0xbd,0x8c,0xdf,0xee,0x79,0x48,0x1b,0x2a,
0xc1,0xf0,0xa3,0x92,0x05,0x34,0x67,0x56,0x78,0x49,0x1a,0x2b,0xbc,0x8d,0xde,0xef,
0x82,0xb3,0xe0,0xd1,0x46,0x77,0x24,0x15,0x3b,0x0a,0x59,0x68,0xff,0xce,0x9d,0xac
};
uint8_t crc8(uint8_t *ptr, uint8_t len)
{
uint8_t crc = 0x00;
while (len--) {
crc = crc_table[crc ^ *ptr++];
}
return (crc);
}
// void WaitDebugStub(void)
// {
// P1_0 = 0;
// for (volatile __xdata uint8_t *i = (volatile __xdata uint8_t *)XRAM_BEGIN; i <= (volatile __xdata uint8_t *)XRAM_END; ++i) {
// *i = 0xA5;
// }
// /*
// for (volatile __xdata uint8_t *i = 0xFF20; i <= 0xFF40; ++i) {
// *i = 0xA5;
// }
// */
// while (1) {
// __asm__(".db 0xA5;");
// }
// }
enum {
FSM_Init,
FSM_WAIT_RF, // 空闲状态等待RF中断
FSM_SETUP_RF, // RF在位 配置NFC芯片透传
FSM_HANDSHAKE_A, // 等待NFC读数据
FSM_HANDSHAKE_B, // 回读
FSM_I2N_A, // I2C -> NFC
FSM_I2N_B, // I2C -> NFC
FSM_N2I_A, // I2C -> NFC
FSM_N2I_B, // I2C -> NFC
FSM_RF_LOST, // 重置各状态并切换回空闲
} g_NfcFsmState;
#define StateTransit(x) g_NfcFsmState = (x)
#define StateLostGuard(sessionReg) { \
if ((NFC_SESSION_NS_REG_RF_FIELD_PRESENT & sessionReg) == 0) { \
StateTransit(FSM_RF_LOST); \
break; \
} \
}
#define SRAM_I2C_BLK_0 0xF8u
#define SRAM_I2C_BLK_1 0xF9u
#define SRAM_I2C_BLK_2 0xFAu
#define SRAM_I2C_BLK_3 0xFBu
#define DebugLog(id) do { \
I2C_start(); \
I2C_write(id); \
I2C_write((uint8_t)g_NfcFsmState); \
I2C_write((uint8_t)sessionReg); \
I2C_write((uint8_t)(receivedSeg >> 8)); \
I2C_write((uint8_t)receivedSeg); \
I2C_write((uint8_t)NFC_FD); \
I2C_stop(); \
} while (0)
#define NFC_GUARD_BRK(x) if (!(x)) {break;}
// struct {
// uint8_t raw;
// // NfcMemoryBlk blkBuf[4];
// }
typedef union {
uint8_t buf[64];
struct {
uint8_t pld[60];
uint8_t cmd; // NFC:cmd I2C:ACK
uint8_t seq;
uint8_t _;
uint8_t crc8;
} data;
struct {
uint8_t pld[52];
uint8_t challenge[4];
uint8_t state[4];
uint8_t cmd;
uint8_t seq;
uint8_t _;
uint8_t crc8;
} hs_i2n;
struct {
uint8_t pld[52];
uint8_t response[4];
uint8_t cmdPld[4];
uint8_t ack;
uint8_t seq;
uint8_t _;
uint8_t crc8;
} hs_n2i;
struct {
uint8_t blk0[16];
uint8_t blk1[16];
uint8_t blk2[16];
uint8_t blk3[16];
};
} NfcBuf;
NfcBuf g_nfcBuf;
#define NFC_CMD_NACK 'N'
#define NFC_CMD_ACK 'A'
#define nfcBuf g_nfcBuf.buf
static uint8_t sessionReg = 0;
static uint16_t receivedSeg = 0;
void ClearMemBlk(NfcMemoryBlk blk)
{
for (uint8_t i = 0; i < sizeof(blk); ++i) {
blk[i] = 0;
}
}
void WriteMemBlk(uint8_t blk[16], uint8_t a, uint8_t b, uint8_t c, uint8_t d)
{
(void)b;
blk[12] = a;
blk[14] = c;
blk[15] = d;
}
extern void inline Epd_SendData(uint8_t data);
void WriteMemBlkToEpd(const uint8_t blk[16], uint8_t cnt)
{
for (uint8_t i = 0; i < cnt; ++i) {
EPD_CS = 0;
U0DBUF = blk[i];
while (U0CSR & 0x01)
{
}
EPD_CS = 1;
}
}
#define DO_EPD_REFRESH
void Nfc_Fsm(void)
{
static uint8_t ackVal = 0;
//DebugLog(0x10);
switch (g_NfcFsmState) {
case FSM_Init: {
StateTransit(FSM_WAIT_RF);
break;
}
case FSM_WAIT_RF: {
if (Nfc_IsFieldActive()) { // 改成中断管脚
StateTransit(FSM_SETUP_RF);
}
break;
}
case FSM_SETUP_RF: { // 初始化通信
// NfcFlash_Pwr(true);
NFC_GUARD_BRK(Nfc_SetFdPin(0x3u, 0x3u));
NFC_GUARD_BRK(Nfc_DirSet(false));
NFC_GUARD_BRK(Nfc_ConfigurePassThru(true));
// 写入握手数据
ClearMemBlk(nfcBuf);
// WriteMemBlk(nfcBuf, 'H', 'S', 0xDE, 0xAD);
g_nfcBuf.hs_i2n.cmd = NFC_CMD_ACK;
NFC_GUARD_BRK(Nfc_MemWriteBlk(SRAM_I2C_BLK_3, nfcBuf));
StateTransit(FSM_HANDSHAKE_A);
break;
}
case FSM_HANDSHAKE_A: { // 03 等待NFC读取握手数据
NFC_GUARD_BRK(Nfc_ReadReg(NFC_SESSION_REG_MEMA, NFC_SESSION_NS_REG_REGA , &sessionReg));
StateLostGuard(sessionReg);
if ((NFC_FD == 0) || ((sessionReg & NFC_SESSION_NS_REG_SRAM_RF_READY) == 0))
{
// NFC读取握手数据
NFC_GUARD_BRK(Nfc_DirSet(true)); // 等待接收握手数据
StateTransit(FSM_HANDSHAKE_B);
}
break;
}
case FSM_HANDSHAKE_B: { // 04 等待NFC写入握手数据
NFC_GUARD_BRK(Nfc_ReadReg(NFC_SESSION_REG_MEMA, NFC_SESSION_NS_REG_REGA , &sessionReg));
StateLostGuard(sessionReg);
if ((NFC_FD == 0) || ((sessionReg & NFC_SESSION_NS_REG_SRAM_I2C_READY) != 0))
{
// NFC已完成握手数据写入
// todo 此处读取握手数据并做校验
receivedSeg = 0;
#ifdef DO_EPD_REFRESH
Epd_BeginBlack(); // 准备接收黑色图像
#endif // DO_EPD_REFRESH
ackVal = true;
StateTransit(FSM_I2N_A);
}
break;
}
case FSM_I2N_A: { // 05
// 发送ACK
NFC_GUARD_BRK(Nfc_DirSet(false));
if (ackVal) {
g_nfcBuf.data.cmd = NFC_CMD_ACK;
} else {
g_nfcBuf.data.cmd = NFC_CMD_NACK;
}
g_nfcBuf.data._ = (uint8_t)receivedSeg;
NFC_GUARD_BRK(Nfc_MemWriteBlk(SRAM_I2C_BLK_3, g_nfcBuf.blk3));
StateTransit(FSM_I2N_B);
break;
}
case FSM_I2N_B: { // 06
// 等待NFC读取
NFC_GUARD_BRK(Nfc_ReadReg(NFC_SESSION_REG_MEMA, NFC_SESSION_NS_REG_REGA , &sessionReg));
StateLostGuard(sessionReg);
if ((NFC_FD == 0) || ((sessionReg & NFC_SESSION_NS_REG_SRAM_RF_READY) == 0)) {
// NFC已读取ACK
NFC_GUARD_BRK(Nfc_DirSet(true)); // 等待接收图像数据
StateTransit(FSM_N2I_A);
}
break;
}
case FSM_N2I_A: { // 07 等待NFC写入图像
NFC_GUARD_BRK(Nfc_ReadReg(NFC_SESSION_REG_MEMA, NFC_SESSION_NS_REG_REGA , &sessionReg));
StateLostGuard(sessionReg);
if (receivedSeg == 250) {
#ifdef DO_EPD_REFRESH
Epd_BeginRed(); // 准备接收图像
#endif // DO_EPD_REFRESH
} else if (receivedSeg == 500) {
#ifdef DO_EPD_REFRESH
Epd_Refresh();
#endif // DO_EPD_REFRESH
StateTransit(FSM_RF_LOST);
break;
}
if ((NFC_FD == 0) || ((sessionReg & NFC_SESSION_NS_REG_SRAM_I2C_READY) != 0)) {
// NFC已完成图像数据写入
// 读取数据
NFC_GUARD_BRK(Nfc_I2cLock(true));
NFC_GUARD_BRK(Nfc_MemReadBlk(SRAM_I2C_BLK_0, g_nfcBuf.blk0));
NFC_GUARD_BRK(Nfc_MemReadBlk(SRAM_I2C_BLK_1, g_nfcBuf.blk1));
NFC_GUARD_BRK(Nfc_MemReadBlk(SRAM_I2C_BLK_2, g_nfcBuf.blk2));
NFC_GUARD_BRK(Nfc_MemReadBlk(SRAM_I2C_BLK_3, g_nfcBuf.blk3));
uint8_t crc = crc8(g_nfcBuf.buf, 63);
if (crc == g_nfcBuf.data.crc8) {
blink();
WriteMemBlkToEpd(g_nfcBuf.blk0, 16);
WriteMemBlkToEpd(g_nfcBuf.blk1, 16);
WriteMemBlkToEpd(g_nfcBuf.blk2, 16);
WriteMemBlkToEpd(g_nfcBuf.blk3, 12);
ackVal = true;
receivedSeg++;
} else {
ackVal = false;
}
NFC_GUARD_BRK(Nfc_I2cLock(false));
g_nfcBuf.data.crc8 = ~crc;
//DebugLog(0x2A);
StateTransit(FSM_I2N_A);
//DebugLog(0x3A);
}
break;
}
case FSM_N2I_B: {
StateTransit(FSM_WAIT_RF);
break;
}
case FSM_RF_LOST: {
Nfc_ConfigurePassThru(false);
NFC_GUARD_BRK(Nfc_DirSet(false));
NFC_GUARD_BRK(Nfc_SetFdPin(0x0u, 0x0u));
StateTransit(FSM_WAIT_RF);
break;
}
}
//DebugLog(0x20);
}
void main(void)
{
halPowerClkMgmtSetMainClkSrc(0);
HAL_ENABLE_INTERRUPTS();
time_init();
LED_INIT();
NfcFlash_IoInit();
// NfcFlash_Pwr(false);
// WaitDebugStub();
Epd_Init();
//Epd_ClearDisplay(0xFF, 0xFF);
//Epd_Refresh();
NfcFlash_Pwr(true);
delayMs(50);
Flash_ReleasePowerDown();
Flash_CheckId();
I2C_init();
//DebugLog(0x70);
while (1) {
Nfc_Fsm();
//__asm__(".db 0xA5;");
//__asm__(".db 0x00;");
continue;
}
}

311
src/nfc/i2c.c Normal file
View File

@@ -0,0 +1,311 @@
#include "i2c.h"
#include "time/time.h"
void I2C_HalfClk(void)
{
__asm__("NOP");
//__asm__("NOP");
//__asm__("NOP");
//__asm__("NOP");
//__asm__("NOP");
// __asm__("NOP");
// __asm__("NOP");
// __asm__("NOP");
}
void I2C_init(void)
{
P0DIR |= BV(4) | BV(6);
SDA = 1;
SCL = 1;
}
void I2C_start(void)
{
I2C_HalfClk();
SDA_OUT();
SDA = 0;
I2C_HalfClk();
SCL = 0;
I2C_HalfClk();
}
void I2C_stop(void)
{
SDA_OUT();
SDA = 0;
SCL = 1;
I2C_HalfClk();
SDA = 1;
I2C_HalfClk();
}
void I2C_ack(void)
{
SCL = 0;
SDA_OUT();
SDA = 0;
I2C_HalfClk();
SCL = 1;
I2C_HalfClk();
SCL = 0;
}
void I2C_nack(void)
{
SCL = 0;
SDA_OUT();
SDA = 1;
I2C_HalfClk();
SCL = 1;
I2C_HalfClk();
SCL = 0;
}
/**
* @brief
*
* @param Data
* @return uint8_t 0=ACK 1=NACK
*/
uint8_t I2C_write(unsigned char Data)
{
for (uint8_t i = 0; i < 8; i++) {
if ((Data & 0x80) == 0) {
SDA = 0;
} else {
SDA = 1;
}
__asm__("NOP");
SCL = 1;
__asm__("NOP");
__asm__("NOP");
__asm__("NOP");
__asm__("NOP");
__asm__("NOP");
__asm__("NOP");
// I2C_HalfClk();
SCL = 0;
Data <<= 1;
}
SDA = 0;
SDA_IN();
__asm__("NOP");
__asm__("NOP");
SCL = 1;
__asm__("NOP");
__asm__("NOP");
volatile uint8_t ack = SDA;
SCL = 0;
__asm__("NOP");
SDA_OUT();
return ack;
}
uint8_t I2C_read(void)
{
SDA_IN();
unsigned char i;
volatile uint8_t Data = 0;
for (i = 0; i < 8; i++) {
SCL = 0;
__asm__("NOP");
__asm__("NOP");
__asm__("NOP");
__asm__("NOP");
__asm__("NOP");
__asm__("NOP");
SCL = 1;
__asm__("NOP");
if (SDA) {
Data |= 1;
}
if (i < 7) {
Data <<= 1;
}
}
__asm__("NOP");
__asm__("NOP");
SCL = 0;
I2C_HalfClk();
return Data;
}
// bool Nfc_MemRead(uint8_t mema, uint8_t *buf)
// {
// bool ret = true;
// I2C_start();
// ret &= !I2C_write(NFC_W_ADDR);
// ret &= !I2C_write(mema); // MEMA
// I2C_stop();
// delayMs(1);
// I2C_start();
// ret &= !I2C_write(NFC_R_ADDR);
// for (uint8_t i = 0; i < 16; ++i) {
// buf[i] = I2C_read();
// I2C_ack();
// }
// I2C_stop();
// return ret;
// }
// bool Nfc_MemWrite(uint8_t mema, uint8_t *buf)
// {
// bool ret = true;
// I2C_start();
// ret &= !I2C_write(NFC_W_ADDR);
// ret &= !I2C_write(mema); // MEMA
// for (uint8_t i = 0; i < 16; ++i) {
// ret &= !I2C_write(buf[i]);
// }
// I2C_stop();
// delayMs(5);
// return ret;
// }
bool Nfc_MemReadBlk(uint8_t mema, NfcMemoryBlk buf)
{
bool ret = true;
I2C_start();
ret &= !I2C_write(NFC_W_ADDR);
ret &= !I2C_write(mema); // MEMA
I2C_stop();
// delayMs(1); // SRAM无需延时
I2C_start();
ret &= !I2C_write(NFC_R_ADDR);
for (uint8_t i = 0; i < 16; ++i) {
buf[i] = I2C_read();
I2C_ack();
}
I2C_stop();
return ret;
}
bool Nfc_MemWriteBlk(uint8_t mema, const NfcMemoryBlk buf)
{
bool ret = true;
I2C_start();
ret &= !I2C_write(NFC_W_ADDR);
ret &= !I2C_write(mema); // MEMA
for (uint8_t i = 0; i < 16; ++i) {
ret &= !I2C_write(buf[i]);
}
I2C_stop();
// delayMs(5); // 写RAM无需延时
return ret;
}
/**
* @brief
*
* @param mema
* @param rega
* @param regdat
* @return true ACK
* @return false NACK
*/
bool Nfc_ReadReg(uint8_t mema, uint8_t rega, uint8_t *regdat)
{
uint8_t ret = false;
I2C_start();
ret |= I2C_write(NFC_W_ADDR);
ret |= I2C_write(mema); // MEMA
ret |= I2C_write(rega); // REGA
I2C_stop();
// if (ret) {
// return false;
// }
I2C_start();
ret |= I2C_write(NFC_R_ADDR);
*regdat = I2C_read();
I2C_ack();
I2C_stop();
return !ret;
}
bool Nfc_WriteReg(uint8_t mema, uint8_t rega, uint8_t mask, uint8_t regdat)
{
bool ret = true;
I2C_start();
ret &= !I2C_write(NFC_W_ADDR);
ret &= !I2C_write(mema); // MEMA
ret &= !I2C_write(rega); // REGA
ret &= !I2C_write(mask); // MASK
ret &= !I2C_write(regdat);
I2C_stop();
return ret;
}
// bool Nfc_FullDump(uint8_t *buf, uint16_t bufLen)
// {
// if (bufLen < 1024) {
// return false;
// }
// bool ret = true;
// for (uint16_t blk = 0; blk < 0x3B; ++blk) {
// ret &= !Nfc_MemRead(blk, (buf[16 * blk]));
// }
// return ret;
// }
/**
* @brief 通过Session寄存器开启pass-through功能
*
* @param enable
*/
bool Nfc_ConfigurePassThru(bool enable)
{
uint8_t reg = 0;
if (enable) {
reg = NFC_SESSION_NC_REG_PTHRU_ON_OFF;
} else {
reg = (uint8_t)~NFC_SESSION_NC_REG_PTHRU_ON_OFF;
}
return Nfc_WriteReg(NFC_SESSION_REG_MEMA, NFC_SESSION_NC_REG_REGA, NFC_SESSION_NC_REG_PTHRU_ON_OFF, reg);
// }
}
bool Nfc_DirSet(bool nfc2iic)
{
uint8_t reg = 0;
if (nfc2iic) {
reg = 1;
} else {
reg = (uint8_t)~1;
}
return Nfc_WriteReg(NFC_SESSION_REG_MEMA, NFC_SESSION_NC_REG_REGA, 1, reg);
}
bool Nfc_I2cLock(bool enable)
{
uint8_t reg = 0;
if (enable) {
reg = NFC_SESSION_NS_REG_I2C_LOCKED;
} else {
reg = (uint8_t)~NFC_SESSION_NS_REG_I2C_LOCKED;
}
return Nfc_WriteReg(NFC_SESSION_REG_MEMA, NFC_SESSION_NS_REG_REGA, NFC_SESSION_NS_REG_I2C_LOCKED, reg);
}
/**
* @brief 通过NS_REG判断当前是否有NFC存在
* @return true
* @return false
*/
bool Nfc_IsFieldActive(void)
{
uint8_t reg = 0;
if (Nfc_ReadReg(NFC_SESSION_REG_MEMA, NFC_SESSION_NS_REG_REGA, &reg)) {
return reg & NFC_SESSION_NS_REG_RF_FIELD_PRESENT;
}
return false;
}
bool Nfc_SetFdPin(uint8_t on, uint8_t off)
{
uint8_t reg = (on << 2) | (off << 4);
return Nfc_WriteReg(NFC_SESSION_REG_MEMA, NFC_SESSION_NC_REG_REGA, NFC_SESSION_NC_REG_FD_ON_OFF, reg);
}

72
src/nfc/i2c.h Normal file
View File

@@ -0,0 +1,72 @@
#ifndef I2C_H
#define I2C_H
#include <stdbool.h>
#include <stdint.h>
#include <cc2510fx.h>
#include "util.h"
// sbit SDA = P1^0;
// sbit SCL = P1^1;
#define SDA P0_4
#define SCL P0_6
#define SDA_OUT() P0DIR |= BV(4);
#define SDA_IN() P0DIR &= ~BV(4);
void I2C_init(void);
void I2C_start(void);
void I2C_stop(void);
void I2C_ack(void);
void I2C_nack(void);
uint8_t I2C_write(unsigned char dado);
uint8_t I2C_read(void);
// void i2c_device_write(unsigned char slave ,unsigned char reg_add ,unsigned char dado);
// unsigned char i2c_device_read(unsigned char slave, unsigned char reg_add);
#define NFC_R_ADDR 0xAB
#define NFC_W_ADDR 0xAA
#define BBV(x) ((uint8_t)((uint8_t)1u << (uint8_t)(x)))
#define NFC_CONFIGU_REG_MEMA 0x3Au
#define NFC_SESSION_REG_MEMA 0xFEu
#define NFC_CONFIGU_NC_REG_REGA 0x00u
#define NFC_CONFIGU_NC_REG_PTHRU_ON_OFF BBV(6)
#define NFC_SESSION_NC_REG_REGA 0x00u
#define NFC_SESSION_NC_REG_PTHRU_ON_OFF BBV(6)
#define NFC_SESSION_NC_REG_FD_ON_OFF ((uint8_t)0x3cu)
#define NFC_SESSION_NS_REG_REGA 0x06u
#define NFC_SESSION_NS_REG_NDEF_DATA_READ BBV(7)
#define NFC_SESSION_NS_REG_I2C_LOCKED BBV(6)
#define NFC_SESSION_NS_REG_RF_LOCKED BBV(5)
#define NFC_SESSION_NS_REG_SRAM_I2C_READY BBV(4)
#define NFC_SESSION_NS_REG_SRAM_RF_READY BBV(3)
#define NFC_SESSION_NS_REG_RF_FIELD_PRESENT BBV(0)
typedef uint8_t NfcMemoryBlk[16];
bool Nfc_MemWriteBlk(uint8_t mema, const NfcMemoryBlk buf);
bool Nfc_MemReadBlk(uint8_t mema, NfcMemoryBlk buf);
bool Nfc_MemWrite(uint8_t mema, uint8_t *buf);
bool Nfc_MemRead(uint8_t mema, uint8_t *buf);
bool Nfc_WriteReg(uint8_t mema, uint8_t rega, uint8_t mask, uint8_t regdat);
bool Nfc_ReadReg(uint8_t mema, uint8_t rega, uint8_t *regdat);
bool Nfc_FullDump(uint8_t *buf, uint16_t bufLen);
bool Nfc_DirSet(bool nfc2iic);
bool Nfc_I2cLock(bool enable);
bool Nfc_ConfigurePassThru(bool enable);
bool Nfc_IsFieldActive(void);
bool Nfc_SetFdPin(uint8_t on, uint8_t off);
#endif // I2C_H

32
src/time/time.c Normal file
View File

@@ -0,0 +1,32 @@
#include "time.h"
#include "../util.h"
static volatile uint32_t currentTime = 0;
void time_isr(void) __interrupt(WDT_VECTOR)
{
currentTime += 2;
IRCON2 &= ~BV(4); // clear flag
}
void time_init()
{
WDCTL = BV(3) | BV(2) | 3; // enable WD, timer mode - 2ms
IEN2 |= BV(5); // enable WD interrupt
}
volatile uint32_t time()
{
uint32_t value;
HAL_CRITICAL_STATEMENT(value = currentTime);
return value;
}
void delayMs(uint16_t millis)
{
uint32_t start = time();
while (time() - start < millis)
{
}
}

10
src/time/time.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef _TIME_H_
#define _TIME_H_
#include <stdint.h>
void time_init();
uint32_t time();
void delayMs(uint16_t millis);
#endif

37
src/util.h Normal file
View File

@@ -0,0 +1,37 @@
#ifndef _UTIL_H_
#define _UTIL_H_
#include <cc2510fx.h>
#include <stdbool.h>
// void SetDebugArray(uint8_t *buf, uint16_t offset, uint16_t size);
#define BV(x) (1 << (x))
#define st(x) \
do \
{ \
x \
} while (__LINE__ == -1)
#define HAL_ENABLE_INTERRUPTS() st(EA = 1;)
#define HAL_DISABLE_INTERRUPTS() st(EA = 0;)
#define HAL_INTERRUPTS_ARE_ENABLED() (EA)
typedef unsigned char halIntState_t;
#define HAL_ENTER_CRITICAL_SECTION(x) st(x = EA; HAL_DISABLE_INTERRUPTS();)
#define HAL_EXIT_CRITICAL_SECTION(x) st(EA = x;)
#define HAL_CRITICAL_STATEMENT(x) st(halIntState_t _s; HAL_ENTER_CRITICAL_SECTION(_s); x; HAL_EXIT_CRITICAL_SECTION(_s);)
#define LED_BOOST_ON() P2_2 = 1
#define LED_BOOST_OFF() P2_2 = 0
#define LED_ON() P2_1 = 1
#define LED_OFF() P2_1 = 0
#define LED_TOGGLE() P2_1 ^= 1
#define LED_INIT() do { \
P2DIR |= BV(1) | BV(2); \
LED_OFF(); \
} while (0)
#endif