1
0
mirror of https://github.com/thooge/esp32-nmea2000-obp60.git synced 2025-12-16 15:33:05 +01:00

66 Commits

Author SHA1 Message Date
norbert-walter
175f525bcd Fix undervoltage detection, format error 2025-01-26 22:11:55 +01:00
Norbert Walter
ba6c1038af Merge pull request #153 from thooge/heartbeat
Integration of heartbeat and page number
2025-01-26 15:19:29 +01:00
Norbert Walter
cbe06f65be Merge pull request #154 from TobiasE-github/master
Dont't display ILUM on Min Power
2025-01-26 15:07:52 +01:00
norbert-walter
e7d5ada610 Fix undervoltage detection 2025-01-26 15:01:47 +01:00
Tobias E
38f1d5de44 Dont't display ILUM on Min Power 2025-01-26 13:09:35 +00:00
Tobias E
93402841cb Merge branch 'master' of https://github.com/TobiasE-github/esp32-nmea2000-obp60 2025-01-26 13:00:48 +00:00
f0cc5d9966 Integration of heartbeat and page number 2025-01-25 19:11:16 +01:00
norbert-walter
9dc857056b Fix LiPo battery level and sensor pad 2025-01-25 18:04:58 +01:00
Norbert Walter
c202554c5c Merge pull request #152 from thooge/battery
Battery symbols for OBP40
2025-01-25 16:20:13 +01:00
norbert-walter
df81e6e443 Fix charge status, add to PageVoltage 2025-01-25 16:19:10 +01:00
097111c270 Added code for new OBP40 battery symbols 2025-01-25 10:21:34 +01:00
bdfaf3c886 Added battery symbols 2025-01-25 09:39:12 +01:00
norbert-walter
26e551c616 Typo 2025-01-24 22:29:12 +01:00
norbert-walter
0cfaf1e793 Merge remote-tracking branch 'origin/master' 2025-01-24 22:19:50 +01:00
norbert-walter
ea9a2ff9c4 Fix for config.json, dependencies to other ode 2025-01-24 22:19:39 +01:00
norbert-walter
f116e41964 Fix for config.json, depensencies to other ode 2025-01-24 22:18:38 +01:00
Norbert Walter
cf7ef8d849 Merge pull request #151 from thooge/master
System page for OBP40 and deep sleep improvements
2025-01-24 18:49:03 +01:00
Norbert Walter
752388a6e7 Merge branch 'master' into master 2025-01-24 18:48:44 +01:00
norbert-walter
0b7863cb86 Typo 2025-01-24 18:41:48 +01:00
norbert-walter
e9ee49a6ef Add undervoltage for LiPo accu for OBP40 2025-01-24 17:33:34 +01:00
norbert-walter
bba24ac2fc Merge remote-tracking branch 'origin/master' 2025-01-24 15:28:09 +01:00
norbert-walter
7afcb86404 OBP40 Battery voltage measuring and capacity calculation 2025-01-24 15:23:02 +01:00
Norbert Walter
fc851093a6 Merge pull request #150 from free-x/obp60
extend CI for OBP boards
2025-01-24 12:52:21 +01:00
1174622b4a System page for OBP40 and deep sleep improvements 2025-01-24 12:44:10 +01:00
free-x
28e4fc0643 extend CI for OBP boards 2025-01-24 12:22:26 +01:00
Norbert Walter
a9525676b2 Merge pull request #149 from thooge/master
Fix for OBP40 in page system and deepSleep
2025-01-24 10:07:24 +01:00
46af8916e7 Fix for OBP40 in page system and deepSleep 2025-01-24 08:06:26 +01:00
norbert-walter
b4ebec872d Merge remote-tracking branch 'origin/master' 2025-01-23 22:55:47 +01:00
norbert-walter
78b5861da4 Typo 2025-01-23 22:55:35 +01:00
Norbert Walter
d6a7323600 Merge pull request #148 from thooge/system
Deep sleep for OBP60 and small fix for BMP180
2025-01-23 22:51:52 +01:00
Norbert Walter
db4547ac3f Merge pull request #146 from thooge/refresh
Improved page refresh possibilities and page white
2025-01-23 22:47:30 +01:00
1ff0de5d24 Deep sleep for OBP60 and small fix for BMP180 2025-01-23 19:49:44 +01:00
a42d31ff49 System page inprovements, e.g. soft reset 2025-01-22 20:14:55 +01:00
TobiasE-github
c85e575378 Merge branch 'norbert-walter:master' into master 2025-01-22 14:12:20 +01:00
44cb8d35ce Improved page refresh possibilities and page white 2025-01-22 12:07:00 +01:00
Norbert Walter
988e7ccbc7 Merge pull request #145 from thooge/master
Fix warning and FRAM code on system page
2025-01-21 22:43:35 +01:00
norbert-walter
535f1cd7c4 Modify power mode fpr OBP40 2025-01-21 22:41:47 +01:00
norbert-walter
fa2cfcccca Merge remote-tracking branch 'origin/master' 2025-01-21 22:08:22 +01:00
norbert-walter
27d23c9d16 Add sleep mode for OBP40 and cleanup code 2025-01-21 22:08:02 +01:00
TobiasE-github
922247ed4a Merge pull request #12 from thooge/master
Sync
2025-01-21 19:26:27 +01:00
norbert-walter
bea4c8298e Modify files for Gitpod 2025-01-21 16:32:40 +01:00
464d6879a3 Fix broken white page and add logo feature 2025-01-21 11:26:49 +01:00
b9356c9ae8 Fix warning and FRAM code on system page 2025-01-21 09:28:53 +01:00
norbert-walter
569273519c Correct splitting between OBP60 and OBP40 hardware 2025-01-20 21:21:58 +01:00
Norbert Walter
4c8ffae0b6 Merge pull request #144 from thooge/system
New system page
2025-01-20 20:22:01 +01:00
a73f50ba74 First working system page 2025-01-20 19:20:37 +01:00
Norbert Walter
f377ab135d Merge pull request #143 from thooge/master
OBP40 integration code and improvements
2025-01-20 16:13:07 +01:00
Norbert Walter
e348e40ab4 Merge pull request #142 from TobiasE-github/master
modified gen_set.py, as PageSixValues does not exist (yet)
2025-01-20 16:10:32 +01:00
1545855326 OBP40 integration code and improvements 2025-01-20 12:49:30 +01:00
9d395c719a More work on system page 2025-01-20 06:33:51 +01:00
322ae30858 Merge branch 'master' into system 2025-01-19 15:09:29 +01:00
Tobias E
27b916c079 modified gen_set.py, as PageSixValues does not exist (yet) 2025-01-19 08:36:13 +00:00
norbert-walter
87a7a79358 Change back to plaformio.ini OBP60 2025-01-19 00:23:22 +01:00
Norbert Walter
e7216e6d2b Merge branch 'wellenvogel:master' into master 2025-01-18 19:12:24 +01:00
Norbert Walter
e7f3430ed6 Merge pull request #141 from thooge/keyboard
Key label improvements: footer function
2025-01-18 19:10:33 +01:00
Norbert Walter
2c2d21535b Merge pull request #139 from TobiasE-github/master
Add SixValues and fix Fluid in gen_set.py
2025-01-18 19:06:40 +01:00
Tobias E
27b02c4860 removed obsolete perl script gen_set.pl 2025-01-18 13:59:37 +00:00
e917a7fc76 Modification of footer layout and new swipe icon 2025-01-17 21:23:41 +01:00
Tobias E
10552763fb add explanation to gen_set.py 2025-01-17 19:24:16 +00:00
Tobias E
24386d4d42 add explanation to gen_set.py 2025-01-17 19:23:26 +00:00
norbert-walter
49be7f117a Modify pad detectionfor OBP60 Light 2025-01-17 18:00:32 +01:00
TobiasE-github
e70660c981 Merge branch 'norbert-walter:master' into master 2025-01-14 20:39:25 +01:00
TobiasE-github
4395c623ea Merge branch 'norbert-walter:master' into master 2025-01-13 06:30:15 +01:00
Tobias E
dfc79c80dc Add SixValues and fix Fluid in gen_set.py 2025-01-12 21:40:39 +00:00
wellenvogel
a129d865c9 warn the user if page translation is enabled for cibuild 2024-12-10 19:16:11 +01:00
57e194e39d Add new system page 2024-12-07 11:11:07 +01:00
122 changed files with 5263 additions and 29806 deletions

View File

@@ -10,7 +10,7 @@
"-DBOARD_HAS_PSRAM",
"-DARDUINO_ESP32S3_DEV",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_CDC_ON_BOOT=0",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
@@ -19,12 +19,12 @@
"flash_mode": "qio",
"hwids": [
[
"0x303A",
"0x1001"
"0x1A86",
"0x7523"
]
],
"mcu": "esp32s3",
"variant": "obp60s3_light"
"variant": "obp40s3"
},
"connectivity": [
"bluetooth",
@@ -41,7 +41,7 @@
"arduino",
"espidf"
],
"name": "OBP60 Light ESP32-S3-N8R8 (8 MB QD, 8 MB PSRAM)",
"name": "OBP40 ESP32-S3-N8R8 (8 MB QD, 8 MB PSRAM)",
"upload": {
"flash_size": "8MB",
"maximum_ram_size": 327680,

View File

@@ -10,7 +10,7 @@ from datetime import datetime
import re
import pprint
from platformio.project.config import ProjectConfig
from platformio.project.exception import InvalidProjectConfError
Import("env")
#print(env.Dump())
@@ -104,7 +104,17 @@ def writeFileIfChanged(fileName,data):
return True
def mergeConfig(base,other):
try:
customconfig = env.GetProjectOption("custom_config")
except InvalidProjectConfError:
customconfig = None
for bdir in other:
if customconfig and os.path.exists(os.path.join(bdir,customconfig)):
cname=os.path.join(bdir,customconfig)
print("merge custom config {}".format(cname))
with open(cname,'rb') as ah:
base += json.load(ah)
continue
cname=os.path.join(bdir,"config.json")
if os.path.exists(cname):
print("merge config %s"%cname)
@@ -274,9 +284,9 @@ class Grove:
def _ss(self,z=False):
if z:
return self.name
return self.name if self.name is not 'Z' else ''
return self.name if self.name != 'Z' else ''
def _suffix(self):
return '_'+self.name if self.name is not 'Z' else ''
return '_'+self.name if self.name != 'Z' else ''
def replace(self,line):
if line is None:
return line

518
extra_script.py.old Normal file
View File

@@ -0,0 +1,518 @@
print("running extra...")
import gzip
import shutil
import os
import sys
import inspect
import json
import glob
from datetime import datetime
import re
import pprint
from platformio.project.config import ProjectConfig
Import("env")
#print(env.Dump())
OWN_FILE="extra_script.py"
GEN_DIR='lib/generated'
CFG_FILE='web/config.json'
XDR_FILE='web/xdrconfig.json'
INDEXJS="index.js"
INDEXCSS="index.css"
CFG_INCLUDE='GwConfigDefinitions.h'
CFG_INCLUDE_IMPL='GwConfigDefImpl.h'
XDR_INCLUDE='GwXdrTypeMappings.h'
TASK_INCLUDE='GwUserTasks.h'
GROVE_CONFIG="GwM5GroveGen.h"
GROVE_CONFIG_IN="lib/hardware/GwM5Grove.in"
EMBEDDED_INCLUDE="GwEmbeddedFiles.h"
def getEmbeddedFiles(env):
rt=[]
efiles=env.GetProjectOption("board_build.embed_files")
for f in efiles.split("\n"):
if f == '':
continue
rt.append(f)
return rt
def basePath():
#see: https://stackoverflow.com/questions/16771894/python-nameerror-global-name-file-is-not-defined
return os.path.dirname(inspect.getfile(lambda: None))
def outPath():
return os.path.join(basePath(),GEN_DIR)
def checkDir():
dn=outPath()
if not os.path.exists(dn):
os.makedirs(dn)
if not os.path.isdir(dn):
print("unable to create %s"%dn)
return False
return True
def isCurrent(infile,outfile):
if os.path.exists(outfile):
otime=os.path.getmtime(outfile)
itime=os.path.getmtime(infile)
if (otime >= itime):
own=os.path.join(basePath(),OWN_FILE)
if os.path.exists(own):
owntime=os.path.getmtime(own)
if owntime > otime:
return False
print("%s is newer then %s, no need to recreate"%(outfile,infile))
return True
return False
def compressFile(inFile,outfile):
if isCurrent(inFile,outfile):
return
print("compressing %s"%inFile)
with open(inFile, 'rb') as f_in:
with gzip.open(outfile, 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
def generateFile(infile,outfile,callback,inMode='rb',outMode='w'):
if isCurrent(infile,outfile):
return
print("creating %s"%outfile)
oh=None
with open(infile,inMode) as ch:
with open(outfile,outMode) as oh:
try:
callback(ch,oh,inFile=infile)
oh.close()
except Exception as e:
try:
oh.close()
except:
pass
os.unlink(outfile)
raise
def writeFileIfChanged(fileName,data):
if os.path.exists(fileName):
with open(fileName,"r") as ih:
old=ih.read()
ih.close()
if old == data:
return False
print("#generating %s"%fileName)
with open(fileName,"w") as oh:
oh.write(data)
return True
def mergeConfig(base,other):
for bdir in other:
cname=os.path.join(bdir,"config.json")
if os.path.exists(cname):
print("merge config %s"%cname)
with open(cname,'rb') as ah:
merge=json.load(ah)
base=base+merge
return base
def replaceTexts(data,replacements):
if replacements is None:
return data
if isinstance(data,str):
for k,v in replacements.items():
data=data.replace("$"+k,str(v))
return data
if isinstance(data,list):
rt=[]
for e in data:
rt.append(replaceTexts(e,replacements))
return rt
if isinstance(data,dict):
rt={}
for k,v in data.items():
rt[replaceTexts(k,replacements)]=replaceTexts(v,replacements)
return rt
return data
def expandConfig(config):
rt=[]
for item in config:
type=item.get('type')
if type != 'array':
rt.append(item)
continue
replacements=item.get('replace')
children=item.get('children')
name=item.get('name')
if name is None:
name="#unknown#"
if not isinstance(replacements,list):
raise Exception("missing replacements at array %s"%name)
for replace in replacements:
if children is not None:
for c in children:
rt.append(replaceTexts(c,replace))
return rt
def generateMergedConfig(inFile,outFile,addDirs=[]):
if not os.path.exists(inFile):
raise Exception("unable to read cfg file %s"%inFile)
data=""
with open(inFile,'rb') as ch:
config=json.load(ch)
config=mergeConfig(config,addDirs)
config=expandConfig(config)
data=json.dumps(config,indent=2)
writeFileIfChanged(outFile,data)
def generateCfg(inFile,outFile,impl):
if not os.path.exists(inFile):
raise Exception("unable to read cfg file %s"%inFile)
data=""
with open(inFile,'rb') as ch:
config=json.load(ch)
data+="//generated from %s\n"%inFile
l=len(config)
idx=0
if not impl:
data+='#include "GwConfigItem.h"\n'
data+='class GwConfigDefinitions{\n'
data+=' public:\n'
data+=' int getNumConfig() const{return %d;}\n'%(l)
for item in config:
n=item.get('name')
if n is None:
continue
if len(n) > 15:
raise Exception("%s: config names must be max 15 caracters"%n)
data+=' static constexpr const char* %s="%s";\n'%(n,n)
data+="};\n"
else:
data+='void GwConfigHandler::populateConfigs(GwConfigInterface **config){\n'
for item in config:
name=item.get('name')
if name is None:
continue
data+=' configs[%d]='%(idx)
idx+=1
secret="false";
if item.get('type') == 'password':
secret="true"
data+=" new GwConfigInterface(%s,\"%s\",%s);\n"%(name,item.get('default'),secret)
data+='}\n'
writeFileIfChanged(outFile,data)
def labelFilter(label):
return re.sub("[^a-zA-Z0-9]","",re.sub("\([0-9]*\)","",label))
def generateXdrMappings(fp,oh,inFile=''):
jdoc=json.load(fp)
oh.write("static GwXDRTypeMapping* typeMappings[]={\n")
first=True
for cat in jdoc:
item=jdoc[cat]
cid=item.get('id')
if cid is None:
continue
tc=item.get('type')
if tc is not None:
if first:
first=False
else:
oh.write(",\n")
oh.write(" new GwXDRTypeMapping(%d,0,%d) /*%s*/"%(cid,tc,cat))
fields=item.get('fields')
if fields is None:
continue
idx=0
for fe in fields:
if not isinstance(fe,dict):
continue
tc=fe.get('t')
id=fe.get('v')
if id is None:
id=idx
idx+=1
l=fe.get('l') or ''
if tc is None or id is None:
continue
if first:
first=False
else:
oh.write(",\n")
oh.write(" new GwXDRTypeMapping(%d,%d,%d) /*%s:%s*/"%(cid,id,tc,cat,l))
oh.write("\n")
oh.write("};\n")
for cat in jdoc:
item=jdoc[cat]
cid=item.get('id')
if cid is None:
continue
selectors=item.get('selector')
if selectors is not None:
for selector in selectors:
label=selector.get('l')
value=selector.get('v')
if label is not None and value is not None:
label=labelFilter(label)
define=("GWXDRSEL_%s_%s"%(cat,label)).upper()
oh.write(" #define %s %s\n"%(define,value))
fields=item.get('fields')
if fields is not None:
idx=0
for field in fields:
v=field.get('v')
if v is None:
v=idx
else:
v=int(v)
label=field.get('l')
if v is not None and label is not None:
define=("GWXDRFIELD_%s_%s"%(cat,labelFilter(label))).upper();
oh.write(" #define %s %s\n"%(define,str(v)))
idx+=1
class Grove:
def __init__(self,name) -> None:
self.name=name
def _ss(self,z=False):
if z:
return self.name
return self.name if self.name is not 'Z' else ''
def _suffix(self):
return '_'+self.name if self.name is not 'Z' else ''
def replace(self,line):
if line is None:
return line
return line.replace('$G$',self._ss()).replace('$Z$',self._ss(True)).replace('$GS$',self._suffix())
def generateGroveDefs(inh,outh,inFile=''):
GROVES=[Grove('Z'),Grove('A'),Grove('B'),Grove('C')]
definition=[]
started=False
def writeConfig():
for grove in GROVES:
for cl in definition:
outh.write(grove.replace(cl))
for line in inh:
if re.match(" *#GROVE",line):
started=True
if len(definition) > 0:
writeConfig()
definition=[]
continue
if started:
definition.append(line)
if len(definition) > 0:
writeConfig()
userTaskDirs=[]
def getUserTaskDirs():
rt=[]
taskdirs=glob.glob(os.path.join( basePath(),'lib','*task*'))
for task in taskdirs:
rt.append(task)
return rt
def checkAndAdd(file,names,ilist):
if not file.endswith('.h'):
return
match=False
for cmp in names:
#print("##check %s<->%s"%(f.lower(),cmp))
if file.lower() == cmp:
match=True
if not match:
return
ilist.append(file)
def genereateUserTasks(outfile):
includes=[]
for task in userTaskDirs:
#print("##taskdir=%s"%task)
base=os.path.basename(task)
includeNames=[base.lower()+".h",'gw'+base.lower()+'.h']
for f in os.listdir(task):
checkAndAdd(f,includeNames,includes)
includeData=""
for i in includes:
print("#task include %s"%i)
includeData+="#include <%s>\n"%i
writeFileIfChanged(outfile,includeData)
def generateEmbedded(elist,outFile):
content=""
for entry in elist:
content+="EMBED_GZ_FILE(\"%s\",%s,\"%s\");\n"%entry
writeFileIfChanged(outFile,content)
def getContentType(fn):
if (fn.endswith('.gz')):
fn=fn[0:-3]
if (fn.endswith('html')):
return "text/html"
if (fn.endswith('json')):
return "application/json"
if (fn.endswith('js')):
return "text/javascript"
if (fn.endswith('css')):
return "text/css"
return "application/octet-stream"
def getLibs():
base=os.path.join(basePath(),"lib")
rt=[]
for sd in os.listdir(base):
if sd == '..':
continue
if sd == '.':
continue
fn=os.path.join(base,sd)
if os.path.isdir(fn):
rt.append(sd)
EXTRAS=['generated']
for e in EXTRAS:
if not e in rt:
rt.append(e)
return rt
def joinFiles(target,pattern,dirlist):
flist=[]
for dir in dirlist:
fn=os.path.join(dir,pattern)
if os.path.exists(fn):
flist.append(fn)
current=False
if os.path.exists(target):
current=True
for f in flist:
if not isCurrent(f,target):
current=False
break
if current:
print("%s is up to date"%target)
return
print("creating %s"%target)
with gzip.open(target,"wb") as oh:
for fn in flist:
print("adding %s to %s"%(fn,target))
with open(fn,"rb") as rh:
shutil.copyfileobj(rh,oh)
OWNLIBS=getLibs()+["FS","WiFi"]
GLOBAL_INCLUDES=[]
def handleDeps(env):
#overwrite the GetProjectConfig
#to inject all our libs
oldGetProjectConfig=env.GetProjectConfig
def GetProjectConfigX(env):
rt=oldGetProjectConfig()
cenv="env:"+env['PIOENV']
libs=[]
for section,options in rt.as_tuple():
if section == cenv:
for key,values in options:
if key == 'lib_deps':
libs=values
mustUpdate=False
for lib in OWNLIBS:
if not lib in libs:
libs.append(lib)
mustUpdate=True
if mustUpdate:
update=[(cenv,[('lib_deps',libs)])]
rt.update(update)
return rt
env.AddMethod(GetProjectConfigX,"GetProjectConfig")
#store the list of all includes after we resolved
#the dependencies for our main project
#we will use them for all compilations afterwards
oldLibBuilder=env.ConfigureProjectLibBuilder
def ConfigureProjectLibBuilderX(env):
global GLOBAL_INCLUDES
project=oldLibBuilder()
#print("##ConfigureProjectLibBuilderX")
#pprint.pprint(project)
if project.depbuilders:
#print("##depbuilders %s"%",".join(map(lambda x: x.path,project.depbuilders)))
for db in project.depbuilders:
idirs=db.get_include_dirs()
for id in idirs:
if not id in GLOBAL_INCLUDES:
GLOBAL_INCLUDES.append(id)
return project
env.AddMethod(ConfigureProjectLibBuilderX,"ConfigureProjectLibBuilder")
def injectIncludes(env,node):
return env.Object(
node,
CPPPATH=env["CPPPATH"]+GLOBAL_INCLUDES
)
env.AddBuildMiddleware(injectIncludes)
def prebuild(env):
global userTaskDirs
print("#prebuild running")
if not checkDir():
sys.exit(1)
ldf_mode=env.GetProjectOption("lib_ldf_mode")
if ldf_mode == 'off':
print("##ldf off - own dependency handling")
handleDeps(env)
userTaskDirs=getUserTaskDirs()
mergedConfig=os.path.join(outPath(),os.path.basename(CFG_FILE))
generateMergedConfig(os.path.join(basePath(),CFG_FILE),mergedConfig,userTaskDirs)
compressFile(mergedConfig,mergedConfig+".gz")
generateCfg(mergedConfig,os.path.join(outPath(),CFG_INCLUDE),False)
generateCfg(mergedConfig,os.path.join(outPath(),CFG_INCLUDE_IMPL),True)
joinFiles(os.path.join(outPath(),INDEXJS+".gz"),INDEXJS,["web"]+userTaskDirs)
joinFiles(os.path.join(outPath(),INDEXCSS+".gz"),INDEXCSS,["web"]+userTaskDirs)
embedded=getEmbeddedFiles(env)
filedefs=[]
for ef in embedded:
print("#checking embedded file %s"%ef)
(dn,fn)=os.path.split(ef)
pureName=fn
if pureName.endswith('.gz'):
pureName=pureName[0:-3]
ct=getContentType(pureName)
usname=ef.replace('/','_').replace('.','_')
filedefs.append((pureName,usname,ct))
inFile=os.path.join(basePath(),"web",pureName)
if os.path.exists(inFile):
compressFile(inFile,ef)
else:
print("#WARNING: infile %s for %s not found"%(inFile,ef))
generateEmbedded(filedefs,os.path.join(outPath(),EMBEDDED_INCLUDE))
genereateUserTasks(os.path.join(outPath(), TASK_INCLUDE))
generateFile(os.path.join(basePath(),XDR_FILE),os.path.join(outPath(),XDR_INCLUDE),generateXdrMappings)
generateFile(os.path.join(basePath(),GROVE_CONFIG_IN),os.path.join(outPath(),GROVE_CONFIG),generateGroveDefs,inMode='r')
version="dev"+datetime.now().strftime("%Y%m%d")
env.Append(CPPDEFINES=[('GWDEVVERSION',version)])
def cleangenerated(source, target, env):
od=outPath()
if os.path.isdir(od):
print("#cleaning up %s"%od)
for f in os.listdir(od):
if f == "." or f == "..":
continue
fn=os.path.join(od,f)
os.unlink(f)
print("#prescript...")
prebuild(env)
board="PLATFORM_BOARD_%s"%env["BOARD"].replace("-","_").upper()
print("Board=#%s#"%board)
print("BuildFlags=%s"%(" ".join(env["BUILD_FLAGS"])))
env.Append(
LINKFLAGS=[ "-u", "custom_app_desc" ],
CPPDEFINES=[(board,"1")]
)
#script does not run on clean yet - maybe in the future
env.AddPostAction("clean",cleangenerated)

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
/****************************************************
AMS 5600 class for Arduino platform

View File

@@ -2,5 +2,5 @@ Craete new page for OBP60
1. Create page under /lib/obp60task/PageXXXX.cpp
2. Set page name in PageXXXX.cpp on file name
3. Register new page in /lib/obp60task/obp60task.cpp line 242 (registerAllPages)
4. Add new page in /lib/obp60task/config.json for each page type or add new page to gen_set.pl and run it to auto-generate the relevant section of config.json
4. Add new page in /lib/obp60task/config.json for each page type or add new page to gen_set.py and run it to auto-generate the relevant section of config.json

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include <Arduino.h>
#include <PCF8574.h> // Driver for PCF8574 output modul from Horter
@@ -70,6 +70,9 @@ bool statusBacklightLED = false;// Actual status of flash LED on/off
int uvDuration = 0; // Under voltage duration in n x 100ms
RTC_DATA_ATTR uint8_t RTC_lastpage; // Remember last page while deep sleeping
LedTaskData *ledTaskData=nullptr;
void hardwareInit(GwApi *api)
@@ -118,6 +121,61 @@ void startLedTask(GwApi *api){
createSpiLedTask(ledTaskData);
}
uint8_t getLastPage() {
return RTC_lastpage;
}
#ifdef BOARD_OBP60S3
void deepSleep(CommonData &common){
RTC_lastpage = common.data.actpage - 1;
// Switch off all power lines
setPortPin(OBP_BACKLIGHT_LED, false); // Backlight Off
setFlashLED(false); // Flash LED Off
buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms
// Shutdown EInk display
getdisplay().setFullWindow(); // Set full Refresh
getdisplay().fillScreen(common.bgcolor); // Clear screen
getdisplay().setTextColor(common.fgcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(85, 150);
getdisplay().print("Sleep Mode");
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(65, 175);
getdisplay().print("To wake up press key and wait 5s");
getdisplay().nextPage(); // Update display contents
getdisplay().powerOff(); // Display power off
setPortPin(OBP_POWER_50, false); // Power off ePaper display
// Stop system
esp_deep_sleep_start(); // Deep Sleep with weakup via touch pin
}
#endif
#ifdef BOARD_OBP40S3
// Deep sleep funktion
void deepSleep(CommonData &common){
RTC_lastpage = common.data.actpage - 1;
// Switch off all power lines
setPortPin(OBP_BACKLIGHT_LED, false); // Backlight Off
setFlashLED(false); // Flash LED Off
// Shutdown EInk display
getdisplay().setFullWindow(); // Set full Refresh
//getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
getdisplay().fillScreen(common.bgcolor); // Clear screen
getdisplay().setTextColor(common.fgcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(85, 150);
getdisplay().print("Sleep Mode");
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(65, 175);
getdisplay().print("To wake up press wheel and wait 5s");
getdisplay().nextPage(); // Partial update
getdisplay().powerOff(); // Display power off
setPortPin(OBP_POWER_EPD, false); // Power off ePaper display
setPortPin(OBP_POWER_SD, false); // Power off SD card
// Stop system
esp_deep_sleep_start(); // Deep Sleep with weakup via GPIO pin
}
#endif
// Valid colors see hue
Color colorMapping(const String &colorString){
Color color = COLOR_RED;
@@ -283,13 +341,9 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
static unsigned long tcpClTxOld = 0;
static unsigned long n2kRxOld = 0;
static unsigned long n2kTxOld = 0;
int textcolor = GxEPD_BLACK;
if(commonData.config->getBool(commonData.config->statusLine) == true){
// Header separator line (optional)
// getdisplay().drawLine(0, 19, 399, 19, commonData.fgcolor);
// Show status info
getdisplay().setTextColor(commonData.fgcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
@@ -326,24 +380,45 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
usbRxOld = commonData.status.usbRx;
usbTxOld = commonData.status.usbTx;
#ifdef HARDWARE_V21
// Display key lock status
if (commonData.keylock) {
getdisplay().drawXBitmap(150, 1, lock_bits, icon_width, icon_height, commonData.fgcolor);
getdisplay().drawXBitmap(170, 1, lock_bits, icon_width, icon_height, commonData.fgcolor);
} else {
getdisplay().drawXBitmap(150, 1, swipe_bits, icon_width, icon_height, commonData.fgcolor);
getdisplay().drawXBitmap(166, 1, swipe_bits, swipe_width, swipe_height, commonData.fgcolor);
}
#endif
#ifdef LIPO_ACCU_1200
if (commonData.data.BatteryChargeStatus == 1) {
getdisplay().drawXBitmap(170, 1, battery_loading_bits, battery_width, battery_height, commonData.fgcolor);
} else {
#ifdef VOLTAGE_SENSOR
if (commonData.data.batteryLevelLiPo < 10) {
getdisplay().drawXBitmap(170, 1, battery_0_bits, battery_width, battery_height, commonData.fgcolor);
} else if (commonData.data.batteryLevelLiPo < 25) {
getdisplay().drawXBitmap(170, 1, battery_25_bits, battery_width, battery_height, commonData.fgcolor);
} else if (commonData.data.batteryLevelLiPo < 50) {
getdisplay().drawXBitmap(170, 1, battery_50_bits, battery_width, battery_height, commonData.fgcolor);
} else if (commonData.data.batteryLevelLiPo < 75) {
getdisplay().drawXBitmap(170, 1, battery_75_bits, battery_width, battery_height, commonData.fgcolor);
} else {
getdisplay().drawXBitmap(170, 1, battery_100_bits, battery_width, battery_height, commonData.fgcolor);
}
#endif // VOLTAGE_SENSOR
}
#endif // LIPO_ACCU_1200
// Current page number in a small box
// Heartbeat as page number
if (heartbeat) {
getdisplay().setTextColor(commonData.bgcolor);
getdisplay().fillRect(201, 0, 23, 19, commonData.fgcolor);
} else {
getdisplay().setTextColor(commonData.fgcolor);
getdisplay().drawRect(201, 0, 23, 19, commonData.fgcolor);
}
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().drawRect(170, 2, 20, 15, commonData.fgcolor);
drawTextCenter(179, 9, String(commonData.data.actpage));
// Heartbeat as dot
getdisplay().setTextColor(commonData.fgcolor);
getdisplay().setFont(&Ubuntu_Bold32pt7b);
getdisplay().setCursor(205, 14);
getdisplay().print(heartbeat ? "." : " ");
heartbeat = !heartbeat;
drawTextCenter(211, 9, String(commonData.data.actpage));
heartbeat = !heartbeat;
// Date and time
getdisplay().setTextColor(commonData.fgcolor);
@@ -381,14 +456,22 @@ void displayFooter(CommonData &commonData) {
getdisplay().setFont(&Atari16px);
getdisplay().setTextColor(commonData.fgcolor);
#ifdef HARDWARE_V21
// Frame around key icon area
getdisplay().drawLine(0, 280, 399, 280, commonData.fgcolor);
if (! commonData.keylock) {
getdisplay().drawLine(68, 280, 68, 299, commonData.fgcolor);
getdisplay().drawLine(134, 280, 134, 299, commonData.fgcolor);
getdisplay().drawLine(200, 280, 200, 299, commonData.fgcolor);
getdisplay().drawLine(266, 280, 266, 299, commonData.fgcolor);
getdisplay().drawLine(332, 280, 332, 299, commonData.fgcolor);
// horizontal elements
const uint16_t top = 280;
const uint16_t bottom = 299;
// horizontal stub lines
getdisplay().drawLine(commonData.keydata[0].x, top, commonData.keydata[0].x+10, top, commonData.fgcolor);
for (int i = 1; i <= 5; i++) {
getdisplay().drawLine(commonData.keydata[i].x-10, top, commonData.keydata[i].x+10, top, commonData.fgcolor);
}
getdisplay().drawLine(commonData.keydata[5].x + commonData.keydata[5].w - 10, top, commonData.keydata[5].x + commonData.keydata[5].w + 1, top, commonData.fgcolor);
// vertical key separators
for (int i = 0; i <= 4; i++) {
getdisplay().drawLine(commonData.keydata[i].x + commonData.keydata[i].w, top, commonData.keydata[i].x + commonData.keydata[i].w, bottom, commonData.fgcolor);
}
for (int i = 0; i < 6; i++) {
uint16_t x, y;
if (commonData.keydata[i].label.length() > 0) {
@@ -416,6 +499,32 @@ void displayFooter(CommonData &commonData) {
getdisplay().setCursor(65, 295);
getdisplay().print("Press 1 and 6 fast to unlock keys");
}
#endif
#ifdef BOARD_OBP40S3
// grapical page indicator
static const uint16_t r = 5;
static const uint16_t space = 4;
uint16_t w = commonData.data.maxpage * r * 2 + (commonData.data.maxpage - 1) * space;
uint16_t x0 = (GxEPD_WIDTH - w) / 2 + r * 2;
for (int i = 0; i < commonData.data.maxpage; i++) {
if (i == (commonData.data.actpage - 1)) {
getdisplay().fillCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor);
} else {
getdisplay().drawCircle(x0 + i * (r * 2 + space), 290, r, commonData.fgcolor);
}
}
// key indicators
// left side = top key "menu"
getdisplay().drawLine(0, 280, 10, 280, commonData.fgcolor);
getdisplay().drawLine(55, 280, 65, 280, commonData.fgcolor);
getdisplay().drawLine(65, 280, 65, 299, commonData.fgcolor);
drawTextCenter(33, 291, commonData.keydata[0].label);
// right side = bottom key "exit"
getdisplay().drawLine(390, 280, 399, 280, commonData.fgcolor);
getdisplay().drawLine(335, 280, 345, 280, commonData.fgcolor);
getdisplay().drawLine(335, 280, 335, 399, commonData.fgcolor);
drawTextCenter(366, 291, commonData.keydata[1].label);
#endif
}
// Sunset und sunrise calculation

View File

@@ -10,6 +10,7 @@
// FRAM address reservations 32kB: 0x0000 - 0x7FFF
// 0x0000 - 0x03ff: single variables
#define FRAM_PAGE_NO 0x0002
#define FRAM_SYSTEM_MODE 0x009
// Voltage page
#define FRAM_VOLTAGE_AVG 0x000A
#define FRAM_VOLTAGE_TREND 0x000B
@@ -36,6 +37,7 @@ extern const GFXfont DSEG7Classic_BoldItalic20pt7b;
extern const GFXfont DSEG7Classic_BoldItalic30pt7b;
extern const GFXfont DSEG7Classic_BoldItalic42pt7b;
extern const GFXfont DSEG7Classic_BoldItalic60pt7b;
extern const GFXfont Atari16px;
// Global functions
#ifdef DISPLAY_GDEW042T2
@@ -62,6 +64,10 @@ Point rotatePoint(const Point& origin, const Point& p, double angle);
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle);
void fillPoly4(const std::vector<Point>& p4, uint16_t color);
void deepSleep(CommonData &common);
uint8_t getLastPage();
void hardwareInit(GwApi *api);
void setPortPin(uint pin, bool value); // Set port pin for extension port
@@ -94,8 +100,8 @@ void displayFooter(CommonData &commonData);
SunData calcSunsetSunrise(GwApi *api, double time, double date, double latitude, double longitude, double timezone); // Calulate sunset and sunrise
void batteryGraphic(uint x, uint y, float percent, int pcolor, int bcolor); // Battery graphic with fill level
void solarGraphic(uint x, uint y, int pcolor, int bcolor); // Solar graphic with fill level
void generatorGraphic(uint x, uint y, int pcolor, int bcolor); // Generator graphic with fill level
void solarGraphic(uint x, uint y, int pcolor, int bcolor); // Solar graphic
void generatorGraphic(uint x, uint y, int pcolor, int bcolor); // Generator graphic
void startLedTask(GwApi *api);
void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUMBER], AsyncWebServerRequest *request);
@@ -114,11 +120,6 @@ static unsigned char right_bits[] PROGMEM = {
0xfe, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0x7f, 0xfe, 0x3f, 0x80, 0x1f,
0x80, 0x0f, 0x80, 0x07, 0x80, 0x03, 0x00, 0x00 };
static unsigned char swipe_bits[] = {
0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0xc8, 0x05, 0x48, 0x0e,
0x4a, 0x12, 0x4d, 0x32, 0x09, 0x50, 0x41, 0x44, 0x62, 0x4c, 0xf2, 0x5f,
0x64, 0x2c, 0x48, 0x24, 0x10, 0x10, 0xe0, 0x0f };
static unsigned char lock_bits[] PROGMEM = {
0xc0, 0x03, 0x60, 0x06, 0x30, 0x0c, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08,
0xfc, 0x3f, 0x04, 0x20, 0x04, 0x20, 0x84, 0x21, 0x84, 0x21, 0x84, 0x21,
@@ -139,19 +140,78 @@ static unsigned char fram_bits[] PROGMEM = {
0xff, 0xff, 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f,
0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f };
static unsigned char ap_bits[] = {
0xe0, 0x03, 0x18, 0x0c, 0x04, 0x10, 0xc2, 0x21, 0x30, 0x06, 0x08, 0x08,
0xc0, 0x01, 0x20, 0x02, 0x00, 0x00, 0x80, 0x00, 0xc0, 0x01, 0xc0, 0x01,
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
static unsigned char dish_bits[] PROGMEM= {
0x3c, 0x00, 0x42, 0x18, 0xfa, 0x1b, 0x02, 0x04, 0x02, 0x0a, 0x02, 0x09,
0x82, 0x08, 0x06, 0x0a, 0x0e, 0x1b, 0x9c, 0x2b, 0x38, 0x2b, 0x74, 0x20,
0xec, 0x1f, 0x1c, 0x00, 0xf4, 0x00, 0xfe, 0x03 };
static std::map<String, unsigned char *> iconmap = {
{"LEFT", left_bits},
{"RIGHT", right_bits},
{"SWIPE", swipe_bits},
{"LOCK", lock_bits},
{"PLUS", plus_bits},
{"MINUS", minus_bits}
{"MINUS", minus_bits},
{"DISH", dish_bits},
{"AP", ap_bits}
};
// Battery
#define battery_width 24
#define battery_height 16
static unsigned char battery_0_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0xff, 0xff, 0x1f,
0x03, 0x00, 0x18, 0x03, 0x00, 0x78, 0x03, 0x00, 0xf8, 0x03, 0x00, 0xd8,
0x03, 0x00, 0xd8, 0x03, 0x00, 0xd8, 0x03, 0x00, 0xf8, 0x03, 0x00, 0x78,
0x03, 0x00, 0x18, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00 };
static unsigned char battery_25_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0xff, 0xff, 0x1f,
0x03, 0x00, 0x18, 0x3b, 0x00, 0x78, 0x3b, 0x00, 0xf8, 0x3b, 0x00, 0xd8,
0x3b, 0x00, 0xd8, 0x3b, 0x00, 0xd8, 0x3b, 0x00, 0xf8, 0x3b, 0x00, 0x78,
0x03, 0x00, 0x18, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00 };
static unsigned char battery_50_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0xff, 0xff, 0x1f,
0x03, 0x00, 0x18, 0xbb, 0x03, 0x78, 0xbb, 0x03, 0xf8, 0xbb, 0x03, 0xd8,
0xbb, 0x03, 0xd8, 0xbb, 0x03, 0xd8, 0xbb, 0x03, 0xf8, 0xbb, 0x03, 0x78,
0x03, 0x00, 0x18, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00 };
static unsigned char battery_75_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0xff, 0xff, 0x1f,
0x03, 0x00, 0x18, 0xbb, 0x3b, 0x78, 0xbb, 0x3b, 0xf8, 0xbb, 0x3b, 0xd8,
0xbb, 0x3b, 0xd8, 0xbb, 0x3b, 0xd8, 0xbb, 0x3b, 0xf8, 0xbb, 0x3b, 0x78,
0x03, 0x00, 0x18, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00 };
static unsigned char battery_100_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0xff, 0xff, 0x1f,
0x03, 0x00, 0x18, 0xbb, 0xbb, 0x7b, 0xbb, 0xbb, 0xfb, 0xbb, 0xbb, 0xdb,
0xbb, 0xbb, 0xdb, 0xbb, 0xbb, 0xdb, 0xbb, 0xbb, 0xfb, 0xbb, 0xbb, 0x7b,
0x03, 0x00, 0x18, 0xff, 0xff, 0x1f, 0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00 };
static unsigned char battery_loading_bits[] = {
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0xfe, 0xe4, 0x0f, 0xff, 0xec, 0x1f,
0x03, 0x08, 0x18, 0x03, 0x18, 0x78, 0x03, 0x30, 0xf8, 0x83, 0x3f, 0xd8,
0x03, 0x7f, 0xd8, 0x03, 0x03, 0xd8, 0x03, 0x06, 0xf8, 0x03, 0x04, 0x78,
0x03, 0x0c, 0x18, 0xff, 0xcb, 0x1f, 0xfe, 0xd3, 0x0f, 0x00, 0x10, 0x00 };
// Other symbols
#define swipe_width 24
#define swipe_height 16
static unsigned char swipe_bits[] PROGMEM = {
0x00, 0x06, 0x00, 0x24, 0x09, 0x24, 0x12, 0x09, 0x48, 0x7f, 0x09, 0xfe,
0x12, 0xb9, 0x48, 0x24, 0xc9, 0x25, 0x40, 0x49, 0x02, 0xa0, 0x49, 0x06,
0x20, 0x01, 0x0a, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08,
0x80, 0x00, 0x04, 0x00, 0x01, 0x04, 0x00, 0x02, 0x02, 0x00, 0xfc, 0x01 };
#define exclamation_width 32
#define exclamation_height 32
static unsigned char exclamation_bits[] = {
static unsigned char exclamation_bits[] PROGMEM = {
0x00, 0xc0, 0x03, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0xb0, 0x0d, 0x00,
0x00, 0xd8, 0x1b, 0x00, 0x00, 0xec, 0x37, 0x00, 0x00, 0xf6, 0x6f, 0x00,
0x00, 0x3b, 0xdc, 0x00, 0x80, 0x3d, 0xbc, 0x01, 0xc0, 0x3e, 0x7c, 0x03,

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include <Arduino.h>
#include "GwApi.h"

View File

@@ -76,9 +76,9 @@
#define OBP_POWER_50 5 // 5.0V power rail
#endif
// Hardware configuration for OBP60 LIGHT
// Hardware configuration for OBP40
#ifdef HARDWARE_LIGHT
#ifdef BOARD_OBP40S3
// Direction pin for RS485 NMEA0183
#define OBP_DIRECTION_PIN 8
// I2C
@@ -149,13 +149,17 @@
// Flash LED (1x WS2812B)
#define NUM_FLASH_LED 1 // Number of flash LED
#define OBP_FLASH_LED 10 // GPIO port
#define OBP_FLASH_LED 41 // GPIO port (power LED)
// Backlight LEDs (6x WS2812B)
#define NUM_BACKLIGHT_LED 6 // Number of Backlight LEDs
#define OBP_BACKLIGHT_LED 40 // GPIO port
#define OBP_BACKLIGHT_LED 41 // GPIO port (power LED)
// Power Rail
#define OBP_POWER_50 41 // Power LED
#define OBP_POWER_EPD 7 // ePaper power
#define OBP_POWER_SD 42 // SD card power
// Deep sleep wakeup
#define OBP_WAKEUP_LEVEL 0 // //1 = High, 0 = Low, depends on switch
#define OBP_WAKEWUP_PIN GPIO_NUM_5// Wakeup pin, same as CONF (wheel press)
// Must define as GPIO_NUM_X
#endif

View File

@@ -22,40 +22,45 @@ long starttime = 0; // Start time point for pressed key
void initKeys(CommonData &commonData) {
// coordinates for virtual keyboard keys
commonData.keydata[0].x = 1;
commonData.keydata[0].y = 281;
commonData.keydata[0].w = 67;
commonData.keydata[0].h = 18;
commonData.keydata[1].x = 69;
commonData.keydata[1].y = 281;
commonData.keydata[1].w = 66;
commonData.keydata[1].h = 18;
static uint16_t top = 281;
static uint16_t width = 65;
static uint16_t height = 18;
commonData.keydata[2].x = 135;
commonData.keydata[2].y = 281;
commonData.keydata[2].w = 66;
commonData.keydata[2].h = 18;
commonData.keydata[0].x = 0;
commonData.keydata[0].y = top;
commonData.keydata[0].w = width + 1;
commonData.keydata[0].h = height;
commonData.keydata[3].x = 201;
commonData.keydata[3].y = 281;
commonData.keydata[3].w = 66;
commonData.keydata[3].h = 18;
commonData.keydata[1].x = commonData.keydata[0].x + commonData.keydata[0].w + 1;
commonData.keydata[1].y = top;
commonData.keydata[1].w = width;
commonData.keydata[1].h = height;
commonData.keydata[4].x = 267;
commonData.keydata[4].y = 281;
commonData.keydata[4].w = 66;
commonData.keydata[4].h = 18;
commonData.keydata[2].x = commonData.keydata[1].x + commonData.keydata[1].w + 1;
commonData.keydata[2].y = top;
commonData.keydata[2].w = width;
commonData.keydata[2].h = height;
commonData.keydata[5].x = 333;
commonData.keydata[5].y = 281;
commonData.keydata[5].w = 66;
commonData.keydata[5].h = 18;
commonData.keydata[3].x = commonData.keydata[2].x + commonData.keydata[2].w + 1;
commonData.keydata[3].y = top;
commonData.keydata[3].w = width;
commonData.keydata[3].h = height;
commonData.keydata[4].x = commonData.keydata[3].x + commonData.keydata[3].w + 1;
commonData.keydata[4].y = top;
commonData.keydata[4].w = width;
commonData.keydata[4].h = height;
commonData.keydata[5].x = commonData.keydata[4].x + commonData.keydata[4].w + 1;
commonData.keydata[5].y = top;
commonData.keydata[5].w = width;
commonData.keydata[5].h = height;
}
#ifdef HARDWARE_V21
// Keypad functions for original OBP60 hardware
int readKeypad(uint thSensitivity) {
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
// Touch sensor values
// 35000 - Not touched
@@ -105,14 +110,14 @@ void initKeys(CommonData &commonData) {
keypad[6] = 0;
}
// Nothing touched
if(keypad[1] == 0 && keypad[2] == 0 && keypad[3] == 0 && keypad[4] == 0 && keypad[5] == 0 && keypad[6] == 0){
/* if(keypad[1] == 0 && keypad[2] == 0 && keypad[3] == 0 && keypad[4] == 0 && keypad[5] == 0 && keypad[6] == 0){
keypad[0] = 1;
}
else{
keypad[0] = 0;
}
} */
for (int i = 0; i < 9; i++) {
for (int i = 1; i <= 6; i++) {
if(i > 0){
// Convert keypad to keycode
if(keypad[i] == 1){
@@ -136,11 +141,13 @@ void initKeys(CommonData &commonData) {
}
// Detect a very short keynumber (10ms)
if (millis() > starttime + 10 && keycode == keycodeold && keylock == true) {
logger->logDebug(GwLog::LOG,"Very short 20ms key touch: %d", keycode);
// Process only valid keys
if(keycode == 1 || keycode == 6){
if(keycode == 1 || keycode == 4 || keycode == 5 || keycode == 6){
keycode2 = keycode;
}
// Clear by unvalid keys
// Clear by invalid keys
else{
keycode2 = 0;
keycodeold2 = 0;
@@ -152,6 +159,7 @@ void initKeys(CommonData &commonData) {
}
// Detect a short keynumber (200ms)
if (keyoff == false && millis() > starttime + 200 && keycode == keycodeold && keylock == true) {
logger->logDebug(GwLog::LOG,"Short 200ms key touch: %d", keycode);
keystatus = keycode;
keycode = 0;
keycodeold = 0;
@@ -163,6 +171,21 @@ void initKeys(CommonData &commonData) {
}
}
// System page with key 5 and 4 in fast series
if (keycode2 == 5 && keycodeold2 == 4) {
logger->logDebug(GwLog::LOG,"Keycode for system page");
keycode = 0;
keycodeold = 0;
keycode2 = 0;
keycodeold2 = 0;
keystatus = 12;
buzzer(TONE4, 50);
delay(30);
buzzer(TONE4, 50);
delay(30);
buzzer(TONE4, 50);
}
// Key lock with key 1 and 6 or 6 and 1 in fast series
if((keycode2 == 1 && keycodeold2 == 6) || (keycode2 == 6 && keycodeold2 == 1)) {
keycode = 0;
@@ -213,34 +236,40 @@ void initKeys(CommonData &commonData) {
}
#endif
#ifdef HARDWARE_LIGHT
#ifdef BOARD_OBP40S3
int readSensorpads(){
// Read key code
if(digitalRead(UP) == LOW){
keycode = 10; // Left swipe
}
else if(digitalRead(DOWN) == LOW){
keycode = 9; // Right swipe
}
else if(digitalRead(CONF) == LOW){
keycode = 3; // Key 3
}
else if(digitalRead(MENUE) == LOW){
keycode = 1; // Key 1
}
else if(digitalRead(EXIT) == LOW){
keycode = 2; // Key 2
}
else{
keycode = 0; // No key activ
}
return keycode;
}
// Keypad functions for OBP60 clone (thSensitivity is inactiv)
int readKeypad(uint thSensitivity) {
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
pinMode(UP, INPUT);
pinMode(DOWN, INPUT);
pinMode(CONF, INPUT);
pinMode(MENUE, INPUT);
pinMode(EXIT, INPUT);
// Read key code
if(digitalRead(UP) == LOW){
keycode = 10; // Left swipe
}
else if(digitalRead(DOWN) == LOW){
keycode = 9; // Right swipe
}
else if(digitalRead(CONF) == LOW){
keycode = 3; // Key 3
}
else if(digitalRead(MENUE) == LOW){
keycode = 1; // Key 1
}
else if(digitalRead(EXIT) == LOW){
keycode = 2; // Key 2
}
else{
keycode = 0; // No key activ
}
// Read pad values
readSensorpads();
// Detect key
if (keycode > 0 ){
@@ -248,11 +277,16 @@ void initKeys(CommonData &commonData) {
starttime = millis(); // Start key pressed
keycodeold = keycode;
}
// If key pressed longer than 200ms
if(millis() > starttime + 200 && keycode == keycodeold) {
keystatus = keycode;
// If key pressed longer than 100ms
if(millis() > starttime + 100 && keycode == keycodeold) {
if (use_syspage and keycode == 3) {
keystatus = 12;
} else {
keystatus = keycode;
}
// Copy keycode
keycodeold = keycode;
while(readSensorpads() > 0){} // Wait for pad release
delay(keydelay);
}
}

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include <Adafruit_Sensor.h> // Adafruit Lib for sensors
#include <Adafruit_BME280.h> // Adafruit Lib for BME280
#include <Adafruit_BMP280.h> // Adafruit Lib for BMP280
@@ -88,8 +88,16 @@ void sensorTask(void *param){
double voffset = (api->getConfig()->getConfigItem(api->getConfig()->vOffset,true)->asString()).toFloat();
double vslope = (api->getConfig()->getConfigItem(api->getConfig()->vSlope,true)->asString()).toFloat();
if(String(powsensor1) == "off"){
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20
sensors.batteryVoltage = sensors.batteryVoltage * vslope + voffset; // Calibration
#ifdef VOLTAGE_SENSOR
float rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
#else
float rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
#endif
sensors.batteryVoltage = rawVoltage * vslope + voffset; // Calibration
#ifdef LIPO_ACCU_1200
sensors.BatteryChargeStatus = 0; // Set to discharging
sensors.batteryLevelLiPo = 0; // Level 0...100%
#endif
sensors.batteryCurrent = 0;
sensors.batteryPower = 0;
// Fill average arrays with start values
@@ -459,19 +467,61 @@ void sensorTask(void *param){
// Send supply voltage value all 1s
if(millis() > starttime5 + 1000 && String(powsensor1) == "off"){
starttime5 = millis();
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20
sensors.batteryVoltage = sensors.batteryVoltage * vslope + voffset; // Calibration
#ifdef VOLTAGE_SENSOR
float rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
#else
float rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
#endif
sensors.batteryVoltage = rawVoltage * vslope + voffset; // Calibration
// Save new data in average array
batV.reading(int(sensors.batteryVoltage * 100));
// Calculate the average values for different time lines from integer values
sensors.batteryVoltage10 = batV.getAvg(10) / 100.0;
sensors.batteryVoltage60 = batV.getAvg(60) / 100.0;
sensors.batteryVoltage300 = batV.getAvg(300) / 100.0;
#if defined LIPO_ACCU_1200 && defined VOLTAGE_SENSOR
// Polynomfit for LiPo capacity calculation for 3,7V LiPo accus, 0...100%
sensors.batteryLevelLiPo = sensors.batteryVoltage60 * 203.8312 -738.1635;
// Limiter
if(sensors.batteryLevelLiPo > 100){
sensors.batteryLevelLiPo = 100;
}
if(sensors.batteryLevelLiPo < 0){
sensors.batteryLevelLiPo = 0;
}
// Charging detection
float deltaV = sensors.batteryVoltage - sensors.batteryVoltage10;
// Higher limits for lower voltages
if(sensors.batteryVoltage10 < 4.0){
if(deltaV > 0.045 && deltaV < 4.15){
sensors.BatteryChargeStatus = 1; // Charging active
}
if(deltaV < -0.04 || deltaV >= 4.15){ // Charging stops by grater than 4,15V
sensors.BatteryChargeStatus = 0; // Discharging
}
}
// Lower limits for higher voltages
else{
if(deltaV > 0.03 && deltaV < 4.15){
sensors.BatteryChargeStatus = 1; // Charging active
}
if(deltaV < -0.03 || deltaV >= 4.15){ // Charging stops by grater than 4,15V
sensors.BatteryChargeStatus = 0; // Discharging
}
}
// Send to NMEA200 bus as instance 10
if(!isnan(sensors.batteryVoltage)){
SetN2kDCBatStatus(N2kMsg, 10, sensors.batteryVoltage, N2kDoubleNA, N2kDoubleNA, 0);
api->sendN2kMessage(N2kMsg);
}
#endif
#ifdef BOARD_OBP60S3
// Send to NMEA200 bus
if(!isnan(sensors.batteryVoltage)){
SetN2kDCBatStatus(N2kMsg, 0, sensors.batteryVoltage, N2kDoubleNA, N2kDoubleNA, 1);
api->sendN2kMessage(N2kMsg);
}
#endif
}
// Send data from environment sensor all 2s

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
@@ -48,7 +48,7 @@ class PageBME280 : public Page
value1 = 23.0 + float(random(0, 10)) / 10.0;
}
// Display data when sensor activated
if((String(useenvsensor) == "BME280") or (String(useenvsensor) == "BMP280")){
if((useenvsensor == "BME280") or (useenvsensor == "BMP280") or (useenvsensor == "BMP180")){
svalue1 = String(value1, 1); // Formatted value as string including unit conversion and switching decimal places
}
else{
@@ -66,7 +66,7 @@ class PageBME280 : public Page
value2 = 43 + float(random(0, 4));
}
// Display data when sensor activated
if(String(useenvsensor) == "BME280"){
if(useenvsensor == "BME280"){
svalue2 = String(value2, 0); // Formatted value as string including unit conversion and switching decimal places
}
else{
@@ -84,7 +84,7 @@ class PageBME280 : public Page
value3 = 1006 + float(random(0, 5));
}
// Display data when sensor activated
if((String(useenvsensor) == "BME280") or (String(useenvsensor) == "BMP280")){
if((useenvsensor == "BME280") or (useenvsensor == "BMP280") or (useenvsensor == "BMP180")){
svalue3 = String(value3 / 100, 1); // Formatted value as string including unit conversion and switching decimal places
}
else{

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -0,0 +1,277 @@
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
#include "images/logo64.xbm"
#include <esp32/clk.h>
#include "qrcode.h"
#define STRINGIZE_IMPL(x) #x
#define STRINGIZE(x) STRINGIZE_IMPL(x)
#define VERSINFO STRINGIZE(GWDEVVERSION)
/*
* Special system page, called directly with fast key sequence 5,4
* Out of normal page order.
*/
class PageSystem : public Page
{
uint64_t chipid;
bool simulation;
String buzzer_mode;
uint8_t buzzer_power;
String cpuspeed;
String rtc_module;
String gps_module;
String env_module;
char mode = 'N'; // (N)ormal, (D)evice list
public:
PageSystem(CommonData &common){
commonData = &common;
common.logger->logDebug(GwLog::LOG,"Instantiate PageSystem");
if (hasFRAM) {
mode = fram.read(FRAM_SYSTEM_MODE);
}
chipid = ESP.getEfuseMac();
simulation = common.config->getBool(common.config->useSimuData);
buzzer_mode = common.config->getString(common.config->buzzerMode);
buzzer_power = common.config->getInt(common.config->buzzerPower);
cpuspeed = common.config->getString(common.config->cpuSpeed);
env_module = common.config->getString(common.config->useEnvSensor);
rtc_module = common.config->getString(common.config->useRTC);
gps_module = common.config->getString(common.config->useGPS);
}
virtual void setupKeys(){
commonData->keydata[0].label = "EXIT";
commonData->keydata[1].label = "MODE";
commonData->keydata[2].label = "";
commonData->keydata[3].label = "RST";
commonData->keydata[4].label = "STBY";
commonData->keydata[5].label = "ILUM";
}
virtual int handleKey(int key){
// do *NOT* handle key #1 this handled by obp60task as exit
// Switch display mode
commonData->logger->logDebug(GwLog::LOG, "System keyboard handler");
if (key == 2) {
if (mode == 'N') {
mode = 'D';
} else {
mode = 'N';
}
if (hasFRAM) fram.write(FRAM_SYSTEM_MODE, mode);
return 0;
}
#ifdef BOARD_OBP60S3
// grab cursor key to disable page navigation
if (key == 3) {
return 0;
}
// soft reset
if (key == 4) {
ESP.restart();
}
// standby / deep sleep
if (key == 5) {
deepSleep(*commonData);
}
// Code for keylock
if (key == 11) {
commonData->keylock = !commonData->keylock;
return 0;
}
#endif
#ifdef BOARD_OBP40S3
// grab cursor keys to disable page navigation
if (key == 9 or key == 10) {
return 0;
}
// standby / deep sleep
if (key == 12) {
deepSleep(*commonData);
}
#endif
return key;
}
void displayBarcode(String serialno, uint16_t x, uint16_t y, uint16_t s) {
// Barcode with serial number
// x, y is top left corner
// s is pixel size of a single box
QRCode qrcode;
uint8_t qrcodeData[qrcode_getBufferSize(4)];
#ifdef BOARD_OBP40S3
String prefix = "OBP40:SN:";
#endif
#ifdef BOARD_OBP60S3
String prefix = "OBP60:SN:";
#endif
qrcode_initText(&qrcode, qrcodeData, 4, 0, (prefix + serialno).c_str());
int16_t x0 = x;
for (uint8_t j = 0; j < qrcode.size; j++) {
for (uint8_t i = 0; i < qrcode.size; i++) {
if (qrcode_getModule(&qrcode, i, j)) {
getdisplay().fillRect(x, y, s, s, commonData->fgcolor);
}
x += s;
}
y += s;
x = x0;
}
}
virtual void displayPage(PageData &pageData){
GwConfigHandler *config = commonData->config;
GwLog *logger = commonData->logger;
// Get config data
String flashLED = config->getString(config->flashLED);
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
LOG_DEBUG(GwLog::LOG,"Drawing at PageSystem");
// Draw page
//***********************************************************
const uint16_t y0 = 120; // data table starts here
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
if (mode == 'N') {
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(8, 50);
getdisplay().print("System Information");
getdisplay().drawXBitmap(320, 25, logo64_bits, logo64_width, logo64_height, commonData->fgcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
char ssid[13];
snprintf(ssid, 13, "%04X%08X", (uint16_t)(chipid >> 32), (uint32_t)chipid);
displayBarcode(String(ssid), 320, 200, 2);
getdisplay().setCursor(8, 70);
getdisplay().print(String("MUDEVICE-") + String(ssid));
getdisplay().setCursor(8, 90);
getdisplay().print("Firmware Version: ");
getdisplay().print(VERSINFO);
getdisplay().setCursor(8, 265);
#ifdef BOARD_OBP60S3
getdisplay().print("Press STBY to enter deep sleep mode");
#endif
#ifdef BOARD_OBP40S3
getdisplay().print("Press wheel to enter deep sleep mode");
#endif
getdisplay().setCursor(2, y0);
getdisplay().print("Simulation:");
getdisplay().setCursor(120, y0);
getdisplay().print(simulation ? "on" : "off");
getdisplay().setCursor(2, y0 + 16);
getdisplay().print("Environment:");
getdisplay().setCursor(120, y0 + 16);
getdisplay().print(env_module);
// total RAM free
int Heap_free = esp_get_free_heap_size();
getdisplay().setCursor(202, y0);
getdisplay().print("Total free:");
getdisplay().setCursor(300, y0);
getdisplay().print(String(Heap_free));
getdisplay().setCursor(2, y0 + 32);
getdisplay().print("Buzzer:");
getdisplay().setCursor(120, y0 + 32);
getdisplay().print(buzzer_mode);
// RAM free for task
int RAM_free = uxTaskGetStackHighWaterMark(NULL);
getdisplay().setCursor(202, y0 + 16);
getdisplay().print("Task free:");
getdisplay().setCursor(300, y0 + 16);
getdisplay().print(String(RAM_free));
// FRAM available / status
getdisplay().setCursor(202, y0 + 32);
getdisplay().print("FRAM:");
getdisplay().setCursor(300, y0 + 32);
getdisplay().print(hasFRAM ? "available" : "not found");
getdisplay().setCursor(202, y0 + 64);
getdisplay().print("CPU speed:");
getdisplay().setCursor(300, y0 + 64);
getdisplay().print(cpuspeed);
getdisplay().print(" / ");
int cpu_freq = esp_clk_cpu_freq() / 1000000;
getdisplay().print(String(cpu_freq));
getdisplay().setCursor(2, y0 + 64);
getdisplay().print("GPS:");
getdisplay().setCursor(120, y0 + 64);
getdisplay().print(gps_module);
getdisplay().setCursor(2, y0 + 80);
getdisplay().print("RTC:");
getdisplay().setCursor(120, y0 + 80);
getdisplay().print(rtc_module);
getdisplay().setCursor(2, y0 + 96);
getdisplay().print("Wifi:");
getdisplay().setCursor(120, y0 + 96);
getdisplay().print(commonData->status.wifiApOn ? "On" : "Off");
} else {
// NMEA2000 device list
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 50);
getdisplay().print("NMEA2000 device list");
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(20, 80);
getdisplay().print("RxD: ");
getdisplay().print(String(commonData->status.n2kRx));
getdisplay().setCursor(20, 100);
getdisplay().print("TxD: ");
getdisplay().print(String(commonData->status.n2kTx));
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page* createPage(CommonData &common){
return new PageSystem(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageSystem(
"System", // Page name
createPage, // Action
0, // No bus values
true // Headers are anabled so far
);
#endif

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
@@ -205,6 +205,18 @@ public:
getdisplay().setCursor(20, 100);
getdisplay().print(name1); // Value name
#if defined BOARD_OBP40S3 && defined LIPO_ACCU_1200 && defined VOLTAGE_SENSOR
// Show charge status
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(185, 100);
if(commonData->data.BatteryChargeStatus == true){
getdisplay().print("Charge");
}
else{
getdisplay().print("Discharge");
}
#endif
// Show unit
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(270, 100);
@@ -213,7 +225,12 @@ public:
// Show battery type
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(295, 100);
#ifdef BOARD_OBP60S3
getdisplay().print(batType);
#endif
#if defined BOARD_OBP40S3 && defined LIPO_ACCU_1200 && defined VOLTAGE_SENSOR
getdisplay().print("LiPo");
#endif
// Show average settings
printAvg(average, 320, 84, true);

View File

@@ -1,14 +1,34 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
#include "MFD_OBP60_400x300_sw.h" // MFD with logo
#include "Logo_OBP_400x300_sw.h" // OBP Logo
class PageWhite : public Page
{
public:
char mode = 'W'; // display mode (W)hite | (L)ogo | (M)FD logo
public:
PageWhite(CommonData &common){
commonData = &common;
common.logger->logDebug(GwLog::LOG,"Instantiate PageWhite");
refreshtime = 15000;
}
virtual int handleKey(int key) {
// Change display mode
if (key == 1) {
if (mode == 'W') {
mode = 'L';
} else if (mode == 'L') {
mode = 'M';
} else {
mode = 'W';
}
return 0;
}
return key;
}
virtual void displayPage(PageData &pageData){
@@ -34,10 +54,23 @@ class PageWhite : public Page
int bgcolor = GxEPD_WHITE;
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
if (mode == 'W') {
getdisplay().setFullWindow();
} else {
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
}
if (mode == 'L') {
getdisplay().drawBitmap(0, 0, gImage_Logo_OBP_400x300_sw, getdisplay().width(), getdisplay().height(), commonData->fgcolor);
} else if (mode == 'M') {
getdisplay().drawBitmap(0, 0, gImage_MFD_OBP60_400x300_sw, getdisplay().width(), getdisplay().height(), commonData->fgcolor);
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
getdisplay().nextPage();
if (mode == 'W') {
getdisplay().hibernate();
}
};
};

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "Pagedata.h"
#include "OBP60Extensions.h"

View File

@@ -31,6 +31,8 @@ typedef struct{
double batteryVoltage300 = 0; // Sliding average over 300 values
double batteryCurrent300 = 0;
double batteryPower300 = 0;
double batteryLevelLiPo = 0; // Battery level for OBP40 LiPo accu
int BatteryChargeStatus = 0; // LiPo charge status: 0 = discharge, 1 = loading activ
double solarVoltage = 0;
double solarCurrent = 0;
double solarPower = 0;
@@ -93,6 +95,7 @@ typedef struct{
uint16_t fgcolor;
uint16_t bgcolor;
bool keylock = false;
String powermode;
} CommonData;
//a base class that all pages must inherit from
@@ -100,19 +103,27 @@ class Page{
protected:
CommonData *commonData;
public:
int refreshtime = 1000;
virtual void displayPage(PageData &pageData)=0;
virtual void displayNew(PageData &pageData){}
virtual void setupKeys() {
#ifdef HARDWARE_V21
commonData->keydata[0].label = "";
commonData->keydata[1].label = "";
commonData->keydata[2].label = "#LEFT";
commonData->keydata[3].label = "#RIGHT";
commonData->keydata[4].label = "";
if (commonData->backlight.mode == KEY) {
if ((commonData->backlight.mode == KEY) && !(commonData->powermode == "Min Power")) {
commonData->keydata[5].label = "ILUM";
} else {
commonData->keydata[5].label = "";
}
#endif
#ifdef BOARD_OBP40S3
commonData->keydata[0].label = "";
commonData->keydata[1].label = "";
#endif
}
//return -1 if handled by the page
virtual int handleKey(int key){return key;}

View File

@@ -6,10 +6,12 @@ https://gitpod.io/#https://github.com/norbert-walter/esp32-nmea2000-obp60/tree/m
Input in terminal:
cd /workspace/esp32-nmea2000-obp60
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_installing_tools
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_obp60_s3
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run_obp40_s3
Compile result in:
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin, ready to flash to offset 0x0000
Compile result for OBP60
########################
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/bootloader.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/firmware.bin
@@ -18,3 +20,19 @@ Compile result in:
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev20231220-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev20231220-update.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin, ready to flash to offset 0x0000
Compile result for OBP40 (CrowPanel 4.2)
########################################
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/bootloader.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/firmware.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/partitions.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev20231220-all.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev20231220-update.bin
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin, ready to flash to offset 0x0000

View File

@@ -938,7 +938,7 @@
"ThreeValues",
"TwoValues",
"Voltage",
"White",
"WhitePage",
"Wind",
"WindRose",
"WindRoseFlex",
@@ -1198,7 +1198,7 @@
"ThreeValues",
"TwoValues",
"Voltage",
"White",
"WhitePage",
"Wind",
"WindRose",
"WindRoseFlex",
@@ -1456,7 +1456,7 @@
"ThreeValues",
"TwoValues",
"Voltage",
"White",
"WhitePage",
"Wind",
"WindRose",
"WindRoseFlex",
@@ -1710,7 +1710,7 @@
"ThreeValues",
"TwoValues",
"Voltage",
"White",
"WhitePage",
"Wind",
"WindRose",
"WindRoseFlex",
@@ -1961,7 +1961,7 @@
"ThreeValues",
"TwoValues",
"Voltage",
"White",
"WhitePage",
"Wind",
"WindRose",
"WindRoseFlex",
@@ -2209,7 +2209,7 @@
"ThreeValues",
"TwoValues",
"Voltage",
"White",
"WhitePage",
"Wind",
"WindRose",
"WindRoseFlex",
@@ -2454,7 +2454,7 @@
"ThreeValues",
"TwoValues",
"Voltage",
"White",
"WhitePage",
"Wind",
"WindRose",
"WindRoseFlex",
@@ -2696,7 +2696,7 @@
"ThreeValues",
"TwoValues",
"Voltage",
"White",
"WhitePage",
"Wind",
"WindRose",
"WindRoseFlex",
@@ -2935,7 +2935,7 @@
"ThreeValues",
"TwoValues",
"Voltage",
"White",
"WhitePage",
"Wind",
"WindRose",
"WindRoseFlex",
@@ -3171,7 +3171,7 @@
"ThreeValues",
"TwoValues",
"Voltage",
"White",
"WhitePage",
"Wind",
"WindRose",
"WindRoseFlex",

File diff suppressed because it is too large Load Diff

View File

@@ -1,112 +0,0 @@
#!/bin/perl -w
#A tool to generate the part of config.json that deals with pages and fields.
#DEPRECATED, moved to get_set.py
die "Please use gen_set.py instead";
#List of all pages and the number of parameters they expect.
%NoOfFieldsPerPage=qw(
ApparentWind 0
XTETrack 0
Battery2 0
Battery 0
BME280 0
Clock 0
DST810 0
FourValues2 4
FourValues 4
Generator 0
KeelPosition 0
OneValue 1
RollPitch 0
RudderPosition 0
Solar 0
ThreeValues 3
TwoValues 2
Voltage 0
White 0
WindRose 0
WindRoseFlex 6
);
# No changes needed beyond this point
#max number of pages supported by OBP60
$NoOfPages=10;
#Default selection for each page
@Defaults=qw(Voltage WindRose OneValue TwoValues ThreeValues FourValues FourValues2 Clock RollPitch Battery2);
@Numbers=qw(one two three four five six seven eight nine ten);
@Pages=sort(keys(%NoOfFieldsPerPage));
$MaxNoOfFieldsPerPage=0; # inital value, gets updated with maximum entry from %NoOfFieldsPerPage
#find max. number of fields without additional modules
foreach (values(%NoOfFieldsPerPage)){
if ($_ > $MaxNoOfFieldsPerPage){
$MaxNoOfFieldsPerPage=$_;
}
}
for ($PageNo=1;$PageNo<=$NoOfPages;$PageNo++){
print "{\n";
print "\t","\"name\": \"page", $PageNo,"type\",\n";
print "\t","\"label\": \"Type\",\n";
print "\t",'"type": "list",',"\n";
print "\t",'"default": "';
print "$Defaults[$PageNo-1]";
print'"',"\n";
print "\t",'"description": "Type of page for page ',$PageNo,'",',"\n";
print "\t",'"list": [';
for ($p=0;$p<=$#Pages;$p++) {
print '"', $Pages[$p], '"' ;
if ($p < $#Pages){print ","}
}
print "]\n";
print "\t",'"category": "OBP60 Page ',$PageNo,'",',"\n";
print "\t",'"capabilities": {',"\n";
print "\t\t",'"obp60":"true"',"\n";
print "\t",'}',"\n";
print "\t",'"condition":[';
for ($vp=$PageNo;$vp<=$NoOfPages;$vp++){
print '"{visiblePages":"',$vp,'"},';
}
print "\b",']',"\n";
print '},',"\n";
for ($FieldNo=1; $FieldNo<=$MaxNoOfFieldsPerPage;$FieldNo++){
print "{\n";
print "\t",'"name": "page',$PageNo,'value',$FieldNo,'",',"\n";
print "\t",'"label": "Field ',$FieldNo,'",',"\n";
print "\t",'"type": "boatData",',"\n";
print "\t",'"default": "",',"\n";
print "\t",'"description": "The display for field ',$Numbers[$FieldNo-1],'",',"\n";
print "\t",'"category": "OBP60 Page ',$PageNo,'",',"\n";
print "\t",'"capabilities": {',"\n";
print "\t",' "obp60":"true"',"\n";
print "\t",'}, ',"\n";
print "\t",'"condition":[';
foreach $page (@Pages) {
if($NoOfFieldsPerPage{$page}>=$FieldNo){
print '{"page',$PageNo,'type":"',$page,'"},';
}
}
print "\b],\n";
print '},',"\n";
}
print "{\n";
print "\t","\"name\": \"page", $PageNo,"fluid\",\n";
print "\t",'"label": "Fluid type",',"\n";
print "\t",'"type": "list",',"\n";
print "\t",'"default": "0",',"\n";
print "\t",'"list": [',"\n";
print "\t",'{"l":"Fuel (0)","v":"0"},',"\n";
print "\t",'{"l":"Water (1)","v":"1"},',"\n";
print "\t",'{"l":"Gray Water (2)","v":"2"},',"\n";
print "\t",'{"l":"Live Well (3)","v":"3"},',"\n";
print "\t",'{"l":"Oil (4)","v":"4"},',"\n";
print "\t",'{"l":"Black Water (5)","v":"5"},',"\n";
print "\t",'{"l":"Fuel Gasoline (6)","v":"6"}',"\n";
print "\t",'],',"\n";
print "\t",'"description": "Fluid type in tank",',"\n";
print "\t",'"category": "OBP60 Page ',$PageNo,'",',"\n";
print "\t",'"capabilities": {',"\n";
print "\t",'"obp60":"true"',"\n";
print "\t",'},',"\n";
print "\t",'"condition":[{"page',$PageNo,'type":"Fluid"}]',"\n";
print '},',"\n";
}

View File

@@ -1,18 +1,22 @@
#!/usr/bin/env python3
# A tool to generate that part of config.json that deals with pages and fields.
#
#Usage: 1. modify this script (e.g.add a page, change number of fields, etc.)
# 2. Delete all lines from config.json from the curly backet before "name": "page1type" to o the end of the file (as of today, delete from line 917 to the end of the File)
# 3. run ./gen_set.py >> config.json
import json
# List of all pages and the number of parameters they expect.
no_of_fields_per_page = {
"ApparentWind": 0,
"Wind": 0,
"XTETrack": 0,
"Battery2": 0,
"Battery": 0,
"BME280": 0,
"Clock": 0,
"DST810": 0,
"Fluid": 0,
"Fluid": 1,
"FourValues2": 4,
"FourValues": 4,
"Generator": 0,
@@ -24,9 +28,10 @@ no_of_fields_per_page = {
"ThreeValues": 3,
"TwoValues": 2,
"Voltage": 0,
"White": 0,
"WhitePage": 0,
"WindRose": 0,
"WindRoseFlex": 6,
# "SixValues" : 6,
}
# No changes needed beyond this point
@@ -119,5 +124,7 @@ for page_no in range(1, no_of_pages + 1):
json_output = json.dumps(output, indent=4)
# print omitting first and last line containing [ ] of JSON array
print(json_output[1:-1])
# print(",")
#print(json_output[1:-1])
# print omitting first line containing [ of JSON array
print(json_output[1:])
# print(",")

View File

@@ -1,2 +0,0 @@
cd /workspace/esp32-nmea2000-obp60
bash /workspace/esp32-nmea2000-obp60/lib/obp60task/run

View File

@@ -0,0 +1,51 @@
#ifndef _LOGO64_XBM_
#define _LOGO64_XBM_ 1
#define logo64_width 64
#define logo64_height 64
static unsigned char logo64_bits[] PROGMEM = {
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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0xc1, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xc1,
0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xc0, 0xc1, 0x7f, 0xf8, 0x01, 0xfe,
0x00, 0x00, 0xc0, 0xc1, 0x1f, 0xe0, 0x01, 0xfc, 0x00, 0x00, 0xe0, 0xc1,
0x0f, 0xc3, 0xf1, 0xf8, 0x00, 0x00, 0xf0, 0xc1, 0xc7, 0x8f, 0xf1, 0xf9,
0x00, 0x00, 0xf8, 0xc1, 0xc7, 0x8f, 0xf1, 0xf9, 0x00, 0x00, 0xf8, 0xc1,
0xe7, 0x9f, 0xf1, 0xf8, 0x00, 0x00, 0xfc, 0xc1, 0xe7, 0x9f, 0x01, 0xfc,
0x00, 0x00, 0xfe, 0xc1, 0xe7, 0x9f, 0x01, 0xfe, 0x00, 0x00, 0xfe, 0xc1,
0xc7, 0x8f, 0xf1, 0xff, 0x00, 0x00, 0xff, 0xc1, 0xc7, 0x8f, 0xf1, 0xff,
0x00, 0x80, 0xff, 0xc1, 0x8f, 0xc7, 0xf1, 0xff, 0x00, 0x80, 0xff, 0xc1,
0x1f, 0xe0, 0xf1, 0xff, 0x00, 0xc0, 0xff, 0xc1, 0x7f, 0xf8, 0xf1, 0xff,
0x00, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xff, 0xc1,
0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff,
0x00, 0xf8, 0xff, 0xc1, 0x0f, 0xe0, 0xf8, 0xfc, 0x00, 0xfc, 0xff, 0xc1,
0x0f, 0xe0, 0xf8, 0xfc, 0x00, 0xfc, 0xff, 0xc1, 0xcf, 0xff, 0xf0, 0xfc,
0x00, 0xfe, 0xff, 0xc1, 0xcf, 0xff, 0xe0, 0xfc, 0x00, 0xff, 0xff, 0xc1,
0xcf, 0xff, 0xe4, 0xfc, 0x00, 0xff, 0xff, 0xc1, 0x0f, 0xe0, 0xc4, 0xfc,
0x80, 0xff, 0xff, 0xc1, 0x0f, 0xe0, 0xcc, 0xfc, 0xc0, 0xff, 0xff, 0xc1,
0xcf, 0xff, 0x8c, 0xfc, 0xe0, 0xff, 0xff, 0xc1, 0xcf, 0xff, 0x9c, 0xfc,
0xe0, 0xff, 0xff, 0xc1, 0xcf, 0xff, 0x1c, 0xfc, 0xf0, 0xff, 0xff, 0xc1,
0xcf, 0xff, 0x3c, 0xfc, 0xf8, 0xff, 0xff, 0xc1, 0x0f, 0xe0, 0x7c, 0xfc,
0xf8, 0xff, 0xff, 0xc1, 0x0f, 0xe0, 0xfc, 0xfc, 0xfc, 0xff, 0xff, 0xc1,
0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff,
0xfe, 0xff, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3c, 0x00, 0x00, 0x38, 0x00, 0x04, 0x00, 0x00, 0x44, 0x00, 0x10, 0x48,
0x00, 0x00, 0x00, 0x01, 0x44, 0x86, 0x7b, 0x48, 0x67, 0xc4, 0xf0, 0x77,
0x3c, 0x09, 0x12, 0x38, 0x91, 0x24, 0x09, 0x11, 0x44, 0xc9, 0x13, 0x08,
0x91, 0xe4, 0x09, 0x61, 0x44, 0x49, 0x12, 0x08, 0x91, 0x24, 0x08, 0x41,
0x3c, 0xc6, 0x73, 0x08, 0x61, 0xc4, 0x71, 0x77, 0x00, 0x00, 0x00, 0x00,
0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 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, 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,
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
#endif

View File

@@ -0,0 +1,171 @@
#ifndef _UNKNOWN_XBM_
#define _UNKNOWN_XBM_ 1
#define unknown_width 120
#define unknown_height 130
static unsigned char unknown_bits[] PROGMEM = {
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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x00, 0xe0, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f, 0x70, 0x80, 0xcf, 0x01, 0x00, 0x00,
0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xf7, 0xc0, 0x7f,
0x00, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x80,
0xff, 0xfb, 0x7b, 0x00, 0x00, 0xf8, 0x7f, 0xe0, 0x0f, 0x00, 0x00, 0x00,
0x00, 0xfc, 0x07, 0xb8, 0xff, 0xfb, 0x7f, 0x00, 0xff, 0x3f, 0xf8, 0x1f,
0x00, 0x00, 0x00, 0x00, 0x9c, 0x0f, 0xd0, 0xff, 0xfd, 0x19, 0xe0, 0xff,
0x0d, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0xf9, 0x3f,
0x0d, 0xfc, 0x7f, 0x86, 0xff, 0x07, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x07,
0xfe, 0xc1, 0xdf, 0x07, 0xff, 0xc1, 0xe3, 0x3d, 0x03, 0x00, 0x00, 0x3f,
0x00, 0x00, 0x07, 0x7e, 0x81, 0xff, 0x84, 0x7f, 0xf3, 0x7b, 0x07, 0x03,
0x00, 0x00, 0x7e, 0x80, 0x3f, 0x0f, 0xf0, 0xc3, 0x3b, 0xe4, 0xdd, 0x9d,
0xcf, 0x80, 0x01, 0x00, 0x00, 0x6c, 0x00, 0xff, 0x3f, 0xe0, 0x17, 0x9c,
0x7f, 0xf7, 0xc3, 0x63, 0x80, 0x01, 0x00, 0x00, 0xfe, 0x0c, 0xf0, 0xfd,
0xc3, 0x3c, 0xde, 0xfd, 0xef, 0xf8, 0x18, 0x80, 0x01, 0x00, 0x00, 0xfe,
0x0e, 0xf0, 0x9f, 0x8f, 0x78, 0xcf, 0xfe, 0x1b, 0x3f, 0x0e, 0xc0, 0x00,
0x00, 0x00, 0xfe, 0x1d, 0xf0, 0xff, 0x9f, 0x21, 0xcc, 0xfb, 0xe7, 0x8f,
0x03, 0xc0, 0x00, 0x00, 0x00, 0xcc, 0x1f, 0xb0, 0xff, 0x1f, 0x00, 0xc0,
0xbf, 0xb9, 0xc7, 0x01, 0xc0, 0x00, 0x00, 0x00, 0xfc, 0x1f, 0x3c, 0x1f,
0xfe, 0x00, 0xfe, 0x6f, 0xfe, 0xf1, 0x01, 0xc0, 0x00, 0x00, 0xf8, 0xfb,
0x1f, 0xbc, 0xfe, 0xff, 0xc0, 0xff, 0x9d, 0x7f, 0x7c, 0x00, 0x60, 0x00,
0x00, 0xfc, 0xef, 0x1d, 0xfc, 0xc3, 0xff, 0xe9, 0xcf, 0xed, 0x1f, 0x1f,
0x00, 0x60, 0x00, 0x00, 0xfe, 0xef, 0x1d, 0x00, 0x97, 0xf0, 0xf9, 0xcf,
0xfd, 0x87, 0x07, 0x03, 0x60, 0x00, 0x00, 0xfe, 0xcc, 0x0c, 0x00, 0xfc,
0x81, 0xff, 0xdf, 0xfd, 0xc0, 0xf9, 0x03, 0x60, 0x00, 0x00, 0xe4, 0xdc,
0x0f, 0x00, 0xf8, 0x9f, 0xff, 0xdf, 0x3d, 0xe0, 0x0f, 0x00, 0x60, 0x00,
0x00, 0xc0, 0xdf, 0x03, 0x00, 0xe0, 0xf1, 0xfe, 0xdf, 0x0c, 0xfe, 0xff,
0x01, 0x60, 0x00, 0x00, 0xc0, 0xcf, 0x01, 0x00, 0x60, 0xf3, 0xff, 0xdb,
0x06, 0xff, 0x01, 0x00, 0x70, 0x00, 0x00, 0x00, 0x8f, 0x01, 0x00, 0x78,
0xff, 0x1f, 0x9b, 0x87, 0xff, 0xff, 0x0f, 0x30, 0x00, 0x00, 0x00, 0x66,
0x03, 0x00, 0xfc, 0x7f, 0xfb, 0x99, 0xc7, 0xff, 0xff, 0x00, 0x30, 0x00,
0x00, 0x00, 0x06, 0x03, 0x00, 0xc6, 0xff, 0xff, 0xd9, 0x67, 0xff, 0xc1,
0x01, 0x70, 0x00, 0x00, 0x00, 0xc7, 0x03, 0x00, 0x07, 0x7c, 0xe3, 0xf9,
0xe3, 0xff, 0x7f, 0x00, 0x70, 0x00, 0x00, 0x80, 0xf3, 0x07, 0x00, 0x1f,
0x6c, 0xe0, 0x7b, 0xe3, 0xff, 0xff, 0x01, 0x70, 0x00, 0x00, 0x80, 0xd9,
0x06, 0x80, 0xff, 0x0f, 0xce, 0xef, 0xe3, 0xff, 0xf7, 0x01, 0x70, 0x00,
0x00, 0xe0, 0xbf, 0x0d, 0xc0, 0xff, 0x43, 0xe4, 0xef, 0xe3, 0x3f, 0x7f,
0x07, 0x60, 0x00, 0x00, 0xe0, 0xbf, 0x1d, 0xe0, 0x78, 0x43, 0x70, 0xec,
0xe1, 0xff, 0xf8, 0x1d, 0x60, 0x00, 0x00, 0xe0, 0xff, 0x19, 0x70, 0x00,
0x03, 0x37, 0xfc, 0xf1, 0xbf, 0xc3, 0x07, 0x60, 0x00, 0x00, 0xc0, 0xff,
0x19, 0x70, 0x80, 0x01, 0x3b, 0xd6, 0xf9, 0xef, 0x1c, 0x3e, 0x60, 0x00,
0x00, 0x80, 0x63, 0x1b, 0xf0, 0xc6, 0x39, 0x19, 0xfe, 0xf8, 0xbf, 0x31,
0xf8, 0x60, 0x00, 0x00, 0x00, 0x60, 0x3b, 0xf8, 0xfe, 0x98, 0x1f, 0xfe,
0xf8, 0x7f, 0x67, 0xe0, 0x61, 0x00, 0x00, 0x00, 0x60, 0x33, 0xfc, 0x7f,
0x80, 0x0f, 0xeb, 0xfc, 0xff, 0x0d, 0x80, 0xc7, 0x00, 0x00, 0x00, 0x60,
0x33, 0x0c, 0x7f, 0x06, 0x0c, 0x7f, 0xec, 0x6f, 0x0b, 0x00, 0xfe, 0x00,
0x00, 0x00, 0x60, 0x76, 0x0e, 0xf8, 0xbf, 0x87, 0x7f, 0xee, 0xdf, 0x00,
0x00, 0xf8, 0x01, 0x00, 0x00, 0xc0, 0x76, 0x0e, 0xb8, 0xa0, 0x87, 0x3f,
0xde, 0x3f, 0x01, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xc0, 0xf6, 0x0f, 0x3c,
0x80, 0xdf, 0x3f, 0xdf, 0x77, 0x02, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0,
0xdd, 0xef, 0x1f, 0x80, 0xfe, 0x9f, 0xdf, 0xe7, 0x06, 0x00, 0xe0, 0x03,
0x00, 0x00, 0x80, 0xfd, 0xfe, 0x1f, 0xcc, 0xff, 0xdf, 0xdf, 0xee, 0x18,
0x00, 0xf0, 0x03, 0x00, 0x00, 0x80, 0xfd, 0xff, 0x1b, 0xdc, 0xf6, 0xcf,
0xdf, 0xc0, 0x19, 0x00, 0x70, 0x00, 0x00, 0x00, 0x80, 0x7f, 0x03, 0x98,
0x01, 0xb6, 0xcf, 0x93, 0x80, 0x33, 0x00, 0x30, 0x00, 0x00, 0x00, 0x80,
0x7f, 0x01, 0x1c, 0xc0, 0xfe, 0xff, 0x9f, 0x00, 0x03, 0x00, 0x30, 0x00,
0x00, 0x00, 0x80, 0x9f, 0x01, 0x0c, 0xc0, 0xff, 0xe7, 0x9b, 0x01, 0x06,
0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x0e, 0xcc, 0xff, 0xe3,
0xbb, 0x01, 0x0c, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0xcf, 0x07,
0x8c, 0xff, 0xf9, 0xbb, 0x01, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x80,
0xbf, 0xff, 0xcf, 0x1f, 0xdf, 0xfd, 0xbb, 0x09, 0x38, 0x00, 0x1c, 0x00,
0x00, 0x00, 0x80, 0xfb, 0xff, 0x8d, 0xdf, 0x6f, 0xfc, 0xbb, 0x01, 0x70,
0x00, 0x0c, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x8f, 0xff, 0x3f, 0xff,
0xbb, 0x01, 0x60, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0xef, 0xe0, 0x8f,
0xbf, 0x1f, 0xbf, 0xab, 0x09, 0xe0, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
0xff, 0xf0, 0x8d, 0xd6, 0xc3, 0xbb, 0xab, 0x01, 0xc0, 0x01, 0x0e, 0x00,
0x00, 0x00, 0x00, 0x7f, 0x31, 0x00, 0x7e, 0xe0, 0x39, 0xab, 0x19, 0x80,
0x03, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x66, 0x19, 0x80, 0x79, 0x7c, 0x3c,
0xa9, 0x01, 0x00, 0x03, 0x06, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x19, 0x80,
0x6d, 0x7e, 0x1c, 0xb1, 0x01, 0x00, 0x07, 0x06, 0x00, 0x00, 0x00, 0x00,
0xe0, 0x1f, 0x80, 0x0d, 0x1c, 0x10, 0xb1, 0x01, 0x00, 0x06, 0x0e, 0x00,
0x00, 0x00, 0x00, 0xc0, 0x3f, 0x10, 0x00, 0x38, 0x00, 0xb1, 0x01, 0x00,
0x0e, 0x06, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3d, 0xb3, 0x00, 0x3b, 0x00,
0xa1, 0x01, 0x00, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe7, 0xf1,
0xd8, 0x7f, 0x03, 0xb1, 0x01, 0x00, 0x1c, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0xc3, 0xfb, 0xf0, 0x7f, 0x01, 0xb1, 0x01, 0x00, 0x18, 0x06, 0x00,
0x00, 0x00, 0x00, 0x00, 0x83, 0xfb, 0xf0, 0x7f, 0x01, 0xb1, 0x01, 0x00,
0x18, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x01, 0x7f, 0x00,
0x80, 0x01, 0x00, 0x30, 0x06, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x3f,
0x01, 0xff, 0x07, 0x80, 0x01, 0x00, 0x30, 0x06, 0x00, 0x00, 0x00, 0x00,
0xc0, 0xfd, 0x1d, 0x01, 0xfb, 0x3f, 0x80, 0x01, 0x00, 0x70, 0x06, 0x00,
0x00, 0x00, 0x00, 0xc0, 0xf0, 0xde, 0x67, 0x18, 0x7f, 0x80, 0x01, 0x00,
0x60, 0x07, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x78, 0xcf, 0x0f, 0x86, 0xfd,
0x81, 0x01, 0x00, 0x65, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xaf, 0xbf,
0x3d, 0x80, 0xf9, 0x81, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
0xe0, 0xaf, 0xff, 0x78, 0x00, 0xe0, 0x83, 0x01, 0x7f, 0xf8, 0x01, 0x00,
0x00, 0x00, 0x00, 0x70, 0xfe, 0x7f, 0x70, 0x20, 0x6c, 0x87, 0xe0, 0x07,
0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x30, 0xf8, 0x0f, 0xf0, 0x30, 0x06,
0xcf, 0xf8, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xdb, 0x0e,
0xd8, 0x00, 0x30, 0xcf, 0x3c, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
0xf8, 0xfb, 0x38, 0xfc, 0x01, 0x20, 0xcc, 0x0f, 0x00, 0x60, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1c, 0x3e, 0xf8, 0xbf, 0x03, 0x06, 0xfd, 0x03, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x1e, 0xf8, 0xdf, 0x0f, 0x02,
0xff, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x0f, 0xf0,
0x07, 0x3e, 0x30, 0xfa, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00,
0xfe, 0x07, 0x00, 0x03, 0x78, 0x30, 0xfb, 0x03, 0x00, 0x80, 0x03, 0x00,
0x00, 0x00, 0x00, 0xff, 0x06, 0x00, 0xc3, 0xff, 0x00, 0xff, 0x1f, 0x00,
0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x03, 0x00, 0xbf, 0xdf, 0x01,
0xfe, 0x1f, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfb, 0x01, 0x00,
0xfe, 0x8f, 0x83, 0xef, 0x0f, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x80,
0xef, 0x00, 0x00, 0xf8, 0x03, 0x83, 0xb1, 0x03, 0x00, 0x60, 0x03, 0x00,
0x00, 0xe0, 0x80, 0x61, 0x00, 0x00, 0x80, 0x01, 0x04, 0xb0, 0x03, 0x03,
0x30, 0x03, 0x00, 0x00, 0xfc, 0xc1, 0x30, 0x06, 0x00, 0x80, 0x01, 0x1e,
0xa0, 0x87, 0x03, 0x30, 0x03, 0x00, 0x00, 0x7e, 0xff, 0xb8, 0x0f, 0x00,
0x80, 0x8b, 0x1f, 0x04, 0x86, 0x03, 0x18, 0x03, 0x00, 0x00, 0xf6, 0x7f,
0xf8, 0x3f, 0x00, 0x80, 0xff, 0x77, 0xfe, 0x86, 0x07, 0x0e, 0x01, 0x00,
0x00, 0xfe, 0x19, 0x00, 0x76, 0x00, 0x00, 0xff, 0x63, 0xf6, 0x86, 0xfd,
0x87, 0x01, 0x00, 0x00, 0xf6, 0x0f, 0x00, 0x7e, 0x00, 0x00, 0xfc, 0x60,
0x00, 0x8c, 0xf3, 0x81, 0x01, 0x00, 0x00, 0x06, 0x06, 0xfe, 0x7c, 0x00,
0x00, 0x70, 0xc0, 0x00, 0x8e, 0x07, 0x83, 0x01, 0x00, 0x00, 0xf8, 0xb3,
0xff, 0x7f, 0x00, 0x00, 0x60, 0xc0, 0x9c, 0x0f, 0xff, 0xc1, 0x00, 0x00,
0x00, 0xfc, 0xd9, 0x03, 0x3f, 0x00, 0x00, 0xe0, 0xc0, 0x80, 0x0d, 0x7e,
0xc0, 0x00, 0x00, 0x00, 0x0e, 0xde, 0x00, 0x1c, 0x00, 0x00, 0xe0, 0xff,
0x01, 0xfc, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0xde, 0xdf, 0x00, 0x00, 0x00,
0x00, 0xfe, 0xbf, 0x03, 0xfc, 0x00, 0x66, 0x00, 0x00, 0x00, 0xda, 0xcc,
0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x62, 0x1f, 0x00, 0x67, 0x00, 0x00,
0x00, 0x7e, 0xcc, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x03, 0xe3, 0x5f, 0xc1,
0x33, 0x00, 0x00, 0x00, 0x3e, 0x8e, 0x01, 0x00, 0x00, 0xf8, 0xf1, 0x03,
0x06, 0xfc, 0x7f, 0x33, 0x00, 0x00, 0x00, 0x0e, 0xde, 0x00, 0x00, 0x00,
0x6e, 0xc0, 0x07, 0x0e, 0xfc, 0x1f, 0x13, 0x00, 0x00, 0x00, 0x1e, 0x7c,
0x00, 0x00, 0x00, 0x1f, 0xe2, 0x3f, 0xef, 0x7f, 0x00, 0x1b, 0x00, 0x00,
0x00, 0x1c, 0x6c, 0x02, 0x00, 0x80, 0x07, 0xf8, 0xff, 0x47, 0x0c, 0x80,
0x19, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x03, 0x00, 0xc0, 0x03, 0xfb, 0xff,
0x0d, 0x0c, 0x80, 0x19, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x60,
0x40, 0x3f, 0x18, 0x4c, 0x3d, 0x80, 0x0b, 0x00, 0x00, 0x00, 0x00, 0xf0,
0x01, 0x00, 0x70, 0x40, 0x1f, 0x18, 0xfc, 0x37, 0x80, 0x0b, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xb8, 0xb0, 0x1f, 0x18, 0x0c, 0x3e, 0x80,
0x9f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc8, 0x08, 0x78,
0x2c, 0x06, 0x00, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
0x60, 0x00, 0xf8, 0xcf, 0x06, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0c, 0x35, 0x00, 0xf8, 0x9f, 0x06, 0x00, 0xfe, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x36, 0x00, 0xf8, 0x77, 0x03, 0x00,
0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xec, 0x31, 0x00, 0xd8,
0xdd, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
0x1a, 0x00, 0x08, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xce, 0x1e, 0x00, 0x0c, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xee, 0x18, 0x00, 0x0c, 0x8c, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce, 0x1f, 0x00, 0x7c,
0xef, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xce,
0x1e, 0x00, 0xf8, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xce, 0xf0, 0x03, 0xfc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0xfb, 0x01, 0x0c, 0x5f, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbe, 0xef, 0x01, 0x06,
0x7d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
0xd7, 0x81, 0x87, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3c, 0xdf, 0xc3, 0xc7, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xfe, 0xff, 0xff, 0x3b, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0xfc, 0x7f, 0xfe,
0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
0xfd, 0x7f, 0xfc, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0x37, 0xe6, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf7, 0xe3, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xfe, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
#endif

View File

@@ -1,4 +1,4 @@
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include "obp60task.h"
#include "Pagedata.h" // Data exchange for pages
#include "OBP60Hardware.h" // PIN definitions
@@ -9,10 +9,17 @@
#include <NMEA0183.h> // NMEA0183
#include <NMEA0183Msg.h>
#include <NMEA0183Messages.h>
#include <GxEPD2_BW.h> // GxEPD2 lib for black 6 white E-Ink displays
#include <GxEPD2_BW.h> // GxEPD2 lib for b/w E-Ink displays
#include "OBP60Extensions.h" // Functions lib for extension board
#include "OBP60Keypad.h" // Functions for keypad
#ifdef BOARD_OBP40S3
#include "driver/rtc_io.h" // Needs for weakup from deep sleep
#include <FS.h> // SD-Card access
#include <SD.h>
#include <SPI.h>
#endif
// True type character sets includes
// See OBP60ExtensionPort.cpp
@@ -20,10 +27,10 @@
//#include GxEPD_BitmapExamples // Example picture
#include "MFD_OBP60_400x300_sw.h" // MFD with logo
#include "Logo_OBP_400x300_sw.h" // OBP Logo
#include "images/unknown.xbm" // unknown page indicator
#include "OBP60QRWiFi.h" // Functions lib for WiFi QR code
#include "OBPSensorTask.h" // Functions lib for sensor data
#include "LedSpiTask.h"
// Global vars
bool initComplete = false; // Initialization complete
@@ -33,6 +40,9 @@ int taskRunCounter = 0; // Task couter for loop section
//####################################################################################
void OBP60Init(GwApi *api){
GwLog *logger = api->getLogger();
GwConfigHandler *config = api->getConfig();
// Set a new device name and hidden the original name in the main config
String devicename = api->getConfig()->getConfigItem(api->getConfig()->deviceName,true)->asString();
api->getConfig()->setValue(GwConfigDefinitions::systemName, devicename, GwConfigInterface::ConfigType::HIDDEN);
@@ -52,19 +62,52 @@ void OBP60Init(GwApi *api){
#ifdef HARDWARE_V21
setPortPin(OBP_POWER_50, true); // Power on 5.0V rail
#endif
#ifdef HARDWARE_LIGHT
#ifdef BOARD_OBP40S3
setPortPin(OBP_POWER_EPD, true);// Power on ePaper display
setPortPin(OBP_POWER_SD, true); // Power on SD card
#endif
}
else{
#ifdef HARDWARE_V21
setPortPin(OBP_POWER_50, false); // Power off 5.0V rail
#endif
#ifdef HARDWARE_LIGHT
#ifdef BOARD_OBP40S3
setPortPin(OBP_POWER_EPD, false);// Power off ePaper display
setPortPin(OBP_POWER_SD, false); // Power off SD card
#endif
}
#ifdef BOARD_OBP40S3
// String sdcard = config->getConfigItem(config->useSDCard, true)->asString();
String sdcard = "on";
if (sdcard == "on") {
SPIClass SD_SPI = SPIClass(HSPI);
SD_SPI.begin(SD_SPI_CLK, SD_SPI_MISO, SD_SPI_MOSI);
if (SD.begin(SD_SPI_CS, SD_SPI, 80000000)) {
String sdtype = "unknown";
uint8_t cardType = SD.cardType();
switch (cardType) {
case CARD_MMC:
sdtype = "MMC";
break;
case CARD_SD:
sdtype = "SDSC";
break;
case CARD_SDHC:
sdtype = "SDHC";
break;
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
LOG_DEBUG(GwLog::LOG,"SD card type %s of size %d MB detected", sdtype, cardSize);
}
}
// Deep sleep wakeup configuration
esp_sleep_enable_ext0_wakeup(OBP_WAKEWUP_PIN, 0); // 1 = High, 0 = Low
rtc_gpio_pullup_en(OBP_WAKEWUP_PIN); // Activate pullup resistor
rtc_gpio_pulldown_dis(OBP_WAKEWUP_PIN); // Disable pulldown resistor
#endif
// Settings for e-paper display
String fastrefresh = api->getConfig()->getConfigItem(api->getConfig()->fastRefresh,true)->asString();
api->getLogger()->logDebug(GwLog::DEBUG,"Fast Refresh Mode is: %s", fastrefresh.c_str());
@@ -74,6 +117,16 @@ void OBP60Init(GwApi *api){
}
#endif
#ifdef BOARD_OBP60S3
touchSleepWakeUpEnable(TP1, 45); // TODO sensitivity should be configurable via web interface
touchSleepWakeUpEnable(TP2, 45);
touchSleepWakeUpEnable(TP3, 45);
touchSleepWakeUpEnable(TP4, 45);
touchSleepWakeUpEnable(TP5, 45);
touchSleepWakeUpEnable(TP6, 45);
esp_sleep_enable_touchpad_wakeup();
#endif
// Get CPU speed
int freq = getCpuFrequencyMhz();
api->getLogger()->logDebug(GwLog::LOG,"CPU speed at boot: %i MHz", freq);
@@ -116,6 +169,7 @@ typedef struct {
GwLog* logger = NULL;
// GwApi* api = NULL;
uint sensitivity = 100;
bool use_syspage = true;
} MyData;
// Keyboard Task
@@ -127,7 +181,7 @@ void keyboardTask(void *param){
// Loop for keyboard task
while (true){
keycode = readKeypad(data->sensitivity);
keycode = readKeypad(data->logger, data->sensitivity, data->use_syspage);
//send a key event
if(keycode != 0){
xQueueSend(data->queue, &keycode, 0);
@@ -204,8 +258,10 @@ void registerAllPages(PageList &list){
//this way this separate source file can be compiled by it's own
//and has no access to any of our data except the one that we
//give as a parameter to the page function
extern PageDescription registerPageOneValue;
extern PageDescription registerPageSystem;
//we add the variable to our list
list.add(&registerPageSystem);
extern PageDescription registerPageOneValue;
list.add(&registerPageOneValue);
extern PageDescription registerPageTwoValues;
list.add(&registerPageTwoValues);
@@ -254,12 +310,39 @@ void registerAllPages(PageList &list){
// Undervoltage detection for shutdown display
void underVoltageDetection(GwApi *api, CommonData &common){
// Read settings
float vslope = uint(api->getConfig()->getConfigItem(api->getConfig()->vSlope,true)->asFloat());
float voffset = uint(api->getConfig()->getConfigItem(api->getConfig()->vOffset,true)->asFloat());
double voffset = (api->getConfig()->getConfigItem(api->getConfig()->vOffset,true)->asString()).toFloat();
double vslope = (api->getConfig()->getConfigItem(api->getConfig()->vSlope,true)->asString()).toFloat();
// Read supply voltage
float actVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // V = 1/20 * Vin
actVoltage = actVoltage * vslope + voffset;
if(actVoltage < MIN_VOLTAGE){
#if defined VOLTAGE_SENSOR && defined LIPO_ACCU_1200
float actVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
float minVoltage = 3.65; // Absolut minimum volatge for 3,7V LiPo accu
#else
float actVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
float minVoltage = MIN_VOLTAGE;
#endif
double calVoltage = actVoltage * vslope + voffset; // Calibration
if(calVoltage < minVoltage){
#if defined VOLTAGE_SENSOR && defined LIPO_ACCU_1200
// Switch off all power lines
setPortPin(OBP_BACKLIGHT_LED, false); // Backlight Off
setFlashLED(false); // Flash LED Off
buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms
// Shutdown EInk display
getdisplay().setFullWindow(); // Set full Refresh
//getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
getdisplay().fillScreen(common.bgcolor);// Clear screen
getdisplay().setTextColor(common.fgcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(65, 150);
getdisplay().print("Undervoltage");
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(65, 175);
getdisplay().print("Charge battery and restart system");
getdisplay().nextPage(); // Partial update
getdisplay().powerOff(); // Display power off
setPortPin(OBP_POWER_EPD, false); // Power off ePaper display
setPortPin(OBP_POWER_SD, false); // Power off SD card
#else
// Switch off all power lines
setPortPin(OBP_BACKLIGHT_LED, false); // Backlight Off
setFlashLED(false); // Flash LED Off
@@ -267,13 +350,17 @@ void underVoltageDetection(GwApi *api, CommonData &common){
setPortPin(OBP_POWER_50, false); // Power rail 5.0V Off
// Shutdown EInk display
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
getdisplay().fillScreen(common.bgcolor); // Clear screen
getdisplay().fillScreen(common.bgcolor);// Clear screen
getdisplay().setTextColor(common.fgcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(65, 150);
getdisplay().print("Undervoltage");
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(65, 175);
getdisplay().print("To wake up repower system");
getdisplay().nextPage(); // Partial update
getdisplay().powerOff(); // Display power off
#endif
// Stop system
while(true){
esp_deep_sleep_start(); // Deep Sleep without weakup. Weakup only after power cycle (restart).
@@ -288,15 +375,19 @@ void OBP60Task(GwApi *api){
// return;
GwLog *logger=api->getLogger();
GwConfigHandler *config=api->getConfig();
#ifdef HARDWARE_V21
startLedTask(api);
#endif
PageList allPages;
registerAllPages(allPages);
CommonData commonData;
commonData.logger=logger;
commonData.config=config;
#ifdef HARDWARE_V21
// Keyboard coordinates for page footer
initKeys(commonData);
#endif
tN2kMsg N2kMsg;
@@ -321,6 +412,10 @@ void OBP60Task(GwApi *api){
bool refreshmode = api->getConfig()->getConfigItem(api->getConfig()->refresh,true)->asBoolean();
String fastrefresh = api->getConfig()->getConfigItem(api->getConfig()->fastRefresh,true)->asString();
uint fullrefreshtime = uint(api->getConfig()->getConfigItem(api->getConfig()->fullRefreshTime,true)->asInt());
#ifdef BOARD_OBP40S3
// bool syspage_enabled = config->getBool(config->systemPage);
bool syspage_enabled = true;
#endif
#ifdef DISPLAY_GDEY042T81
getdisplay().init(115200, true, 2, false); // Use this for Waveshare boards with "clever" reset circuit, 2ms reset pulse
@@ -361,6 +456,26 @@ void OBP60Task(GwApi *api){
PageStruct pages[MAX_PAGE_NUMBER];
// Set start page
int pageNumber = int(api->getConfig()->getConfigItem(api->getConfig()->startPage,true)->asInt()) - 1;
LOG_DEBUG(GwLog::LOG,"Checking wakeup...");
#ifdef BOARD_OBP60S3
if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_TOUCHPAD) {
LOG_DEBUG(GwLog::LOG,"Wake up by touch pad %d",esp_sleep_get_touchpad_wakeup_status());
pageNumber = getLastPage();
} else {
LOG_DEBUG(GwLog::LOG,"Other wakeup reason");
}
#endif
#ifdef BOARD_OBP40S3
if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT0) {
LOG_DEBUG(GwLog::LOG,"Wake up by key");
pageNumber = getLastPage();
} else {
LOG_DEBUG(GwLog::LOG,"Other wakeup reason");
}
#endif
LOG_DEBUG(GwLog::LOG,"...done");
int lastPage=pageNumber;
BoatValueList boatValues; //all the boat values for the api query
@@ -406,6 +521,8 @@ void OBP60Task(GwApi *api){
pages[i].parameters.values.push_back(value);
}
}
// add out of band system page (always available)
Page *syspage = allPages.pages[0]->creator(commonData);
// Display screenshot handler for HTTP request
// http://192.168.15.1/api/user/OBP60Task/screenshot
@@ -420,6 +537,9 @@ void OBP60Task(GwApi *api){
allParameters.page0=3;
allParameters.queue=xQueueCreate(10,sizeof(int));
allParameters.sensitivity= api->getConfig()->getInt(GwConfigDefinitions::tSensitivity);
#ifdef BOARD_OBP40S3
allParameters.use_syspage = syspage_enabled;
#endif
xTaskCreate(keyboardTask,"keyboard",2000,&allParameters,configMAX_PRIORITIES-1,NULL);
SharedData *shared=new SharedData(api);
createSensorTask(shared);
@@ -435,6 +555,7 @@ void OBP60Task(GwApi *api){
commonData.backlight.mode = backlightMapping(config->getConfigItem(config->backlight,true)->asString());
commonData.backlight.color = colorMapping(config->getConfigItem(config->blColor,true)->asString());
commonData.backlight.brightness = 2.55 * uint(config->getConfigItem(config->blBrightness,true)->asInt());
commonData.powermode = api->getConfig()->getConfigItem(api->getConfig()->powerMode,true)->asString();
bool uvoltage = api->getConfig()->getConfigItem(api->getConfig()->underVoltage,true)->asBoolean();
String cpuspeed = api->getConfig()->getConfigItem(api->getConfig()->cpuSpeed,true)->asString();
@@ -467,15 +588,17 @@ void OBP60Task(GwApi *api){
// Main loop runs with 100ms
//####################################################################################
bool systemPage = false;
Page *currentPage;
while (true){
delay(100); // Delay 100ms (loop time)
bool keypressed = false;
// Undervoltage detection
if(uvoltage == true){
underVoltageDetection(api, commonData);
}
}
// Set CPU speed after boot after 1min
if(millis() > firststart + (1 * 60 * 1000) && cpuspeedsetted == false){
@@ -512,12 +635,29 @@ void OBP60Task(GwApi *api){
int keyboardMessage=0;
while (xQueueReceive(allParameters.queue,&keyboardMessage,0)){
LOG_DEBUG(GwLog::LOG,"new key from keyboard %d",keyboardMessage);
Page *currentPage=pages[pageNumber].page;
if (currentPage ){
keyboardMessage=currentPage->handleKey(keyboardMessage);
keypressed = true;
if (keyboardMessage == 12 and !systemPage) {
LOG_DEBUG(GwLog::LOG, "Calling system page");
systemPage = true; // System page is out of band
syspage->setupKeys();
keyboardMessage = 0;
}
if (keyboardMessage > 0)
else {
currentPage = pages[pageNumber].page;
if (systemPage && keyboardMessage == 1) {
// exit system mode with exit key number 1
systemPage = false;
currentPage->setupKeys();
keyboardMessage = 0;
}
}
if (systemPage) {
keyboardMessage = syspage->handleKey(keyboardMessage);
} else if (currentPage) {
keyboardMessage = currentPage->handleKey(keyboardMessage);
}
if (keyboardMessage > 0) // not handled by page
{
// Decoding all key codes
// #6 Backlight on if key controled
@@ -528,6 +668,12 @@ void OBP60Task(GwApi *api){
toggleBacklightLED(commonData.backlight.brightness, commonData.backlight.color);
}
}
#ifdef BOARD_OBP40S3
// #3 Deep sleep mode for OBP40
if ((keyboardMessage == 3) and !syspage_enabled){
deepSleep(commonData);
}
#endif
// #9 Swipe right or #4 key right
if ((keyboardMessage == 9) or (keyboardMessage == 4))
{
@@ -573,8 +719,7 @@ void OBP60Task(GwApi *api){
}
else{
setBacklightLED(0, COLOR_BLUE); // Backlight LEDs off (blue without britghness)
}
}
}
}
}
@@ -624,43 +769,67 @@ void OBP60Task(GwApi *api){
}
}
// Refresh display data all 1s
if(millis() > starttime3 + 1000){
// Refresh display data, default all 1s
currentPage = pages[pageNumber].page;
int pagetime = 1000;
if ((lastPage == pageNumber) and (!keypressed)) {
// same page we use page defined time
pagetime = currentPage->refreshtime;
}
if(millis() > starttime3 + pagetime){
LOG_DEBUG(GwLog::DEBUG,"Page with refreshtime=%d", pagetime);
starttime3 = millis();
//refresh data from api
api->getBoatDataValues(boatValues.numValues,boatValues.allBoatValues);
api->getStatus(commonData.status);
// Clear display
// getdisplay().fillRect(0, 0, getdisplay().width(), getdisplay().height(), commonData.bgcolor);
getdisplay().fillScreen(commonData.bgcolor); // Clear display
// Show header if enabled
getdisplay().fillRect(0, 0, getdisplay().width(), getdisplay().height(), commonData.bgcolor); // Clear display
if (pages[pageNumber].description && pages[pageNumber].description->header){
if (pages[pageNumber].description && pages[pageNumber].description->header or systemPage){
// build header using commonData
getdisplay().fillScreen(commonData.bgcolor); // Clear display
displayHeader(commonData, date, time, hdop); // Show page header
}
// Call the particular page
Page *currentPage=pages[pageNumber].page;
if (currentPage == NULL){
LOG_DEBUG(GwLog::ERROR,"page number %d not found",pageNumber);
// Error handling for missing page
if (systemPage) {
displayFooter(commonData);
PageData sysparams; // empty
syspage->displayPage(sysparams);
}
else{
if (lastPage != pageNumber){
if (hasFRAM) fram.write(FRAM_PAGE_NO, pageNumber); // remember page for device restart
currentPage->setupKeys();
currentPage->displayNew(pages[pageNumber].parameters);
lastPage=pageNumber;
else {
if (currentPage == NULL){
LOG_DEBUG(GwLog::ERROR,"page number %d not found", pageNumber);
// Error handling for missing page
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
getdisplay().fillScreen(commonData.bgcolor); // Clear display
getdisplay().drawXBitmap(200 - unknown_width / 2, 150 - unknown_height / 2, unknown_bits, unknown_width, unknown_height, commonData.fgcolor);
getdisplay().setCursor(140, 250);
getdisplay().setFont(&Atari16px);
getdisplay().print("Here be dragons!");
getdisplay().nextPage(); // Partial update (fast)
}
//call the page code
LOG_DEBUG(GwLog::DEBUG,"calling page %d",pageNumber);
// Show footer if enabled (together with header)
if (pages[pageNumber].description && pages[pageNumber].description->header){
displayFooter(commonData);
else{
if (lastPage != pageNumber){
if (hasFRAM) fram.write(FRAM_PAGE_NO, pageNumber); // remember page for device restart
currentPage->setupKeys();
currentPage->displayNew(pages[pageNumber].parameters);
lastPage=pageNumber;
}
//call the page code
LOG_DEBUG(GwLog::DEBUG,"calling page %d",pageNumber);
// Show footer if enabled (together with header)
if (pages[pageNumber].description && pages[pageNumber].description->header){
displayFooter(commonData);
}
currentPage->displayPage(pages[pageNumber].parameters);
}
currentPage->displayPage(pages[pageNumber].parameters);
}
}
} // refresh display all 1s
}
}
vTaskDelete(NULL);

View File

@@ -1,7 +1,7 @@
#pragma once
#include "GwApi.h"
//we only compile for some boards
#ifdef BOARD_OBP60S3
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#define USBSerial Serial
#ifdef HARDWARE_V21
// CAN NMEA2000
@@ -14,12 +14,12 @@
#define GWSERIAL_RX 8
#define GWSERIAL_MODE "UNI"
#endif
#ifdef HARDWARE_LIGHT
#ifdef BOARD_OBP40S3
// CAN NMEA2000
#define ESP32_CAN_TX_PIN 15
#define ESP32_CAN_RX_PIN 16
// Bus load in 50mA steps
#define N2K_LOAD_LEVEL 2 // 5x50mA = 100mA max bus load with back light on
#define N2K_LOAD_LEVEL 2 // 2x50mA = 100mA max bus load
// RS485 NMEA0183
#define GWSERIAL_TX 9
#define GWSERIAL_RX 14
@@ -35,6 +35,11 @@
// OBP60 Task
void OBP60Task(GwApi *param);
DECLARE_USERTASK_PARAM(OBP60Task, 35000); // Need 35k RAM as stack size
#ifdef HARDWARE_V21
DECLARE_CAPABILITY(obp60,true);
#endif
#ifdef BOARD_OBP40S3
DECLARE_CAPABILITY(obp40,true)
#endif
DECLARE_STRING_CAPABILITY(HELP_URL, "https://obp60-v2-docu.readthedocs.io/de/latest/"); // Link to help pages
#endif
#endif

View File

@@ -2,7 +2,11 @@
#if you want a pio run to only build
#your special environments you can set this here
#by uncommenting the next line
default_envs = obp60_s3
default_envs =
obp60_s3
obp40_s3
[env:obp60_s3]
platform = espressif32@6.8.1
board_build.variants_dir = variants
@@ -10,7 +14,6 @@ board_build.variants_dir = variants
#board = obp60_s3_n16 #ESP32-S3 N16,16MB flash, no PSRAM, zero series
#board = obp60_s3_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM
board = obp60_s3_n16r8 #ESP32-S3 N16R8, 16MB flash, 8MB PSRAM, production series
#board = obp60_s3_light_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM, OBP60 clone
#board_build.partitions = default_8MB.csv #ESP32-S3 N8, 8MB flash
board_build.partitions = default_16MB.csv #ESP32-S3 N16, 16MB flash
framework = arduino
@@ -39,23 +42,62 @@ lib_deps =
adafruit/Adafruit FRAM I2C@^2.0.3
build_flags=
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
# -D ARDUINO_USB_MODE=1 #0=OTG (to implement other external devices), 1=CDC (is a serial device)
# -D ARDUINO_USB_CDC_ON_BOOT=1 #0=JTAG, 1=CDC (serial device)
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (seral device)
# -D TIME=$UNIX_TIME #Set PC time for RTC (only settable via VSC)
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
-D BOARD_OBP60S3 #Board OBP60 V2.1 with ESP32S3
# -D HARDWARE_V20 #OBP60 hardware revision V2.0
-D HARDWARE_V21 #OBP60 hardware revision V2.1
# -D HARDWARE_LIGHT #OBP60 hardware clone
# -D DISPLAY_GDEW042T2 #old E-Ink display from Waveshare, R10 0.47 ohm
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm
${env.build_flags}
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
upload_port = /dev/ttyACM0 #OBP60 original
#upload_port = /dev/ttyUSB0 #OBP60 clone
upload_port = /dev/ttyACM0 #OBP60 download via USB-C direct
upload_protocol = esptool #firmware upload via USB OTG seriell, by first upload need to set the ESP32-S3 in the upload mode with shortcut GND to Pin27
upload_speed = 230400
monitor_speed = 115200
[env:obp40_s3]
platform = espressif32@6.8.1
board_build.variants_dir = variants
board = obp40_s3_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM, OBP60 clone (CrowPanel 4.2)
board_build.partitions = default_8MB.csv #ESP32-S3 N8, 8MB flash
custom_config = config_obp40.json
framework = arduino
lib_deps =
${basedeps.lib_deps}
Wire
SPI
SD
esphome/AsyncTCP-esphome@2.0.1
robtillaart/PCF8574@0.3.9
adafruit/Adafruit Unified Sensor @ 1.1.13
blemasle/MCP23017@2.0.0
adafruit/Adafruit BusIO@1.5.0
adafruit/Adafruit GFX Library@1.11.9
#zinggjm/GxEPD2@1.5.8
#https://github.com/ZinggJM/GxEPD2
https://github.com/thooge/GxEPD2
sstaub/Ticker@4.4.0
adafruit/Adafruit BMP280 Library@2.6.2
adafruit/Adafruit BME280 Library@2.2.2
adafruit/Adafruit BMP085 Library@1.2.1
enjoyneering/HTU21D@1.2.1
robtillaart/INA226@0.2.0
paulstoffregen/OneWire@2.3.8
milesburton/DallasTemperature@3.11.0
signetica/SunRise@2.0.2
adafruit/Adafruit FRAM I2C@^2.0.3
build_flags=
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
-D BOARD_OBP40S3 #Board OBP40 V1.0 with ESP32S3 SKU:DIE07300S (CrowPanel 4.2)
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
-D LIPO_ACCU_1200 #Hardware extension, LiPo accu 3,7V 1200mAh
-D VOLTAGE_SENSOR #Hardware extension, LiPo voltage sensor with two resistors
${env.build_flags}
upload_port = /dev/ttyUSB0 #OBP40 download via external USB/Serail converter
upload_protocol = esptool #firmware upload via USB OTG seriell, by first upload need to set the ESP32-S3 in the upload mode with shortcut GND to Pin27
upload_speed = 230400
monitor_speed = 115200

View File

@@ -1,61 +0,0 @@
[platformio]
#if you want a pio run to only build
#your special environments you can set this here
#by uncommenting the next line
default_envs = obp60_s3
[env:obp60_s3]
platform = espressif32@6.8.1
board_build.variants_dir = variants
#board = obp60_s3_n8 #ESP32-S3 N8, 8MB flash, no PSRAM
#board = obp60_s3_n16 #ESP32-S3 N16,16MB flash, no PSRAM, zero series
#board = obp60_s3_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM
#board = obp60_s3_n16r8 #ESP32-S3 N16R8, 16MB flash, 8MB PSRAM, production series
board = obp60_s3_light_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM, OBP60 clone
board_build.partitions = default_8MB.csv #ESP32-S3 N8, 8MB flash
#board_build.partitions = default_16MB.csv #ESP32-S3 N16, 16MB flash
framework = arduino
lib_deps =
${basedeps.lib_deps}
Wire
SPI
esphome/AsyncTCP-esphome@2.0.1
robtillaart/PCF8574@0.3.9
adafruit/Adafruit Unified Sensor @ 1.1.13
blemasle/MCP23017@2.0.0
adafruit/Adafruit BusIO@1.5.0
adafruit/Adafruit GFX Library@1.11.9
#zinggjm/GxEPD2@1.5.8
#https://github.com/ZinggJM/GxEPD2
https://github.com/thooge/GxEPD2
sstaub/Ticker@4.4.0
adafruit/Adafruit BMP280 Library@2.6.2
adafruit/Adafruit BME280 Library@2.2.2
adafruit/Adafruit BMP085 Library@1.2.1
enjoyneering/HTU21D@1.2.1
robtillaart/INA226@0.2.0
paulstoffregen/OneWire@2.3.8
milesburton/DallasTemperature@3.11.0
signetica/SunRise@2.0.2
adafruit/Adafruit FRAM I2C@^2.0.3
build_flags=
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
# -D ARDUINO_USB_MODE=1 #0=OTG (to implement other external devices), 1=CDC (is a serial device)
# -D ARDUINO_USB_CDC_ON_BOOT=1 #0=JTAG, 1=CDC (serial device)
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (seral device)
# -D TIME=$UNIX_TIME #Set PC time for RTC (only settable via VSC)
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
-D BOARD_OBP60S3 #Board OBP60 V2.1 with ESP32S3
# -D HARDWARE_V20 #OBP60 hardware revision V2.0
# -D HARDWARE_V21 #OBP60 hardware revision V2.1
-D HARDWARE_LIGHT #OBP60 hardware clone
# -D DISPLAY_GDEW042T2 #old E-Ink display from Waveshare, R10 0.47 ohm
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm
${env.build_flags}
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
#upload_port = /dev/ttyACM0 #OBP60 original
upload_port = /dev/ttyUSB0 #OBP60 clone
upload_protocol = esptool #firmware upload via USB OTG seriell, by first upload need to set the ESP32-S3 in the upload mode with shortcut GND to Pin27
upload_speed = 230400
monitor_speed = 115200

View File

@@ -1,61 +0,0 @@
[platformio]
#if you want a pio run to only build
#your special environments you can set this here
#by uncommenting the next line
default_envs = obp60_s3
[env:obp60_s3]
platform = espressif32@6.8.1
board_build.variants_dir = variants
#board = obp60_s3_n8 #ESP32-S3 N8, 8MB flash, no PSRAM
#board = obp60_s3_n16 #ESP32-S3 N16,16MB flash, no PSRAM, zero series
#board = obp60_s3_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM
board = obp60_s3_n16r8 #ESP32-S3 N16R8, 16MB flash, 8MB PSRAM, production series
#board = obp60_s3_light_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM, OBP60 clone
#board_build.partitions = default_8MB.csv #ESP32-S3 N8, 8MB flash
board_build.partitions = default_16MB.csv #ESP32-S3 N16, 16MB flash
framework = arduino
lib_deps =
${basedeps.lib_deps}
Wire
SPI
esphome/AsyncTCP-esphome@2.0.1
robtillaart/PCF8574@0.3.9
adafruit/Adafruit Unified Sensor @ 1.1.13
blemasle/MCP23017@2.0.0
adafruit/Adafruit BusIO@1.5.0
adafruit/Adafruit GFX Library@1.11.9
#zinggjm/GxEPD2@1.5.8
#https://github.com/ZinggJM/GxEPD2
https://github.com/thooge/GxEPD2
sstaub/Ticker@4.4.0
adafruit/Adafruit BMP280 Library@2.6.2
adafruit/Adafruit BME280 Library@2.2.2
adafruit/Adafruit BMP085 Library@1.2.1
enjoyneering/HTU21D@1.2.1
robtillaart/INA226@0.2.0
paulstoffregen/OneWire@2.3.8
milesburton/DallasTemperature@3.11.0
signetica/SunRise@2.0.2
adafruit/Adafruit FRAM I2C@^2.0.3
build_flags=
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
# -D ARDUINO_USB_MODE=1 #0=OTG (to implement other external devices), 1=CDC (is a serial device)
# -D ARDUINO_USB_CDC_ON_BOOT=1 #0=JTAG, 1=CDC (serial device)
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (seral device)
# -D TIME=$UNIX_TIME #Set PC time for RTC (only settable via VSC)
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
-D BOARD_OBP60S3 #Board OBP60 V2.1 with ESP32S3
# -D HARDWARE_V20 #OBP60 hardware revision V2.0
-D HARDWARE_V21 #OBP60 hardware revision V2.1
# -D HARDWARE_LIGHT #OBP60 hardware clone
# -D DISPLAY_GDEW042T2 #old E-Ink display from Waveshare, R10 0.47 ohm
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm
${env.build_flags}
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
upload_port = /dev/ttyACM0 #OBP60 original
#upload_port = /dev/ttyUSB0 #OBP60 clone
upload_protocol = esptool #firmware upload via USB OTG seriell, by first upload need to set the ESP32-S3 in the upload mode with shortcut GND to Pin27
upload_speed = 230400
monitor_speed = 115200

View File

@@ -1,33 +0,0 @@
#!/bin/bash
# This script compile the software and loads the bin files into the web flash tool
# in the Gitpod Docker container.
# The web flashtool can be started from the Github website with:
# http://YourGitHubName.github.io/LoRa-Boat-Monitor/flash_tool/esp_flash_tool.html
# Attention! Start this cript only in the Gitpod Docker container.
# Start the script with: bash run
# Path definitions
projectpath="./.pio/build/nodemcu-32s"
toolpath="./docs/flash_tool"
# Install tools
echo "Installing tools"
cd /workspace/esp32-nmea2000
pip3 install -U esptool
pip3 install platformio
# Compile the firmware
echo "Compiling Firmware"
platformio run -e obp60_s3
# Copy all bin files in docs folder for online flash tool
#echo "Copy bin files"
#cp $projectpath/bootloader.bin $toolpath/bootloader.bin
#cp $projectpath/partitions.bin $toolpath/partitions.bin
#cp $projectpath/firmware.bin $toolpath/firmware.bin
# Merge all bin files to one merge file
#echo "Merge all bin files"
#esptool.py --chip ESP32 merge_bin -o $toolpath/merged-firmware.bin --flash_mode dio --flash_size 4MB 0x1000 $toolpath/bootloader.bin 0x8000 $toolpath/partitions.bin 0x10000 $toolpath/firmware.bin

View File

@@ -0,0 +1,13 @@
#!/bin/bash
# This script installing the tool chain
# in the Gitpod Docker container.
# Attention! Start this cript only in the Gitpod Docker container.
# Start the script with: bash run
# Install tools
echo "Installing tools"
cd /workspace/esp32-nmea2000
pip3 install -U esptool
pip3 install platformio

View File

@@ -0,0 +1,10 @@
#!/bin/bash
# This script compile the software für OBP40-S3
# Attention! Start this cript only in the Gitpod Docker container.
# Start the script with: bash run
# Compile the firmware
echo "Compiling Firmware"
platformio run -e obp60_s3

View File

@@ -0,0 +1,10 @@
#!/bin/bash
# This script compile the software für OBP60-S3
# Attention! Start this cript only in the Gitpod Docker container.
# Start the script with: bash run
# Compile the firmware
echo "Compiling Firmware"
platformio run -e obp60_s3

View File

@@ -1,3 +0,0 @@
FROM gitpod/workspace-full
USER gitpod

View File

@@ -1,11 +0,0 @@
tasks:
- command: pip3 install -U platformio && platformio run
image:
file: .gitpod.Dockerfile
vscode:
extensions:
- Atishay-Jain.All-Autocomplete
- esbenp.prettier-vscode
- shardulm94.trailing-spaces

View File

@@ -1,476 +0,0 @@
#ifdef BOARD_OBP60S3
/****************************************************
AMS 5600 class for Arduino platform
Author: Tom Denton
Date: 15 Dec 2014
File: AMS_5600.cpp
Version 1.00
www.ams.com
Description: This class has been designed to
access the AMS 5600 “potuino” shield.
*****************************************************/
// updated jan 2022 by isc - read two bytes together
// datasheet: https://ams.com/documents/20143/36005/AS5600_DS000365_5-00.pdf
#include "Arduino.h"
#include "AS5600.h"
#include "Wire.h"
/****************************************************
Method: AMS_5600
In: none
Out: none
Description: constructor class for AMS 5600
*****************************************************/
AMS_5600::AMS_5600()
{
}
/* mode = 0, output PWM, mode = 1 output analog (full range from 0% to 100% between GND and VDD */
void AMS_5600::setOutPut(uint8_t mode)
{
int _conf_lo = _addr_conf+1; // lower byte address
uint8_t config_status;
config_status = readOneByte(_conf_lo);
if (mode == 1) {
config_status = config_status & 0xcf;
} else {
uint8_t config_status;
config_status = readOneByte(_conf_lo);
if (mode == 1)
config_status = config_status & 0xcf;
else
config_status = config_status & 0xef;
writeOneByte(_conf_lo, lowByte(config_status));
}
}
/****************************************************
Method: AMS_5600
In: none
Out: i2c address of AMS 5600
Description: returns i2c address of AMS 5600
****************************************************/
int AMS_5600::getAddress()
{
return _ams5600_Address;
}
/*******************************************************
Method: setMaxAngle
In: new maximum angle to set OR none
Out: value of max angle register
Description: sets a value in maximum angle register.
If no value is provided, method will read position of
magnet. Setting this register zeros out max position
register.
*******************************************************/
word AMS_5600::setMaxAngle(word newMaxAngle)
{
word _maxAngle;
if (newMaxAngle == -1)
_maxAngle = getRawAngle();
else
_maxAngle = newMaxAngle;
writeOneByte(_addr_mang, highByte(_maxAngle));
delay(2);
writeOneByte(_addr_mang+1, lowByte(_maxAngle));
delay(2);
word retVal = readTwoBytesSeparately(_addr_mang);
return retVal;
}
/*******************************************************
Method: getMaxAngle
In: none
Out: value of max angle register
Description: gets value of maximum angle register.
*******************************************************/
word AMS_5600::getMaxAngle()
{
return readTwoBytesSeparately(_addr_mang);
}
/*******************************************************
Method: setStartPosition
In: new start angle position
Out: value of start position register
Description: sets a value in start position register.
If no value is provided, method will read position of
magnet.
*******************************************************/
word AMS_5600::setStartPosition(word startAngle)
{
word _rawStartAngle;
if (startAngle == -1)
_rawStartAngle = getRawAngle();
else
_rawStartAngle = startAngle;
writeOneByte(_addr_zpos, highByte(_rawStartAngle));
delay(2);
writeOneByte(_addr_zpos+1, lowByte(_rawStartAngle));
delay(2);
word _zPosition = readTwoBytesSeparately(_addr_zpos);
return (_zPosition);
}
/*******************************************************
Method: getStartPosition
In: none
Out: value of start position register
Description: gets value of start position register.
*******************************************************/
word AMS_5600::getStartPosition()
{
return readTwoBytesSeparately(_addr_zpos);
}
/*******************************************************
Method: setEndtPosition
In: new end angle position
Out: value of end position register
Description: sets a value in end position register.
If no value is provided, method will read position of
magnet.
*******************************************************/
word AMS_5600::setEndPosition(word endAngle)
{
word _rawEndAngle;
if (endAngle == -1)
_rawEndAngle = getRawAngle();
else
_rawEndAngle = endAngle;
writeOneByte(_addr_mpos, highByte(_rawEndAngle));
delay(2);
writeOneByte(_addr_mpos+1, lowByte(_rawEndAngle));
delay(2);
word _mPosition = readTwoBytesSeparately(_addr_mpos);
return (_mPosition);
}
/*******************************************************
Method: getEndPosition
In: none
Out: value of end position register
Description: gets value of end position register.
*******************************************************/
word AMS_5600::getEndPosition()
{
word retVal = readTwoBytesSeparately(_addr_mpos);
return retVal;
}
/*******************************************************
Method: getRawAngle
In: none
Out: value of raw angle register
Description: gets raw value of magnet position.
start, end, and max angle settings do not apply
*******************************************************/
word AMS_5600::getRawAngle()
{
return readTwoBytesTogether(_addr_raw_angle);
}
/*******************************************************
Method: getScaledAngle
In: none
Out: value of scaled angle register
Description: gets scaled value of magnet position.
start, end, or max angle settings are used to
determine value
*******************************************************/
word AMS_5600::getScaledAngle()
{
return readTwoBytesTogether(_addr_angle);
}
/*******************************************************
Method: detectMagnet
In: none
Out: 1 if magnet is detected, 0 if not
Description: reads status register and examines the
MH bit
*******************************************************/
int AMS_5600::detectMagnet()
{
int magStatus;
int retVal = 0;
/*0 0 MD ML MH 0 0 0*/
/* MD high = magnet detected*/
/* ML high = AGC Maximum overflow, magnet to weak*/
/* MH high = AGC minimum overflow, Magnet to strong*/
magStatus = readOneByte(_addr_status);
if (magStatus & 0x20)
retVal = 1;
return retVal;
}
/*******************************************************
Method: getMagnetStrength
In: none
Out: 0 if no magnet is detected
1 if magnet is to weak
2 if magnet is just right
3 if magnet is to strong
Description: reads status register andexamins the MH,ML,MD bits
*******************************************************/
int AMS_5600::getMagnetStrength()
{
int magStatus;
int retVal = 0;
/*0 0 MD ML MH 0 0 0*/
/* MD high = magnet detected */
/* ML high = AGC Maximum overflow, magnet to weak*/
/* MH high = AGC minimum overflow, Magnet to strong*/
magStatus = readOneByte(_addr_status);
if (detectMagnet() == 1) {
retVal = 2; /* just right */
if (magStatus & 0x10)
retVal = 1; /* too weak */
else if (magStatus & 0x08)
retVal = 3; /* too strong */
}
return retVal;
}
/*******************************************************
Method: get Agc
In: none
Out: value of AGC register
Description: gets value of AGC register.
*******************************************************/
int AMS_5600::getAgc()
{
return readOneByte(_addr_agc);
}
/*******************************************************
Method: getMagnitude
In: none
Out: value of magnitude register
Description: gets value of magnitude register.
*******************************************************/
word AMS_5600::getMagnitude()
{
return readTwoBytesTogether(_addr_magnitude);
}
/*******************************************************
Method: getConf
In: none
Out: value of CONF register
Description: gets value of CONF register.
*******************************************************/
word AMS_5600::getConf()
{
return readTwoBytesSeparately(_addr_conf);
}
/*******************************************************
Method: setConf
In: value of CONF register
Out: none
Description: sets value of CONF register.
*******************************************************/
void AMS_5600::setConf(word _conf)
{
writeOneByte(_addr_conf, highByte(_conf));
delay(2);
writeOneByte(_addr_conf+1, lowByte(_conf));
delay(2);
}
/*******************************************************
Method: getBurnCount
In: none
Out: value of zmco register
Description: determines how many times chip has been
permanently written to.
*******************************************************/
int AMS_5600::getBurnCount()
{
return readOneByte(_addr_zmco);
}
/*******************************************************
Method: burnAngle
In: none
Out: 1 success
-1 no magnet
-2 burn limit exceeded
-3 start and end positions not set (useless burn)
Description: burns start and end positions to chip.
THIS CAN ONLY BE DONE 3 TIMES
*******************************************************/
int AMS_5600::burnAngle()
{
word _zPosition = getStartPosition();
word _mPosition = getEndPosition();
word _maxAngle = getMaxAngle();
int retVal = 1;
if (detectMagnet() == 1) {
if (getBurnCount() < 3) {
if ((_zPosition == 0) && (_mPosition == 0))
retVal = -3;
else
writeOneByte(_addr_burn, 0x80);
}
else
retVal = -2;
} else
retVal = -1;
return retVal;
}
/*******************************************************
Method: burnMaxAngleAndConfig
In: none
Out: 1 success
-1 burn limit exceeded
-2 max angle is to small, must be at or above 18 degrees
Description: burns max angle and config data to chip.
THIS CAN ONLY BE DONE 1 TIME
*******************************************************/
int AMS_5600::burnMaxAngleAndConfig()
{
word _maxAngle = getMaxAngle();
int retVal = 1;
if (getBurnCount() == 0) {
if (_maxAngle * 0.087 < 18)
retVal = -2;
else
writeOneByte(_addr_burn, 0x40);
}
else
retVal = -1;
return retVal;
}
/*******************************************************
Method: readOneByte
In: register to read
Out: data read from i2c
Description: reads one byte register from i2c
*******************************************************/
int AMS_5600::readOneByte(int in_adr)
{
int retVal = -1;
Wire.beginTransmission(_ams5600_Address);
Wire.write(in_adr);
Wire.endTransmission();
Wire.requestFrom(_ams5600_Address, (uint8_t) 1);
/*
while (Wire.available() == 0)
;
retVal = Wire.read();
*/
if(Wire.available() >= 1){
retVal = Wire.read();
}
return retVal;
}
/*******************************************************
Method: readTwoBytes
In: two registers to read
Out: data read from i2c as a word
Description: reads two bytes register from i2c
*******************************************************/
word AMS_5600::readTwoBytesTogether(int addr_in)
{
// use only for Angle, Raw Angle and Magnitude
// read 2 bytes together to prevent getting inconsistent
// data while the encoder is moving
// according to the datasheet the address is automatically incremented
// but only for Angle, Raw Angle and Magnitude
// the title says it's auto, but the paragraph after it
// says it does NOT
// tested and it does auto increment
// PAGE 13: https://ams.com/documents/20143/36005/AS5600_DS000365_5-00.pdf
// Automatic Increment of the Address Pointer for ANGLE, RAW ANGLE and MAGNITUDE Registers
// These are special registers which suppress the automatic
// increment of the address pointer on reads, so a re-read of these
// registers requires no I²C write command to reload the address
// pointer. This special treatment of the pointer is effective only if
// the address pointer is set to the high byte of the register.
/* Read 2 Bytes */
Wire.beginTransmission(_ams5600_Address);
Wire.write(addr_in);
Wire.endTransmission();
Wire.requestFrom(_ams5600_Address, (uint8_t) 2);
/*
while (Wire.available() < 2)
;
int highByte = Wire.read();
int lowByte = Wire.read();
*/
int highByte = 0;
int lowByte = 0;
if (Wire.available() >= 2){
highByte = Wire.read();
lowByte = Wire.read();
}
// in case newer version of IC used the same address to
// store something else, get only the 3 bits
//return ( ( highByte & 0b111 ) << 8 ) | lowByte;
// but in case newer version has higher resolution
// we're good to go
return ( highByte << 8 ) | lowByte;
}
/*******************************************************
Method: readTwoBytes
In: two registers to read
Out: data read from i2c as a word
Description: reads two bytes register from i2c
*******************************************************/
word AMS_5600::readTwoBytesSeparately(int addr_in)
{
int highByte = readOneByte(addr_in );
int lowByte = readOneByte(addr_in+1);
return ( highByte << 8 ) | lowByte;
}
/*******************************************************
Method: writeOneByte
In: address and data to write
Out: none
Description: writes one byte to a i2c register
*******************************************************/
void AMS_5600::writeOneByte(int adr_in, int dat_in)
{
Wire.beginTransmission(_ams5600_Address);
Wire.write(adr_in);
Wire.write(dat_in);
Wire.endTransmission();
}
/********** END OF AMS 5600 CALSS *****************/
#endif

View File

@@ -1,91 +0,0 @@
/****************************************************
AMS 5600 class for Arduino platform
Author: Tom Denton
Date: 15 Dec 2014
File: AMS_5600.h
Version 1.00
www.ams.com
Description: This class has been designed to
access the AMS 5600 “potuino” shield.
***************************************************/
// updated jan 2022 by isc - read two bytes together
// datasheet: https://ams.com/documents/20143/36005/AS5600_DS000365_5-00.pdf
#ifndef AMS_5600_h
#define AMS_5600_h
#include <Arduino.h>
class AMS_5600
{
public:
AMS_5600(void);
int getAddress();
word setMaxAngle(word newMaxAngle = -1);
word getMaxAngle();
word setStartPosition(word startAngle = -1);
word getStartPosition();
word setEndPosition(word endAngle = -1);
word getEndPosition();
word getRawAngle();
word getScaledAngle();
int detectMagnet();
int getMagnetStrength();
int getAgc();
word getMagnitude();
word getConf();
void setConf(word _conf);
int getBurnCount();
int burnAngle();
int burnMaxAngleAndConfig();
void setOutPut(uint8_t mode);
private:
// i2c address
static const uint8_t _ams5600_Address = 0x36;
// single byte registers
static const uint8_t _addr_status = 0x0b; // magnet status
static const uint8_t _addr_agc = 0x1a; // automatic gain control
static const uint8_t _addr_burn = 0xff; // permanent burning of configs (zpos, mpos, mang, conf)
static const uint8_t _addr_zmco = 0x00; // number of times zpos/mpos has been permanently burned
// zpos/mpos can be permanently burned 3x
// mang/conf can be burned only once
// double byte registers, specify starting address (lower addr, but higher byte data)
// addr = upper byte of data (MSB), only bits 0:3 are used
// addr+1 = lower byte of data (LSB)
static const uint8_t _addr_zpos = 0x01; // zero position (start)
// 0x02 - lower byte
static const uint8_t _addr_mpos = 0x03; // maximum position (stop)
// 0x04 - lower byte
static const uint8_t _addr_mang = 0x05; // maximum angle
// 0x06 - lower byte
static const uint8_t _addr_conf = 0x07; // configuration
// 0x08 - lower byte
static const uint8_t _addr_raw_angle = 0x0c; // raw angle
// 0x0d - lower byte
static const uint8_t _addr_angle = 0x0e; // mapped angle
// 0x0f - lower byte
static const uint8_t _addr_magnitude = 0x1b; // magnitude of internal CORDIC
// 0x1c - lower byte
int readOneByte(int in_adr);
word readTwoBytesSeparately(int addr_in);
word readTwoBytesTogether(int addr_in);
void writeOneByte(int adr_in, int dat_in);
};
#endif

View File

@@ -1,259 +0,0 @@
uint8_t colorTo3Byte[256][3]=
{
{/*00*/0b10010010,0b01001001,0b00100100,},
{/*01*/0b10010010,0b01001001,0b00100110,},
{/*02*/0b10010010,0b01001001,0b00110100,},
{/*03*/0b10010010,0b01001001,0b00110110,},
{/*04*/0b10010010,0b01001001,0b10100100,},
{/*05*/0b10010010,0b01001001,0b10100110,},
{/*06*/0b10010010,0b01001001,0b10110100,},
{/*07*/0b10010010,0b01001001,0b10110110,},
{/*08*/0b10010010,0b01001101,0b00100100,},
{/*09*/0b10010010,0b01001101,0b00100110,},
{/*10*/0b10010010,0b01001101,0b00110100,},
{/*11*/0b10010010,0b01001101,0b00110110,},
{/*12*/0b10010010,0b01001101,0b10100100,},
{/*13*/0b10010010,0b01001101,0b10100110,},
{/*14*/0b10010010,0b01001101,0b10110100,},
{/*15*/0b10010010,0b01001101,0b10110110,},
{/*16*/0b10010010,0b01101001,0b00100100,},
{/*17*/0b10010010,0b01101001,0b00100110,},
{/*18*/0b10010010,0b01101001,0b00110100,},
{/*19*/0b10010010,0b01101001,0b00110110,},
{/*20*/0b10010010,0b01101001,0b10100100,},
{/*21*/0b10010010,0b01101001,0b10100110,},
{/*22*/0b10010010,0b01101001,0b10110100,},
{/*23*/0b10010010,0b01101001,0b10110110,},
{/*24*/0b10010010,0b01101101,0b00100100,},
{/*25*/0b10010010,0b01101101,0b00100110,},
{/*26*/0b10010010,0b01101101,0b00110100,},
{/*27*/0b10010010,0b01101101,0b00110110,},
{/*28*/0b10010010,0b01101101,0b10100100,},
{/*29*/0b10010010,0b01101101,0b10100110,},
{/*30*/0b10010010,0b01101101,0b10110100,},
{/*31*/0b10010010,0b01101101,0b10110110,},
{/*32*/0b10010011,0b01001001,0b00100100,},
{/*33*/0b10010011,0b01001001,0b00100110,},
{/*34*/0b10010011,0b01001001,0b00110100,},
{/*35*/0b10010011,0b01001001,0b00110110,},
{/*36*/0b10010011,0b01001001,0b10100100,},
{/*37*/0b10010011,0b01001001,0b10100110,},
{/*38*/0b10010011,0b01001001,0b10110100,},
{/*39*/0b10010011,0b01001001,0b10110110,},
{/*40*/0b10010011,0b01001101,0b00100100,},
{/*41*/0b10010011,0b01001101,0b00100110,},
{/*42*/0b10010011,0b01001101,0b00110100,},
{/*43*/0b10010011,0b01001101,0b00110110,},
{/*44*/0b10010011,0b01001101,0b10100100,},
{/*45*/0b10010011,0b01001101,0b10100110,},
{/*46*/0b10010011,0b01001101,0b10110100,},
{/*47*/0b10010011,0b01001101,0b10110110,},
{/*48*/0b10010011,0b01101001,0b00100100,},
{/*49*/0b10010011,0b01101001,0b00100110,},
{/*50*/0b10010011,0b01101001,0b00110100,},
{/*51*/0b10010011,0b01101001,0b00110110,},
{/*52*/0b10010011,0b01101001,0b10100100,},
{/*53*/0b10010011,0b01101001,0b10100110,},
{/*54*/0b10010011,0b01101001,0b10110100,},
{/*55*/0b10010011,0b01101001,0b10110110,},
{/*56*/0b10010011,0b01101101,0b00100100,},
{/*57*/0b10010011,0b01101101,0b00100110,},
{/*58*/0b10010011,0b01101101,0b00110100,},
{/*59*/0b10010011,0b01101101,0b00110110,},
{/*60*/0b10010011,0b01101101,0b10100100,},
{/*61*/0b10010011,0b01101101,0b10100110,},
{/*62*/0b10010011,0b01101101,0b10110100,},
{/*63*/0b10010011,0b01101101,0b10110110,},
{/*64*/0b10011010,0b01001001,0b00100100,},
{/*65*/0b10011010,0b01001001,0b00100110,},
{/*66*/0b10011010,0b01001001,0b00110100,},
{/*67*/0b10011010,0b01001001,0b00110110,},
{/*68*/0b10011010,0b01001001,0b10100100,},
{/*69*/0b10011010,0b01001001,0b10100110,},
{/*70*/0b10011010,0b01001001,0b10110100,},
{/*71*/0b10011010,0b01001001,0b10110110,},
{/*72*/0b10011010,0b01001101,0b00100100,},
{/*73*/0b10011010,0b01001101,0b00100110,},
{/*74*/0b10011010,0b01001101,0b00110100,},
{/*75*/0b10011010,0b01001101,0b00110110,},
{/*76*/0b10011010,0b01001101,0b10100100,},
{/*77*/0b10011010,0b01001101,0b10100110,},
{/*78*/0b10011010,0b01001101,0b10110100,},
{/*79*/0b10011010,0b01001101,0b10110110,},
{/*80*/0b10011010,0b01101001,0b00100100,},
{/*81*/0b10011010,0b01101001,0b00100110,},
{/*82*/0b10011010,0b01101001,0b00110100,},
{/*83*/0b10011010,0b01101001,0b00110110,},
{/*84*/0b10011010,0b01101001,0b10100100,},
{/*85*/0b10011010,0b01101001,0b10100110,},
{/*86*/0b10011010,0b01101001,0b10110100,},
{/*87*/0b10011010,0b01101001,0b10110110,},
{/*88*/0b10011010,0b01101101,0b00100100,},
{/*89*/0b10011010,0b01101101,0b00100110,},
{/*90*/0b10011010,0b01101101,0b00110100,},
{/*91*/0b10011010,0b01101101,0b00110110,},
{/*92*/0b10011010,0b01101101,0b10100100,},
{/*93*/0b10011010,0b01101101,0b10100110,},
{/*94*/0b10011010,0b01101101,0b10110100,},
{/*95*/0b10011010,0b01101101,0b10110110,},
{/*96*/0b10011011,0b01001001,0b00100100,},
{/*97*/0b10011011,0b01001001,0b00100110,},
{/*98*/0b10011011,0b01001001,0b00110100,},
{/*99*/0b10011011,0b01001001,0b00110110,},
{/*100*/0b10011011,0b01001001,0b10100100,},
{/*101*/0b10011011,0b01001001,0b10100110,},
{/*102*/0b10011011,0b01001001,0b10110100,},
{/*103*/0b10011011,0b01001001,0b10110110,},
{/*104*/0b10011011,0b01001101,0b00100100,},
{/*105*/0b10011011,0b01001101,0b00100110,},
{/*106*/0b10011011,0b01001101,0b00110100,},
{/*107*/0b10011011,0b01001101,0b00110110,},
{/*108*/0b10011011,0b01001101,0b10100100,},
{/*109*/0b10011011,0b01001101,0b10100110,},
{/*110*/0b10011011,0b01001101,0b10110100,},
{/*111*/0b10011011,0b01001101,0b10110110,},
{/*112*/0b10011011,0b01101001,0b00100100,},
{/*113*/0b10011011,0b01101001,0b00100110,},
{/*114*/0b10011011,0b01101001,0b00110100,},
{/*115*/0b10011011,0b01101001,0b00110110,},
{/*116*/0b10011011,0b01101001,0b10100100,},
{/*117*/0b10011011,0b01101001,0b10100110,},
{/*118*/0b10011011,0b01101001,0b10110100,},
{/*119*/0b10011011,0b01101001,0b10110110,},
{/*120*/0b10011011,0b01101101,0b00100100,},
{/*121*/0b10011011,0b01101101,0b00100110,},
{/*122*/0b10011011,0b01101101,0b00110100,},
{/*123*/0b10011011,0b01101101,0b00110110,},
{/*124*/0b10011011,0b01101101,0b10100100,},
{/*125*/0b10011011,0b01101101,0b10100110,},
{/*126*/0b10011011,0b01101101,0b10110100,},
{/*127*/0b10011011,0b01101101,0b10110110,},
{/*128*/0b11010010,0b01001001,0b00100100,},
{/*129*/0b11010010,0b01001001,0b00100110,},
{/*130*/0b11010010,0b01001001,0b00110100,},
{/*131*/0b11010010,0b01001001,0b00110110,},
{/*132*/0b11010010,0b01001001,0b10100100,},
{/*133*/0b11010010,0b01001001,0b10100110,},
{/*134*/0b11010010,0b01001001,0b10110100,},
{/*135*/0b11010010,0b01001001,0b10110110,},
{/*136*/0b11010010,0b01001101,0b00100100,},
{/*137*/0b11010010,0b01001101,0b00100110,},
{/*138*/0b11010010,0b01001101,0b00110100,},
{/*139*/0b11010010,0b01001101,0b00110110,},
{/*140*/0b11010010,0b01001101,0b10100100,},
{/*141*/0b11010010,0b01001101,0b10100110,},
{/*142*/0b11010010,0b01001101,0b10110100,},
{/*143*/0b11010010,0b01001101,0b10110110,},
{/*144*/0b11010010,0b01101001,0b00100100,},
{/*145*/0b11010010,0b01101001,0b00100110,},
{/*146*/0b11010010,0b01101001,0b00110100,},
{/*147*/0b11010010,0b01101001,0b00110110,},
{/*148*/0b11010010,0b01101001,0b10100100,},
{/*149*/0b11010010,0b01101001,0b10100110,},
{/*150*/0b11010010,0b01101001,0b10110100,},
{/*151*/0b11010010,0b01101001,0b10110110,},
{/*152*/0b11010010,0b01101101,0b00100100,},
{/*153*/0b11010010,0b01101101,0b00100110,},
{/*154*/0b11010010,0b01101101,0b00110100,},
{/*155*/0b11010010,0b01101101,0b00110110,},
{/*156*/0b11010010,0b01101101,0b10100100,},
{/*157*/0b11010010,0b01101101,0b10100110,},
{/*158*/0b11010010,0b01101101,0b10110100,},
{/*159*/0b11010010,0b01101101,0b10110110,},
{/*160*/0b11010011,0b01001001,0b00100100,},
{/*161*/0b11010011,0b01001001,0b00100110,},
{/*162*/0b11010011,0b01001001,0b00110100,},
{/*163*/0b11010011,0b01001001,0b00110110,},
{/*164*/0b11010011,0b01001001,0b10100100,},
{/*165*/0b11010011,0b01001001,0b10100110,},
{/*166*/0b11010011,0b01001001,0b10110100,},
{/*167*/0b11010011,0b01001001,0b10110110,},
{/*168*/0b11010011,0b01001101,0b00100100,},
{/*169*/0b11010011,0b01001101,0b00100110,},
{/*170*/0b11010011,0b01001101,0b00110100,},
{/*171*/0b11010011,0b01001101,0b00110110,},
{/*172*/0b11010011,0b01001101,0b10100100,},
{/*173*/0b11010011,0b01001101,0b10100110,},
{/*174*/0b11010011,0b01001101,0b10110100,},
{/*175*/0b11010011,0b01001101,0b10110110,},
{/*176*/0b11010011,0b01101001,0b00100100,},
{/*177*/0b11010011,0b01101001,0b00100110,},
{/*178*/0b11010011,0b01101001,0b00110100,},
{/*179*/0b11010011,0b01101001,0b00110110,},
{/*180*/0b11010011,0b01101001,0b10100100,},
{/*181*/0b11010011,0b01101001,0b10100110,},
{/*182*/0b11010011,0b01101001,0b10110100,},
{/*183*/0b11010011,0b01101001,0b10110110,},
{/*184*/0b11010011,0b01101101,0b00100100,},
{/*185*/0b11010011,0b01101101,0b00100110,},
{/*186*/0b11010011,0b01101101,0b00110100,},
{/*187*/0b11010011,0b01101101,0b00110110,},
{/*188*/0b11010011,0b01101101,0b10100100,},
{/*189*/0b11010011,0b01101101,0b10100110,},
{/*190*/0b11010011,0b01101101,0b10110100,},
{/*191*/0b11010011,0b01101101,0b10110110,},
{/*192*/0b11011010,0b01001001,0b00100100,},
{/*193*/0b11011010,0b01001001,0b00100110,},
{/*194*/0b11011010,0b01001001,0b00110100,},
{/*195*/0b11011010,0b01001001,0b00110110,},
{/*196*/0b11011010,0b01001001,0b10100100,},
{/*197*/0b11011010,0b01001001,0b10100110,},
{/*198*/0b11011010,0b01001001,0b10110100,},
{/*199*/0b11011010,0b01001001,0b10110110,},
{/*200*/0b11011010,0b01001101,0b00100100,},
{/*201*/0b11011010,0b01001101,0b00100110,},
{/*202*/0b11011010,0b01001101,0b00110100,},
{/*203*/0b11011010,0b01001101,0b00110110,},
{/*204*/0b11011010,0b01001101,0b10100100,},
{/*205*/0b11011010,0b01001101,0b10100110,},
{/*206*/0b11011010,0b01001101,0b10110100,},
{/*207*/0b11011010,0b01001101,0b10110110,},
{/*208*/0b11011010,0b01101001,0b00100100,},
{/*209*/0b11011010,0b01101001,0b00100110,},
{/*210*/0b11011010,0b01101001,0b00110100,},
{/*211*/0b11011010,0b01101001,0b00110110,},
{/*212*/0b11011010,0b01101001,0b10100100,},
{/*213*/0b11011010,0b01101001,0b10100110,},
{/*214*/0b11011010,0b01101001,0b10110100,},
{/*215*/0b11011010,0b01101001,0b10110110,},
{/*216*/0b11011010,0b01101101,0b00100100,},
{/*217*/0b11011010,0b01101101,0b00100110,},
{/*218*/0b11011010,0b01101101,0b00110100,},
{/*219*/0b11011010,0b01101101,0b00110110,},
{/*220*/0b11011010,0b01101101,0b10100100,},
{/*221*/0b11011010,0b01101101,0b10100110,},
{/*222*/0b11011010,0b01101101,0b10110100,},
{/*223*/0b11011010,0b01101101,0b10110110,},
{/*224*/0b11011011,0b01001001,0b00100100,},
{/*225*/0b11011011,0b01001001,0b00100110,},
{/*226*/0b11011011,0b01001001,0b00110100,},
{/*227*/0b11011011,0b01001001,0b00110110,},
{/*228*/0b11011011,0b01001001,0b10100100,},
{/*229*/0b11011011,0b01001001,0b10100110,},
{/*230*/0b11011011,0b01001001,0b10110100,},
{/*231*/0b11011011,0b01001001,0b10110110,},
{/*232*/0b11011011,0b01001101,0b00100100,},
{/*233*/0b11011011,0b01001101,0b00100110,},
{/*234*/0b11011011,0b01001101,0b00110100,},
{/*235*/0b11011011,0b01001101,0b00110110,},
{/*236*/0b11011011,0b01001101,0b10100100,},
{/*237*/0b11011011,0b01001101,0b10100110,},
{/*238*/0b11011011,0b01001101,0b10110100,},
{/*239*/0b11011011,0b01001101,0b10110110,},
{/*240*/0b11011011,0b01101001,0b00100100,},
{/*241*/0b11011011,0b01101001,0b00100110,},
{/*242*/0b11011011,0b01101001,0b00110100,},
{/*243*/0b11011011,0b01101001,0b00110110,},
{/*244*/0b11011011,0b01101001,0b10100100,},
{/*245*/0b11011011,0b01101001,0b10100110,},
{/*246*/0b11011011,0b01101001,0b10110100,},
{/*247*/0b11011011,0b01101001,0b10110110,},
{/*248*/0b11011011,0b01101101,0b00100100,},
{/*249*/0b11011011,0b01101101,0b00100110,},
{/*250*/0b11011011,0b01101101,0b00110100,},
{/*251*/0b11011011,0b01101101,0b00110110,},
{/*252*/0b11011011,0b01101101,0b10100100,},
{/*253*/0b11011011,0b01101101,0b10100110,},
{/*254*/0b11011011,0b01101101,0b10110100,},
{/*255*/0b11011011,0b01101101,0b10110110,}
};

View File

@@ -1,503 +0,0 @@
const uint8_t DSEG7Classic_BoldItalic16pt7bBitmaps[] PROGMEM = {
0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF,
0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF,
0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0xFF, 0x3F, 0xFD, 0xFF, 0xFD, 0xFF, 0xF0, 0x6E, 0xFE, 0xFF,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0x0F, 0xFF, 0xF0, 0x7F,
0xFF, 0xCD, 0xFF, 0xF6, 0x77, 0xFF, 0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C,
0xF0, 0x01, 0xE7, 0x80, 0x0F, 0x3C, 0x00, 0x79, 0xC0, 0x03, 0xDE, 0x00,
0x1E, 0xF0, 0x00, 0xF7, 0x80, 0x07, 0xBC, 0x00, 0x39, 0xC0, 0x00, 0xC0,
0x00, 0x00, 0x60, 0x00, 0x33, 0x80, 0x03, 0x9E, 0x00, 0x3C, 0xF0, 0x01,
0xE7, 0x00, 0x0F, 0x38, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0,
0x00, 0xE7, 0x80, 0x07, 0x3C, 0x00, 0x79, 0xDF, 0xFD, 0xCD, 0xFF, 0xF6,
0x1F, 0xFF, 0xC0, 0xFF, 0xFE, 0x00, 0x04, 0x31, 0xCF, 0x3C, 0xF3, 0xCF,
0x3C, 0xF3, 0xCF, 0x38, 0x60, 0x06, 0x39, 0xE7, 0x9E, 0x79, 0xE7, 0x9C,
0x73, 0xC7, 0x0C, 0x00, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF, 0xC1, 0xFF, 0xF6,
0x07, 0xFF, 0x70, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00, 0x01, 0xE0, 0x00,
0x0F, 0x00, 0x00, 0x78, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0,
0x00, 0x07, 0x80, 0x00, 0x38, 0x1F, 0xFE, 0xC3, 0xFF, 0xF8, 0x6F, 0xFF,
0x83, 0x80, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x00, 0x00, 0x38,
0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x80, 0x00,
0x3C, 0x00, 0x01, 0xDF, 0xFC, 0x0D, 0xFF, 0xF0, 0x1F, 0xFF, 0xC0, 0xFF,
0xFE, 0x00, 0x1F, 0xFF, 0xE1, 0xFF, 0xFF, 0x0F, 0xFF, 0xB0, 0x7F, 0xF7,
0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00,
0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00,
0x0E, 0x0F, 0xFF, 0x63, 0xFF, 0xF8, 0x1F, 0xFF, 0x60, 0x00, 0x0E, 0x00,
0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0,
0x00, 0x1E, 0x00, 0x01, 0xC0, 0x00, 0x1C, 0x00, 0x03, 0xC1, 0xFF, 0xDC,
0x3F, 0xFE, 0xC7, 0xFF, 0xF0, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0x16, 0x00,
0x03, 0x70, 0x00, 0x77, 0x80, 0x0F, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x78,
0x00, 0xF7, 0x80, 0x0F, 0x70, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF,
0x00, 0x0F, 0xF0, 0x00, 0xEE, 0xFF, 0xF6, 0x3F, 0xFF, 0x81, 0xFF, 0xF6,
0x00, 0x00, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01,
0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1C, 0x00, 0x01, 0xC0, 0x00,
0x3C, 0x00, 0x01, 0xC0, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xE3,
0xFF, 0xFD, 0xBF, 0xFE, 0x3B, 0xFF, 0x87, 0x80, 0x00, 0xF0, 0x00, 0x1E,
0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0E, 0x00, 0x03, 0xC0, 0x00, 0x78,
0x00, 0x0F, 0x00, 0x01, 0xE0, 0x00, 0x3B, 0xFF, 0xC1, 0xFF, 0xFC, 0x1F,
0xFF, 0x60, 0x00, 0x1C, 0x00, 0x07, 0x80, 0x00, 0xF0, 0x00, 0x1E, 0x00,
0x03, 0xC0, 0x00, 0x78, 0x00, 0x0F, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00,
0x0F, 0x0F, 0xFE, 0xE3, 0xFF, 0xEC, 0xFF, 0xFE, 0x1F, 0xFF, 0xC0, 0x0F,
0xFF, 0xF0, 0xFF, 0xFF, 0x37, 0xFF, 0xC3, 0xBF, 0xF8, 0x3C, 0x00, 0x03,
0xC0, 0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0x80, 0x00,
0x78, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x77, 0xFF,
0x81, 0xFF, 0xFC, 0x6F, 0xFF, 0xB7, 0x00, 0x07, 0x78, 0x00, 0xF7, 0x80,
0x0F, 0x70, 0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0,
0x00, 0xEF, 0x00, 0x0E, 0xF0, 0x01, 0xEE, 0xFF, 0xEE, 0xDF, 0xFF, 0x63,
0xFF, 0xF8, 0x3F, 0xFF, 0x80, 0x1F, 0xFF, 0xE1, 0xFF, 0xFF, 0x6F, 0xFF,
0xB7, 0x7F, 0xF7, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x78, 0x00, 0xF7, 0x80,
0x0F, 0x78, 0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0,
0x00, 0xFF, 0x00, 0x0E, 0xE0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x60,
0x00, 0x0E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E,
0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xC0, 0x00, 0x1C, 0x00, 0x03,
0xC0, 0x00, 0x1C, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x7F,
0xFF, 0xCD, 0xFF, 0xF6, 0x77, 0xFF, 0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C,
0xF0, 0x01, 0xE7, 0x80, 0x0F, 0x3C, 0x00, 0x79, 0xC0, 0x03, 0xDE, 0x00,
0x1E, 0xF0, 0x00, 0xF7, 0x80, 0x07, 0xBC, 0x00, 0x39, 0xDF, 0xFE, 0xC3,
0xFF, 0xF8, 0x6F, 0xFF, 0xB3, 0x80, 0x03, 0x9E, 0x00, 0x3C, 0xF0, 0x01,
0xE7, 0x00, 0x0F, 0x38, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0,
0x00, 0xE7, 0x80, 0x07, 0x3C, 0x00, 0x79, 0xDF, 0xFD, 0xCD, 0xFF, 0xF6,
0x1F, 0xFF, 0xC0, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0xE1, 0xFF, 0xFF, 0x6F,
0xFF, 0xB7, 0x7F, 0xF7, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x78, 0x00, 0xF7,
0x80, 0x0F, 0x78, 0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F,
0xF0, 0x00, 0xFF, 0x00, 0x0E, 0xEF, 0xFF, 0x63, 0xFF, 0xF8, 0x1F, 0xFF,
0x60, 0x00, 0x0E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00,
0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xC0, 0x00, 0x1C, 0x00,
0x03, 0xC1, 0xFF, 0xDC, 0x3F, 0xFE, 0xC7, 0xFF, 0xF0, 0x7F, 0xFF, 0x00,
0x73, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x73, 0x9C, 0xFF, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0xFF, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF, 0xCD, 0xFF, 0xF6,
0x77, 0xFF, 0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7, 0x80,
0x0F, 0x3C, 0x00, 0x79, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0xF7,
0x80, 0x07, 0xBC, 0x00, 0x39, 0xDF, 0xFE, 0xC3, 0xFF, 0xF8, 0x6F, 0xFF,
0xB3, 0x80, 0x03, 0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7, 0x00, 0x0F, 0x38,
0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0xE7, 0x80, 0x07,
0x3C, 0x00, 0x79, 0xC0, 0x01, 0xCC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0x00, 0x00, 0x38, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03,
0xC0, 0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x80, 0x00,
0x78, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0x7F, 0xF8, 0x1F, 0xFF,
0xC6, 0xFF, 0xFB, 0x70, 0x00, 0x77, 0x80, 0x0F, 0x78, 0x00, 0xF7, 0x00,
0x0F, 0x70, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0E, 0xF0,
0x00, 0xEF, 0x00, 0x1E, 0xEF, 0xFE, 0xED, 0xFF, 0xF6, 0x3F, 0xFF, 0x83,
0xFF, 0xF8, 0x07, 0xFF, 0x87, 0xFF, 0xF6, 0xFF, 0xF9, 0xC0, 0x00, 0x78,
0x00, 0x1E, 0x00, 0x07, 0x00, 0x01, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00,
0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3B, 0xFF, 0x8D, 0xFF, 0xF0,
0xFF, 0xFE, 0x3F, 0xFF, 0x80, 0x00, 0x00, 0x08, 0x00, 0x00, 0xC0, 0x00,
0x0E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00, 0x01, 0xE0,
0x00, 0x0F, 0x00, 0x00, 0x78, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00,
0xF0, 0x00, 0x07, 0x03, 0xFF, 0xD8, 0x7F, 0xFF, 0x0D, 0xFF, 0xF6, 0x70,
0x00, 0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xE0, 0x01, 0xE7, 0x00, 0x0F,
0x78, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1C, 0xF0, 0x00, 0xE7, 0x80,
0x0F, 0x3B, 0xFF, 0xB9, 0xBF, 0xFE, 0xC3, 0xFF, 0xF8, 0x1F, 0xFF, 0xC0,
0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0x37, 0xFF, 0xC3, 0xBF, 0xF8, 0x3C, 0x00,
0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0x80,
0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x77,
0xFF, 0x81, 0xFF, 0xFC, 0x6F, 0xFF, 0x87, 0x00, 0x00, 0x78, 0x00, 0x07,
0x80, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00,
0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0E, 0xFF, 0xE0, 0xDF, 0xFF,
0x03, 0xFF, 0xF8, 0x3F, 0xFF, 0x80, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0x37,
0xFF, 0xC3, 0xBF, 0xF8, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03,
0xC0, 0x00, 0x3C, 0x00, 0x03, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00,
0x78, 0x00, 0x07, 0x80, 0x00, 0x77, 0xFF, 0x81, 0xFF, 0xFC, 0x6F, 0xFF,
0x87, 0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x70, 0x00, 0x07, 0x00,
0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0,
0x00, 0x0E, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0,
0xFF, 0xFF, 0x37, 0xFF, 0xC3, 0xBF, 0xF8, 0x3C, 0x00, 0x03, 0xC0, 0x00,
0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0x80, 0x00, 0x78, 0x00,
0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x70, 0x00, 0x00, 0x00,
0x00, 0x60, 0x00, 0x37, 0x00, 0x07, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x70,
0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xEF,
0x00, 0x0E, 0xF0, 0x01, 0xEE, 0xFF, 0xEE, 0xDF, 0xFF, 0x63, 0xFF, 0xF8,
0x3F, 0xFF, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x38, 0x00, 0x03, 0xC0,
0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x38,
0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07,
0x7F, 0xF8, 0x1F, 0xFF, 0xC6, 0xFF, 0xFB, 0x70, 0x00, 0x77, 0x80, 0x0F,
0x78, 0x00, 0xF7, 0x00, 0x0F, 0x70, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00,
0xFF, 0x00, 0x0E, 0xF0, 0x00, 0xEF, 0x00, 0x1E, 0xE0, 0x00, 0xEC, 0x00,
0x06, 0x00, 0x00, 0x00, 0x19, 0xDE, 0xF7, 0xBD, 0xEF, 0x73, 0xBC, 0xE3,
0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0xF0,
0x00, 0x07, 0x80, 0x00, 0x3C, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00, 0x00,
0x78, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x00,
0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x70, 0x00, 0x73, 0xC0, 0x07,
0x9E, 0x00, 0x3C, 0xE0, 0x01, 0xE7, 0x00, 0x0F, 0x78, 0x00, 0x7B, 0xC0,
0x03, 0xDE, 0x00, 0x1C, 0xF0, 0x00, 0xE7, 0x80, 0x0F, 0x3B, 0xFF, 0xB9,
0xBF, 0xFE, 0xC3, 0xFF, 0xF8, 0x1F, 0xFF, 0xC0, 0x0F, 0xFF, 0xF0, 0xFF,
0xFF, 0x37, 0xFF, 0xC3, 0xBF, 0xF8, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C,
0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0x80, 0x00, 0x78, 0x00, 0x07,
0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x77, 0xFF, 0x81, 0xFF, 0xFC,
0x6F, 0xFF, 0xB7, 0x00, 0x07, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x70, 0x00,
0xF7, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xEF, 0x00,
0x0E, 0xF0, 0x01, 0xEE, 0x00, 0x0E, 0xC0, 0x00, 0x60, 0x00, 0x00, 0x00,
0x00, 0x0C, 0x00, 0x03, 0x80, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00,
0x03, 0xC0, 0x00, 0xF0, 0x00, 0x38, 0x00, 0x1E, 0x00, 0x07, 0x80, 0x01,
0xE0, 0x00, 0x78, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x70,
0x00, 0x1E, 0x00, 0x07, 0x80, 0x01, 0xC0, 0x00, 0x70, 0x00, 0x3C, 0x00,
0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0E, 0xFF, 0xE3,
0x7F, 0xFC, 0x3F, 0xFF, 0x8F, 0xFF, 0xE0, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF,
0xCD, 0xFF, 0xF6, 0x77, 0xFF, 0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xF0,
0x01, 0xE7, 0x80, 0x0F, 0x3C, 0x00, 0x79, 0xC0, 0x03, 0xDE, 0x00, 0x1E,
0xF0, 0x00, 0xF7, 0x80, 0x07, 0xBC, 0x00, 0x39, 0xC0, 0x00, 0xC0, 0x00,
0x00, 0x60, 0x00, 0x33, 0x80, 0x03, 0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7,
0x00, 0x0F, 0x38, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00,
0xE7, 0x80, 0x07, 0x3C, 0x00, 0x79, 0xC0, 0x01, 0xCC, 0x00, 0x06, 0x00,
0x00, 0x00, 0x07, 0xFF, 0x81, 0xFF, 0xFC, 0x6F, 0xFF, 0xB7, 0x00, 0x07,
0x78, 0x00, 0xF7, 0x80, 0x0F, 0x70, 0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00,
0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xEF, 0x00, 0x0E, 0xF0, 0x01, 0xEE, 0x00,
0x0E, 0xC0, 0x00, 0x60, 0x00, 0x00, 0x07, 0xFF, 0x81, 0xFF, 0xFC, 0x6F,
0xFF, 0xB7, 0x00, 0x07, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x70, 0x00, 0xF7,
0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xEF, 0x00, 0x0E,
0xF0, 0x01, 0xEE, 0xFF, 0xEE, 0xDF, 0xFF, 0x63, 0xFF, 0xF8, 0x3F, 0xFF,
0x80, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF, 0xCD, 0xFF, 0xF6, 0x77, 0xFF, 0x73,
0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7, 0x80, 0x0F, 0x3C, 0x00,
0x79, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0xF7, 0x80, 0x07, 0xBC,
0x00, 0x39, 0xDF, 0xFE, 0xC3, 0xFF, 0xF8, 0x6F, 0xFF, 0x83, 0x80, 0x00,
0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x00, 0x00, 0x38, 0x00, 0x03, 0xC0,
0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00, 0x01,
0xC0, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xE1, 0xFF,
0xFF, 0x6F, 0xFF, 0xB7, 0x7F, 0xF7, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x78,
0x00, 0xF7, 0x80, 0x0F, 0x78, 0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00, 0xFF,
0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0E, 0xEF, 0xFF, 0x63, 0xFF, 0xF8,
0x1F, 0xFF, 0x60, 0x00, 0x0E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01,
0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xC0, 0x00,
0x1C, 0x00, 0x03, 0xC0, 0x00, 0x1C, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x07,
0xFF, 0x87, 0xFF, 0xF6, 0xFF, 0xF9, 0xC0, 0x00, 0x78, 0x00, 0x1E, 0x00,
0x07, 0x00, 0x01, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03,
0xC0, 0x00, 0xF0, 0x00, 0x38, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0C, 0x00, 0x01, 0xC0, 0x00, 0x3C, 0x00, 0x07, 0x80, 0x00, 0xF0,
0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x70, 0x00, 0x1E, 0x00, 0x03, 0xC0,
0x00, 0x78, 0x00, 0x0F, 0x00, 0x01, 0xDF, 0xFE, 0x0F, 0xFF, 0xE0, 0xFF,
0xFB, 0x00, 0x00, 0xE0, 0x00, 0x3C, 0x00, 0x07, 0x80, 0x00, 0xF0, 0x00,
0x1E, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00,
0x78, 0x7F, 0xF7, 0x1F, 0xFF, 0x67, 0xFF, 0xF0, 0xFF, 0xFE, 0x00, 0x00,
0x00, 0x0C, 0x00, 0x03, 0x80, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00,
0x03, 0xC0, 0x00, 0xF0, 0x00, 0x38, 0x00, 0x1E, 0x00, 0x07, 0x80, 0x01,
0xE0, 0x00, 0x78, 0x00, 0x1D, 0xFF, 0xE1, 0xFF, 0xFD, 0xBF, 0xFE, 0x70,
0x00, 0x1E, 0x00, 0x07, 0x80, 0x01, 0xC0, 0x00, 0x70, 0x00, 0x3C, 0x00,
0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0E, 0xFF, 0xE3,
0x7F, 0xFC, 0x3F, 0xFF, 0x8F, 0xFF, 0xE0, 0x60, 0x00, 0x37, 0x00, 0x07,
0x78, 0x00, 0xF7, 0x80, 0x0F, 0x70, 0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00,
0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xEF, 0x00, 0x0E, 0xF0, 0x01, 0xEE, 0xFF,
0xEE, 0xDF, 0xFF, 0x63, 0xFF, 0xF8, 0x3F, 0xFF, 0x80, 0x00, 0x00, 0x09,
0x80, 0x00, 0xCE, 0x00, 0x0E, 0x78, 0x00, 0xF3, 0xC0, 0x07, 0x9E, 0x00,
0x3C, 0xF0, 0x01, 0xE7, 0x80, 0x0F, 0x38, 0x00, 0x7B, 0xC0, 0x03, 0xDE,
0x00, 0x1E, 0xF0, 0x00, 0xF7, 0x80, 0x07, 0x38, 0x00, 0x18, 0x00, 0x00,
0x0C, 0x00, 0x06, 0x70, 0x00, 0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xE0,
0x01, 0xE7, 0x00, 0x0F, 0x78, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1C,
0xF0, 0x00, 0xE7, 0x80, 0x0F, 0x3B, 0xFF, 0xB9, 0xBF, 0xFE, 0xC3, 0xFF,
0xF8, 0x1F, 0xFF, 0xC0, 0x00, 0x00, 0x09, 0x80, 0x00, 0xCE, 0x00, 0x0E,
0x78, 0x00, 0xF3, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7, 0x80,
0x0F, 0x38, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0xF7,
0x80, 0x07, 0x3B, 0xFF, 0xD8, 0x7F, 0xFF, 0x0D, 0xFF, 0xF6, 0x70, 0x00,
0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xE0, 0x01, 0xE7, 0x00, 0x0F, 0x78,
0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1C, 0xF0, 0x00, 0xE7, 0x80, 0x0F,
0x3B, 0xFF, 0xB9, 0xBF, 0xFE, 0xC3, 0xFF, 0xF8, 0x1F, 0xFF, 0xC0, 0x00,
0x00, 0x09, 0x80, 0x00, 0xCE, 0x00, 0x0E, 0x78, 0x00, 0xF3, 0xC0, 0x07,
0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7, 0x80, 0x0F, 0x38, 0x00, 0x7B, 0xC0,
0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0xF7, 0x80, 0x07, 0x3B, 0xFF, 0xD8,
0x7F, 0xFF, 0x0D, 0xFF, 0xF6, 0x70, 0x00, 0x73, 0xC0, 0x07, 0x9E, 0x00,
0x3C, 0xE0, 0x01, 0xE7, 0x00, 0x0F, 0x78, 0x00, 0x7B, 0xC0, 0x03, 0xDE,
0x00, 0x1C, 0xF0, 0x00, 0xE7, 0x80, 0x0F, 0x38, 0x00, 0x39, 0x80, 0x00,
0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x00, 0x03, 0x70, 0x00, 0x77,
0x80, 0x0F, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x78, 0x00, 0xF7, 0x80, 0x0F,
0x70, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00,
0xEE, 0xFF, 0xF6, 0x3F, 0xFF, 0x81, 0xFF, 0xF6, 0x00, 0x00, 0xE0, 0x00,
0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00,
0x01, 0xE0, 0x00, 0x1C, 0x00, 0x01, 0xC0, 0x00, 0x3C, 0x1F, 0xFD, 0xC3,
0xFF, 0xEC, 0x7F, 0xFF, 0x07, 0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF,
0xC1, 0xFF, 0xF6, 0x07, 0xFF, 0x70, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00,
0x01, 0xE0, 0x00, 0x0F, 0x00, 0x00, 0x78, 0x00, 0x03, 0xC0, 0x00, 0x1E,
0x00, 0x00, 0xF0, 0x00, 0x07, 0x80, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x00,
0x00, 0x60, 0x00, 0x03, 0x80, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07,
0x00, 0x00, 0x38, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00,
0x07, 0x80, 0x00, 0x3C, 0x00, 0x01, 0xDF, 0xFC, 0x0D, 0xFF, 0xF0, 0x1F,
0xFF, 0xC0, 0xFF, 0xFE, 0x00, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0xFF, 0x1F, 0xFC, 0x1F, 0xFF, 0x1F, 0xFF, 0xCF,
0xFF, 0xE0, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0x0F,
0xFF, 0xF0, 0x7F, 0xFF, 0xCD, 0xFF, 0xF6, 0x77, 0xFF, 0x73, 0xC0, 0x07,
0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7, 0x80, 0x0F, 0x3C, 0x00, 0x79, 0xC0,
0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0xF7, 0x80, 0x07, 0xBC, 0x00, 0x39,
0xDF, 0xFE, 0xC3, 0xFF, 0xF8, 0x6F, 0xFF, 0xB3, 0x80, 0x03, 0x9E, 0x00,
0x3C, 0xF0, 0x01, 0xE7, 0x00, 0x0F, 0x38, 0x00, 0x7B, 0xC0, 0x03, 0xDE,
0x00, 0x1E, 0xF0, 0x00, 0xE7, 0x80, 0x07, 0x3C, 0x00, 0x79, 0xC0, 0x01,
0xCC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x38,
0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03,
0xC0, 0x00, 0x38, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00,
0x78, 0x00, 0x07, 0x7F, 0xF8, 0x1F, 0xFF, 0xC6, 0xFF, 0xFB, 0x70, 0x00,
0x77, 0x80, 0x0F, 0x78, 0x00, 0xF7, 0x00, 0x0F, 0x70, 0x00, 0xFF, 0x00,
0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0E, 0xF0, 0x00, 0xEF, 0x00, 0x1E, 0xEF,
0xFE, 0xED, 0xFF, 0xF6, 0x3F, 0xFF, 0x83, 0xFF, 0xF8, 0x07, 0xFF, 0x87,
0xFF, 0xF6, 0xFF, 0xF9, 0xC0, 0x00, 0x78, 0x00, 0x1E, 0x00, 0x07, 0x00,
0x01, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00,
0xF0, 0x00, 0x3B, 0xFF, 0x8D, 0xFF, 0xF0, 0xFF, 0xFE, 0x3F, 0xFF, 0x80,
0x00, 0x00, 0x08, 0x00, 0x00, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0xF0, 0x00,
0x07, 0x80, 0x00, 0x3C, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00, 0x00, 0x78,
0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x03, 0xFF,
0xD8, 0x7F, 0xFF, 0x0D, 0xFF, 0xF6, 0x70, 0x00, 0x73, 0xC0, 0x07, 0x9E,
0x00, 0x3C, 0xE0, 0x01, 0xE7, 0x00, 0x0F, 0x78, 0x00, 0x7B, 0xC0, 0x03,
0xDE, 0x00, 0x1C, 0xF0, 0x00, 0xE7, 0x80, 0x0F, 0x3B, 0xFF, 0xB9, 0xBF,
0xFE, 0xC3, 0xFF, 0xF8, 0x1F, 0xFF, 0xC0, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF,
0x37, 0xFF, 0xC3, 0xBF, 0xF8, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00,
0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80,
0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x77, 0xFF, 0x81, 0xFF, 0xFC, 0x6F,
0xFF, 0x87, 0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x70, 0x00, 0x07,
0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00,
0xF0, 0x00, 0x0E, 0xFF, 0xE0, 0xDF, 0xFF, 0x03, 0xFF, 0xF8, 0x3F, 0xFF,
0x80, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0x37, 0xFF, 0xC3, 0xBF, 0xF8, 0x3C,
0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03,
0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00,
0x77, 0xFF, 0x81, 0xFF, 0xFC, 0x6F, 0xFF, 0x87, 0x00, 0x00, 0x78, 0x00,
0x07, 0x80, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00,
0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xC0,
0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0x37, 0xFF, 0xC3,
0xBF, 0xF8, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00,
0x3C, 0x00, 0x03, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00,
0x07, 0x80, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x37, 0x00,
0x07, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x70, 0x00, 0xF7, 0x00, 0x0F, 0xF0,
0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xEF, 0x00, 0x0E, 0xF0, 0x01, 0xEE,
0xFF, 0xEE, 0xDF, 0xFF, 0x63, 0xFF, 0xF8, 0x3F, 0xFF, 0x80, 0x00, 0x00,
0x03, 0x00, 0x00, 0x38, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0xC0,
0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x80, 0x00, 0x78,
0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0x7F, 0xF8, 0x1F, 0xFF, 0xC6,
0xFF, 0xFB, 0x70, 0x00, 0x77, 0x80, 0x0F, 0x78, 0x00, 0xF7, 0x00, 0x0F,
0x70, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0E, 0xF0, 0x00,
0xEF, 0x00, 0x1E, 0xE0, 0x00, 0xEC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x19,
0xDE, 0xF7, 0xBD, 0xEF, 0x73, 0xBC, 0xE3, 0x00, 0x00, 0x00, 0x08, 0x00,
0x00, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x80, 0x00, 0x3C,
0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00, 0x00, 0x78, 0x00, 0x03, 0xC0, 0x00,
0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0C,
0x00, 0x06, 0x70, 0x00, 0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xE0, 0x01,
0xE7, 0x00, 0x0F, 0x78, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1C, 0xF0,
0x00, 0xE7, 0x80, 0x0F, 0x3B, 0xFF, 0xB9, 0xBF, 0xFE, 0xC3, 0xFF, 0xF8,
0x1F, 0xFF, 0xC0, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0x37, 0xFF, 0xC3, 0xBF,
0xF8, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x3C,
0x00, 0x03, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07,
0x80, 0x00, 0x77, 0xFF, 0x81, 0xFF, 0xFC, 0x6F, 0xFF, 0xB7, 0x00, 0x07,
0x78, 0x00, 0xF7, 0x80, 0x0F, 0x70, 0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00,
0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xEF, 0x00, 0x0E, 0xF0, 0x01, 0xEE, 0x00,
0x0E, 0xC0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x03, 0x80,
0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00,
0x38, 0x00, 0x1E, 0x00, 0x07, 0x80, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x1C,
0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x70, 0x00, 0x1E, 0x00, 0x07, 0x80,
0x01, 0xC0, 0x00, 0x70, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00,
0xF0, 0x00, 0x3C, 0x00, 0x0E, 0xFF, 0xE3, 0x7F, 0xFC, 0x3F, 0xFF, 0x8F,
0xFF, 0xE0, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF, 0xCD, 0xFF, 0xF6, 0x77, 0xFF,
0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7, 0x80, 0x0F, 0x3C,
0x00, 0x79, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0xF7, 0x80, 0x07,
0xBC, 0x00, 0x39, 0xC0, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x33, 0x80,
0x03, 0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7, 0x00, 0x0F, 0x38, 0x00, 0x7B,
0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0xE7, 0x80, 0x07, 0x3C, 0x00,
0x79, 0xC0, 0x01, 0xCC, 0x00, 0x06, 0x00, 0x00, 0x00, 0x07, 0xFF, 0x81,
0xFF, 0xFC, 0x6F, 0xFF, 0xB7, 0x00, 0x07, 0x78, 0x00, 0xF7, 0x80, 0x0F,
0x70, 0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00,
0xEF, 0x00, 0x0E, 0xF0, 0x01, 0xEE, 0x00, 0x0E, 0xC0, 0x00, 0x60, 0x00,
0x00, 0x07, 0xFF, 0x81, 0xFF, 0xFC, 0x6F, 0xFF, 0xB7, 0x00, 0x07, 0x78,
0x00, 0xF7, 0x80, 0x0F, 0x70, 0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00, 0xFF,
0x00, 0x0F, 0xF0, 0x00, 0xEF, 0x00, 0x0E, 0xF0, 0x01, 0xEE, 0xFF, 0xEE,
0xDF, 0xFF, 0x63, 0xFF, 0xF8, 0x3F, 0xFF, 0x80, 0x0F, 0xFF, 0xF0, 0x7F,
0xFF, 0xCD, 0xFF, 0xF6, 0x77, 0xFF, 0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C,
0xF0, 0x01, 0xE7, 0x80, 0x0F, 0x3C, 0x00, 0x79, 0xC0, 0x03, 0xDE, 0x00,
0x1E, 0xF0, 0x00, 0xF7, 0x80, 0x07, 0xBC, 0x00, 0x39, 0xDF, 0xFE, 0xC3,
0xFF, 0xF8, 0x6F, 0xFF, 0x83, 0x80, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00,
0x07, 0x00, 0x00, 0x38, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0,
0x00, 0x07, 0x80, 0x00, 0x3C, 0x00, 0x01, 0xC0, 0x00, 0x0C, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1F, 0xFF, 0xE1, 0xFF, 0xFF, 0x6F, 0xFF, 0xB7, 0x7F,
0xF7, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x78,
0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF,
0x00, 0x0E, 0xEF, 0xFF, 0x63, 0xFF, 0xF8, 0x1F, 0xFF, 0x60, 0x00, 0x0E,
0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01,
0xE0, 0x00, 0x1E, 0x00, 0x01, 0xC0, 0x00, 0x1C, 0x00, 0x03, 0xC0, 0x00,
0x1C, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x07, 0xFF, 0x87, 0xFF, 0xF6, 0xFF,
0xF9, 0xC0, 0x00, 0x78, 0x00, 0x1E, 0x00, 0x07, 0x00, 0x01, 0xC0, 0x00,
0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x38,
0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x01, 0xC0,
0x00, 0x3C, 0x00, 0x07, 0x80, 0x00, 0xF0, 0x00, 0x1E, 0x00, 0x03, 0xC0,
0x00, 0x70, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0F, 0x00,
0x01, 0xDF, 0xFE, 0x0F, 0xFF, 0xE0, 0xFF, 0xFB, 0x00, 0x00, 0xE0, 0x00,
0x3C, 0x00, 0x07, 0x80, 0x00, 0xF0, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00,
0x78, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x78, 0x7F, 0xF7, 0x1F, 0xFF,
0x67, 0xFF, 0xF0, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x03, 0x80,
0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00,
0x38, 0x00, 0x1E, 0x00, 0x07, 0x80, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x1D,
0xFF, 0xE1, 0xFF, 0xFD, 0xBF, 0xFE, 0x70, 0x00, 0x1E, 0x00, 0x07, 0x80,
0x01, 0xC0, 0x00, 0x70, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00,
0xF0, 0x00, 0x3C, 0x00, 0x0E, 0xFF, 0xE3, 0x7F, 0xFC, 0x3F, 0xFF, 0x8F,
0xFF, 0xE0, 0x60, 0x00, 0x37, 0x00, 0x07, 0x78, 0x00, 0xF7, 0x80, 0x0F,
0x70, 0x00, 0xF7, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00,
0xEF, 0x00, 0x0E, 0xF0, 0x01, 0xEE, 0xFF, 0xEE, 0xDF, 0xFF, 0x63, 0xFF,
0xF8, 0x3F, 0xFF, 0x80, 0x00, 0x00, 0x09, 0x80, 0x00, 0xCE, 0x00, 0x0E,
0x78, 0x00, 0xF3, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7, 0x80,
0x0F, 0x38, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0xF7,
0x80, 0x07, 0x38, 0x00, 0x18, 0x00, 0x00, 0x0C, 0x00, 0x06, 0x70, 0x00,
0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xE0, 0x01, 0xE7, 0x00, 0x0F, 0x78,
0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1C, 0xF0, 0x00, 0xE7, 0x80, 0x0F,
0x3B, 0xFF, 0xB9, 0xBF, 0xFE, 0xC3, 0xFF, 0xF8, 0x1F, 0xFF, 0xC0, 0x00,
0x00, 0x09, 0x80, 0x00, 0xCE, 0x00, 0x0E, 0x78, 0x00, 0xF3, 0xC0, 0x07,
0x9E, 0x00, 0x3C, 0xF0, 0x01, 0xE7, 0x80, 0x0F, 0x38, 0x00, 0x7B, 0xC0,
0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0xF7, 0x80, 0x07, 0x3B, 0xFF, 0xD8,
0x7F, 0xFF, 0x0D, 0xFF, 0xF6, 0x70, 0x00, 0x73, 0xC0, 0x07, 0x9E, 0x00,
0x3C, 0xE0, 0x01, 0xE7, 0x00, 0x0F, 0x78, 0x00, 0x7B, 0xC0, 0x03, 0xDE,
0x00, 0x1C, 0xF0, 0x00, 0xE7, 0x80, 0x0F, 0x3B, 0xFF, 0xB9, 0xBF, 0xFE,
0xC3, 0xFF, 0xF8, 0x1F, 0xFF, 0xC0, 0x00, 0x00, 0x09, 0x80, 0x00, 0xCE,
0x00, 0x0E, 0x78, 0x00, 0xF3, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xF0, 0x01,
0xE7, 0x80, 0x0F, 0x38, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0,
0x00, 0xF7, 0x80, 0x07, 0x3B, 0xFF, 0xD8, 0x7F, 0xFF, 0x0D, 0xFF, 0xF6,
0x70, 0x00, 0x73, 0xC0, 0x07, 0x9E, 0x00, 0x3C, 0xE0, 0x01, 0xE7, 0x00,
0x0F, 0x78, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x1C, 0xF0, 0x00, 0xE7,
0x80, 0x0F, 0x38, 0x00, 0x39, 0x80, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x16, 0x00, 0x03, 0x70, 0x00, 0x77, 0x80, 0x0F, 0x78, 0x00, 0xF7,
0x80, 0x0F, 0x78, 0x00, 0xF7, 0x80, 0x0F, 0x70, 0x00, 0xFF, 0x00, 0x0F,
0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xEE, 0xFF, 0xF6, 0x3F, 0xFF,
0x81, 0xFF, 0xF6, 0x00, 0x00, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00,
0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1C, 0x00,
0x01, 0xC0, 0x00, 0x3C, 0x1F, 0xFD, 0xC3, 0xFF, 0xEC, 0x7F, 0xFF, 0x07,
0xFF, 0xF0, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF, 0xC1, 0xFF, 0xF6, 0x07, 0xFF,
0x70, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00,
0x00, 0x78, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07,
0x80, 0x00, 0x38, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x60, 0x00, 0x03, 0x80,
0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x00, 0x00, 0x38, 0x00, 0x03,
0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00,
0x01, 0xDF, 0xFC, 0x0D, 0xFF, 0xF0, 0x1F, 0xFF, 0xC0, 0xFF, 0xFE, 0x00,
0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0xFF, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF };
const GFXglyph DSEG7Classic_BoldItalic16pt7bGlyphs[] PROGMEM = {
{ 0, 0, 0, 6, 0, 1 }, // 0x20 ' '
{ 0, 0, 0, 25, 0, 1 }, // 0x21 '!'
{ 0, 8, 21, 11, 1, -20 }, // 0x22 '"'
{ 21, 8, 21, 11, 1, -20 }, // 0x23 '#'
{ 42, 8, 21, 11, 1, -20 }, // 0x24 '$'
{ 63, 8, 21, 11, 1, -20 }, // 0x25 '%'
{ 84, 8, 21, 11, 1, -20 }, // 0x26 '&'
{ 105, 8, 21, 11, 1, -20 }, // 0x27 '''
{ 126, 8, 21, 11, 1, -20 }, // 0x28 '('
{ 147, 8, 21, 11, 1, -20 }, // 0x29 ')'
{ 168, 8, 21, 11, 1, -20 }, // 0x2A '*'
{ 189, 8, 21, 11, 1, -20 }, // 0x2B '+'
{ 210, 8, 21, 11, 1, -20 }, // 0x2C ','
{ 231, 15, 3, 25, 5, -16 }, // 0x2D '-'
{ 237, 4, 4, 0, -3, -3 }, // 0x2E '.'
{ 239, 8, 21, 11, 1, -20 }, // 0x2F '/'
{ 260, 21, 31, 25, 2, -30 }, // 0x30 '0'
{ 342, 6, 29, 25, 17, -29 }, // 0x31 '1'
{ 364, 21, 31, 25, 2, -30 }, // 0x32 '2'
{ 446, 20, 31, 25, 3, -30 }, // 0x33 '3'
{ 524, 20, 29, 25, 3, -29 }, // 0x34 '4'
{ 597, 19, 31, 25, 3, -30 }, // 0x35 '5'
{ 671, 20, 31, 25, 2, -30 }, // 0x36 '6'
{ 749, 20, 30, 25, 3, -30 }, // 0x37 '7'
{ 824, 21, 31, 25, 2, -30 }, // 0x38 '8'
{ 906, 20, 31, 25, 3, -30 }, // 0x39 '9'
{ 984, 5, 16, 6, 1, -22 }, // 0x3A ':'
{ 994, 8, 21, 11, 1, -20 }, // 0x3B ';'
{ 1015, 8, 21, 11, 1, -20 }, // 0x3C '<'
{ 1036, 8, 21, 11, 1, -20 }, // 0x3D '='
{ 1057, 8, 21, 11, 1, -20 }, // 0x3E '>'
{ 1078, 8, 21, 11, 1, -20 }, // 0x3F '?'
{ 1099, 8, 21, 11, 1, -20 }, // 0x40 '@'
{ 1120, 21, 30, 25, 2, -30 }, // 0x41 'A'
{ 1199, 20, 30, 25, 2, -29 }, // 0x42 'B'
{ 1274, 18, 17, 25, 2, -16 }, // 0x43 'C'
{ 1313, 21, 30, 25, 2, -29 }, // 0x44 'D'
{ 1392, 20, 31, 25, 2, -30 }, // 0x45 'E'
{ 1470, 20, 30, 25, 2, -30 }, // 0x46 'F'
{ 1545, 20, 31, 25, 2, -30 }, // 0x47 'G'
{ 1623, 20, 29, 25, 2, -29 }, // 0x48 'H'
{ 1696, 5, 14, 25, 17, -14 }, // 0x49 'I'
{ 1705, 21, 30, 25, 2, -29 }, // 0x4A 'J'
{ 1784, 20, 30, 25, 2, -30 }, // 0x4B 'K'
{ 1859, 18, 30, 25, 2, -29 }, // 0x4C 'L'
{ 1927, 21, 30, 25, 2, -30 }, // 0x4D 'M'
{ 2006, 20, 16, 25, 2, -16 }, // 0x4E 'N'
{ 2046, 20, 17, 25, 2, -16 }, // 0x4F 'O'
{ 2089, 21, 30, 25, 2, -30 }, // 0x50 'P'
{ 2168, 20, 30, 25, 3, -30 }, // 0x51 'Q'
{ 2243, 18, 16, 25, 2, -16 }, // 0x52 'R'
{ 2279, 19, 30, 25, 3, -29 }, // 0x53 'S'
{ 2351, 18, 30, 25, 2, -29 }, // 0x54 'T'
{ 2419, 20, 15, 25, 2, -14 }, // 0x55 'U'
{ 2457, 21, 30, 25, 2, -29 }, // 0x56 'V'
{ 2536, 21, 30, 25, 2, -29 }, // 0x57 'W'
{ 2615, 21, 29, 25, 2, -29 }, // 0x58 'X'
{ 2692, 20, 30, 25, 3, -29 }, // 0x59 'Y'
{ 2767, 21, 31, 25, 2, -30 }, // 0x5A 'Z'
{ 2849, 8, 21, 11, 1, -20 }, // 0x5B '['
{ 2870, 8, 21, 11, 1, -20 }, // 0x5C '\'
{ 2891, 8, 21, 11, 1, -20 }, // 0x5D ']'
{ 2912, 8, 21, 11, 1, -20 }, // 0x5E '^'
{ 2933, 17, 4, 25, 3, -3 }, // 0x5F '_'
{ 2942, 8, 21, 11, 1, -20 }, // 0x60 '`'
{ 2963, 21, 30, 25, 2, -30 }, // 0x61 'a'
{ 3042, 20, 30, 25, 2, -29 }, // 0x62 'b'
{ 3117, 18, 17, 25, 2, -16 }, // 0x63 'c'
{ 3156, 21, 30, 25, 2, -29 }, // 0x64 'd'
{ 3235, 20, 31, 25, 2, -30 }, // 0x65 'e'
{ 3313, 20, 30, 25, 2, -30 }, // 0x66 'f'
{ 3388, 20, 31, 25, 2, -30 }, // 0x67 'g'
{ 3466, 20, 29, 25, 2, -29 }, // 0x68 'h'
{ 3539, 5, 14, 25, 17, -14 }, // 0x69 'i'
{ 3548, 21, 30, 25, 2, -29 }, // 0x6A 'j'
{ 3627, 20, 30, 25, 2, -30 }, // 0x6B 'k'
{ 3702, 18, 30, 25, 2, -29 }, // 0x6C 'l'
{ 3770, 21, 30, 25, 2, -30 }, // 0x6D 'm'
{ 3849, 20, 16, 25, 2, -16 }, // 0x6E 'n'
{ 3889, 20, 17, 25, 2, -16 }, // 0x6F 'o'
{ 3932, 21, 30, 25, 2, -30 }, // 0x70 'p'
{ 4011, 20, 30, 25, 3, -30 }, // 0x71 'q'
{ 4086, 18, 16, 25, 2, -16 }, // 0x72 'r'
{ 4122, 19, 30, 25, 3, -29 }, // 0x73 's'
{ 4194, 18, 30, 25, 2, -29 }, // 0x74 't'
{ 4262, 20, 15, 25, 2, -14 }, // 0x75 'u'
{ 4300, 21, 30, 25, 2, -29 }, // 0x76 'v'
{ 4379, 21, 30, 25, 2, -29 }, // 0x77 'w'
{ 4458, 21, 29, 25, 2, -29 }, // 0x78 'x'
{ 4535, 20, 30, 25, 3, -29 }, // 0x79 'y'
{ 4610, 21, 31, 25, 2, -30 }, // 0x7A 'z'
{ 4692, 8, 21, 11, 1, -20 }, // 0x7B '{'
{ 4713, 8, 21, 11, 1, -20 }, // 0x7C '|'
{ 4734, 8, 21, 11, 1, -20 }, // 0x7D '}'
{ 4755, 8, 21, 11, 1, -20 } }; // 0x7E '~'
const GFXfont DSEG7Classic_BoldItalic16pt7b PROGMEM = {
(uint8_t *)DSEG7Classic_BoldItalic16pt7bBitmaps,
(GFXglyph *)DSEG7Classic_BoldItalic16pt7bGlyphs,
0x20, 0x7E, 34 };
// Approx. 5448 bytes

View File

@@ -1,737 +0,0 @@
const uint8_t DSEG7Classic_BoldItalic20pt7bBitmaps[] PROGMEM = {
0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80,
0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80,
0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0,
0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80,
0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80,
0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0,
0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80,
0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x7F, 0xF0, 0x3F, 0xFF, 0x1F, 0xFF, 0xEF, 0xFF, 0xFD, 0xFF, 0xFE,
0x3F, 0xFF, 0x00, 0x67, 0xBF, 0xF7, 0x00, 0xFF, 0xE0, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x7F, 0xF0, 0x03, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xF0, 0x2F,
0xFF, 0xFD, 0x8E, 0xFF, 0xFF, 0x71, 0xEF, 0xFF, 0xDE, 0x3E, 0x00, 0x07,
0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xE0,
0x00, 0x7C, 0x78, 0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3E,
0x7C, 0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00,
0x07, 0xC7, 0x80, 0x00, 0x78, 0xE0, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03,
0x80, 0x00, 0x1C, 0x78, 0x00, 0x07, 0x8F, 0x00, 0x01, 0xF3, 0xE0, 0x00,
0x3E, 0x7C, 0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00, 0x1E, 0x3E,
0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03,
0xE3, 0xE0, 0x00, 0x7C, 0x7C, 0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF1, 0xEF,
0xFF, 0xDE, 0x77, 0xFF, 0xFD, 0xC5, 0xFF, 0xFF, 0x90, 0x7F, 0xFF, 0xF8,
0x07, 0xFF, 0xFF, 0x00, 0x06, 0x1C, 0x79, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E,
0x7C, 0xF9, 0xF3, 0xCF, 0x9F, 0x1E, 0x1C, 0x00, 0x71, 0xE7, 0xCF, 0x9F,
0x3C, 0x79, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0x78, 0x70, 0x40, 0x03,
0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFD, 0x80, 0xFF, 0xFF,
0x70, 0x0F, 0xFF, 0xDE, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00,
0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F,
0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00,
0x00, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x3F, 0xFF, 0x78,
0x0F, 0xFF, 0xF7, 0x03, 0xFF, 0xFF, 0x03, 0xBF, 0xFF, 0xC0, 0x7B, 0xFF,
0xF0, 0x0F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F,
0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00,
0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x0F, 0x00, 0x00, 0x01, 0xEF, 0xFF, 0xC0, 0x77, 0xFF, 0xFC,
0x05, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0x00, 0x0F,
0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0x60, 0xFF, 0xFF, 0x70,
0x3F, 0xFF, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1F,
0x00, 0x00, 0x0F, 0x80, 0x00, 0x07, 0xC0, 0x00, 0x03, 0xE0, 0x00, 0x01,
0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00,
0x3E, 0x00, 0x00, 0x1F, 0x03, 0xFF, 0xF7, 0x83, 0xFF, 0xFD, 0xC3, 0xFF,
0xFF, 0x00, 0xFF, 0xFF, 0x70, 0x3F, 0xFF, 0x78, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x3E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x80,
0x00, 0x07, 0xC0, 0x00, 0x03, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8,
0x00, 0x00, 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1F, 0x03, 0xFF, 0xF7,
0x87, 0xFF, 0xFD, 0xC7, 0xFF, 0xFE, 0x47, 0xFF, 0xFF, 0x81, 0xFF, 0xFF,
0xC0, 0x20, 0x00, 0x01, 0xB8, 0x00, 0x01, 0xDE, 0x00, 0x01, 0xEF, 0x80,
0x01, 0xF7, 0xC0, 0x00, 0xFB, 0xE0, 0x00, 0x7D, 0xF0, 0x00, 0x3E, 0xF8,
0x00, 0x1F, 0x78, 0x00, 0x0F, 0xBC, 0x00, 0x07, 0xFE, 0x00, 0x03, 0xFF,
0x00, 0x01, 0xFF, 0x80, 0x00, 0xF7, 0xC0, 0x00, 0xFB, 0xE0, 0x00, 0x7D,
0xEF, 0xFF, 0xDE, 0xEF, 0xFF, 0xF7, 0x0F, 0xFF, 0xFC, 0x03, 0xFF, 0xFD,
0xC0, 0xFF, 0xFD, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00,
0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x00, 0x00,
0x0F, 0x80, 0x00, 0x07, 0xC0, 0x00, 0x03, 0xE0, 0x00, 0x01, 0xF0, 0x00,
0x00, 0xF8, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0x00,
0x00, 0x01, 0x00, 0x0F, 0xFF, 0xFE, 0x1F, 0xFF, 0xFE, 0x2F, 0xFF, 0xFC,
0x77, 0xFF, 0xF8, 0x7B, 0xFF, 0xF0, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00,
0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00,
0x78, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00,
0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF7, 0xFF, 0xE0, 0xEF, 0xFF, 0xF0,
0x1F, 0xFF, 0xF8, 0x0F, 0xFF, 0xF7, 0x07, 0xFF, 0xEF, 0x00, 0x00, 0x1F,
0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E,
0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E,
0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x0F, 0xFF, 0xDE,
0x3F, 0xFF, 0xEE, 0x7F, 0xFF, 0xE4, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xF0,
0x03, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xE0, 0xBF, 0xFF, 0xF0, 0x77, 0xFF,
0xF8, 0x1E, 0xFF, 0xFC, 0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00,
0x78, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x03, 0xE0, 0x00,
0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x7F, 0xFE, 0x03, 0xBF,
0xFF, 0xC0, 0x1F, 0xFF, 0xF8, 0x3B, 0xFF, 0xFD, 0xCF, 0x7F, 0xFE, 0xF3,
0xC0, 0x00, 0x7D, 0xF0, 0x00, 0x1F, 0x7C, 0x00, 0x07, 0xDF, 0x00, 0x01,
0xE7, 0xC0, 0x00, 0x79, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F, 0x00,
0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9E,
0x00, 0x03, 0xE7, 0xBF, 0xFF, 0x7B, 0xBF, 0xFF, 0xEE, 0x5F, 0xFF, 0xF9,
0x0F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFE, 0x0F, 0xFF,
0xFF, 0x0B, 0xFF, 0xFF, 0x6E, 0xFF, 0xFF, 0x77, 0xBF, 0xFF, 0x7B, 0xE0,
0x00, 0x7D, 0xF0, 0x00, 0x3E, 0xF8, 0x00, 0x1F, 0x7C, 0x00, 0x0F, 0xBE,
0x00, 0x07, 0xDE, 0x00, 0x03, 0xEF, 0x00, 0x01, 0xFF, 0x80, 0x00, 0xFF,
0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x3D, 0xF0, 0x00, 0x3E, 0xF8, 0x00, 0x1F,
0x78, 0x00, 0x07, 0xB8, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x70, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00,
0x1F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0xC0, 0x00,
0x03, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x3E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0x80, 0x00, 0x01, 0xC0,
0x00, 0x00, 0x40, 0x03, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xF0, 0x2F, 0xFF,
0xFD, 0x8E, 0xFF, 0xFF, 0x71, 0xEF, 0xFF, 0xDE, 0x3E, 0x00, 0x07, 0xC7,
0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xE0, 0x00,
0x7C, 0x78, 0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3E, 0x7C,
0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07,
0xC7, 0xBF, 0xFF, 0x78, 0xEF, 0xFF, 0xF7, 0x03, 0xFF, 0xFF, 0x03, 0xBF,
0xFF, 0xDC, 0x7B, 0xFF, 0xF7, 0x8F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3E,
0x7C, 0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00, 0x1E, 0x3E, 0x00,
0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3,
0xE0, 0x00, 0x7C, 0x7C, 0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF1, 0xEF, 0xFF,
0xDE, 0x77, 0xFF, 0xFD, 0xC5, 0xFF, 0xFF, 0x90, 0x7F, 0xFF, 0xF8, 0x07,
0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0x0B, 0xFF, 0xFF,
0x6E, 0xFF, 0xFF, 0x77, 0xBF, 0xFF, 0x7B, 0xE0, 0x00, 0x7D, 0xF0, 0x00,
0x3E, 0xF8, 0x00, 0x1F, 0x7C, 0x00, 0x0F, 0xBE, 0x00, 0x07, 0xDE, 0x00,
0x03, 0xEF, 0x00, 0x01, 0xFF, 0x80, 0x00, 0xFF, 0xC0, 0x00, 0x7F, 0xE0,
0x00, 0x3D, 0xF0, 0x00, 0x3E, 0xF8, 0x00, 0x1F, 0x7B, 0xFF, 0xF7, 0xBB,
0xFF, 0xFD, 0xC3, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x70, 0x3F, 0xFF, 0x78,
0x00, 0x00, 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F,
0x00, 0x00, 0x07, 0x80, 0x00, 0x07, 0xC0, 0x00, 0x03, 0xE0, 0x00, 0x01,
0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00,
0x1F, 0x03, 0xFF, 0xF7, 0x87, 0xFF, 0xFD, 0xC7, 0xFF, 0xFE, 0x47, 0xFF,
0xFF, 0x81, 0xFF, 0xFF, 0xC0, 0x39, 0xF7, 0xCE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xF3, 0xEF, 0xBC, 0xFF, 0xE0, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80,
0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80,
0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF,
0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80,
0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80,
0x7F, 0xF0, 0x03, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xF0, 0x2F, 0xFF, 0xFD,
0x8E, 0xFF, 0xFF, 0x71, 0xEF, 0xFF, 0xDE, 0x3E, 0x00, 0x07, 0xC7, 0xC0,
0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xE0, 0x00, 0x7C,
0x78, 0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3E, 0x7C, 0x00,
0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7,
0xBF, 0xFF, 0x78, 0xEF, 0xFF, 0xF7, 0x03, 0xFF, 0xFF, 0x03, 0xBF, 0xFF,
0xDC, 0x7B, 0xFF, 0xF7, 0x8F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3E, 0x7C,
0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00, 0x1E, 0x3E, 0x00, 0x07,
0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xE0,
0x00, 0x7C, 0x7C, 0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF1, 0xE0, 0x00, 0x1E,
0x70, 0x00, 0x01, 0xC4, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x07, 0x00,
0x00, 0x01, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07,
0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1E, 0x00, 0x00,
0x07, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00,
0x00, 0x0F, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF7, 0xFF, 0xE0, 0x3B,
0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0x83, 0xBF, 0xFF, 0xDC, 0xF7, 0xFF, 0xEF,
0x3C, 0x00, 0x07, 0xDF, 0x00, 0x01, 0xF7, 0xC0, 0x00, 0x7D, 0xF0, 0x00,
0x1E, 0x7C, 0x00, 0x07, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xF0,
0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9,
0xE0, 0x00, 0x3E, 0x7B, 0xFF, 0xF7, 0xBB, 0xFF, 0xFE, 0xE5, 0xFF, 0xFF,
0x90, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xF8, 0x07,
0xFF, 0xF8, 0x1F, 0xFF, 0xF9, 0xDF, 0xFF, 0xE3, 0xDF, 0xFF, 0x87, 0x80,
0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00,
0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00,
0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF7, 0xFF, 0xE3,
0xBF, 0xFF, 0xE2, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0x80,
0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x07, 0x80, 0x00,
0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8,
0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00,
0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x0F, 0x80,
0x00, 0x01, 0xF0, 0x0F, 0xFF, 0xDE, 0x03, 0xFF, 0xFD, 0xC0, 0xFF, 0xFF,
0xC0, 0xEF, 0xFF, 0xF7, 0x1E, 0xFF, 0xFD, 0xE3, 0xC0, 0x00, 0x7C, 0xF8,
0x00, 0x0F, 0x9F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3C, 0x7C, 0x00, 0x07,
0x8F, 0x80, 0x01, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xC0,
0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xC0, 0x00, 0x7C,
0x7B, 0xFF, 0xF7, 0x9D, 0xFF, 0xFF, 0x71, 0x7F, 0xFF, 0xE4, 0x1F, 0xFF,
0xFE, 0x01, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xE0,
0xBF, 0xFF, 0xF0, 0x77, 0xFF, 0xF8, 0x1E, 0xFF, 0xFC, 0x07, 0xC0, 0x00,
0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0,
0x00, 0x01, 0xE0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F,
0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00,
0x0F, 0x7F, 0xFE, 0x03, 0xBF, 0xFF, 0xC0, 0x1F, 0xFF, 0xF8, 0x3B, 0xFF,
0xFC, 0x0F, 0x7F, 0xFE, 0x03, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00,
0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00,
0x00, 0x7C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0xBF, 0xFF, 0x03, 0xBF,
0xFF, 0xE0, 0x5F, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xC0,
0x03, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xE0, 0xBF, 0xFF, 0xF0, 0x77, 0xFF,
0xF8, 0x1E, 0xFF, 0xFC, 0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00,
0x78, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x03, 0xE0, 0x00,
0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x7F, 0xFE, 0x03, 0xBF,
0xFF, 0xC0, 0x1F, 0xFF, 0xF8, 0x3B, 0xFF, 0xFC, 0x0F, 0x7F, 0xFE, 0x03,
0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00,
0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00,
0x00, 0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1E,
0x00, 0x00, 0x07, 0x80, 0x00, 0x03, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00,
0x00, 0x03, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xE0, 0xBF, 0xFF, 0xF0, 0x77,
0xFF, 0xF8, 0x1E, 0xFF, 0xFC, 0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00,
0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xE0, 0x00,
0x00, 0x78, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x03, 0xE0,
0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x03,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0xCF, 0x00, 0x00,
0xF3, 0xC0, 0x00, 0x7D, 0xF0, 0x00, 0x1F, 0x7C, 0x00, 0x07, 0xDF, 0x00,
0x01, 0xE7, 0xC0, 0x00, 0x79, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F,
0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F,
0x9E, 0x00, 0x03, 0xE7, 0xBF, 0xFF, 0x7B, 0xBF, 0xFF, 0xEE, 0x5F, 0xFF,
0xF9, 0x0F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xC0, 0x08, 0x00, 0x00, 0x07,
0x00, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00,
0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1E, 0x00,
0x00, 0x07, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E,
0x00, 0x00, 0x0F, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF7, 0xFF, 0xE0,
0x3B, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0x83, 0xBF, 0xFF, 0xDC, 0xF7, 0xFF,
0xEF, 0x3C, 0x00, 0x07, 0xDF, 0x00, 0x01, 0xF7, 0xC0, 0x00, 0x7D, 0xF0,
0x00, 0x1E, 0x7C, 0x00, 0x07, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9,
0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00,
0xF9, 0xE0, 0x00, 0x3E, 0x78, 0x00, 0x07, 0xB8, 0x00, 0x00, 0xE4, 0x00,
0x00, 0x10, 0x1C, 0xF7, 0xDF, 0x7D, 0xE7, 0xBE, 0xFB, 0xEF, 0xBE, 0xFB,
0xE7, 0x8E, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1C, 0x00, 0x00,
0x07, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0,
0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00,
0x7C, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3C, 0x00,
0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x01,
0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x07, 0x1E, 0x00, 0x01, 0xE3, 0xC0,
0x00, 0x7C, 0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3C,
0x7C, 0x00, 0x07, 0x8F, 0x80, 0x01, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00,
0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3,
0xC0, 0x00, 0x7C, 0x7B, 0xFF, 0xF7, 0x9D, 0xFF, 0xFF, 0x71, 0x7F, 0xFF,
0xE4, 0x1F, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x81,
0xFF, 0xFF, 0xE0, 0xBF, 0xFF, 0xF0, 0x77, 0xFF, 0xF8, 0x1E, 0xFF, 0xFC,
0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00,
0x00, 0x07, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3E,
0x00, 0x00, 0x0F, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00,
0x3E, 0x00, 0x00, 0x0F, 0x7F, 0xFE, 0x03, 0xBF, 0xFF, 0xC0, 0x1F, 0xFF,
0xF8, 0x3B, 0xFF, 0xFD, 0xCF, 0x7F, 0xFE, 0xF3, 0xC0, 0x00, 0x7D, 0xF0,
0x00, 0x1F, 0x7C, 0x00, 0x07, 0xDF, 0x00, 0x01, 0xE7, 0xC0, 0x00, 0x79,
0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00,
0xF9, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9E, 0x00, 0x03, 0xE7, 0x80,
0x00, 0x7B, 0x80, 0x00, 0x0E, 0x40, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00,
0x38, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03,
0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1E, 0x00, 0x00, 0x3C,
0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0,
0x00, 0x0F, 0x80, 0x00, 0x1E, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x80, 0x00,
0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01,
0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F,
0x00, 0x00, 0x3C, 0x00, 0x00, 0x7B, 0xFF, 0xF1, 0xDF, 0xFF, 0xF1, 0x7F,
0xFF, 0xE1, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80,
0xFF, 0xFF, 0xF0, 0x2F, 0xFF, 0xFD, 0x8E, 0xFF, 0xFF, 0x71, 0xEF, 0xFF,
0xDE, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F,
0x00, 0x03, 0xE3, 0xE0, 0x00, 0x7C, 0x78, 0x00, 0x0F, 0x8F, 0x00, 0x01,
0xF3, 0xE0, 0x00, 0x3E, 0x7C, 0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0,
0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7, 0x80, 0x00, 0x78, 0xE0, 0x00, 0x07,
0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x1C, 0x78, 0x00, 0x07, 0x8F, 0x00,
0x01, 0xF3, 0xE0, 0x00, 0x3E, 0x7C, 0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1,
0xF0, 0x00, 0x1E, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00,
0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xE0, 0x00, 0x7C, 0x7C, 0x00, 0x0F, 0x8F,
0x00, 0x01, 0xF1, 0xE0, 0x00, 0x1E, 0x70, 0x00, 0x01, 0xC4, 0x00, 0x00,
0x10, 0x01, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xE0, 0xEF,
0xFF, 0xF7, 0x3D, 0xFF, 0xFB, 0xCF, 0x00, 0x01, 0xF7, 0xC0, 0x00, 0x7D,
0xF0, 0x00, 0x1F, 0x7C, 0x00, 0x07, 0x9F, 0x00, 0x01, 0xE7, 0xC0, 0x00,
0xF9, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F, 0x00, 0x03, 0xE7, 0xC0,
0x00, 0xF9, 0xF0, 0x00, 0x3E, 0x78, 0x00, 0x0F, 0x9E, 0x00, 0x01, 0xEE,
0x00, 0x00, 0x39, 0x00, 0x00, 0x04, 0x01, 0xFF, 0xF8, 0x00, 0xFF, 0xFF,
0x00, 0x7F, 0xFF, 0xE0, 0xEF, 0xFF, 0xF7, 0x3D, 0xFF, 0xFB, 0xCF, 0x00,
0x01, 0xF7, 0xC0, 0x00, 0x7D, 0xF0, 0x00, 0x1F, 0x7C, 0x00, 0x07, 0x9F,
0x00, 0x01, 0xE7, 0xC0, 0x00, 0xF9, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F,
0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xF0, 0x00, 0x3E, 0x78, 0x00,
0x0F, 0x9E, 0xFF, 0xFD, 0xEE, 0xFF, 0xFF, 0xB9, 0x7F, 0xFF, 0xE4, 0x3F,
0xFF, 0xFC, 0x07, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0xFF, 0xFF,
0xF0, 0x2F, 0xFF, 0xFD, 0x8E, 0xFF, 0xFF, 0x71, 0xEF, 0xFF, 0xDE, 0x3E,
0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03,
0xE3, 0xE0, 0x00, 0x7C, 0x78, 0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF3, 0xE0,
0x00, 0x3E, 0x7C, 0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00, 0x3E,
0x3E, 0x00, 0x07, 0xC7, 0xBF, 0xFF, 0x78, 0xEF, 0xFF, 0xF7, 0x03, 0xFF,
0xFF, 0x03, 0xBF, 0xFF, 0xC0, 0x7B, 0xFF, 0xF0, 0x0F, 0x00, 0x00, 0x03,
0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00,
0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F,
0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x00, 0x00,
0x01, 0xE0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0F,
0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0x0B, 0xFF, 0xFF, 0x6E, 0xFF, 0xFF, 0x77,
0xBF, 0xFF, 0x7B, 0xE0, 0x00, 0x7D, 0xF0, 0x00, 0x3E, 0xF8, 0x00, 0x1F,
0x7C, 0x00, 0x0F, 0xBE, 0x00, 0x07, 0xDE, 0x00, 0x03, 0xEF, 0x00, 0x01,
0xFF, 0x80, 0x00, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x3D, 0xF0, 0x00,
0x3E, 0xF8, 0x00, 0x1F, 0x7B, 0xFF, 0xF7, 0xBB, 0xFF, 0xFD, 0xC3, 0xFF,
0xFF, 0x00, 0xFF, 0xFF, 0x70, 0x3F, 0xFF, 0x78, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x3E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x80,
0x00, 0x07, 0xC0, 0x00, 0x03, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8,
0x00, 0x00, 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07,
0x80, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x40, 0x01, 0xFF, 0xF8, 0x07, 0xFF,
0xF8, 0x1F, 0xFF, 0xF9, 0xDF, 0xFF, 0xE3, 0xDF, 0xFF, 0x87, 0x80, 0x00,
0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01,
0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F,
0x00, 0x00, 0x3E, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF0, 0x00, 0x03, 0x80,
0x00, 0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x70, 0x00, 0x00, 0x78,
0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8,
0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8,
0x00, 0x00, 0xF7, 0xFF, 0xE0, 0xEF, 0xFF, 0xF0, 0x1F, 0xFF, 0xF8, 0x0F,
0xFF, 0xF7, 0x07, 0xFF, 0xEF, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00,
0x00, 0x1F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00,
0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00,
0x00, 0x3E, 0x00, 0x00, 0x3E, 0x0F, 0xFF, 0xDE, 0x3F, 0xFF, 0xEE, 0x7F,
0xFF, 0xE4, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xF0, 0x08, 0x00, 0x00, 0x38,
0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0,
0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1E, 0x00, 0x00, 0x3C, 0x00,
0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00,
0x0F, 0x80, 0x00, 0x1E, 0xFF, 0xFC, 0x3B, 0xFF, 0xFC, 0x0F, 0xFF, 0xFC,
0xEF, 0xFF, 0xF1, 0xEF, 0xFF, 0xC3, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F,
0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0,
0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00,
0x00, 0x3C, 0x00, 0x00, 0x7B, 0xFF, 0xF1, 0xDF, 0xFF, 0xF1, 0x7F, 0xFF,
0xE1, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xC0, 0x38, 0x00, 0x01, 0xCF, 0x00,
0x00, 0xF3, 0xC0, 0x00, 0x7D, 0xF0, 0x00, 0x1F, 0x7C, 0x00, 0x07, 0xDF,
0x00, 0x01, 0xE7, 0xC0, 0x00, 0x79, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F,
0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xF0, 0x00, 0x3E, 0x7C, 0x00,
0x0F, 0x9E, 0x00, 0x03, 0xE7, 0xBF, 0xFF, 0x7B, 0xBF, 0xFF, 0xEE, 0x5F,
0xFF, 0xF9, 0x0F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xC0, 0x08, 0x00, 0x00,
0x63, 0x80, 0x00, 0x1C, 0x78, 0x00, 0x07, 0x8F, 0x80, 0x01, 0xF1, 0xF0,
0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F,
0x1E, 0x00, 0x03, 0xE3, 0xC0, 0x00, 0x7C, 0xF8, 0x00, 0x0F, 0x9F, 0x00,
0x01, 0xF3, 0xE0, 0x00, 0x3C, 0x7C, 0x00, 0x0F, 0x8F, 0x80, 0x01, 0xF1,
0xE0, 0x00, 0x1E, 0x38, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00,
0x07, 0x1E, 0x00, 0x01, 0xE3, 0xC0, 0x00, 0x7C, 0xF8, 0x00, 0x0F, 0x9F,
0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3C, 0x7C, 0x00, 0x07, 0x8F, 0x80, 0x01,
0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8,
0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xC0, 0x00, 0x7C, 0x7B, 0xFF, 0xF7,
0x9D, 0xFF, 0xFF, 0x71, 0x7F, 0xFF, 0xE4, 0x1F, 0xFF, 0xFE, 0x01, 0xFF,
0xFF, 0xC0, 0x08, 0x00, 0x00, 0x63, 0x80, 0x00, 0x1C, 0x78, 0x00, 0x07,
0x8F, 0x80, 0x01, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xC0,
0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1E, 0x00, 0x03, 0xE3, 0xC0, 0x00, 0x7C,
0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3C, 0x7C, 0x00,
0x0F, 0x8F, 0x80, 0x01, 0xF1, 0xEF, 0xFF, 0xDE, 0x3B, 0xFF, 0xFD, 0xC0,
0xFF, 0xFF, 0xC0, 0xEF, 0xFF, 0xF7, 0x1E, 0xFF, 0xFD, 0xE3, 0xC0, 0x00,
0x7C, 0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3C, 0x7C,
0x00, 0x07, 0x8F, 0x80, 0x01, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07,
0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xC0,
0x00, 0x7C, 0x7B, 0xFF, 0xF7, 0x9D, 0xFF, 0xFF, 0x71, 0x7F, 0xFF, 0xE4,
0x1F, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xC0, 0x08, 0x00, 0x00, 0x63, 0x80,
0x00, 0x1C, 0x78, 0x00, 0x07, 0x8F, 0x80, 0x01, 0xF1, 0xF0, 0x00, 0x3E,
0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1E, 0x00,
0x03, 0xE3, 0xC0, 0x00, 0x7C, 0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x01, 0xF3,
0xE0, 0x00, 0x3C, 0x7C, 0x00, 0x0F, 0x8F, 0x80, 0x01, 0xF1, 0xEF, 0xFF,
0xDE, 0x3B, 0xFF, 0xFD, 0xC0, 0xFF, 0xFF, 0xC0, 0xEF, 0xFF, 0xF7, 0x1E,
0xFF, 0xFD, 0xE3, 0xC0, 0x00, 0x7C, 0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x01,
0xF3, 0xE0, 0x00, 0x3C, 0x7C, 0x00, 0x07, 0x8F, 0x80, 0x01, 0xF1, 0xF0,
0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F,
0x1F, 0x00, 0x03, 0xE3, 0xC0, 0x00, 0x7C, 0x78, 0x00, 0x07, 0x9C, 0x00,
0x00, 0x71, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x01, 0xB8, 0x00, 0x01,
0xDE, 0x00, 0x01, 0xEF, 0x80, 0x01, 0xF7, 0xC0, 0x00, 0xFB, 0xE0, 0x00,
0x7D, 0xF0, 0x00, 0x3E, 0xF8, 0x00, 0x1F, 0x78, 0x00, 0x0F, 0xBC, 0x00,
0x07, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x00, 0xF7, 0xC0,
0x00, 0xFB, 0xE0, 0x00, 0x7D, 0xEF, 0xFF, 0xDE, 0xEF, 0xFF, 0xF7, 0x0F,
0xFF, 0xFC, 0x03, 0xFF, 0xFD, 0xC0, 0xFF, 0xFD, 0xE0, 0x00, 0x01, 0xF0,
0x00, 0x00, 0xF8, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1E,
0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x07, 0xC0, 0x00, 0x03,
0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x7C, 0x0F, 0xFF,
0xDE, 0x1F, 0xFF, 0xF7, 0x1F, 0xFF, 0xF9, 0x1F, 0xFF, 0xFE, 0x07, 0xFF,
0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFD,
0x80, 0xFF, 0xFF, 0x70, 0x0F, 0xFF, 0xDE, 0x00, 0x00, 0x07, 0xC0, 0x00,
0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00,
0x07, 0xC0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0,
0x00, 0x00, 0x78, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00,
0x00, 0x78, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00,
0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0,
0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x01, 0xEF, 0xFF, 0xC0,
0x77, 0xFF, 0xFC, 0x05, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xF8, 0x07, 0xFF,
0xFF, 0x00, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF,
0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80,
0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80,
0x7F, 0xF0, 0x0F, 0xFF, 0xC1, 0xFF, 0xFF, 0x1F, 0xFF, 0xF9, 0xFF, 0xFF,
0xE7, 0xFF, 0xFF, 0x00, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F,
0xF0, 0x03, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xF0, 0x2F, 0xFF, 0xFD, 0x8E,
0xFF, 0xFF, 0x71, 0xEF, 0xFF, 0xDE, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00,
0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xE0, 0x00, 0x7C, 0x78,
0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3E, 0x7C, 0x00, 0x07,
0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xBF,
0xFF, 0x78, 0xEF, 0xFF, 0xF7, 0x03, 0xFF, 0xFF, 0x03, 0xBF, 0xFF, 0xDC,
0x7B, 0xFF, 0xF7, 0x8F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3E, 0x7C, 0x00,
0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00, 0x1E, 0x3E, 0x00, 0x07, 0xC7,
0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xE0, 0x00,
0x7C, 0x7C, 0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF1, 0xE0, 0x00, 0x1E, 0x70,
0x00, 0x01, 0xC4, 0x00, 0x00, 0x10, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00,
0x01, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0,
0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07,
0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00,
0x0F, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF7, 0xFF, 0xE0, 0x3B, 0xFF,
0xFC, 0x01, 0xFF, 0xFF, 0x83, 0xBF, 0xFF, 0xDC, 0xF7, 0xFF, 0xEF, 0x3C,
0x00, 0x07, 0xDF, 0x00, 0x01, 0xF7, 0xC0, 0x00, 0x7D, 0xF0, 0x00, 0x1E,
0x7C, 0x00, 0x07, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xF0, 0x00,
0x3E, 0x7C, 0x00, 0x0F, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xE0,
0x00, 0x3E, 0x7B, 0xFF, 0xF7, 0xBB, 0xFF, 0xFE, 0xE5, 0xFF, 0xFF, 0x90,
0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFC, 0x00, 0x01, 0xFF, 0xF8, 0x07, 0xFF,
0xF8, 0x1F, 0xFF, 0xF9, 0xDF, 0xFF, 0xE3, 0xDF, 0xFF, 0x87, 0x80, 0x00,
0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01,
0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F,
0x00, 0x00, 0x3E, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF7, 0xFF, 0xE3, 0xBF,
0xFF, 0xE2, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0x80, 0x00,
0x00, 0x00, 0x60, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x07, 0x80, 0x00, 0x01,
0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00,
0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F,
0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x0F, 0x80, 0x00,
0x01, 0xF0, 0x0F, 0xFF, 0xDE, 0x03, 0xFF, 0xFD, 0xC0, 0xFF, 0xFF, 0xC0,
0xEF, 0xFF, 0xF7, 0x1E, 0xFF, 0xFD, 0xE3, 0xC0, 0x00, 0x7C, 0xF8, 0x00,
0x0F, 0x9F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3C, 0x7C, 0x00, 0x07, 0x8F,
0x80, 0x01, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00,
0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xC0, 0x00, 0x7C, 0x7B,
0xFF, 0xF7, 0x9D, 0xFF, 0xFF, 0x71, 0x7F, 0xFF, 0xE4, 0x1F, 0xFF, 0xFE,
0x01, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xE0, 0xBF,
0xFF, 0xF0, 0x77, 0xFF, 0xF8, 0x1E, 0xFF, 0xFC, 0x07, 0xC0, 0x00, 0x01,
0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0, 0x00,
0x01, 0xE0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x80,
0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F,
0x7F, 0xFE, 0x03, 0xBF, 0xFF, 0xC0, 0x1F, 0xFF, 0xF8, 0x3B, 0xFF, 0xFC,
0x0F, 0x7F, 0xFE, 0x03, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00,
0x7C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x07, 0xBF, 0xFF, 0x03, 0xBF, 0xFF,
0xE0, 0x5F, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xC0, 0x03,
0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xE0, 0xBF, 0xFF, 0xF0, 0x77, 0xFF, 0xF8,
0x1E, 0xFF, 0xFC, 0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x78,
0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00,
0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x7F, 0xFE, 0x03, 0xBF, 0xFF,
0xC0, 0x1F, 0xFF, 0xF8, 0x3B, 0xFF, 0xFC, 0x0F, 0x7F, 0xFE, 0x03, 0xC0,
0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07,
0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00,
0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1E, 0x00,
0x00, 0x07, 0x80, 0x00, 0x03, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
0x03, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xE0, 0xBF, 0xFF, 0xF0, 0x77, 0xFF,
0xF8, 0x1E, 0xFF, 0xFC, 0x07, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00,
0x78, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x03, 0xE0, 0x00,
0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x03, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0xCF, 0x00, 0x00, 0xF3,
0xC0, 0x00, 0x7D, 0xF0, 0x00, 0x1F, 0x7C, 0x00, 0x07, 0xDF, 0x00, 0x01,
0xE7, 0xC0, 0x00, 0x79, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F, 0x00,
0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9E,
0x00, 0x03, 0xE7, 0xBF, 0xFF, 0x7B, 0xBF, 0xFF, 0xEE, 0x5F, 0xFF, 0xF9,
0x0F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xC0, 0x08, 0x00, 0x00, 0x07, 0x00,
0x00, 0x01, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07,
0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1E, 0x00, 0x00,
0x07, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E, 0x00,
0x00, 0x0F, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF7, 0xFF, 0xE0, 0x3B,
0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0x83, 0xBF, 0xFF, 0xDC, 0xF7, 0xFF, 0xEF,
0x3C, 0x00, 0x07, 0xDF, 0x00, 0x01, 0xF7, 0xC0, 0x00, 0x7D, 0xF0, 0x00,
0x1E, 0x7C, 0x00, 0x07, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xF0,
0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9,
0xE0, 0x00, 0x3E, 0x78, 0x00, 0x07, 0xB8, 0x00, 0x00, 0xE4, 0x00, 0x00,
0x10, 0x1C, 0xF7, 0xDF, 0x7D, 0xE7, 0xBE, 0xFB, 0xEF, 0xBE, 0xFB, 0xE7,
0x8E, 0x10, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x07,
0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00,
0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C,
0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3C, 0x00, 0x00,
0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x01, 0xC0,
0x00, 0x00, 0x00, 0xE0, 0x00, 0x07, 0x1E, 0x00, 0x01, 0xE3, 0xC0, 0x00,
0x7C, 0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3C, 0x7C,
0x00, 0x07, 0x8F, 0x80, 0x01, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07,
0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xC0,
0x00, 0x7C, 0x7B, 0xFF, 0xF7, 0x9D, 0xFF, 0xFF, 0x71, 0x7F, 0xFF, 0xE4,
0x1F, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x81, 0xFF,
0xFF, 0xE0, 0xBF, 0xFF, 0xF0, 0x77, 0xFF, 0xF8, 0x1E, 0xFF, 0xFC, 0x07,
0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x1F, 0x00, 0x00,
0x07, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3E, 0x00,
0x00, 0x0F, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x3E,
0x00, 0x00, 0x0F, 0x7F, 0xFE, 0x03, 0xBF, 0xFF, 0xC0, 0x1F, 0xFF, 0xF8,
0x3B, 0xFF, 0xFD, 0xCF, 0x7F, 0xFE, 0xF3, 0xC0, 0x00, 0x7D, 0xF0, 0x00,
0x1F, 0x7C, 0x00, 0x07, 0xDF, 0x00, 0x01, 0xE7, 0xC0, 0x00, 0x79, 0xF0,
0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9,
0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9E, 0x00, 0x03, 0xE7, 0x80, 0x00,
0x7B, 0x80, 0x00, 0x0E, 0x40, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x38,
0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0,
0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1E, 0x00, 0x00, 0x3C, 0x00,
0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00,
0x0F, 0x80, 0x00, 0x1E, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
0xE0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F,
0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0,
0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00,
0x00, 0x3C, 0x00, 0x00, 0x7B, 0xFF, 0xF1, 0xDF, 0xFF, 0xF1, 0x7F, 0xFF,
0xE1, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0x80, 0xFF,
0xFF, 0xF0, 0x2F, 0xFF, 0xFD, 0x8E, 0xFF, 0xFF, 0x71, 0xEF, 0xFF, 0xDE,
0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00,
0x03, 0xE3, 0xE0, 0x00, 0x7C, 0x78, 0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF3,
0xE0, 0x00, 0x3E, 0x7C, 0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00,
0x3E, 0x3E, 0x00, 0x07, 0xC7, 0x80, 0x00, 0x78, 0xE0, 0x00, 0x07, 0x00,
0x00, 0x00, 0x03, 0x80, 0x00, 0x1C, 0x78, 0x00, 0x07, 0x8F, 0x00, 0x01,
0xF3, 0xE0, 0x00, 0x3E, 0x7C, 0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0,
0x00, 0x1E, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F,
0x1F, 0x00, 0x03, 0xE3, 0xE0, 0x00, 0x7C, 0x7C, 0x00, 0x0F, 0x8F, 0x00,
0x01, 0xF1, 0xE0, 0x00, 0x1E, 0x70, 0x00, 0x01, 0xC4, 0x00, 0x00, 0x10,
0x01, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xE0, 0xEF, 0xFF,
0xF7, 0x3D, 0xFF, 0xFB, 0xCF, 0x00, 0x01, 0xF7, 0xC0, 0x00, 0x7D, 0xF0,
0x00, 0x1F, 0x7C, 0x00, 0x07, 0x9F, 0x00, 0x01, 0xE7, 0xC0, 0x00, 0xF9,
0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F, 0x00, 0x03, 0xE7, 0xC0, 0x00,
0xF9, 0xF0, 0x00, 0x3E, 0x78, 0x00, 0x0F, 0x9E, 0x00, 0x01, 0xEE, 0x00,
0x00, 0x39, 0x00, 0x00, 0x04, 0x01, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0x00,
0x7F, 0xFF, 0xE0, 0xEF, 0xFF, 0xF7, 0x3D, 0xFF, 0xFB, 0xCF, 0x00, 0x01,
0xF7, 0xC0, 0x00, 0x7D, 0xF0, 0x00, 0x1F, 0x7C, 0x00, 0x07, 0x9F, 0x00,
0x01, 0xE7, 0xC0, 0x00, 0xF9, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F,
0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xF0, 0x00, 0x3E, 0x78, 0x00, 0x0F,
0x9E, 0xFF, 0xFD, 0xEE, 0xFF, 0xFF, 0xB9, 0x7F, 0xFF, 0xE4, 0x3F, 0xFF,
0xFC, 0x07, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xF0,
0x2F, 0xFF, 0xFD, 0x8E, 0xFF, 0xFF, 0x71, 0xEF, 0xFF, 0xDE, 0x3E, 0x00,
0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3,
0xE0, 0x00, 0x7C, 0x78, 0x00, 0x0F, 0x8F, 0x00, 0x01, 0xF3, 0xE0, 0x00,
0x3E, 0x7C, 0x00, 0x07, 0xCF, 0x80, 0x00, 0xF1, 0xF0, 0x00, 0x3E, 0x3E,
0x00, 0x07, 0xC7, 0xBF, 0xFF, 0x78, 0xEF, 0xFF, 0xF7, 0x03, 0xFF, 0xFF,
0x03, 0xBF, 0xFF, 0xC0, 0x7B, 0xFF, 0xF0, 0x0F, 0x00, 0x00, 0x03, 0xE0,
0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00,
0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00,
0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x01,
0xE0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x0F, 0xFF,
0xFE, 0x0F, 0xFF, 0xFF, 0x0B, 0xFF, 0xFF, 0x6E, 0xFF, 0xFF, 0x77, 0xBF,
0xFF, 0x7B, 0xE0, 0x00, 0x7D, 0xF0, 0x00, 0x3E, 0xF8, 0x00, 0x1F, 0x7C,
0x00, 0x0F, 0xBE, 0x00, 0x07, 0xDE, 0x00, 0x03, 0xEF, 0x00, 0x01, 0xFF,
0x80, 0x00, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x3D, 0xF0, 0x00, 0x3E,
0xF8, 0x00, 0x1F, 0x7B, 0xFF, 0xF7, 0xBB, 0xFF, 0xFD, 0xC3, 0xFF, 0xFF,
0x00, 0xFF, 0xFF, 0x70, 0x3F, 0xFF, 0x78, 0x00, 0x00, 0x7C, 0x00, 0x00,
0x3E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x80, 0x00,
0x07, 0xC0, 0x00, 0x03, 0xE0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00,
0x00, 0x7C, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x07, 0x80,
0x00, 0x01, 0xC0, 0x00, 0x00, 0x40, 0x01, 0xFF, 0xF8, 0x07, 0xFF, 0xF8,
0x1F, 0xFF, 0xF9, 0xDF, 0xFF, 0xE3, 0xDF, 0xFF, 0x87, 0x80, 0x00, 0x1F,
0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0,
0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00,
0x00, 0x3E, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF0, 0x00, 0x03, 0x80, 0x00,
0x02, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x70, 0x00, 0x00, 0x78, 0x00,
0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x7C, 0x00, 0x00, 0x78, 0x00, 0x00, 0x78, 0x00, 0x00, 0xF8, 0x00,
0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00,
0x00, 0xF7, 0xFF, 0xE0, 0xEF, 0xFF, 0xF0, 0x1F, 0xFF, 0xF8, 0x0F, 0xFF,
0xF7, 0x07, 0xFF, 0xEF, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0x00, 0x00,
0x1F, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00,
0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00,
0x3E, 0x00, 0x00, 0x3E, 0x0F, 0xFF, 0xDE, 0x3F, 0xFF, 0xEE, 0x7F, 0xFF,
0xE4, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xF0, 0x08, 0x00, 0x00, 0x38, 0x00,
0x00, 0x78, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00,
0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1E, 0x00, 0x00, 0x3C, 0x00, 0x00,
0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F,
0x80, 0x00, 0x1E, 0xFF, 0xFC, 0x3B, 0xFF, 0xFC, 0x0F, 0xFF, 0xFC, 0xEF,
0xFF, 0xF1, 0xEF, 0xFF, 0xC3, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00,
0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00,
0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x7B, 0xFF, 0xF1, 0xDF, 0xFF, 0xF1, 0x7F, 0xFF, 0xE1,
0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xC0, 0x38, 0x00, 0x01, 0xCF, 0x00, 0x00,
0xF3, 0xC0, 0x00, 0x7D, 0xF0, 0x00, 0x1F, 0x7C, 0x00, 0x07, 0xDF, 0x00,
0x01, 0xE7, 0xC0, 0x00, 0x79, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F, 0x9F,
0x00, 0x03, 0xE7, 0xC0, 0x00, 0xF9, 0xF0, 0x00, 0x3E, 0x7C, 0x00, 0x0F,
0x9E, 0x00, 0x03, 0xE7, 0xBF, 0xFF, 0x7B, 0xBF, 0xFF, 0xEE, 0x5F, 0xFF,
0xF9, 0x0F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xC0, 0x08, 0x00, 0x00, 0x63,
0x80, 0x00, 0x1C, 0x78, 0x00, 0x07, 0x8F, 0x80, 0x01, 0xF1, 0xF0, 0x00,
0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1E,
0x00, 0x03, 0xE3, 0xC0, 0x00, 0x7C, 0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x01,
0xF3, 0xE0, 0x00, 0x3C, 0x7C, 0x00, 0x0F, 0x8F, 0x80, 0x01, 0xF1, 0xE0,
0x00, 0x1E, 0x38, 0x00, 0x01, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x07,
0x1E, 0x00, 0x01, 0xE3, 0xC0, 0x00, 0x7C, 0xF8, 0x00, 0x0F, 0x9F, 0x00,
0x01, 0xF3, 0xE0, 0x00, 0x3C, 0x7C, 0x00, 0x07, 0x8F, 0x80, 0x01, 0xF1,
0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00,
0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xC0, 0x00, 0x7C, 0x7B, 0xFF, 0xF7, 0x9D,
0xFF, 0xFF, 0x71, 0x7F, 0xFF, 0xE4, 0x1F, 0xFF, 0xFE, 0x01, 0xFF, 0xFF,
0xC0, 0x08, 0x00, 0x00, 0x63, 0x80, 0x00, 0x1C, 0x78, 0x00, 0x07, 0x8F,
0x80, 0x01, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00,
0xF8, 0xF8, 0x00, 0x1F, 0x1E, 0x00, 0x03, 0xE3, 0xC0, 0x00, 0x7C, 0xF8,
0x00, 0x0F, 0x9F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3C, 0x7C, 0x00, 0x0F,
0x8F, 0x80, 0x01, 0xF1, 0xEF, 0xFF, 0xDE, 0x3B, 0xFF, 0xFD, 0xC0, 0xFF,
0xFF, 0xC0, 0xEF, 0xFF, 0xF7, 0x1E, 0xFF, 0xFD, 0xE3, 0xC0, 0x00, 0x7C,
0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x01, 0xF3, 0xE0, 0x00, 0x3C, 0x7C, 0x00,
0x07, 0x8F, 0x80, 0x01, 0xF1, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x07, 0xC7,
0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F, 0x00, 0x03, 0xE3, 0xC0, 0x00,
0x7C, 0x7B, 0xFF, 0xF7, 0x9D, 0xFF, 0xFF, 0x71, 0x7F, 0xFF, 0xE4, 0x1F,
0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xC0, 0x08, 0x00, 0x00, 0x63, 0x80, 0x00,
0x1C, 0x78, 0x00, 0x07, 0x8F, 0x80, 0x01, 0xF1, 0xF0, 0x00, 0x3E, 0x3E,
0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1E, 0x00, 0x03,
0xE3, 0xC0, 0x00, 0x7C, 0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x01, 0xF3, 0xE0,
0x00, 0x3C, 0x7C, 0x00, 0x0F, 0x8F, 0x80, 0x01, 0xF1, 0xEF, 0xFF, 0xDE,
0x3B, 0xFF, 0xFD, 0xC0, 0xFF, 0xFF, 0xC0, 0xEF, 0xFF, 0xF7, 0x1E, 0xFF,
0xFD, 0xE3, 0xC0, 0x00, 0x7C, 0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x01, 0xF3,
0xE0, 0x00, 0x3C, 0x7C, 0x00, 0x07, 0x8F, 0x80, 0x01, 0xF1, 0xF0, 0x00,
0x3E, 0x3E, 0x00, 0x07, 0xC7, 0xC0, 0x00, 0xF8, 0xF8, 0x00, 0x1F, 0x1F,
0x00, 0x03, 0xE3, 0xC0, 0x00, 0x7C, 0x78, 0x00, 0x07, 0x9C, 0x00, 0x00,
0x71, 0x00, 0x00, 0x04, 0x00, 0x20, 0x00, 0x01, 0xB8, 0x00, 0x01, 0xDE,
0x00, 0x01, 0xEF, 0x80, 0x01, 0xF7, 0xC0, 0x00, 0xFB, 0xE0, 0x00, 0x7D,
0xF0, 0x00, 0x3E, 0xF8, 0x00, 0x1F, 0x78, 0x00, 0x0F, 0xBC, 0x00, 0x07,
0xFE, 0x00, 0x03, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x00, 0xF7, 0xC0, 0x00,
0xFB, 0xE0, 0x00, 0x7D, 0xEF, 0xFF, 0xDE, 0xEF, 0xFF, 0xF7, 0x0F, 0xFF,
0xFC, 0x03, 0xFF, 0xFD, 0xC0, 0xFF, 0xFD, 0xE0, 0x00, 0x01, 0xF0, 0x00,
0x00, 0xF8, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1E, 0x00,
0x00, 0x1F, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x07, 0xC0, 0x00, 0x03, 0xE0,
0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x7C, 0x0F, 0xFF, 0xDE,
0x1F, 0xFF, 0xF7, 0x1F, 0xFF, 0xF9, 0x1F, 0xFF, 0xFE, 0x07, 0xFF, 0xFF,
0x00, 0x03, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFD, 0x80,
0xFF, 0xFF, 0x70, 0x0F, 0xFF, 0xDE, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00,
0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07,
0xC0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00,
0x00, 0x78, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00,
0x78, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x0F, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07,
0xC0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x03, 0xE0, 0x00,
0x00, 0x7C, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x01, 0xEF, 0xFF, 0xC0, 0x77,
0xFF, 0xFC, 0x05, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xF8, 0x07, 0xFF, 0xFF,
0x00, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80,
0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80,
0x60, 0x18, 0x06, 0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06,
0x01, 0x80, 0x7F, 0xF0, 0xFF, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x7F,
0xF0 };
const GFXglyph DSEG7Classic_BoldItalic20pt7bGlyphs[] PROGMEM = {
{ 0, 0, 0, 8, 0, 1 }, // 0x20 ' '
{ 0, 0, 0, 32, 0, 1 }, // 0x21 '!'
{ 0, 10, 26, 14, 1, -25 }, // 0x22 '"'
{ 33, 10, 26, 14, 1, -25 }, // 0x23 '#'
{ 66, 10, 26, 14, 1, -25 }, // 0x24 '$'
{ 99, 10, 26, 14, 1, -25 }, // 0x25 '%'
{ 132, 10, 26, 14, 1, -25 }, // 0x26 '&'
{ 165, 10, 26, 14, 1, -25 }, // 0x27 '''
{ 198, 10, 26, 14, 1, -25 }, // 0x28 '('
{ 231, 10, 26, 14, 1, -25 }, // 0x29 ')'
{ 264, 10, 26, 14, 1, -25 }, // 0x2A '*'
{ 297, 10, 26, 14, 1, -25 }, // 0x2B '+'
{ 330, 10, 26, 14, 1, -25 }, // 0x2C ','
{ 363, 18, 5, 32, 7, -21 }, // 0x2D '-'
{ 375, 5, 5, 0, -4, -4 }, // 0x2E '.'
{ 379, 10, 26, 14, 1, -25 }, // 0x2F '/'
{ 412, 27, 39, 32, 2, -38 }, // 0x30 '0'
{ 544, 7, 35, 32, 22, -36 }, // 0x31 '1'
{ 575, 27, 39, 32, 2, -38 }, // 0x32 '2'
{ 707, 25, 39, 32, 4, -38 }, // 0x33 '3'
{ 829, 25, 35, 32, 4, -36 }, // 0x34 '4'
{ 939, 24, 39, 32, 4, -38 }, // 0x35 '5'
{ 1056, 26, 39, 32, 2, -38 }, // 0x36 '6'
{ 1183, 25, 37, 32, 4, -38 }, // 0x37 '7'
{ 1299, 27, 39, 32, 2, -38 }, // 0x38 '8'
{ 1431, 25, 39, 32, 4, -38 }, // 0x39 '9'
{ 1553, 6, 20, 8, 1, -28 }, // 0x3A ':'
{ 1568, 10, 26, 14, 1, -25 }, // 0x3B ';'
{ 1601, 10, 26, 14, 1, -25 }, // 0x3C '<'
{ 1634, 10, 26, 14, 1, -25 }, // 0x3D '='
{ 1667, 10, 26, 14, 1, -25 }, // 0x3E '>'
{ 1700, 10, 26, 14, 1, -25 }, // 0x3F '?'
{ 1733, 10, 26, 14, 1, -25 }, // 0x40 '@'
{ 1766, 27, 37, 32, 2, -38 }, // 0x41 'A'
{ 1891, 26, 37, 32, 2, -36 }, // 0x42 'B'
{ 2012, 23, 22, 32, 2, -21 }, // 0x43 'C'
{ 2076, 27, 37, 32, 2, -36 }, // 0x44 'D'
{ 2201, 26, 39, 32, 2, -38 }, // 0x45 'E'
{ 2328, 26, 37, 32, 2, -38 }, // 0x46 'F'
{ 2449, 26, 39, 32, 2, -38 }, // 0x47 'G'
{ 2576, 26, 35, 32, 2, -36 }, // 0x48 'H'
{ 2690, 6, 17, 32, 22, -18 }, // 0x49 'I'
{ 2703, 27, 37, 32, 2, -36 }, // 0x4A 'J'
{ 2828, 26, 37, 32, 2, -38 }, // 0x4B 'K'
{ 2949, 23, 37, 32, 2, -36 }, // 0x4C 'L'
{ 3056, 27, 37, 32, 2, -38 }, // 0x4D 'M'
{ 3181, 26, 20, 32, 2, -21 }, // 0x4E 'N'
{ 3246, 26, 22, 32, 2, -21 }, // 0x4F 'O'
{ 3318, 27, 37, 32, 2, -38 }, // 0x50 'P'
{ 3443, 25, 37, 32, 4, -38 }, // 0x51 'Q'
{ 3559, 23, 20, 32, 2, -21 }, // 0x52 'R'
{ 3617, 24, 37, 32, 4, -36 }, // 0x53 'S'
{ 3728, 23, 37, 32, 2, -36 }, // 0x54 'T'
{ 3835, 26, 19, 32, 2, -18 }, // 0x55 'U'
{ 3897, 27, 37, 32, 2, -36 }, // 0x56 'V'
{ 4022, 27, 37, 32, 2, -36 }, // 0x57 'W'
{ 4147, 27, 35, 32, 2, -36 }, // 0x58 'X'
{ 4266, 25, 37, 32, 4, -36 }, // 0x59 'Y'
{ 4382, 27, 39, 32, 2, -38 }, // 0x5A 'Z'
{ 4514, 10, 26, 14, 1, -25 }, // 0x5B '['
{ 4547, 10, 26, 14, 1, -25 }, // 0x5C '\'
{ 4580, 10, 26, 14, 1, -25 }, // 0x5D ']'
{ 4613, 10, 26, 14, 1, -25 }, // 0x5E '^'
{ 4646, 21, 5, 32, 4, -4 }, // 0x5F '_'
{ 4660, 10, 26, 14, 1, -25 }, // 0x60 '`'
{ 4693, 27, 37, 32, 2, -38 }, // 0x61 'a'
{ 4818, 26, 37, 32, 2, -36 }, // 0x62 'b'
{ 4939, 23, 22, 32, 2, -21 }, // 0x63 'c'
{ 5003, 27, 37, 32, 2, -36 }, // 0x64 'd'
{ 5128, 26, 39, 32, 2, -38 }, // 0x65 'e'
{ 5255, 26, 37, 32, 2, -38 }, // 0x66 'f'
{ 5376, 26, 39, 32, 2, -38 }, // 0x67 'g'
{ 5503, 26, 35, 32, 2, -36 }, // 0x68 'h'
{ 5617, 6, 17, 32, 22, -18 }, // 0x69 'i'
{ 5630, 27, 37, 32, 2, -36 }, // 0x6A 'j'
{ 5755, 26, 37, 32, 2, -38 }, // 0x6B 'k'
{ 5876, 23, 37, 32, 2, -36 }, // 0x6C 'l'
{ 5983, 27, 37, 32, 2, -38 }, // 0x6D 'm'
{ 6108, 26, 20, 32, 2, -21 }, // 0x6E 'n'
{ 6173, 26, 22, 32, 2, -21 }, // 0x6F 'o'
{ 6245, 27, 37, 32, 2, -38 }, // 0x70 'p'
{ 6370, 25, 37, 32, 4, -38 }, // 0x71 'q'
{ 6486, 23, 20, 32, 2, -21 }, // 0x72 'r'
{ 6544, 24, 37, 32, 4, -36 }, // 0x73 's'
{ 6655, 23, 37, 32, 2, -36 }, // 0x74 't'
{ 6762, 26, 19, 32, 2, -18 }, // 0x75 'u'
{ 6824, 27, 37, 32, 2, -36 }, // 0x76 'v'
{ 6949, 27, 37, 32, 2, -36 }, // 0x77 'w'
{ 7074, 27, 35, 32, 2, -36 }, // 0x78 'x'
{ 7193, 25, 37, 32, 4, -36 }, // 0x79 'y'
{ 7309, 27, 39, 32, 2, -38 }, // 0x7A 'z'
{ 7441, 10, 26, 14, 1, -25 }, // 0x7B '{'
{ 7474, 10, 26, 14, 1, -25 }, // 0x7C '|'
{ 7507, 10, 26, 14, 1, -25 }, // 0x7D '}'
{ 7540, 10, 26, 14, 1, -25 } }; // 0x7E '~'
const GFXfont DSEG7Classic_BoldItalic20pt7b PROGMEM = {
(uint8_t *)DSEG7Classic_BoldItalic20pt7bBitmaps,
(GFXglyph *)DSEG7Classic_BoldItalic20pt7bGlyphs,
0x20, 0x7E, 43 };
// Approx. 8245 bytes

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,232 +0,0 @@
#include <FreeRTOS.h>
#include "LedSpiTask.h"
#include "GwHardware.h"
#include "GwApi.h"
#include <driver/spi_master.h>
#include <driver/gpio.h>
#include <esp_rom_gpio.h>
#include <soc/spi_periph.h>
#include "ColorTo3Byte.h"
/*
controlling some WS2812 using SPI
https://controllerstech.com/ws2812-leds-using-spi/
*/
static uint8_t mulcolor(uint8_t f1, uint8_t f2){
uint16_t rt=f1;
rt*=(uint16_t)f2;
return rt >> 8;
}
Color setBrightness(const Color &color,uint8_t brightness){
uint16_t br255=brightness*255;
br255=br255/100;
//very simple for now
Color rt=color;
rt.g=mulcolor(rt.g,br255);
rt.b=mulcolor(rt.b,br255);
rt.r=mulcolor(rt.r,br255);
return rt;
}
static void colorCompTo3Byte(uint8_t comp,uint8_t *buffer){
for (int i=0;i<3;i++){
*(buffer+i)=colorTo3Byte[comp][i];
}
}
//depending on LED strip - handle color order
static size_t ledsToBuffer(int numLeds,const Color *leds,uint8_t *buffer){
uint8_t *p=buffer;
for (int i=0;i<numLeds;i++){
colorCompTo3Byte(leds[i].g,p);
p+=3;
colorCompTo3Byte(leds[i].r,p);
p+=3;
colorCompTo3Byte(leds[i].b,p);
p+=3;
}
return p-buffer;
}
/**
* prepare a GPIO pin to be used as the data line for an led stripe
*/
bool prepareGpio(GwLog *logger, uint8_t pin){
esp_err_t err=gpio_set_direction((gpio_num_t)pin,GPIO_MODE_OUTPUT);
if (err != ESP_OK){
LOG_DEBUG(GwLog::ERROR,"unable to set gpio mode for %d: %d",pin,(int)err);
return false;
}
err=gpio_set_level((gpio_num_t)pin,0);
if (err != ESP_OK){
LOG_DEBUG(GwLog::ERROR,"unable to set gpio level for %d: %d",pin,(int)err);
return false;
}
return true;
}
/**
* initialize the SPI bus and add a device for the LED output
* it still does not attach any PINs to the bus
* this will be done later when sending out
* this way we can use one hardware SPI for multiple led stripes
* @param bus : the SPI bus
* @param device: <out> the device handle being filled
* @return false on error
*/
bool prepareSpi(GwLog *logger,spi_host_device_t bus,spi_device_handle_t *device){
spi_bus_config_t buscfg = {
.mosi_io_num = -1,
.miso_io_num = -1,
.sclk_io_num = -1,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 0,
.flags=SPICOMMON_BUSFLAG_GPIO_PINS
};
esp_err_t err=spi_bus_initialize(bus,&buscfg,SPI_DMA_CH_AUTO);
if (err != ESP_OK){
LOG_DEBUG(GwLog::ERROR,"unable to initialize SPI bus %d,mosi=%d, error=%d",
(int)bus,-1,(int)err);
return false;
}
spi_device_interface_config_t devcfg = {
.command_bits = 0,
.address_bits = 0,
.dummy_bits = 0,
.mode = 0,
.duty_cycle_pos = 128,
.cs_ena_pretrans = 0,
.cs_ena_posttrans =0,
.clock_speed_hz = 2500000, //2.5 Mhz
.input_delay_ns =0,
.spics_io_num = -1, //CS pin
.queue_size = 1 //see https://github.com/espressif/esp-idf/issues/9450
};
err=spi_bus_add_device(bus,&devcfg,device);
if (err != ESP_OK){
LOG_DEBUG(GwLog::ERROR,"unable to add device to SPI bus %d,mosi=%d, error=%d",
(int)bus,-1,(int)err);
return false;
}
//slightly speed up the transactions
//as we are the only ones using the bus we can safely acquire it forever
err=spi_device_acquire_bus(*device,portMAX_DELAY);
if (err != ESP_OK){
LOG_DEBUG(GwLog::ERROR,"unable to acquire SPI bus %d,mosi=%d, error=%d",
(int)bus,-1,(int)err);
return false;
}
return true;
}
/**
* send out a set of Color values to a connected led stripe
* this method will block until sen dis complete
* But as the transfer is using DMA the CPU is not busy during the wait time
* @param pin: the IO pin to be used. Will be attached to the SPI device before and deattached after
* @param numLeds: the number of Color values
* @param leds: pointer to the first Color value
* @param bus: the SPI bus
* @param device: the SPI device handle
**/
bool sendToLeds(GwLog *logger, uint8_t pin, int numLeds, Color *leds, spi_host_device_t bus, spi_device_handle_t &device, uint8_t *buffer = NULL)
{
//need to send a long reset before
//as on S3 MOSI is high on idle on older frameworks
//see https://github.com/espressif/esp-idf/issues/13974
const int zeroprefix=80; //3.2us per byte
bool ownsBuffer = false;
size_t bufferSize = numLeds * 3 * 3+zeroprefix;
if (buffer == NULL)
{
ownsBuffer = true;
buffer = (uint8_t *)heap_caps_malloc(bufferSize, MALLOC_CAP_DMA|MALLOC_CAP_32BIT);
if (!buffer)
{
LOG_DEBUG(GwLog::ERROR, "unable to allocate %d bytes of DMA buffer", (int)bufferSize);
return false;
}
}
bool rv = true;
for (int i=0;i<zeroprefix;i++)buffer[i]=0;
ledsToBuffer(numLeds, leds, buffer+zeroprefix);
struct spi_transaction_t ta = {
.flags = 0,
.cmd = 0,
.addr = 0,
.length = bufferSize * 8,
.rxlength = 0,
.tx_buffer = buffer};
int64_t now = esp_timer_get_time();
esp_rom_gpio_connect_out_signal(pin, spi_periph_signal[bus].spid_out, false, false);
esp_err_t ret = spi_device_transmit(device, &ta);
esp_rom_gpio_connect_out_signal(pin, SIG_GPIO_OUT_IDX, false, false);
int64_t end = esp_timer_get_time();
if (ret != ESP_OK)
{
LOG_DEBUG(GwLog::ERROR, "unable to send led data: %d", (int)ret);
rv = false;
}
else
{
LOG_DEBUG(GwLog::DEBUG, "successfully send led data for %d leds, %lld us", numLeds, end - now);
}
if (ownsBuffer)
{
heap_caps_free(buffer);
}
return rv;
}
#define EXIT_TASK delay(50);vTaskDelete(NULL);return;
void handleSpiLeds(void *param){
LedTaskData *taskData=(LedTaskData*)param;
GwLog *logger=taskData->api->getLogger();
LOG_DEBUG(GwLog::ERROR,"spi led task initialized");
spi_host_device_t bus=SPI3_HOST;
bool spiValid=false;
LOG_DEBUG(GwLog::ERROR,"SpiLed task started");
if (! prepareGpio(logger,OBP_FLASH_LED)){
EXIT_TASK;
}
if (! prepareGpio(logger,OBP_BACKLIGHT_LED)){
EXIT_TASK;
}
spi_device_handle_t device;
if (! prepareSpi(logger,bus,&device)){
EXIT_TASK;
}
bool first=true;
LedInterface current;
while (true)
{
LedInterface newLeds=taskData->getLedData();
if (first || current.backlightChanged(newLeds) || current.flasChanged(newLeds)){
first=false;
LOG_DEBUG(GwLog::ERROR,"handle SPI leds");
if (current.backlightChanged(newLeds) || first){
LOG_DEBUG(GwLog::ERROR,"setting backlight r=%02d,g=%02d,b=%02d",
newLeds.backlight[0].r,newLeds.backlight[0].g,newLeds.backlight[0].b);
sendToLeds(logger,OBP_BACKLIGHT_LED,newLeds.backlightLen(),newLeds.backlight,bus,device);
}
if (current.flasChanged(newLeds) || first){
LOG_DEBUG(GwLog::ERROR,"setting flashr=%02d,g=%02d,b=%02d",
newLeds.flash[0].r,newLeds.flash[0].g,newLeds.flash[0].b);
sendToLeds(logger,OBP_FLASH_LED,newLeds.flashLen(),newLeds.flash,bus,device);
}
current=newLeds;
}
delay(50);
}
vTaskDelete(NULL);
}
void createSpiLedTask(LedTaskData *param){
xTaskCreate(handleSpiLeds,"handleLeds",4000,param,3,NULL);
}

View File

@@ -1,96 +0,0 @@
#ifndef _GWSPILEDS_H
#define _GWSPILEDS_H
#include "GwSynchronized.h"
#include "GwApi.h"
#include "OBP60Hardware.h"
class Color{
public:
uint8_t r;
uint8_t g;
uint8_t b;
Color():r(0),g(0),b(0){}
Color(uint8_t cr, uint8_t cg,uint8_t cb):
b(cb),g(cg),r(cr){}
Color(const Color &o):b(o.b),g(o.g),r(o.r){}
bool equal(const Color &o) const{
return o.r == r && o.g == g && o.b == b;
}
bool operator == (const Color &other) const{
return equal(other);
}
bool operator != (const Color &other) const{
return ! equal(other);
}
};
static Color COLOR_GREEN=Color(0,255,0);
static Color COLOR_RED=Color(255,0,0);
static Color COLOR_BLUE=Color(0,0,255);
static Color COLOR_WHITE=Color(255,255,255);
static Color COLOR_BLACK=Color(0,0,0);
Color setBrightness(const Color &color,uint8_t brightness);
class LedInterface {
private:
bool equals(const Color *v1, const Color *v2, int num) const{
for (int i=0;i<num;i++){
if (!v1->equal(*v2)) return false;
v1++;
v2++;
}
return true;
}
void set(Color *v,int len, const Color &c){
for (int i=0;i<len;i++){
*v=c;
v++;
}
}
public:
Color flash[NUM_FLASH_LED];
Color backlight[NUM_BACKLIGHT_LED];
int flashLen() const {return NUM_FLASH_LED;}
int backlightLen() const {return NUM_BACKLIGHT_LED;}
bool flasChanged(const LedInterface &other){
return ! equals(flash,other.flash,flashLen());
}
bool backlightChanged(const LedInterface &other){
return ! equals(backlight,other.backlight,backlightLen());
}
void setFlash(const Color &c){
set(flash,flashLen(),c);
}
void setBacklight(const Color &c){
set(backlight,backlightLen(),c);
}
};
class LedTaskData{
private:
SemaphoreHandle_t locker;
LedInterface leds;
long updateCount=0;
public:
GwApi *api=NULL;
LedTaskData(GwApi *api){
locker=xSemaphoreCreateMutex();
this->api=api;
}
void setLedData(const LedInterface &values){
GWSYNCHRONIZED(&locker);
leds=values;
}
LedInterface getLedData(){
GWSYNCHRONIZED(&locker);
return leds;
}
};
//task function
void createSpiLedTask(LedTaskData *param);
#endif

View File

@@ -1,939 +0,0 @@
const unsigned char gImage_Logo_OBP_400x300_sw[15000] = { /* 0X00,0X01,0X90,0X01,0X2C,0X01, */
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,
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,0X00,0X00,0X00,0X00,0X00,0X00,0X40,
0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X00,
0X00,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,
0X00,0X00,0X01,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,
0X00,0X00,0X00,0X00,0X01,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X00,0X03,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X00,0X07,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X00,0X07,0X80,0X00,0X03,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X00,0X0F,0X80,0X00,0X03,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,
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,0X00,0X00,0X00,0X00,0X00,0X1F,0X80,
0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X00,
0X3F,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,
0X00,0X00,0X3F,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,
0X00,0X00,0X00,0X00,0X7F,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X00,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X00,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X01,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XFF,0XFF,0X00,0X03,0XFF,0XFF,0XF8,0X00,0X00,0X0F,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X03,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XFF,0XF8,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X3F,0XFF,0XFF,0XF8,
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,0X00,0X00,0X00,0X00,0X03,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XFF,0XE0,0X00,0X00,0X1F,0XFF,0XF8,0X00,0X00,0X00,0X07,0XFF,
0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X07,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0X80,0X00,0X00,0X07,0XFF,0XF8,0X00,0X00,0X00,
0X03,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,
0X00,0X0F,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0X00,0X00,0X00,0X03,0XFF,0XF8,0X00,
0X00,0X00,0X01,0XFF,0XFF,0XF8,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,0X00,
0X00,0X00,0X00,0X1F,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFE,0X00,0X00,0X00,0X00,0XFF,
0XF8,0X00,0X00,0X00,0X00,0XFF,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X1F,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFC,0X00,0X00,0X00,
0X00,0X7F,0XF8,0X00,0X00,0X00,0X00,0X7F,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X3F,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XF8,0X00,
0X00,0X00,0X00,0X7F,0XF8,0X00,0X00,0X00,0X00,0X7F,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X7F,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XF0,0X00,0X00,0X00,0X00,0X3F,0XF8,0X00,0X00,0X00,0X00,0X3F,0XFF,0XF8,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,0X00,0X00,0X00,0X00,0X7F,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XE0,0X00,0X00,0X00,0X00,0X1F,0XF8,0X00,0X1E,0X00,0X00,0X3F,0XFF,0XF8,
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,0X00,0X00,0X00,0X00,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XE0,0X00,0X0F,0XC0,0X00,0X1F,0XF8,0X00,0X1F,0XE0,0X00,0X3F,
0XFF,0XF8,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,0X00,0X00,0X00,0X01,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X3F,0XF0,0X00,0X0F,0XF8,0X00,0X1F,0XF0,
0X00,0X3F,0XFF,0XF8,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,0X00,0X00,0X00,
0X01,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X7F,0XF8,0X00,0X0F,0XF8,0X00,
0X1F,0XF8,0X00,0X3F,0XFF,0XF8,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,0X00,
0X00,0X00,0X03,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0XFF,0XFC,0X00,0X07,
0XF8,0X00,0X1F,0XF8,0X00,0X3F,0XFF,0XF8,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,0X00,0X00,0X00,0X07,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0X80,0X01,0XFF,0XFE,
0X00,0X07,0XF8,0X00,0X1F,0XF8,0X00,0X3F,0XFF,0XF8,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,0X00,0X00,0X00,0X0F,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0X80,0X01,
0XFF,0XFE,0X00,0X07,0XF8,0X00,0X1F,0XF8,0X00,0X3F,0XFF,0XF8,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,0X00,0X00,0X00,0X0F,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0X80,0X01,0XFF,0XFF,0X00,0X07,0XF8,0X00,0X1F,0XF8,0X00,0X3F,0XFF,0XF8,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,0X00,0X00,0X00,0X1F,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0X80,0X03,0XFF,0XFF,0X00,0X03,0XF8,0X00,0X1F,0XF0,0X00,0X3F,0XFF,0XF8,
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,0X00,0X00,0X00,0X3F,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0X80,0X03,0XFF,0XFF,0X00,0X03,0XF8,0X00,0X1F,0XE0,0X00,0X3F,
0XFF,0XF8,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,0X00,0X00,0X00,0X3F,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0X00,0X03,0XFF,0XFF,0X00,0X03,0XF8,0X00,0X00,0X00,
0X00,0X3F,0XFF,0XF8,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,0X00,0X00,0X00,
0X7F,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0X00,0X03,0XFF,0XFF,0X00,0X03,0XF8,0X00,
0X00,0X00,0X00,0X7F,0XFF,0XF8,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,0X00,
0X00,0X00,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0X00,0X03,0XFF,0XFF,0X00,0X03,
0XF8,0X00,0X00,0X00,0X00,0X7F,0XFF,0XF8,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,0X00,0X00,0X00,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0X00,0X03,0XFF,0XFF,
0X00,0X03,0XF8,0X00,0X00,0X00,0X00,0XFF,0XFF,0XF8,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,0X00,0X00,0X01,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0X00,0X03,
0XFF,0XFF,0X00,0X03,0XF8,0X00,0X00,0X00,0X01,0XFF,0XFF,0XF8,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,0X00,0X00,0X03,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0X00,0X03,0XFF,0XFF,0X00,0X03,0XF8,0X00,0X00,0X00,0X03,0XFF,0XFF,0XF8,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,0X00,0X00,0X03,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0X00,0X03,0XFF,0XFF,0X00,0X03,0XF8,0X00,0X00,0X00,0X07,0XFF,0XFF,0XF8,
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,0X00,0X00,0X07,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0X00,0X03,0XFF,0XFF,0X00,0X03,0XF8,0X00,0X00,0X00,0X0F,0XFF,
0XFF,0XF8,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,0X00,0X00,0X0F,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0X80,0X03,0XFF,0XFF,0X00,0X03,0XF8,0X00,0X00,0X00,
0X7F,0XFF,0XFF,0XF8,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,0X00,0X00,0X1F,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0X80,0X03,0XFF,0XFF,0X00,0X07,0XF8,0X00,
0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,
0X00,0X1F,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0X80,0X01,0XFF,0XFE,0X00,0X07,
0XF8,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X3F,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0X80,0X01,0XFF,0XFE,
0X00,0X07,0XF8,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0X80,0X00,
0XFF,0XFC,0X00,0X07,0XF8,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XC0,0X00,0XFF,0XFC,0X00,0X0F,0XF8,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XC0,0X00,0X3F,0XF8,0X00,0X0F,0XF8,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,
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,0X00,0X01,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XE0,0X00,0X1F,0XE0,0X00,0X1F,0XF8,0X00,0X1F,0XFF,0XFF,0XFF,
0XFF,0XF8,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,0X00,0X03,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XE0,0X00,0X00,0X00,0X00,0X1F,0XF8,0X00,0X1F,0XFF,
0XFF,0XFF,0XFF,0XF8,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,0X00,0X03,0XFF,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XF0,0X00,0X00,0X00,0X00,0X3F,0XF8,0X00,
0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,
0X07,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XF8,0X00,0X00,0X00,0X00,0X3F,
0XF8,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X0F,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XF8,0X00,0X00,0X00,
0X00,0X7F,0XF8,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X0F,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFC,0X00,
0X00,0X00,0X00,0XFF,0XF8,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XFE,0X00,0X00,0X00,0X01,0XFF,0XF8,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X00,0X3F,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XFF,0X80,0X00,0X00,0X03,0XFF,0XF8,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XF8,
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,0X00,0X3F,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XFF,0XC0,0X00,0X00,0X0F,0XFF,0XF8,0X00,0X1F,0XFF,0XFF,0XFF,
0XFF,0XF8,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,0X00,0X7F,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XF0,0X00,0X00,0X3F,0XFF,0XF8,0X00,0X1F,0XFF,
0XFF,0XFF,0XFF,0XF8,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,0X00,0XFF,0XFF,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFE,0X00,0X01,0XFF,0XFF,0XF8,0X00,
0X3F,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X01,
0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,
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,0X0F,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XF8,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,0X1F,0XFF,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XF8,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,0X1F,0XFF,0XFF,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X3F,
0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X03,0XFE,0X00,0X1F,0XFF,0XF8,
0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X03,0XFE,0X00,0X0F,
0XFF,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X0F,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X03,0XFE,
0X00,0X07,0XFF,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X1F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,
0X03,0XFE,0X00,0X03,0XFF,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,
0X00,0X00,0X03,0XFE,0X00,0X03,0XFF,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X3F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XC0,0X00,0X00,0X00,0X03,0XFE,0X00,0X01,0XFF,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XC0,0X00,0X00,0X00,0X03,0XFE,0X00,0X00,0XFF,0XF0,0X00,0X7F,0XFF,0XF8,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X03,0XFE,0X00,0X00,0XFF,0XF0,0X00,0X7F,
0XFF,0XF8,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,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X03,0XFE,0X00,0X00,0X7F,0XF0,
0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X03,0XFE,0X00,0X00,
0X3F,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X01,0XFF,0XFF,0XFF,0XFE,
0X00,0X00,0X3F,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X01,0XFF,0XFF,
0XFF,0XFE,0X00,0X00,0X1F,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X01,
0XFF,0XFF,0XFF,0XFE,0X00,0X00,0X0F,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XC0,0X01,0XFF,0XFF,0XFF,0XFE,0X00,0X00,0X0F,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X0F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XC0,0X01,0XFF,0XFF,0XFF,0XFE,0X00,0X00,0X07,0XF0,0X00,0X7F,0XFF,0XF8,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XC0,0X01,0XFF,0XFF,0XFF,0XFE,0X00,0X00,0X03,0XF0,0X00,0X7F,
0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X01,0XFF,0XFF,0XFF,0XFE,0X00,0X00,0X03,0XF0,
0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3F,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X07,0XFE,0X00,0X00,
0X01,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X07,0XFE,
0X00,0X00,0X00,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,
0X07,0XFE,0X00,0X00,0X00,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,
0X00,0X00,0X07,0XFE,0X00,0X00,0X00,0X70,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XC0,0X00,0X00,0X00,0X07,0XFE,0X00,0X00,0X00,0X30,0X00,0X7F,0XFF,0XF8,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XC0,0X00,0X00,0X00,0X07,0XFE,0X00,0X08,0X00,0X30,0X00,0X7F,0XFF,0XF8,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X07,0XFE,0X00,0X0C,0X00,0X10,0X00,0X7F,
0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X07,0XFE,0X00,0X0C,0X00,0X00,
0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X0F,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X07,0XFE,0X00,0X0E,
0X00,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X01,0XFF,0XFF,0XFF,0XFE,
0X00,0X0F,0X00,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X01,0XFF,0XFF,
0XFF,0XFE,0X00,0X0F,0X00,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X3F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X01,
0XFF,0XFF,0XFF,0XFE,0X00,0X0F,0X80,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XC0,0X01,0XFF,0XFF,0XFF,0XFE,0X00,0X0F,0XC0,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XC0,0X01,0XFF,0XFF,0XFF,0XFE,0X00,0X0F,0XC0,0X00,0X00,0X7F,0XFF,0XF8,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XC0,0X01,0XFF,0XFF,0XFF,0XFE,0X00,0X0F,0XE0,0X00,0X00,0X7F,
0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X01,0XFF,0XFF,0XFF,0XFE,0X00,0X0F,0XF0,0X00,
0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X01,0XFF,0XFF,0XFF,0XFE,0X00,0X0F,
0XF8,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0XFF,0XFF,0XFF,0XFE,
0X00,0X0F,0XF8,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,
0X01,0XFE,0X00,0X0F,0XFC,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X0F,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,
0X00,0X00,0X01,0XFE,0X00,0X0F,0XFE,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X0F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XC0,0X00,0X00,0X00,0X01,0XFE,0X00,0X0F,0XFE,0X00,0X00,0X7F,0XFF,0XF8,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XC0,0X00,0X00,0X00,0X01,0XFE,0X00,0X0F,0XFF,0X00,0X00,0X7F,0XFF,0XF8,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X3F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X01,0XFE,0X00,0X0F,0XFF,0X80,0X00,0X7F,
0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X01,0XFE,0X00,0X0F,0XFF,0X80,
0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X01,0XFE,0X00,0X0F,
0XFF,0XC0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X01,0XFE,
0X00,0X0F,0XFF,0XE0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,
0X01,0XFE,0X00,0X0F,0XFF,0XE0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XC0,0X00,
0X00,0X00,0X01,0XFE,0X00,0X1F,0XFF,0XF0,0X00,0X7F,0XFF,0XF8,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X0F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3F,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X7F,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,0X00,0X03,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0X80,
0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0X80,0X00,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XC0,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XF8,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,
0XFF,0XFE,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X40,0X00,0X0F,0XFF,0XE0,0X00,0X00,
0X00,0X00,0X00,0X7E,0X00,0X00,0X00,0X00,0X00,0X00,0X02,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X03,0XFF,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XC0,0X00,0X0F,0XFF,0XF8,
0X00,0X00,0X00,0X00,0X00,0X7E,0X00,0X00,0X00,0X00,0X00,0X00,0X0E,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X00,0X00,0X07,0XC0,0X00,0X0F,
0XFF,0XFC,0X00,0X00,0X00,0X00,0X00,0X7E,0X00,0X00,0X00,0X00,0X00,0X00,0X3E,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XC0,0X00,0X00,0X00,0X00,0X00,0X0F,0XC0,
0X00,0X0F,0XFF,0XFE,0X00,0X00,0X00,0X00,0X00,0X7E,0X00,0X00,0X00,0X00,0X00,0X00,
0X7E,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XE0,0X00,0X00,0X00,0X00,0X00,
0X0F,0XC0,0X00,0X0F,0XFF,0XFE,0X00,0X00,0X00,0X00,0X00,0X7E,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,0X00,0X00,0X00,0X00,0X03,0XF8,0X1F,0XE0,0X00,0X00,0X00,
0X00,0X00,0X0F,0XC0,0X00,0X0F,0XE0,0XFF,0X00,0X00,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,0X00,0X00,0X00,0X00,0X03,0XF8,0X0F,0XE0,0X03,
0XE0,0X00,0X3F,0XE0,0X1F,0XC0,0X00,0X0F,0XE0,0X7F,0X00,0X0E,0X00,0X7E,0X00,0X00,
0X00,0X3F,0X00,0X01,0XFC,0X00,0XFE,0X00,0X3F,0XC0,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XF8,0X0F,
0XC0,0X1F,0XFC,0X00,0XFF,0XF8,0X7F,0XFC,0X00,0X0F,0XE0,0X7F,0X1F,0X9F,0X83,0XFF,
0X80,0X7E,0X01,0XFF,0XE0,0X07,0XFF,0X03,0XFF,0XE0,0XFF,0XF0,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,
0XF8,0X1F,0XC0,0X3F,0XFE,0X03,0XFF,0XFC,0X7F,0XFC,0X00,0X0F,0XE0,0X7F,0X1F,0XFF,
0X07,0XFF,0XE0,0X7E,0X03,0XFF,0XF0,0X1F,0XFF,0XC3,0XFF,0XE1,0XFF,0XF8,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X03,0XFF,0XFF,0X80,0X7F,0XFF,0X83,0XFF,0XFE,0X7F,0XFC,0X00,0X0F,0XE0,0XFF,
0X1F,0XFF,0X0F,0XFF,0XF0,0X7E,0X07,0XFF,0XF8,0X3F,0XFF,0XE3,0XFF,0XE3,0XFF,0XFC,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X03,0XFF,0XFF,0X00,0XFF,0XFF,0X87,0XF8,0XFE,0X7F,0XFC,0X00,0X0F,
0XFF,0XFE,0X1F,0XFE,0X1F,0XFF,0XF0,0X7E,0X0F,0XE3,0XF8,0X3F,0XFF,0XE3,0XFF,0XE3,
0XE1,0XFC,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0X01,0XFE,0X3F,0XC7,0XF0,0X7E,0X1F,0XC0,
0X00,0X0F,0XFF,0XFE,0X1F,0XF2,0X1F,0XC3,0XF8,0X7E,0X0F,0XC1,0XFC,0X7F,0X87,0XF0,
0XFE,0X07,0XE0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XC1,0XFC,0X1F,0XC0,0X00,0XFE,
0X0F,0XC0,0X00,0X0F,0XFF,0XFC,0X1F,0XE0,0X3F,0X83,0XF8,0X7E,0X1F,0XC0,0XFC,0X7F,
0X03,0X80,0XFE,0X03,0XFC,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XE1,0XFC,0X0F,0XC0,
0X07,0XFE,0X0F,0XC0,0X00,0X0F,0XFF,0XF8,0X1F,0XC0,0X3F,0X81,0XF8,0X7E,0X1F,0XC0,
0XFC,0X7E,0X00,0X00,0XFE,0X03,0XFF,0XE0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XF8,0X0F,0XE1,0XF8,
0X0F,0XC0,0XFF,0XFE,0X0F,0XC0,0X00,0X0F,0XFF,0XE0,0X1F,0XC0,0X3F,0X81,0XF8,0X7E,
0X1F,0XFF,0XFE,0X7E,0X00,0X00,0XFE,0X01,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XF8,0X0F,
0XF1,0XF8,0X0F,0XC3,0XFF,0XFE,0X0F,0XC0,0X00,0X0F,0XE0,0X00,0X1F,0XC0,0X3F,0X01,
0XFC,0X7E,0X1F,0XFF,0XFE,0X7E,0X00,0X00,0XFE,0X00,0XFF,0XFC,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,
0XF8,0X0F,0XF1,0XF8,0X0F,0XC7,0XFC,0X7E,0X0F,0XC0,0X00,0X0F,0XE0,0X00,0X1F,0XC0,
0X3F,0X81,0XF8,0X7E,0X1F,0XFF,0XFE,0X7E,0X00,0X00,0XFE,0X00,0X3F,0XFC,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X03,0XF8,0X0F,0XF1,0XFC,0X1F,0XC7,0XF0,0X7E,0X0F,0XC0,0X00,0X0F,0XE0,0X00,
0X1F,0XC0,0X3F,0X81,0XF8,0X7E,0X1F,0XC0,0X00,0X7F,0X03,0XC0,0XFE,0X00,0X01,0XFE,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X03,0XFC,0X3F,0XF1,0XFC,0X1F,0XC7,0XE0,0X7E,0X0F,0XC0,0X00,0X0F,
0XE0,0X00,0X1F,0XC0,0X1F,0X83,0XF8,0X7E,0X1F,0XC0,0X00,0X7F,0X07,0XF0,0XFE,0X00,
0X60,0X7E,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XE0,0XFF,0X3F,0X87,0XE0,0XFE,0X0F,0XFC,
0X00,0X0F,0XE0,0X00,0X1F,0XC0,0X1F,0XE7,0XF0,0X7E,0X0F,0XE1,0XFC,0X7F,0XCF,0XF0,
0X7F,0XC7,0XF0,0X7E,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XE0,0XFF,0XFF,0X87,0XFF,0XFE,
0X0F,0XFC,0X00,0X0F,0XE0,0X00,0X1F,0XC0,0X0F,0XFF,0XF0,0X7E,0X0F,0XFF,0XF8,0X3F,
0XFF,0XE0,0X7F,0XC7,0XFF,0XFC,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XC0,0X7F,0XFF,0X07,
0XFF,0XFE,0X0F,0XFC,0X00,0X0F,0XE0,0X00,0X1F,0XC0,0X07,0XFF,0XE0,0X7E,0X07,0XFF,
0XF0,0X1F,0XFF,0XC0,0X7F,0XE3,0XFF,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0X80,0X1F,
0XFE,0X03,0XFF,0X3F,0X07,0XFC,0X00,0X0F,0XE0,0X00,0X1F,0XC0,0X03,0XFF,0XC0,0X7E,
0X03,0XFF,0XE0,0X0F,0XFF,0X80,0X3F,0XE1,0XFF,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XF8,
0X00,0X07,0XF8,0X00,0XFC,0X3F,0X03,0XFC,0X00,0X0F,0XE0,0X00,0X1F,0XC0,0X00,0XFF,
0X00,0X7E,0X00,0XFF,0X80,0X03,0XFE,0X00,0X1F,0XE0,0X7F,0XC0,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,0X00,0X00,0X00,0X00,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,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,0X00,
0X00,0X00,0X00,0X00,0X03,0XFE,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFE,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFE,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFC,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFC,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XE0,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,};

View File

@@ -1,939 +0,0 @@
const unsigned char gImage_MFD_OBP60_400x300_sw[15000] = { /* 0X00,0X01,0X90,0X01,0X2C,0X01, */
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,0X00,0X00,0X00,0X1F,0XE0,0X3F,
0XC0,0X00,0X00,0X7E,0X00,0X40,0XFC,0X07,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X08,0X1F,0X80,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XE0,0X0F,0XC0,0X00,0X00,0X00,
0X00,0X1F,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,
0XF0,0X3F,0XC0,0X00,0X00,0X7E,0X01,0XC0,0XFC,0X1F,0XF0,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X38,0X1F,0X80,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XF8,0X0F,0XC0,0X00,
0X00,0X00,0X00,0X1F,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X1F,0XF0,0X7F,0XC0,0X00,0X00,0X7E,0X07,0XC0,0XFC,0X1F,0XF0,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0XF8,0X1F,0X80,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XFC,0X0F,
0XC0,0X00,0X00,0X00,0X00,0X1F,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X1F,0XF0,0X7F,0XC0,0X00,0X00,0X7E,0X0F,0XC0,0XFC,0X3F,0XE0,0X00,
0X00,0X00,0X00,0X00,0X00,0X01,0XF8,0X1F,0X80,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,
0XFE,0X0F,0XC0,0X00,0X00,0X00,0X00,0X1F,0X80,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X1F,0XF0,0X7F,0XC0,0X00,0X00,0X7E,0X0F,0XC0,0X00,0X3F,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X07,0XFF,0XFE,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0X80,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XF8,0X7F,0XC0,0X00,0X00,0X7E,0X0F,0XC0,
0X00,0X3F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XF8,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X07,0XF0,0XFF,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0X80,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XF8,0XFF,0XC3,0XE0,0XF8,0X7E,
0X3F,0XF8,0XFC,0XFF,0XE7,0XC1,0XF0,0XF8,0XF8,0X01,0XFC,0X07,0XFF,0X1F,0X80,0X7F,
0X00,0XF8,0XF8,0X00,0X07,0XF0,0X7F,0X0F,0XC0,0X7F,0X80,0XF9,0XF0,0X1F,0X80,0XFF,
0X83,0XF0,0X3F,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0X78,0XF7,0XC3,0XE0,
0XF8,0X7E,0X3F,0XF8,0XFC,0XFF,0XE7,0XC1,0XF0,0XFB,0XFC,0X07,0XFF,0X07,0XFF,0X1F,
0X81,0XFF,0XC0,0XFB,0XFC,0X00,0X07,0XF0,0X3F,0X0F,0XC1,0XFF,0XE0,0XFB,0XFC,0X1F,
0X83,0XFF,0XE1,0XF8,0X3E,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0X78,0XF7,
0XC3,0XE0,0XF8,0X7E,0X3F,0XF8,0XFC,0XFF,0XE7,0XC1,0XF0,0XFF,0XFE,0X0F,0XFF,0XC7,
0XFF,0X1F,0X83,0XFF,0XE0,0XFF,0XFE,0X00,0X07,0XF0,0X3F,0X0F,0XC3,0XFF,0XF0,0XFF,
0XFE,0X1F,0X87,0XFF,0XF1,0XF8,0X3E,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,
0X7C,0XF7,0XC3,0XE0,0XF8,0X7E,0X3F,0XF8,0XFC,0XFF,0XE7,0XC1,0XF0,0XFF,0XFE,0X1F,
0XFF,0XC7,0XFF,0X1F,0X87,0XFF,0XF0,0XFF,0XFE,0X00,0X07,0XF0,0X3F,0X8F,0XC3,0XE3,
0XF0,0XFF,0XFE,0X1F,0X87,0XFF,0XF0,0XF8,0X7E,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X1F,0X3D,0XE7,0XC3,0XE0,0XF8,0X7E,0X0F,0XC0,0XFC,0X3F,0X07,0XC1,0XF0,0XFF,
0XFE,0X1F,0X87,0XE1,0XF8,0X1F,0X87,0XE3,0XF0,0XFF,0XFE,0X00,0X07,0XF0,0X3F,0X8F,
0XC3,0XE1,0X80,0XFC,0X7F,0X1F,0X87,0XC1,0XF0,0XFC,0X7C,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X1F,0X3D,0XE7,0XC3,0XE0,0XF8,0X7E,0X0F,0XC0,0XFC,0X3F,0X07,0XC1,
0XF0,0XFC,0X7E,0X3F,0X07,0X01,0XF8,0X1F,0X8F,0XC1,0XF8,0XFC,0X7E,0X00,0X07,0XF0,
0X3F,0X8F,0XC3,0XFC,0X00,0XFC,0X3F,0X1F,0X80,0X07,0XF0,0X7C,0X7C,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X1F,0X3F,0XE7,0XC3,0XE0,0XF8,0X7E,0X0F,0XC0,0XFC,0X3F,
0X07,0XC1,0XF0,0XFC,0X3E,0X3F,0X00,0X01,0XF8,0X1F,0X8F,0XC1,0XF8,0XFC,0X3E,0X00,
0X07,0XF0,0X3F,0X0F,0XC3,0XFF,0XE0,0XF8,0X3F,0X1F,0X80,0X7F,0XF0,0X7C,0XF8,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0X3F,0XE7,0XC3,0XE0,0XF8,0X7E,0X0F,0XC0,
0XFC,0X3F,0X07,0XC1,0XF0,0XF8,0X3E,0X3F,0X00,0X01,0XF8,0X1F,0X8F,0XC1,0XF8,0XF8,
0X3E,0X00,0X07,0XF0,0X3F,0X0F,0XC1,0XFF,0XF0,0XF8,0X3F,0X1F,0X83,0XFF,0XF0,0X7C,
0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0X1F,0XC7,0XC3,0XE1,0XF8,0X7E,
0X0F,0XC0,0XFC,0X3F,0X07,0XC3,0XF0,0XF8,0X3E,0X3F,0X00,0X01,0XF8,0X1F,0X8F,0XC1,
0XF8,0XF8,0X3E,0X00,0X07,0XF0,0X3F,0X0F,0XC0,0X7F,0XF8,0XF8,0X3F,0X1F,0X87,0XF1,
0XF0,0X3E,0XF8,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0X1F,0XC7,0XC3,0XF1,
0XF8,0X7E,0X0F,0XC0,0XFC,0X3F,0X07,0XE3,0XF0,0XF8,0X3E,0X3F,0X03,0X01,0XF8,0X1F,
0X8F,0XC1,0XF8,0XF8,0X3E,0X00,0X07,0XF0,0X7F,0X0F,0XC0,0X03,0XF8,0XFC,0X3F,0X1F,
0X8F,0XC1,0XF0,0X3F,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0X1F,0XC7,
0XC3,0XFF,0XF8,0X7E,0X0F,0XC0,0XFC,0X3F,0X07,0XFF,0XF0,0XF8,0X3E,0X1F,0X87,0XE1,
0XF8,0X1F,0X87,0XE3,0XF0,0XF8,0X3E,0X00,0X07,0XFF,0XFE,0X0F,0XC0,0XE0,0XF8,0XFC,
0X7F,0X1F,0X8F,0XC3,0XF0,0X1F,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,
0X1F,0XC7,0XC3,0XFF,0XF8,0X7E,0X0F,0XF8,0XFC,0X3F,0X07,0XFF,0XF0,0XF8,0X3E,0X1F,
0XFF,0XC1,0XFF,0X1F,0X87,0XFF,0XF0,0XF8,0X3E,0X00,0X07,0XFF,0XFE,0X0F,0XC7,0XE1,
0XF8,0XFF,0XFE,0X1F,0X8F,0XFF,0XF0,0X1F,0XF0,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X1F,0X0F,0X87,0XC3,0XFF,0XF8,0X7E,0X0F,0XF8,0XFC,0X3F,0X07,0XFF,0XF0,0XF8,
0X3E,0X0F,0XFF,0XC1,0XFF,0X1F,0X83,0XFF,0XE0,0XF8,0X3E,0X00,0X07,0XFF,0XFC,0X0F,
0XC3,0XFF,0XF0,0XFF,0XFE,0X1F,0X8F,0XFF,0XF0,0X1F,0XE0,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X1F,0X0F,0X87,0XC1,0XFE,0XF8,0X7E,0X07,0XF8,0XFC,0X3F,0X03,0XFD,
0XF0,0XF8,0X3E,0X07,0XFF,0X80,0XFF,0X1F,0X81,0XFF,0XC0,0XF8,0X3E,0X00,0X07,0XFF,
0XF8,0X0F,0XC3,0XFF,0XE0,0XFF,0XFC,0X1F,0X87,0XFD,0XF0,0X0F,0XE0,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X1F,0X0F,0X87,0XC0,0XF8,0XF8,0X7E,0X03,0XF8,0XFC,0X3F,
0X01,0XF1,0XF0,0XF8,0X3E,0X01,0XFE,0X00,0X7F,0X1F,0X80,0X7F,0X00,0XF8,0X3E,0X00,
0X07,0XFF,0XC0,0X0F,0XC0,0X7F,0X80,0XF9,0XF0,0X1F,0X81,0XF0,0XF8,0X0F,0XC0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF8,0X00,0X00,0X00,0X00,0X00,0X0F,
0XC0,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,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF8,0X00,0X00,0X00,0X00,
0X00,0X0F,0XC0,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,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF8,0X00,0X00,
0X00,0X00,0X01,0XFF,0X80,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,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF8,
0X00,0X00,0X00,0X00,0X01,0XFF,0X80,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,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0XF8,0X00,0X00,0X00,0X00,0X01,0XFF,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0XF8,0X00,0X00,0X00,0X00,0X00,0XFC,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XF8,0X01,0XFF,0XFC,0X03,0XFF,0XF0,0X00,0XFC,
0X00,0X3F,0X80,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,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XFE,0X01,0XFF,0XFF,0X03,0XFF,0XFC,
0X03,0XFF,0X00,0XFF,0XE0,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,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0X81,0XFF,0XFF,0X83,
0XFF,0XFE,0X07,0XFF,0X81,0XFF,0XF0,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,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0XC1,0XFF,
0XFF,0X83,0XFF,0XFE,0X0F,0XFF,0XC3,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,
0XC1,0XFF,0XFF,0XC3,0XFF,0XFE,0X1F,0X8F,0XC3,0XF1,0XF8,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,
0XFE,0X1F,0XE1,0XFC,0X1F,0XC3,0XF0,0X7F,0X1F,0X87,0X83,0XE0,0XF8,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X01,0XFC,0X0F,0XE1,0XFC,0X1F,0X83,0XF0,0X3F,0X1F,0X00,0X07,0XE0,0XF8,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X01,0XF8,0X07,0XE1,0XFC,0X1F,0X83,0XF0,0X3F,0X3F,0X3E,0X07,0XE0,
0XFC,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,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X03,0XF8,0X07,0XF1,0XFF,0XFF,0X03,0XF0,0X7F,0X3F,0X7F,
0X87,0XE0,0XFC,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,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XF8,0X07,0XF1,0XFF,0XFE,0X03,0XFF,0XFE,
0X3F,0XFF,0XC7,0XE0,0XFC,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,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XF8,0X07,0XF1,0XFF,0XFF,0X03,
0XFF,0XFE,0X3F,0XFF,0XC7,0XE0,0XFC,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,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XF8,0X07,0XF1,0XFF,
0XFF,0X83,0XFF,0XFC,0X3F,0X87,0XE7,0XE0,0XFC,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XF8,0X07,
0XF1,0XFF,0XFF,0XC3,0XFF,0XF8,0X3F,0X07,0XE7,0XE0,0XFC,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,
0XF8,0X07,0XE1,0XFC,0X0F,0XC3,0XFF,0XE0,0X3F,0X03,0XE7,0XE0,0XFC,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X01,0XFC,0X0F,0XE1,0XFC,0X0F,0XE3,0XF0,0X00,0X1F,0X03,0XE3,0XE0,0XFC,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X01,0XFE,0X1F,0XE1,0XFC,0X0F,0XE3,0XF0,0X00,0X1F,0X07,0XE3,0XE0,
0XF8,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,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0XC1,0XFF,0XFF,0XC3,0XF0,0X00,0X1F,0X87,
0XE3,0XF1,0XF8,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,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0XC1,0XFF,0XFF,0XC3,0XF0,0X00,
0X0F,0XFF,0XC1,0XFF,0XF8,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,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0X81,0XFF,0XFF,0X83,
0XF0,0X00,0X07,0XFF,0X81,0XFF,0XF0,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,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XFE,0X01,0XFF,
0XFF,0X83,0XF0,0X00,0X03,0XFF,0X00,0XFF,0XE0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XF8,
0X01,0XFF,0XFC,0X03,0XF0,0X00,0X00,0XFC,0X00,0X3F,0X80,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X40,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,
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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XC0,0X07,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XC0,0X07,
0XFF,0XFC,0X07,0XFF,0X00,0X07,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,
0XC0,0X07,0XFF,0XE0,0X00,0XFF,0X00,0X00,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X0F,0XC0,0X07,0XFF,0XC0,0X00,0X7F,0X00,0X00,0X7F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X1F,0XC0,0X07,0XFF,0X80,0X00,0X3F,0X00,0X00,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X1F,0XC0,0X07,0XFF,0X00,0X00,0X1F,0X00,0X00,0X1F,0XF0,
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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3F,0XC0,0X07,0XFE,0X00,0XC0,0X0F,0X01,0XE0,
0X1F,0XF0,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,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XC0,0X07,0XFE,0X03,0XF0,0X0F,
0X01,0XF0,0X1F,0XF0,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,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XC0,0X07,0XFC,0X03,
0XF8,0X0F,0X01,0XF0,0X1F,0XF0,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XC0,0X07,
0XFC,0X07,0XF8,0X07,0X01,0XF0,0X1F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,
0XC0,0X07,0XFC,0X07,0XFC,0X07,0X01,0XE0,0X1F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X03,0XFF,0XC0,0X07,0XFC,0X07,0XFC,0X07,0X00,0X00,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X03,0XFF,0XC0,0X07,0XFC,0X07,0XFC,0X07,0X00,0X00,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X07,0XFF,0XC0,0X07,0XFC,0X07,0XFC,0X07,0X00,0X00,0X7F,0XF0,
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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X0F,0XFF,0XC0,0X07,0XFC,0X07,0XFC,0X07,0X00,0X00,
0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X0F,0XFF,0XC0,0X07,0XFC,0X07,0XF8,0X07,
0X01,0XDF,0XFF,0XF0,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,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XFF,0XC0,0X07,0XFC,0X07,
0XF8,0X0F,0X01,0XFF,0XFF,0XF0,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3F,0XFF,0XC0,0X07,
0XFE,0X03,0XF8,0X0F,0X01,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,
0XC0,0X07,0XFE,0X00,0XE0,0X0F,0X01,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X7F,0XFF,0XC0,0X07,0XFF,0X00,0X00,0X1F,0X01,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0XFF,0XFF,0XC0,0X07,0XFF,0X00,0X00,0X3F,0X01,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X01,0XFF,0XFF,0XC0,0X07,0XFF,0X80,0X00,0X7F,0X01,0XFF,0XFF,0XF0,
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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XC0,0X07,0XFF,0XE0,0X00,0XFF,0X01,0XFF,
0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XC0,0X07,0XFF,0XF8,0X03,0XFF,
0X01,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XFF,0XC0,0X07,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XFF,0XC0,0X07,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X0F,0XFF,0XFF,
0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,
0XFF,0XFF,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X3F,0XFF,0XFF,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X3F,0XFF,0XFF,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,
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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0XFF,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X00,0X00,0X78,
0X0F,0XF0,0X3F,0XF0,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,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X00,
0X00,0X78,0X07,0XF0,0X3F,0XF0,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFF,0XC0,0X07,
0XFE,0X00,0X00,0X78,0X07,0XF0,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XFF,
0XC0,0X07,0XFE,0X00,0X00,0X78,0X03,0XF0,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,
0XFF,0XFF,0XC0,0X07,0XFE,0X00,0X00,0X78,0X01,0XF0,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X07,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X03,0XFF,0XF8,0X01,0XF0,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X0F,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X03,0XFF,0XF8,0X00,0XF0,0X3F,0XF0,
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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X1F,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X03,0XFF,0XF8,0X00,0X70,
0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X00,0X00,0XF8,
0X00,0X70,0X3F,0XF0,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,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3F,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X00,
0X00,0XF8,0X00,0X30,0X3F,0XF0,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0XFF,0XFF,0XC0,0X07,
0XFE,0X00,0X00,0XF8,0X00,0X10,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X7F,0XFF,0XFF,0XFF,
0XC0,0X07,0XFE,0X00,0X00,0XF8,0X00,0X10,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,
0XFF,0XFF,0XC0,0X07,0XFE,0X00,0X00,0XF8,0X08,0X00,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X01,
0XFF,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X03,0XFF,0XF8,0X0C,0X00,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X01,0XFF,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X03,0XFF,0XF8,0X0E,0X00,0X3F,0XF0,
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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X03,0XFF,0XF8,0X0E,0X00,
0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X03,0XFF,0XF8,
0X0F,0X00,0X3F,0XF0,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,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X0F,0XFF,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X00,
0X00,0X78,0X0F,0X80,0X3F,0XF0,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X0F,0XFF,0XFF,0XFF,0XFF,0XC0,0X07,
0XFE,0X00,0X00,0X78,0X0F,0X80,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X1F,0XFF,0XFF,0XFF,0XFF,
0XC0,0X07,0XFE,0X00,0X00,0X78,0X0F,0XC0,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3F,0XFF,0XFF,
0XFF,0XFF,0XC0,0X07,0XFE,0X00,0X00,0X78,0X0F,0XE0,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X3F,
0XFF,0XFF,0XFF,0XFF,0XC0,0X07,0XFE,0X00,0X00,0X78,0X0F,0XE0,0X3F,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X7F,0XFF,0XFF,0XFF,0XFF,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,
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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,
0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0XFF,0XFF,0XFF,0XFF,0XFF,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,
0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X01,0XFF,0XFF,0XFF,0XFF,0XFF,0XC0,0X07,0XFF,0XFF,
0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X03,0XFF,0XFF,0XFF,0XFF,0XFF,0XC0,0X07,
0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,
0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFF,0XFF,0XFF,
0XFF,0XFF,0XC0,0X07,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XFF,0XF0,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,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,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,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,
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,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,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,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,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,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,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XF8,0X00,0X00,0X00,0X20,0X0F,0XE0,
0X00,0X00,0X38,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,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFC,0X00,0X00,0X00,0X60,
0X0F,0XF8,0X00,0X00,0X38,0X00,0X00,0X01,0X80,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFE,0X00,0X00,
0X00,0XE0,0X0F,0XF8,0X00,0X00,0X00,0X00,0X00,0X03,0X80,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0X0E,
0X06,0X00,0XC0,0XE0,0X0E,0X3C,0X08,0X38,0X00,0X18,0X03,0X03,0X81,0XC0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X07,0X1E,0X1F,0X87,0XFB,0XF8,0X0E,0X3C,0XDC,0XFE,0X38,0X7F,0X0F,0XE7,0XE7,0XF0,
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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X07,0XFC,0X3F,0XCF,0X3B,0XF8,0X0F,0XF8,0XF9,0XFF,0X38,0XE7,0X1F,0XE7,
0XE6,0X38,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,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X07,0XFE,0X78,0XE0,0X38,0XE0,0X0F,0XF8,0XE1,0XC7,0X39,0XE3,
0XBC,0X03,0X87,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,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X07,0X0E,0X70,0XE3,0XF8,0XE0,0X0F,0XE0,0XE1,0XC7,
0X39,0XFF,0XB8,0X03,0X87,0XF0,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,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0X0F,0X70,0XEF,0X38,0XE0,0X0E,0X00,
0XE1,0XC7,0X39,0XFF,0XB8,0X03,0X81,0XF8,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0X1E,0X39,0XEE,0X38,0XE0,
0X0E,0X00,0XE1,0XC7,0X38,0XE0,0X3C,0XF3,0X80,0X38,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFE,0X3F,0XCF,
0XF8,0XF0,0X0E,0X00,0XE0,0XFF,0X38,0XFF,0X1F,0XE3,0XEF,0X78,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X07,0XFC,
0X1F,0X87,0XD8,0XF8,0X0E,0X00,0XE0,0X7C,0X38,0X7E,0X0F,0XC1,0XE7,0XF0,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X38,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X78,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0XF8,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X20,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,
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,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,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,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,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,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,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,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,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,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,};

View File

@@ -1,407 +0,0 @@
#ifdef BOARD_OBP60S3
#include <Arduino.h>
#define FASTLED_ALL_PINS_HARDWARE_SPI
#define FASTLED_ESP32_SPI_BUS FSPI
#define FASTLED_ESP32_FLASH_LOCK 1
#include <PCF8574.h> // Driver for PCF8574 output modul from Horter
#include <Wire.h> // I2C
#include <RTClib.h> // Driver for DS1388 RTC
#include "SunRise.h" // Lib for sunrise and sunset calculation
#include "Pagedata.h"
#include "OBP60Hardware.h"
#include "OBP60Extensions.h"
// Character sets
#include "Ubuntu_Bold8pt7b.h"
#include "Ubuntu_Bold12pt7b.h"
#include "Ubuntu_Bold16pt7b.h"
#include "Ubuntu_Bold20pt7b.h"
#include "Ubuntu_Bold32pt7b.h"
#include "DSEG7Classic-BoldItalic16pt7b.h"
#include "DSEG7Classic-BoldItalic20pt7b.h"
#include "DSEG7Classic-BoldItalic30pt7b.h"
#include "DSEG7Classic-BoldItalic42pt7b.h"
#include "DSEG7Classic-BoldItalic60pt7b.h"
// E-Ink Display
#define GxEPD_WIDTH 400 // Display width
#define GxEPD_HEIGHT 300 // Display height
#ifdef DISPLAY_GDEW042T2
// Set display type and SPI pins for display
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> display(GxEPD2_420(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
// Export display in new funktion
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay(){return display;}
#endif
#ifdef DISPLAY_GDEY042T81
// Set display type and SPI pins for display
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> display(GxEPD2_420_GDEY042T81(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
// Export display in new funktion
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay(){return display;}
#endif
#ifdef DISPLAY_GYE042A87
// Set display type and SPI pins for display
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> display(GxEPD2_420_GYE042A87(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
// Export display in new funktion
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay(){return display;}
#endif
#ifdef DISPLAY_SE0420NQ04
// Set display type and SPI pins for display
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> display(GxEPD2_420_SE0420NQ04(OBP_SPI_CS, OBP_SPI_DC, OBP_SPI_RST, OBP_SPI_BUSY)); // GDEW042T2 400x300, UC8176 (IL0398)
// Export display in new funktion
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay(){return display;}
#endif
// Horter I2C moduls
PCF8574 pcf8574_Out(PCF8574_I2C_ADDR1); // First digital output modul PCF8574 from Horter
// Global vars
bool blinkingLED = false; // Enable / disable blinking flash LED
bool statusLED = false; // Actual status of flash LED on/off
bool statusBacklightLED = false;// Actual status of flash LED on/off
int uvDuration = 0; // Under voltage duration in n x 100ms
LedTaskData *ledTaskData=nullptr;
void hardwareInit()
{
// Init power rail 5.0V
setPortPin(OBP_POWER_50, true);
Wire.begin();
// Init PCF8574 digital outputs
Wire.setClock(I2C_SPEED); // Set I2C clock on 10 kHz
if(pcf8574_Out.begin()){ // Initialize PCF8574
pcf8574_Out.write8(255); // Clear all outputs
}
}
void startLedTask(GwApi *api){
ledTaskData=new LedTaskData(api);
createSpiLedTask(ledTaskData);
}
void setPortPin(uint pin, bool value){
pinMode(pin, OUTPUT);
digitalWrite(pin, value);
}
void togglePortPin(uint pin){
pinMode(pin, OUTPUT);
digitalWrite(pin, !digitalRead(pin));
}
// Valid colors see hue
Color colorMapping(const String &colorString){
Color color=COLOR_RED;
if(colorString == "Orange"){color = Color(255,153,0);}
if(colorString == "Yellow"){color = Color(255,255,0);}
if(colorString == "Green"){color = COLOR_GREEN;}
if(colorString == "Blue"){color = COLOR_BLUE;}
if(colorString == "Aqua"){color = Color(51,102,255);}
if(colorString == "Violet"){color = Color(255,0,102);}
if(colorString == "White"){color = COLOR_WHITE;}
return color;
}
// All defined colors see pixeltypes.h in FastLED lib
void setBacklightLED(uint brightness, const Color &color){
if (ledTaskData == nullptr) return;
Color nv=setBrightness(color,brightness);
LedInterface current=ledTaskData->getLedData();
current.setBacklight(nv);
ledTaskData->setLedData(current);
}
void toggleBacklightLED(uint brightness, const Color &color){
if (ledTaskData == nullptr) return;
statusBacklightLED = !statusBacklightLED;
Color nv=setBrightness(statusBacklightLED?color:COLOR_BLACK,brightness);
LedInterface current=ledTaskData->getLedData();
current.setBacklight(nv);
ledTaskData->setLedData(current);
}
void setFlashLED(bool status){
if (ledTaskData == nullptr) return;
Color c=status?COLOR_RED:COLOR_BLACK;
LedInterface current=ledTaskData->getLedData();
current.setFlash(c);
ledTaskData->setLedData(current);
}
void blinkingFlashLED(){
if(blinkingLED == true){
statusLED = !statusLED; // Toggle LED for each run
setFlashLED(statusLED);
}
}
void setBlinkingLED(bool status){
blinkingLED = status;
}
uint buzzerpower = 50;
void buzzer(uint frequency, uint duration){
if(frequency > 8000){ // Max 8000Hz
frequency = 8000;
}
if(buzzerpower > 100){ // Max 100%
buzzerpower = 100;
}
if(duration > 1000){ // Max 1000ms
duration = 1000;
}
// Using LED PWM function for sound generation
pinMode(OBP_BUZZER, OUTPUT);
ledcSetup(0, frequency, 8); // Ch 0, ferquency in Hz, 8 Bit resolution of PWM
ledcAttachPin(OBP_BUZZER, 0);
ledcWrite(0, uint(buzzerpower * 1.28)); // 50% duty cycle are 100%
delay(duration);
ledcWrite(0, 0); // 0% duty cycle are 0%
}
void setBuzzerPower(uint power){
buzzerpower = power;
}
// Delete xdr prefix from string
String xdrDelete(String input){
if(input.substring(0,3) == "xdr"){
input = input.substring(3, input.length());
}
return input;
}
// Show a triangle for trend direction high (x, y is the left edge)
void displayTrendHigh(int16_t x, int16_t y, uint16_t size, uint16_t color){
getdisplay().fillTriangle(x, y, x+size*2, y, x+size, y-size*2, color);
}
// Show a triangle for trend direction low (x, y is the left edge)
void displayTrendLow(int16_t x, int16_t y, uint16_t size, uint16_t color){
getdisplay().fillTriangle(x, y, x+size*2, y, x+size, y+size*2, color);
}
// Show header informations
void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop){
static bool heartbeat = false;
static unsigned long usbRxOld = 0;
static unsigned long usbTxOld = 0;
static unsigned long serRxOld = 0;
static unsigned long serTxOld = 0;
static unsigned long tcpSerRxOld = 0;
static unsigned long tcpSerTxOld = 0;
static unsigned long tcpClRxOld = 0;
static unsigned long tcpClTxOld = 0;
static unsigned long n2kRxOld = 0;
static unsigned long n2kTxOld = 0;
int textcolor = GxEPD_BLACK;
if(commonData.config->getBool(commonData.config->statusLine) == true){
if(commonData.config->getString(commonData.config->displaycolor) == "Normal"){
textcolor = GxEPD_BLACK;
}
else{
textcolor = GxEPD_WHITE;
}
// Show status info
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(0, 15);
if(commonData.status.wifiApOn){
getdisplay().print(" AP ");
}
// If receive new telegram data then display bus name
if(commonData.status.tcpClRx != tcpClRxOld || commonData.status.tcpClTx != tcpClTxOld || commonData.status.tcpSerRx != tcpSerRxOld || commonData.status.tcpSerTx != tcpSerTxOld){
getdisplay().print("TCP ");
}
if(commonData.status.n2kRx != n2kRxOld || commonData.status.n2kTx != n2kTxOld){
getdisplay().print("N2K ");
}
if(commonData.status.serRx != serRxOld || commonData.status.serTx != serTxOld){
getdisplay().print("183 ");
}
if(commonData.status.usbRx != usbRxOld || commonData.status.usbTx != usbTxOld){
getdisplay().print("USB ");
}
double gpshdop = formatValue(hdop, commonData).value;
if(commonData.config->getString(commonData.config->useGPS) != "off" && gpshdop > 0.3){
getdisplay().print("GPS");
}
// Save old telegram counter
tcpClRxOld = commonData.status.tcpClRx;
tcpClTxOld = commonData.status.tcpClTx;
tcpSerRxOld = commonData.status.tcpSerRx;
tcpSerTxOld = commonData.status.tcpSerTx;
n2kRxOld = commonData.status.n2kRx;
n2kTxOld = commonData.status.n2kTx;
serRxOld = commonData.status.serRx;
serTxOld = commonData.status.serTx;
usbRxOld = commonData.status.usbRx;
usbTxOld = commonData.status.usbTx;
// Heartbeat as dot
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold32pt7b);
getdisplay().setCursor(205, 14);
if(heartbeat == true){
getdisplay().print(".");
}
else{
getdisplay().print(" ");
}
heartbeat = !heartbeat;
// Date and time
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(230, 15);
if(date->valid == true){
String acttime = formatValue(time, commonData).svalue;
acttime = acttime.substring(0, 5);
String actdate = formatValue(date, commonData).svalue;
getdisplay().print(acttime);
getdisplay().print(" ");
getdisplay().print(actdate);
getdisplay().print(" ");
if(commonData.config->getInt(commonData.config->timeZone) == 0){
getdisplay().print("UTC");
}
else{
getdisplay().print("LOT");
}
}
else{
if(commonData.config->getBool(commonData.config->useSimuData) == true){
getdisplay().print("12:00 01.01.2024 LOT");
}
else{
getdisplay().print("No GPS data");
}
}
}
}
// Sunset und sunrise calculation
SunData calcSunsetSunrise(GwApi *api, double time, double date, double latitude, double longitude, double timezone){
GwLog *logger=api->getLogger();
SunData returnset;
SunRise sr;
int secPerHour = 3600;
int secPerYear = 86400;
sr.hasRise = false;
sr.hasSet = false;
time_t t = 0;
time_t sunR = 0;
time_t sunS = 0;
if (!isnan(time) && !isnan(date) && !isnan(latitude) && !isnan(longitude) && !isnan(timezone)) {
// Calculate local epoch
t = (date * secPerYear) + time;
// api->getLogger()->logDebug(GwLog::DEBUG,"... calcSun: Lat %f, Lon %f, at: %d ", latitude, longitude, t);
sr.calculate(latitude, longitude, t); // LAT, LON, EPOCH
// Sunrise
if (sr.hasRise) {
sunR = (sr.riseTime + int(timezone * secPerHour) + 30) % secPerYear; // add 30 seconds: round to minutes
returnset.sunriseHour = int (sunR / secPerHour);
returnset.sunriseMinute = int((sunR - returnset.sunriseHour * secPerHour)/60);
}
// Sunset
if (sr.hasSet) {
sunS = (sr.setTime + int(timezone * secPerHour) + 30) % secPerYear; // add 30 seconds: round to minutes
returnset.sunsetHour = int (sunS / secPerHour);
returnset.sunsetMinute = int((sunS - returnset.sunsetHour * secPerHour)/60);
}
// Sun control (return value by sun on sky = false, sun down = true)
if ((t >= sr.riseTime) && (t <= sr.setTime))
returnset.sunDown = false;
else returnset.sunDown = true;
}
// Return values
return returnset;
}
// Battery graphic with fill level
void batteryGraphic(uint x, uint y, float percent, int pcolor, int bcolor){
// Show battery
int xb = x; // X position
int yb = y; // Y position
int t = 4; // Line thickness
// Percent limits
if(percent < 0){
percent = 0;
}
if(percent > 99){
percent = 99;
}
// Battery corpus 100x80 with fill level
int level = int((100.0 - percent) * (80-(2*t)) / 100.0);
getdisplay().fillRect(xb, yb, 100, 80, pcolor);
if(percent < 99){
getdisplay().fillRect(xb+t, yb+t, 100-(2*t), level, bcolor);
}
// Plus pol 20x15
int xp = xb + 20;
int yp = yb - 15 + t;
getdisplay().fillRect(xp, yp, 20, 15, pcolor);
getdisplay().fillRect(xp+t, yp+t, 20-(2*t), 15-(2*t), bcolor);
// Minus pol 20x15
int xm = xb + 60;
int ym = yb -15 + t;
getdisplay().fillRect(xm, ym, 20, 15, pcolor);
getdisplay().fillRect(xm+t, ym+t, 20-(2*t), 15-(2*t), bcolor);
}
// Solar graphic with fill level
void solarGraphic(uint x, uint y, int pcolor, int bcolor){
// Show solar modul
int xb = x; // X position
int yb = y; // Y position
int t = 4; // Line thickness
int percent = 0;
// Solar corpus 100x80
int level = int((100.0 - percent) * (80-(2*t)) / 100.0);
getdisplay().fillRect(xb, yb, 100, 80, pcolor);
if(percent < 99){
getdisplay().fillRect(xb+t, yb+t, 100-(2*t), level, bcolor);
}
// Draw horizontel lines
getdisplay().fillRect(xb, yb+28-t, 100, t, pcolor);
getdisplay().fillRect(xb, yb+54-t, 100, t, pcolor);
// Draw vertical lines
getdisplay().fillRect(xb+19+t, yb, t, 80, pcolor);
getdisplay().fillRect(xb+39+2*t, yb, t, 80, pcolor);
getdisplay().fillRect(xb+59+3*t, yb, t, 80, pcolor);
}
// Generator graphic with fill level
void generatorGraphic(uint x, uint y, int pcolor, int bcolor){
// Show battery
int xb = x; // X position
int yb = y; // Y position
int t = 4; // Line thickness
// Generator corpus with radius 45
getdisplay().fillCircle(xb, yb, 45, pcolor);
getdisplay().fillCircle(xb, yb, 41, bcolor);
// Insert G
getdisplay().setTextColor(pcolor);
getdisplay().setFont(&Ubuntu_Bold32pt7b);
getdisplay().setCursor(xb-22, yb+20);
getdisplay().print("G");
}
#endif

View File

@@ -1,72 +0,0 @@
#ifndef _OBP60EXTENSIONPORT_H
#define _OBP60EXTENSIONPORT_H
#include <Arduino.h>
#include "OBP60Hardware.h"
#define FASTLED_ALL_PINS_HARDWARE_SPI
#define FASTLED_ESP32_SPI_BUS FSPI
#define FASTLED_ESP32_FLASH_LOCK 1
#include "LedSpiTask.h"
#include <GxEPD2_BW.h> // E-paper lib V2
// Fonts declarations for display (#inclues see OBP60Extensions.cpp)
extern const GFXfont Ubuntu_Bold8pt7b;
extern const GFXfont Ubuntu_Bold12pt7b;
extern const GFXfont Ubuntu_Bold16pt7b;
extern const GFXfont Ubuntu_Bold20pt7b;
extern const GFXfont Ubuntu_Bold32pt7b;
extern const GFXfont DSEG7Classic_BoldItalic16pt7b;
extern const GFXfont DSEG7Classic_BoldItalic20pt7b;
extern const GFXfont DSEG7Classic_BoldItalic30pt7b;
extern const GFXfont DSEG7Classic_BoldItalic42pt7b;
extern const GFXfont DSEG7Classic_BoldItalic60pt7b;
// Gloabl functions
#ifdef DISPLAY_GDEW042T2
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay();
#endif
#ifdef DISPLAY_GDEY042T81
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay();
#endif
#ifdef DISPLAY_GYE042A87
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay();
#endif
#ifdef DISPLAY_SE0420NQ04
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay();
#endif
void hardwareInit();
void setPortPin(uint pin, bool value); // Set port pin for extension port
void togglePortPin(uint pin); // Toggle extension port pin
Color colorMapping(const String &colorString); // Color mapping string to CHSV colors
void setBacklightLED(uint brightness, const Color &color);// Set backlight LEDs
void toggleBacklightLED(uint brightness,const Color &color);// Toggle backlight LEDs
void setFlashLED(bool status); // Set flash LED
void blinkingFlashLED(); // Blinking function for flash LED
void setBlinkingLED(bool on); // Set blinking flash LED active
void buzzer(uint frequency, uint duration); // Buzzer function
void setBuzzerPower(uint power); // Set buzzer power
String xdrDelete(String input); // Delete xdr prefix from string
void displayTrendHigh(int16_t x, int16_t y, uint16_t size, uint16_t color);
void displayTrendLow(int16_t x, int16_t y, uint16_t size, uint16_t color);
void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop); // Draw display header
SunData calcSunsetSunrise(GwApi *api, double time, double date, double latitude, double longitude, double timezone); // Calulate sunset and sunrise
void batteryGraphic(uint x, uint y, float percent, int pcolor, int bcolor); // Battery graphic with fill level
void solarGraphic(uint x, uint y, int pcolor, int bcolor); // Solar graphic with fill level
void generatorGraphic(uint x, uint y, int pcolor, int bcolor); // Generator graphic with fill level
void startLedTask(GwApi *api);
#endif

View File

@@ -1,755 +0,0 @@
#ifdef BOARD_OBP60S3
#include <Arduino.h>
#include "GwApi.h"
#include "Pagedata.h"
// ToDo
// simulation data
// hold values by missing data
FormatedData formatValue(GwApi::BoatValue *value, CommonData &commondata){
GwLog *logger = commondata.logger;
FormatedData result;
static int dayoffset = 0;
double rawvalue = 0;
// Load configuration values
String stimeZone = commondata.config->getString(commondata.config->timeZone); // [UTC -14.00...+12.00]
double timeZone = stimeZone.toDouble();
String lengthFormat = commondata.config->getString(commondata.config->lengthFormat); // [m|ft]
String distanceFormat = commondata.config->getString(commondata.config->distanceFormat); // [m|km|nm]
String speedFormat = commondata.config->getString(commondata.config->speedFormat); // [m/s|km/h|kn]
String windspeedFormat = commondata.config->getString(commondata.config->windspeedFormat); // [m/s|km/h|kn|bft]
String tempFormat = commondata.config->getString(commondata.config->tempFormat); // [K|°C|°F]
String dateFormat = commondata.config->getString(commondata.config->dateFormat); // [DE|GB|US]
bool usesimudata = commondata.config->getBool(commondata.config->useSimuData); // [on|off]
// If boat value not valid
if (! value->valid && !usesimudata){
result.svalue = "---";
return result;
}
// LOG_DEBUG(GwLog::DEBUG,"formatValue init: getFormat: %s date->value: %f time->value: %f", value->getFormat(), commondata.date->value, commondata.time->value);
static const int bsize = 30;
char buffer[bsize+1];
buffer[0]=0;
//########################################################
// Formats for several boat data
//########################################################
if (value->getFormat() == "formatDate"){
int dayoffset = 0;
if (commondata.time->value + int(timeZone*3600) > 86400) {dayoffset = 1;}
if (commondata.time->value + int(timeZone*3600) < 0) {dayoffset = -1;}
// LOG_DEBUG(GwLog::DEBUG,"... formatDate value->value: %f tz: %f dayoffset: %d", value->value, timeZone, dayoffset);
tmElements_t parts;
time_t tv=tNMEA0183Msg::daysToTime_t(value->value + dayoffset);
tNMEA0183Msg::breakTime(tv,parts);
if(usesimudata == false) {
if(String(dateFormat) == "DE"){
snprintf(buffer,bsize,"%02d.%02d.%04d",parts.tm_mday,parts.tm_mon+1,parts.tm_year+1900);
}
else if(String(dateFormat) == "GB"){
snprintf(buffer,bsize,"%02d/%02d/%04d",parts.tm_mday,parts.tm_mon+1,parts.tm_year+1900);
}
else if(String(dateFormat) == "US"){
snprintf(buffer,bsize,"%02d/%02d/%04d",parts.tm_mon+1,parts.tm_mday,parts.tm_year+1900);
}
else{
snprintf(buffer,bsize,"%02d.%02d.%04d",parts.tm_mday,parts.tm_mon+1,parts.tm_year+1900);
}
}
else{
snprintf(buffer,bsize,"01.01.2022");
}
if(timeZone == 0){
result.unit = "UTC";
}
else{
result.unit = "LOT";
}
}
//########################################################
else if(value->getFormat() == "formatTime"){
double timeInSeconds = 0;
double inthr = 0;
double intmin = 0;
double intsec = 0;
double val = 0;
timeInSeconds = value->value + int(timeZone * 3600);
if (timeInSeconds > 86400) {timeInSeconds = timeInSeconds - 86400;}
if (timeInSeconds < 0) {timeInSeconds = timeInSeconds + 86400;}
// LOG_DEBUG(GwLog::DEBUG,"... formatTime value: %f tz: %f corrected timeInSeconds: %f ", value->value, timeZone, timeInSeconds);
if(usesimudata == false) {
val=modf(timeInSeconds/3600.0,&inthr);
val=modf(val*3600.0/60.0,&intmin);
modf(val*60.0,&intsec);
snprintf(buffer,bsize,"%02.0f:%02.0f:%02.0f",inthr,intmin,intsec);
}
else{
static long sec;
static long lasttime;
if(millis() > lasttime + 990){
sec ++;
}
sec = sec % 60;
snprintf(buffer,bsize,"11:36:%02i", int(sec));
lasttime = millis();
}
if(timeZone == 0){
result.unit = "UTC";
}
else{
result.unit = "LOT";
}
}
//########################################################
else if (value->getFormat() == "formatFixed0"){
if(usesimudata == false) {
snprintf(buffer,bsize,"%3.0f",value->value);
rawvalue = value->value;
}
else{
rawvalue = 8.0 + float(random(0, 10)) / 10.0;
snprintf(buffer,bsize,"%3.0f", rawvalue);
}
result.unit = "";
}
//########################################################
else if (value->getFormat() == "formatCourse" || value->getFormat() == "formatWind"){
double course = 0;
if(usesimudata == false) {
course = value->value;
rawvalue = value->value;
}
else{
course = 2.53 + float(random(0, 10) / 100.0);
rawvalue = course;
}
course = course * 57.2958; // Unit conversion form rad to deg
// Format 3 numbers with prefix zero
snprintf(buffer,bsize,"%03.0f",course);
result.unit = "Deg";
}
//########################################################
else if (value->getFormat() == "formatKnots" && (value->getName() == "SOG" || value->getName() == "STW")){
double speed = 0;
if(usesimudata == false) {
speed = value->value;
rawvalue = value->value;
}
else{
rawvalue = 4.0 + float(random(0, 40));
speed = rawvalue;
}
if(String(speedFormat) == "km/h"){
speed = speed * 3.6; // Unit conversion form m/s to km/h
result.unit = "km/h";
}
else if(String(speedFormat) == "kn"){
speed = speed * 1.94384; // Unit conversion form m/s to kn
result.unit = "kn";
}
else{
speed = speed; // Unit conversion form m/s to m/s
result.unit = "m/s";
}
if(speed < 10){
snprintf(buffer,bsize,"%3.2f",speed);
}
if(speed >= 10 && speed < 100){
snprintf(buffer,bsize,"%3.1f",speed);
}
if(speed >= 100){
snprintf(buffer,bsize,"%3.0f",speed);
}
}
//########################################################
else if (value->getFormat() == "formatKnots" && (value->getName() == "AWS" || value->getName() == "TWS" || value->getName() == "MaxAws" || value->getName() == "MaxTws")){
double speed = 0;
if(usesimudata == false) {
speed = value->value;
rawvalue = value->value;
}
else{
rawvalue = 4.0 + float(random(0, 40));
speed = rawvalue;
}
if(String(windspeedFormat) == "km/h"){
speed = speed * 3.6; // Unit conversion form m/s to km/h
result.unit = "km/h";
}
else if(String(windspeedFormat) == "kn"){
speed = speed * 1.94384; // Unit conversion form m/s to kn
result.unit = "kn";
}
else if(String(windspeedFormat) == "bft"){
if(speed < 0.3){
speed = 0;
}
if(speed >=0.3 && speed < 1.5){
speed = 1;
}
if(speed >=1.5 && speed < 3.3){
speed = 2;
}
if(speed >=3.3 && speed < 5.4){
speed = 3;
}
if(speed >=5.4 && speed < 7.9){
speed = 4;
}
if(speed >=7.9 && speed < 10.7){
speed = 5;
}
if(speed >=10.7 && speed < 13.8){
speed = 6;
}
if(speed >=13.8 && speed < 17.1){
speed = 7;
}
if(speed >=17.1 && speed < 20.7){
speed = 8;
}
if(speed >=20.7 && speed < 24.4){
speed = 9;
}
if(speed >=24.4 && speed < 28.4){
speed = 10;
}
if(speed >=28.4 && speed < 32.6){
speed = 11;
}
if(speed >=32.6){
speed = 12;
}
result.unit = "bft";
}
else{
speed = speed; // Unit conversion form m/s to m/s
result.unit = "m/s";
}
if(String(windspeedFormat) == "bft"){
snprintf(buffer,bsize,"%2.0f",speed);
}
else{
if(speed < 10){
snprintf(buffer,bsize,"%3.2f",speed);
}
if(speed >= 10 && speed < 100){
snprintf(buffer,bsize,"%3.1f",speed);
}
if(speed >= 100){
snprintf(buffer,bsize,"%3.0f",speed);
}
}
}
//########################################################
else if (value->getFormat() == "formatRot"){
double rotation = 0;
if(usesimudata == false) {
rotation = value->value;
rawvalue = value->value;
}
else{
rawvalue = 0.04 + float(random(0, 10)) / 100.0;
rotation = rawvalue;
}
rotation = rotation * 57.2958; // Unit conversion form rad/s to deg/s
result.unit = "Deg/s";
if(rotation < -100){
rotation = -99;
}
if(rotation > 100){
rotation = 99;
}
if(rotation > -10 && rotation < 10){
snprintf(buffer,bsize,"%3.2f",rotation);
}
if(rotation <= -10 || rotation >= 10){
snprintf(buffer,bsize,"%3.0f",rotation);
}
}
//########################################################
else if (value->getFormat() == "formatDop"){
double dop = 0;
if(usesimudata == false) {
dop = value->value;
rawvalue = value->value;
}
else{
rawvalue = 2.0 + float(random(0, 40)) / 10.0;
dop = rawvalue;
}
result.unit = "m";
if(dop > 99.9){
dop = 99.9;
}
if(dop < 10){
snprintf(buffer,bsize,"%3.2f",dop);
}
if(dop >= 10 && dop < 100){
snprintf(buffer,bsize,"%3.1f",dop);
}
}
//########################################################
else if (value->getFormat() == "formatLatitude"){
if(usesimudata == false) {
double lat = value->value;
rawvalue = value->value;
String latitude = "";
String latdir = "";
float degree = abs(int(lat));
float minute = abs((lat - int(lat)) * 60);
if(lat > 0){
latdir = "N";
}
else{
latdir = "S";
}
latitude = String(degree,0) + "\" " + String(minute,4) + "' " + latdir;
result.unit = "";
strcpy(buffer, latitude.c_str());
}
else{
rawvalue = 35.0 + float(random(0, 10)) / 10000.0;
snprintf(buffer,bsize," 51\" %2.4f' N", rawvalue);
}
}
//########################################################
else if (value->getFormat() == "formatLongitude"){
if(usesimudata == false) {
double lon = value->value;
rawvalue = value->value;
String longitude = "";
String londir = "";
float degree = abs(int(lon));
float minute = abs((lon - int(lon)) * 60);
if(lon > 0){
londir = "E";
}
else{
londir = "W";
}
longitude = String(degree,0) + "\" " + String(minute,4) + "' " + londir;
result.unit = "";
strcpy(buffer, longitude.c_str());
}
else{
rawvalue = 6.0 + float(random(0, 10)) / 100000.0;
snprintf(buffer,bsize," 15\" %2.4f'", rawvalue);
}
}
//########################################################
else if (value->getFormat() == "formatDepth"){
double depth = 0;
if(usesimudata == false) {
depth = value->value;
rawvalue = value->value;
}
else{
rawvalue = 18.0 + float(random(0, 100)) / 10.0;
depth = rawvalue;
}
if(String(lengthFormat) == "ft"){
depth = depth * 3.28084;
result.unit = "ft";
}
else{
result.unit = "m";
}
if(depth < 10){
snprintf(buffer,bsize,"%3.2f",depth);
}
if(depth >= 10 && depth < 100){
snprintf(buffer,bsize,"%3.1f",depth);
}
if(depth >= 100){
snprintf(buffer,bsize,"%3.0f",depth);
}
}
//########################################################
else if (value->getFormat() == "kelvinToC"){
double temp = 0;
if(usesimudata == false) {
temp = value->value;
rawvalue = value->value;
}
else{
rawvalue = 296.0 + float(random(0, 10)) / 10.0;
temp = rawvalue;
}
if(String(tempFormat) == "C"){
temp = temp - 273.15;
result.unit = "C";
}
else if(String(tempFormat) == "F"){
temp = temp - 459.67;
result.unit = "F";
}
else{
result.unit = "K";
}
if(temp < 10){
snprintf(buffer,bsize,"%3.2f",temp);
}
if(temp >= 10 && temp < 100){
snprintf(buffer,bsize,"%3.1f",temp);
}
if(temp >= 100){
snprintf(buffer,bsize,"%3.0f",temp);
}
}
//########################################################
else if (value->getFormat() == "mtr2nm"){
double distance = 0;
if(usesimudata == false) {
distance = value->value;
rawvalue = value->value;
}
else{
rawvalue = 2960.0 + float(random(0, 10));
distance = rawvalue;
}
if(String(distanceFormat) == "km"){
distance = distance * 0.001;
result.unit = "km";
}
else if(String(distanceFormat) == "nm"){
distance = distance * 0.000539957;
result.unit = "nm";
}
else{;
result.unit = "m";
}
if(distance < 10){
snprintf(buffer,bsize,"%3.2f",distance);
}
if(distance >= 10 && distance < 100){
snprintf(buffer,bsize,"%3.1f",distance);
}
if(distance >= 100){
snprintf(buffer,bsize,"%3.0f",distance);
}
}
//########################################################
// Special XDR formats
// Refer XDR formats in GwXDRMappings.cpp line 40
//########################################################
else if (value->getFormat() == "formatXdr:P:P"){
double pressure = 0;
if(usesimudata == false) {
pressure = value->value;
rawvalue = value->value;
pressure = pressure / 100.0; // Unit conversion form Pa to hPa
}
else{
rawvalue = 968 + float(random(0, 10));
pressure = rawvalue;
}
snprintf(buffer,bsize,"%4.0f",pressure);
result.unit = "hPa";
}
//########################################################
else if (value->getFormat() == "formatXdr:P:B"){
double pressure = 0;
if(usesimudata == false) {
pressure = value->value;
rawvalue = value->value;
pressure = pressure / 100.0; // Unit conversion form Pa to mBar
}
else{
rawvalue = value->value;
pressure = 968 + float(random(0, 10));
}
snprintf(buffer,bsize,"%4.0f",pressure);
result.unit = "mBar";
}
//########################################################
else if (value->getFormat() == "formatXdr:U:V"){
double voltage = 0;
if(usesimudata == false) {
voltage = value->value;
rawvalue = value->value;
}
else{
rawvalue = 12 + float(random(0, 30)) / 10.0;
voltage = rawvalue;
}
if(voltage < 10){
snprintf(buffer,bsize,"%3.2f",voltage);
}
else{
snprintf(buffer,bsize,"%3.1f",voltage);
}
result.unit = "V";
}
//########################################################
else if (value->getFormat() == "formatXdr:I:A"){
double current = 0;
if(usesimudata == false) {
current = value->value;
rawvalue = value->value;
}
else{
rawvalue = 8.2 + float(random(0, 50)) / 10.0;
current = rawvalue;
}
if(current < 10){
snprintf(buffer,bsize,"%3.2f",current);
}
if(current >= 10 && current < 100){
snprintf(buffer,bsize,"%3.1f",current);
}
if(current >= 100){
snprintf(buffer,bsize,"%3.0f",current);
}
result.unit = "A";
}
//########################################################
else if (value->getFormat() == "formatXdr:C:K"){
double temperature = 0;
if(usesimudata == false) {
temperature = value->value - 273.15; // Convert K to C
rawvalue = value->value - 273.15;
}
else{
rawvalue = 21.8 + float(random(0, 50)) / 10.0;
temperature = rawvalue;
}
if(temperature < 10){
snprintf(buffer,bsize,"%3.2f",temperature);
}
if(temperature >= 10 && temperature < 100){
snprintf(buffer,bsize,"%3.1f",temperature);
}
if(temperature >= 100){
snprintf(buffer,bsize,"%3.0f",temperature);
}
result.unit = "Deg C";
}
//########################################################
else if (value->getFormat() == "formatXdr:C:C"){
double temperature = 0;
if(usesimudata == false) {
temperature = value->value; // Value in C
rawvalue = value->value;
}
else{
rawvalue = 21.8 + float(random(0, 50)) / 10.0;
temperature = rawvalue;
}
if(temperature < 10){
snprintf(buffer,bsize,"%3.2f",temperature);
}
if(temperature >= 10 && temperature < 100){
snprintf(buffer,bsize,"%3.1f",temperature);
}
if(temperature >= 100){
snprintf(buffer,bsize,"%3.0f",temperature);
}
result.unit = "Deg C";
}
//########################################################
else if (value->getFormat() == "formatXdr:H:P"){
double humidity = 0;
if(usesimudata == false) {
humidity = value->value; // Value in %
rawvalue = value->value;
}
else{
rawvalue = 41.3 + float(random(0, 50)) / 10.0;
humidity = rawvalue;
}
if(humidity < 10){
snprintf(buffer,bsize,"%3.2f",humidity);
}
if(humidity >= 10 && humidity < 100){
snprintf(buffer,bsize,"%3.1f",humidity);
}
if(humidity >= 100){
snprintf(buffer,bsize,"%3.0f",humidity);
}
result.unit = "%";
}
//########################################################
else if (value->getFormat() == "formatXdr:V:P"){
double volume = 0;
if(usesimudata == false) {
volume = value->value; // Value in %
rawvalue = value->value;
}
else{
rawvalue = 85.8 + float(random(0, 50)) / 10.0;
volume = rawvalue;
}
if(volume < 10){
snprintf(buffer,bsize,"%3.2f",volume);
}
if(volume >= 10 && volume < 100){
snprintf(buffer,bsize,"%3.1f",volume);
}
if(volume >= 100){
snprintf(buffer,bsize,"%3.0f",volume);
}
result.unit = "%";
}
//########################################################
else if (value->getFormat() == "formatXdr:V:M"){
double volume = 0;
if(usesimudata == false) {
volume = value->value; // Value in l
rawvalue = value->value;
}
else{
rawvalue = 75.2 + float(random(0, 50)) / 10.0;
volume = rawvalue;
}
if(volume < 10){
snprintf(buffer,bsize,"%3.2f",volume);
}
if(volume >= 10 && volume < 100){
snprintf(buffer,bsize,"%3.1f",volume);
}
if(volume >= 100){
snprintf(buffer,bsize,"%3.0f",volume);
}
result.unit = "l";
}
//########################################################
else if (value->getFormat() == "formatXdr:R:I"){
double flow = 0;
if(usesimudata == false) {
flow = value->value; // Value in l/min
rawvalue = value->value;
}
else{
rawvalue = 7.5 + float(random(0, 20)) / 10.0;
flow = rawvalue;
}
if(flow < 10){
snprintf(buffer,bsize,"%3.2f",flow);
}
if(flow >= 10 && flow < 100){
snprintf(buffer,bsize,"%3.1f",flow);
}
if(flow >= 100){
snprintf(buffer,bsize,"%3.0f",flow);
}
result.unit = "l/min";
}
//########################################################
else if (value->getFormat() == "formatXdr:G:"){
double generic = 0;
if(usesimudata == false) {
generic = value->value; // Value in l/min
rawvalue = value->value;
}
else{
rawvalue = 18.5 + float(random(0, 20)) / 10.0;
generic = rawvalue;
}
if(generic < 10){
snprintf(buffer,bsize,"%3.2f",generic);
}
if(generic >= 10 && generic < 100){
snprintf(buffer,bsize,"%3.1f",generic);
}
if(generic >= 100){
snprintf(buffer,bsize,"%3.0f",generic);
}
result.unit = "";
}
//########################################################
else if (value->getFormat() == "formatXdr:A:P"){
double dplace = 0;
if(usesimudata == false) {
dplace = value->value; // Value in %
rawvalue = value->value;
}
else{
rawvalue = 55.3 + float(random(0, 20)) / 10.0;
dplace = rawvalue;
}
if(dplace < 10){
snprintf(buffer,bsize,"%3.2f",dplace);
}
if(dplace >= 10 && dplace < 100){
snprintf(buffer,bsize,"%3.1f",dplace);
}
if(dplace >= 100){
snprintf(buffer,bsize,"%3.0f",dplace);
}
result.unit = "%";
}
//########################################################
else if (value->getFormat() == "formatXdr:A:D"){
double angle = 0;
if(usesimudata == false) {
angle = value->value;
angle = angle * 57.2958; // Unit conversion form rad to deg
rawvalue = value->value;
}
else{
rawvalue = PI / 100 + (random(-5, 5) / 360 * 2* PI);
angle = rawvalue * 57.2958;
}
if(angle > -10 && angle < 10){
snprintf(buffer,bsize,"%3.1f",angle);
}
else{
snprintf(buffer,bsize,"%3.0f",angle);
}
result.unit = "Deg";
}
//########################################################
else if (value->getFormat() == "formatXdr:T:R"){
double rpm = 0;
if(usesimudata == false) {
rpm = value->value; // Value in rpm
rawvalue = value->value;
}
else{
rawvalue = 2505 + random(0, 20);
rpm = rawvalue;
}
if(rpm < 10){
snprintf(buffer,bsize,"%3.2f",rpm);
}
if(rpm >= 10 && rpm < 100){
snprintf(buffer,bsize,"%3.1f",rpm);
}
if(rpm >= 100){
snprintf(buffer,bsize,"%3.0f",rpm);
}
result.unit = "rpm";
}
//########################################################
// Default format
//########################################################
else{
if(value->value < 10){
snprintf(buffer,bsize,"%3.2f",value->value);
}
if(value->value >= 10 && value->value < 100){
snprintf(buffer,bsize,"%3.1f",value->value);
}
if(value->value >= 100){
snprintf(buffer,bsize,"%3.0f",value->value);
}
result.unit = "";
}
buffer[bsize]=0;
result.value = rawvalue; // Return value is only necessary in case of simulation of graphic pointer
result.svalue = String(buffer);
return result;
}
#endif

View File

@@ -1,80 +0,0 @@
// General hardware definitions
// CAN and RS485 bus pin definitions see obp60task.h
// Direction pin for RS485 NMEA0183
#define OBP_DIRECTION_PIN 18
// I2C
#define I2C_SPEED 10000UL // 10kHz clock speed on I2C bus
#define OBP_I2C_SDA 47
#define OBP_I2C_SCL 21
// DS1388 RTC
#define DS1388_I2C_ADDR 0x68 // Addr. 0x68
// BME280
#define BME280_I2C_ADDR 0x76 // Addr. 0x76 (0x77)
// BMP280
#define BMP280_I2C_ADDR 0x77 // Addr. 0x77 (0x76) Attention: Pull up resistor
// BMP085 / BMP180
#define BMP180_I2C_ADDR 0x77 // Addr. 0x77 (fix)
// SHT21 / HUT21
#define SHT21_I2C_ADDR 0x40 // Addr. 0x40 (fix)
// AS5600
#define AS5600_I2C_ADDR 0x36 // Addr. 0x36 (fix)
// INA219
#define SHUNT_VOLTAGE 0.075 // Shunt voltage in V by max. current (75mV)
#define INA219_I2C_ADDR1 0x40 // Addr. 0x41 (fix A0 = 5V, A1 = GND) for battery
#define INA219_I2C_ADDR2 0x41 // Addr. 0x44 (fix A0 = GND, A1 = 5V) for solar panels
#define INA219_I2C_ADDR3 0x45 // Addr. 0x45 (fix A0 = 5V, A1 = 5V) for generator
// INA226
#define INA226_I2C_ADDR1 0x41 // Addr. 0x41 (fix A0 = 5V, A1 = GND) for battery
#define INA226_I2C_ADDR2 0x44 // Addr. 0x44 (fix A0 = GND, A1 = 5V) for solar panels
#define INA226_I2C_ADDR3 0x45 // Addr. 0x45 (fix A0 = 5V, A1 = 5V) for generator
// Horter modules
#define PCF8574_I2C_ADDR1 0x20 // First digital out module
// SPI (E-Ink display, Extern Bus)
#define OBP_SPI_CS 39
#define OBP_SPI_DC 40
#define OBP_SPI_RST 41
#define OBP_SPI_BUSY 42
#define OBP_SPI_CLK 38
#define OBP_SPI_DIN 48
#define SHOW_TIME 6000 // Show time in [ms] for logo and WiFi QR code
#define FULL_REFRESH_TIME 600 // Refresh cycle time in [s][600...3600] for full display update (very important healcy function)
#define MAX_PAGE_NUMBER 10 // Max number of pages for show data
#define FONT1 "Ubuntu_Bold8pt7b"
#define FONT2 "Ubuntu_Bold24pt7b"
#define FONT3 "Ubuntu_Bold32pt7b"
#define FONT4 "DSEG7Classic_BoldItalic80pt7b"
// GPS (NEO-6M, NEO-M8N, ATGM336H)
#define OBP_GPS_RX 2
#define OBP_GPS_TX 1
// 1Wire (DS18B20)
#define OBP_1WIRE 6 // External 1Wire
// Buzzer
#define OBP_BUZZER 16
#define TONE1 1500 // 1500Hz
#define TONE2 2500 // 2500Hz
#define TONE3 3500 // 3500Hz
#define TONE4 4000 // 4000Hz
// Analog Input
#define OBP_ANALOG0 4 // Voltage power supplay
#define MIN_VOLTAGE 10.0 // Min voltage for under voltage detection (then goto deep sleep)
#define POWER_FAIL_TIME 2 // in [ms] Accept min voltage until 2 x 1ms (for under voltage gaps by engine start)
// Touch buttons
#define TP1 14 // Left outside
#define TP2 13
#define TP3 12
#define TP4 11
#define TP5 10
#define TP6 9 // Right outside
// Flash LED (1x WS2812B)
#define NUM_FLASH_LED 1 // Number of flash LED
#define OBP_FLASH_LED 7 // GPIO port
// Backlight LEDs (6x WS2812B)
#define NUM_BACKLIGHT_LED 6 // Numebr of Backlight LEDs
#define OBP_BACKLIGHT_LED 15 // GPIO port
// Power Rail
#define OBP_POWER_50 5 // 5.0V power rail

View File

@@ -1,180 +0,0 @@
#ifndef _OBP60FUNCTIONS_H
#define _OBP60FUNCTIONS_H
#include <Arduino.h>
#include "OBP60Hardware.h"
// Global vars
// Touch keypad over ESP32 touch sensor inputs
int keypad[9]; // Raw data array for keys
int key; // Value of key [0|1], 0 = touched, 1 = not touched
int keycode = 0; // Keycode of pressed key [0...8], 0 = nothing touched
int keycode2 = 0; // Keycode of very short pressed key [0...8], 0 = nothing touched
int keycodeold = 0; // Old keycode
int keycodeold2 = 0; // Old keycode for short pressed key
bool keyoff = false; // Disable all keys
int keydelay = 250; // Delay after key pressed in [ms]
bool keylock = false; // Key lock after pressed key is valid (repeat protection by conginous pressing)
long starttime = 0; // Start time point for pressed key
int readKeypad(uint thSensitivity) {
// Touch sensor values
// 35000 - Not touched
// 50000 - Light toched with fingertip
// 70000 - Touched
// 170000 - Strong touched
uint32_t touchthreshold = (thSensitivity * -1200) + 170000; // thSensitivity 0...100%
int keystatus = 0; // Status of key [0...11], 0 = processed, 1...8 = key 1..8, 9 = right swipe , 10 = left swipe, 11 keys disabled
keycode = 0;
// Read key code
if(touchRead(14) > touchthreshold){ // Touch pad 1
keypad[1] = 1;
}
else{
keypad[1] = 0;
}
if(touchRead(13) > touchthreshold){ // Touch pad 2
keypad[2] = 1;
}
else{
keypad[2] = 0;
}
if(touchRead(12) > touchthreshold){ // Touch pad 3
keypad[3] = 1;
}
else{
keypad[3] = 0;
}
if(touchRead(11) > touchthreshold){ // Touch pad 4
keypad[4] = 1;
}
else{
keypad[4] = 0;
}
if(touchRead(10) > touchthreshold){ // Touch pad 5
keypad[5] = 1;
}
else{
keypad[5] = 0;
}
if(touchRead(9) > touchthreshold){ // Touch pad 6
keypad[6] = 1;
}
else{
keypad[6] = 0;
}
// Nothing touched
if(keypad[1] == 0 && keypad[2] == 0 && keypad[3] == 0 && keypad[4] == 0 && keypad[5] == 0 && keypad[6] == 0){
keypad[0] = 1;
}
else{
keypad[0] = 0;
}
for (int i = 0; i < 9; i++) {
if(i > 0){
// Convert keypad to keycode
if(keypad[i] == 1){
key = 1;
}
else{
key = 0;
}
keycode += key * i;
}
}
// Detect short keynumber
if (keycode > 0 ){
if(keylock == false){
starttime = millis();
keylock = true;
}
if (keycode != keycodeold){
keylock = false;
}
// Detect a very short keynumber (10ms)
if (millis() > starttime + 10 && keycode == keycodeold && keylock == true) {
// Process only valid keys
if(keycode == 1 || keycode == 6){
keycode2 = keycode;
}
// Clear by unvalid keys
else{
keycode2 = 0;
keycodeold2 = 0;
}
}
// Timeout for very short pressed key
if(millis() > starttime + 200){
keycode2 = 0;
}
// Detect a short keynumber (200ms)
if (keyoff == false && millis() > starttime + 200 && keycode == keycodeold && keylock == true) {
keystatus = keycode;
keycode = 0;
keycodeold = 0;
keycode2 = 0;
keycodeold2 = 0;
buzzer(TONE4, 100);
keylock = false;
delay(keydelay);
}
}
// Key lock with key 1 and 6 or 6 and 1 in fast series
if((keycode2 == 1 && keycodeold2 == 6) || (keycode2 == 6 && keycodeold2 == 1)) {
keycode = 0;
keycodeold = 0;
keycode2 = 0;
keycodeold2 = 0;
buzzer(TONE4, 1000);
keylock = false;
delay(keydelay);
keyoff = !keyoff;
keystatus = 11;
}
// Detect swipe right
if (keyoff == false && keycode > 0 && keycodeold > 0 && keycode > keycodeold && !((keycode == 1 && keycodeold == 6) || (keycode == 6 && keycodeold == 1))){
//if (keycode > 0 && keycodeold > 0 && keycode > keycodeold){
keycode = 0;
keycodeold = 0;
keycode2 = 0;
keycodeold2 = 0;
keystatus = 9;
buzzer(TONE3, 150);
buzzer(TONE4, 150);
}
// Detect swipe left
if (keyoff == false && keycode > 0 && keycodeold > 0 && keycode < keycodeold && !((keycode == 1 && keycodeold == 6) || (keycode == 6 && keycodeold == 1))){
//if (keycode > 0 && keycodeold > 0 && keycode < keycodeold){
keycode = 0;
keycodeold = 0;
keycode2 = 0;
keycodeold2 = 0;
keystatus = 10;
buzzer(TONE4, 150);
buzzer(TONE3, 150);
}
// Reset keylock after release
if (keycode == 0){
keylock = false;
}
// Copy keycode
keycodeold = keycode;
keycodeold2 = keycode2;
return keystatus;
}
#endif

View File

@@ -1,59 +0,0 @@
#ifndef _OBP60QRWIFI_H
#define _OBP60QRWIFI_H
#include <Arduino.h>
#include "OBP60Extensions.h"
#include "qrcode.h"
void qrWiFi(String ssid, String passwd, String displaycolor){
// Set display color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set start point and pixel size
int16_t box_x = 100; // X offset
int16_t box_y = 30; // Y offset
int16_t box_s = 6; // Pixel size
int16_t init_x = box_x;
// Create the QR code
QRCode qrcode;
uint8_t qrcodeData[qrcode_getBufferSize(4)];
// Content for QR code: "WIFI:S:mySSID;T:WPA;P:myPASSWORD;;"
String text = "WIFI:S:" + String(ssid) + ";T:WPA;P:" + String(passwd) + ";;";
const char *qrcodecontent = text.c_str();
qrcode_initText(&qrcode, qrcodeData, 4, 0, qrcodecontent);
// Top quiet zone
for (uint8_t y = 0; y < qrcode.size; y++) {
// Each horizontal module
for (uint8_t x = 0; x < qrcode.size; x++) {
if(qrcode_getModule(&qrcode, x, y)){
getdisplay().fillRect(box_x, box_y, box_s, box_s, pixelcolor);
} else {
getdisplay().fillRect(box_x, box_y, box_s, box_s, bgcolor);
}
box_x = box_x + box_s;
}
box_y = box_y + box_s;
box_x = init_x;
}
getdisplay().setFont(&Ubuntu_Bold32pt7b);
getdisplay().setTextColor(textcolor);
getdisplay().setCursor(140, 285);
getdisplay().print("WiFi");
getdisplay().nextPage(); // Full Refresh
}
#endif

View File

@@ -1,699 +0,0 @@
#ifdef BOARD_OBP60S3
#include <Adafruit_Sensor.h> // Adafruit Lib for sensors
#include <Adafruit_BME280.h> // Adafruit Lib for BME280
#include <Adafruit_BMP280.h> // Adafruit Lib for BMP280
#include <Adafruit_BMP085.h> // Adafruit Lib for BMP085 and BMP180
#include <HTU21D.h> // Lib for SHT21/HTU21
#include "AS5600.h" // Lib for magnetic rotation sensor AS5600
#include <INA226.h> // Lib for power management IC INA226
#include <Ticker.h> // Timer Lib for timer
#include <RTClib.h> // DS1388 RTC
#include <OneWire.h> // 1Wire Lib
#include <DallasTemperature.h> // Lib for DS18B20
#include "OBPSensorTask.h" // Lib for sensor reading
#include "OBP60Hardware.h" // Hardware definitions
#include "N2kMessages.h" // Lib for NMEA2000
#include "NMEA0183.h" // Lib for NMEA0183
#include "ObpNmea0183.h" // Check NMEA0183 sentence for uncorrect content
#include "OBP60Extensions.h" // Lib for hardware extensions
#include "movingAvg.h" // Lib for moving average building
// Timer for hardware functions
Ticker Timer1(blinkingFlashLED, 500); // Satrt Timer1 for flash LED all 500ms
// Initialization for all sensors (RS232, I2C, 1Wire, IOs)
//####################################################################################
void sensorTask(void *param){
SharedData *shared = (SharedData *)param;
GwApi *api = shared->api;
GwLog *logger = api->getLogger();
LOG_DEBUG(GwLog::LOG, "Sensor task started");
SensorData sensors;
ObpNmea0183 NMEA0183;
Adafruit_BME280 bme280; // Evironment sensor BME280
Adafruit_BMP280 bmp280; // Evironment sensor BMP280
Adafruit_BMP085 bmp085; // Evironment sensor BMP085 and BMP180
HTU21D sht21(HTU21D_RES_RH12_TEMP14); // Environment sensor SHT21 and HTU21
AMS_5600 as5600; // Rotation sensor AS5600
INA226 ina226_1(INA226_I2C_ADDR1);// Power management sensor INA226 Battery
INA226 ina226_2(INA226_I2C_ADDR2);// Power management sensor INA226 Solar
INA226 ina226_3(INA226_I2C_ADDR3);// Power management sensor INA226 Generator
RTC_DS1388 ds1388; // RTC DS1388
OneWire oneWire(OBP_1WIRE); // 1Wire bus
DallasTemperature ds18b20(&oneWire);// Sensors for DS18B20
DeviceAddress tempDeviceAddress;// Table for DS18B20 device addresses
// Init sensor stuff
bool oneWire_ready = false; // 1Wire initialized and ready to use
bool RTC_ready = false; // DS1388 initialized and ready to use
bool GPS_ready = false; // GPS initialized and ready to use
bool BME280_ready = false; // BME280 initialized and ready to use
bool BMP280_ready = false; // BMP280 initialized and ready to use
bool BMP180_ready = false; // BMP180 initialized and ready to use
bool SHT21_ready = false; // SHT21 initialized and ready to use
bool AS5600_ready = false; // AS5600 initialized and ready to use
bool INA226_1_ready = false; // INA226_1 initialized and ready to use
bool INA226_2_ready = false; // INA226_2 initialized and ready to use
bool INA226_3_ready = false; // INA226_3 initialized and ready to use
// Create integer arrays for average building
const int avgsize = 300;
constexpr int arrayBatV{avgsize};
constexpr int arrayBatC{avgsize};
movingAvg batV(arrayBatV);
movingAvg batC(arrayBatC);
batV.begin();
batC.begin();
// Start timer
Timer1.start(); // Start Timer1 for blinking LED
// Direction settings for NMEA0183
String nmea0183Mode = api->getConfig()->getConfigItem(api->getConfig()->serialDirection, true)->asString();
api->getLogger()->logDebug(GwLog::LOG, "NMEA0183 Mode is: %s", nmea0183Mode.c_str());
pinMode(OBP_DIRECTION_PIN, OUTPUT);
if (String(nmea0183Mode) == "receive" || String(nmea0183Mode) == "off")
{
digitalWrite(OBP_DIRECTION_PIN, false);
}
if (String(nmea0183Mode) == "send")
{
digitalWrite(OBP_DIRECTION_PIN, true);
}
// Internal voltage sensor initialization
String powsensor1 = api->getConfig()->getConfigItem(api->getConfig()->usePowSensor1, true)->asString();
double voffset = (api->getConfig()->getConfigItem(api->getConfig()->vOffset,true)->asString()).toFloat();
double vslope = (api->getConfig()->getConfigItem(api->getConfig()->vSlope,true)->asString()).toFloat();
if(String(powsensor1) == "off"){
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20
sensors.batteryVoltage = sensors.batteryVoltage * vslope + voffset; // Calibration
sensors.batteryCurrent = 0;
sensors.batteryPower = 0;
// Fill average arrays with start values
for (int i=1; i<=avgsize+1; ++i) {
batV.reading(int(sensors.batteryVoltage * 100));
batC.reading(int(sensors.batteryCurrent * 10));
}
}
// Settings for 1Wire bus
String oneWireOn=api->getConfig()->getConfigItem(api->getConfig()->useTempSensor,true)->asString();
int numberOfDevices;
if(String(oneWireOn) == "DS18B20"){
ds18b20.begin();
DeviceAddress tempDeviceAddress;
numberOfDevices = ds18b20.getDeviceCount();
// Limit for 8 sensors
if(numberOfDevices > 8){
numberOfDevices = 8;
}
if (numberOfDevices < 1) {
oneWire_ready = false;
api->getLogger()->logDebug(GwLog::ERROR,"Modul DS18B20 not found, check wiring");
}
else{
api->getLogger()->logDebug(GwLog::LOG,"1Wire modul found at:");
for(int i=0;i<numberOfDevices; i++){
// Search the wire for address
if(ds18b20.getAddress(tempDeviceAddress, i)){
api->getLogger()->logDebug(GwLog::LOG,"DS18B20-%01d: %12d", i, tempDeviceAddress[i]);
} else {
api->getLogger()->logDebug(GwLog::LOG,"DS18B20-%01d: Sensor with errors, check wiring!", i);
}
}
oneWire_ready = true;
}
}
// Settings for RTC
String rtcOn=api->getConfig()->getConfigItem(api->getConfig()->useRTC,true)->asString();
if(String(rtcOn) == "DS1388"){
if (!ds1388.begin()) {
RTC_ready = false;
api->getLogger()->logDebug(GwLog::ERROR,"Modul DS1388 not found, check wiring");
}
else{
api->getLogger()->logDebug(GwLog::LOG,"Modul DS1388 found");
uint year = ds1388.now().year();
if(year < 2023){
// ds1388.adjust(DateTime(__DATE__, __TIME__)); // Set date and time from PC file time
}
RTC_ready = true;
}
}
// Settings for GPS sensors
String gpsOn=api->getConfig()->getConfigItem(api->getConfig()->useGPS,true)->asString();
if(String(gpsOn) == "NEO-6M"){
Serial2.begin(9600, SERIAL_8N1, OBP_GPS_RX, OBP_GPS_TX, false); // not inverted (false)
if (!Serial2) {
api->getLogger()->logDebug(GwLog::ERROR,"GPS modul NEO-6M not found, check wiring");
GPS_ready = false;
}
else{
api->getLogger()->logDebug(GwLog::LOG,"GPS modul NEO-M6 found");
NMEA0183.SetMessageStream(&Serial2);
NMEA0183.Open();
GPS_ready = true;
}
}
if(String(gpsOn) == "NEO-M8N"){
Serial2.begin(9600, SERIAL_8N1, OBP_GPS_RX, OBP_GPS_TX, false); // not inverted (false)
if (!Serial2) {
api->getLogger()->logDebug(GwLog::ERROR,"GPS modul NEO-M8N not found, check wiring");
GPS_ready = false;
}
else{
api->getLogger()->logDebug(GwLog::LOG,"GPS modul NEO-M8N found");
NMEA0183.SetMessageStream(&Serial2);
NMEA0183.Open();
GPS_ready = true;
}
}
if(String(gpsOn) == "ATGM336H"){
Serial2.begin(9600, SERIAL_8N1, OBP_GPS_RX, OBP_GPS_TX, false); // not inverted (false)
if (!Serial2) {
api->getLogger()->logDebug(GwLog::ERROR,"GPS modul ATGM336H not found, check wiring");
GPS_ready = false;
}
else{
api->getLogger()->logDebug(GwLog::LOG,"GPS modul ATGM336H found");
NMEA0183.SetMessageStream(&Serial2);
NMEA0183.Open();
GPS_ready = true;
}
}
// Settings for environment sensors on I2C bus
String envSensors=api->getConfig()->getConfigItem(api->getConfig()->useEnvSensor,true)->asString();
if(String(envSensors) == "BME280"){
if (!bme280.begin(BME280_I2C_ADDR)) {
api->getLogger()->logDebug(GwLog::ERROR,"Modul BME280 not found, check wiring");
}
else{
api->getLogger()->logDebug(GwLog::LOG,"Modul BME280 found");
sensors.airTemperature = bme280.readTemperature();
sensors.airPressure = bme280.readPressure()/100;
sensors.airHumidity = bme280.readHumidity();
BME280_ready = true;
}
}
else if(String(envSensors) == "BMP280"){
if (!bmp280.begin(BMP280_I2C_ADDR)) {
api->getLogger()->logDebug(GwLog::ERROR,"Modul BMP280 not found, check wiring");
}
else{
api->getLogger()->logDebug(GwLog::LOG,"Modul BMP280 found");
sensors.airTemperature = bmp280.readTemperature();
sensors.airPressure =bmp280.readPressure()/100;
BMP280_ready = true;
}
}
else if(String(envSensors) == "BMP085" || String(envSensors) == "BMP180"){
if (!bmp085.begin()) {
api->getLogger()->logDebug(GwLog::ERROR,"Modul BMP085/BMP180 not found, check wiring");
}
else{
api->getLogger()->logDebug(GwLog::LOG,"Modul BMP085/BMP180 found");
sensors.airTemperature = bmp085.readTemperature();
sensors.airPressure =bmp085.readPressure()/100;
BMP180_ready = true;
}
}
else if(String(envSensors) == "HTU21" || String(envSensors) == "SHT21"){
if (!sht21.begin()) {
api->getLogger()->logDebug(GwLog::ERROR,"Modul HTU21/SHT21 not found, check wiring");
}
else{
api->getLogger()->logDebug(GwLog::LOG,"Modul HTU21/SHT21 found");
sensors.airHumidity = sht21.readCompensatedHumidity();
sensors.airTemperature = sht21.readTemperature();
SHT21_ready = true;
}
}
// Settings for rotation sensors AS5600 on I2C bus
String envsensor = api->getConfig()->getConfigItem(api->getConfig()->useEnvSensor, true)->asString();
String rotsensor = api->getConfig()->getConfigItem(api->getConfig()->useRotSensor, true)->asString();
String rotfunction = api->getConfig()->getConfigItem(api->getConfig()->rotFunction, true)->asString();
String rotSensor=api->getConfig()->getConfigItem(api->getConfig()->useRotSensor,true)->asString();
if(String(rotSensor) == "AS5600"){
Wire.beginTransmission(AS5600_I2C_ADDR);
if (Wire.endTransmission() != 0) {
api->getLogger()->logDebug(GwLog::ERROR,"Modul AS5600 not found, check wiring");
}
else{
api->getLogger()->logDebug(GwLog::LOG,"Modul AS5600 found");
sensors.rotationAngle = DegToRad(as5600.getRawAngle() * 0.087); // 0...4095 segments = 0.087 degree
//sensors.magnitude = as5600.getMagnitude(); // Magnetic magnitude in [mT]
AS5600_ready = true;
}
}
// Settings for power amangement sensors INA226 #1 for Battery on I2C bus
String shunt1 = api->getConfig()->getConfigItem(api->getConfig()->shunt1, true)->asString();
// Settings for power amangement sensors INA226 #1 for Solar on I2C bus
String powsensor2 = api->getConfig()->getConfigItem(api->getConfig()->usePowSensor2, true)->asString();
String shunt2 = api->getConfig()->getConfigItem(api->getConfig()->shunt2, true)->asString();
// Settings for power amangement sensors INA226 #1 for Generator on I2C bus
String powsensor3 = api->getConfig()->getConfigItem(api->getConfig()->usePowSensor3, true)->asString();
String shunt3 = api->getConfig()->getConfigItem(api->getConfig()->shunt3, true)->asString();
float shuntResistor = 1.0; // Default value for shunt resistor
float maxCurrent = 10.0; // Default value for max. current
float corrFactor = 1; // Correction factor for fix calibration
// Battery sensor initialization
if(String(powsensor1) == "INA226"){
if (!ina226_1.begin()){
api->getLogger()->logDebug(GwLog::ERROR,"Modul 1 INA226 not found, check wiring");
}
else{
api->getLogger()->logDebug(GwLog::LOG,"Modul 1 INA226 found");
shuntResistor = SHUNT_VOLTAGE / float(shunt1.toInt()); // Calculate shunt resisitor for max. shunt voltage 75mV
maxCurrent = shunt1.toFloat();
api->getLogger()->logDebug(GwLog::LOG,"Calibation Modul 2 INA226, Imax:%3.0fA Rs:%7.5fOhm Us:%5.3f", maxCurrent, shuntResistor, SHUNT_VOLTAGE);
// ina226_1.setMaxCurrentShunt(maxCurrent, shuntResistor);
ina226_1.setMaxCurrentShunt(10, 0.01); // Calibration with fix values (because the original values outer range)
corrFactor = (maxCurrent / 10) * (0.001 / shuntResistor) / (maxCurrent / 100); // Correction factor for fix calibration
sensors.batteryVoltage = ina226_1.getBusVoltage();
sensors.batteryCurrent = ina226_1.getCurrent() * corrFactor;
sensors.batteryPower = ina226_1.getPower() * corrFactor;
// Fill average arrays with start values
for (int i=1; i<=avgsize+1; ++i) {
batV.reading(int(sensors.batteryVoltage * 100));
batC.reading(int(sensors.batteryCurrent * 10));
}
INA226_1_ready = true;
}
}
// Solar sensor initialization
if(String(powsensor2) == "INA226"){
if (!ina226_2.begin()){
api->getLogger()->logDebug(GwLog::ERROR,"Modul 2 INA226 not found, check wiring");
}
else{
api->getLogger()->logDebug(GwLog::LOG,"Modul 2 INA226 found");
shuntResistor = SHUNT_VOLTAGE / float(shunt2.toInt()); // Calculate shunt resisitor for max. shunt voltage 75mV
maxCurrent = shunt2.toFloat();
api->getLogger()->logDebug(GwLog::LOG,"Calibation Modul 2 INA226, Imax:%3.0fA Rs:%7.5fOhm Us:%5.3f", maxCurrent, shuntResistor, SHUNT_VOLTAGE);
// ina226_1.setMaxCurrentShunt(maxCurrent, shuntResistor);
ina226_2.setMaxCurrentShunt(10, 0.01); // Calibration with fix values (because the original values outer range)
corrFactor = (maxCurrent / 10) * (0.001 / shuntResistor) / (maxCurrent / 100); // Correction factor for fix calibration
sensors.solarVoltage = ina226_2.getBusVoltage();
sensors.solarCurrent = ina226_2.getCurrent() * corrFactor;
sensors.solarPower = ina226_2.getPower() * corrFactor;
// Fill average arrays with start values
INA226_2_ready = true;
}
}
// Generator sensor initialization
if(String(powsensor3) == "INA226"){
if (!ina226_3.begin()){
api->getLogger()->logDebug(GwLog::ERROR,"Modul 3 INA226 not found, check wiring");
}
else{
api->getLogger()->logDebug(GwLog::LOG,"Modul 3 INA226 found");
shuntResistor = SHUNT_VOLTAGE / float(shunt3.toInt()); // Calculate shunt resisitor for max. shunt voltage 75mV
maxCurrent = shunt3.toFloat();
api->getLogger()->logDebug(GwLog::LOG,"Calibation Modul 3 INA226, Imax:%3.0fA Rs:%7.5fOhm Us:%5.3f", maxCurrent, shuntResistor, SHUNT_VOLTAGE);
// ina226_1.setMaxCurrentShunt(maxCurrent, shuntResistor);
ina226_3.setMaxCurrentShunt(10, 0.01); // Calibration with fix values (because the original values outer range)
corrFactor = (maxCurrent / 10) * (0.001 / shuntResistor) / (maxCurrent / 100); // Correction factor for fix calibration
sensors.generatorVoltage = ina226_3.getBusVoltage();
sensors.generatorCurrent = ina226_3.getCurrent() * corrFactor;
sensors.generatorPower = ina226_3.getPower() * corrFactor;
// Fill average arrays with start values
INA226_3_ready = true;
}
}
int rotoffset = api->getConfig()->getConfigItem(api->getConfig()->rotOffset,true)->asInt();
static long loopCounter = 0; // Loop counter for 1Wire data transmission
long starttime0 = millis(); // GPS update all 100ms
long starttime5 = millis(); // Voltage update all 1s
long starttime6 = millis(); // Environment sensor update all 1s
long starttime7 = millis(); // Rotation sensor update all 500ms
long starttime8 = millis(); // Battery power sensor update all 1s
long starttime9 = millis(); // Solar power sensor update all 1s
long starttime10 = millis(); // Generator power sensor update all 1s
long starttime11 = millis(); // Copy GPS data to RTC all 5min
long starttime12 = millis(); // Get RTC data all 500ms
long starttime13 = millis(); // Get 1Wire sensor data all 2s
tN2kMsg N2kMsg;
shared->setSensorData(sensors); //set initially read values
GwApi::BoatValue *gpsdays=new GwApi::BoatValue(GwBoatData::_GPSD);
GwApi::BoatValue *gpsseconds=new GwApi::BoatValue(GwBoatData::_GPST);
GwApi::BoatValue *valueList[]={gpsdays, gpsseconds};
// Sensor task loop runs with 100ms
//####################################################################################
while (true){
delay(100); // Loop time 100ms
Timer1.update(); // Update for Timer2
if (millis() > starttime0 + 100)
{
starttime0 = millis();
// Send NMEA0183 GPS data on several bus systems all 100ms
if (GPS_ready == true)
{
SNMEA0183Msg NMEA0183Msg;
while (NMEA0183.GetMessageCor(NMEA0183Msg))
{
api->sendNMEA0183Message(NMEA0183Msg);
}
}
}
// If RTC DS1388 ready, then copy GPS data to RTC all 5min
if(millis() > starttime11 + 5*60*1000){
starttime11 = millis();
if(rtcOn == "DS1388" && RTC_ready == true && GPS_ready == true){
api->getBoatDataValues(2,valueList);
if(gpsdays->valid && gpsseconds->valid){
long ts = tNMEA0183Msg::daysToTime_t(gpsdays->value - (30*365+7))+floor(gpsseconds->value); // Adjusted to reference year 2000 (-30 years and 7 days for switch years)
// sample input: date = "Dec 26 2009", time = "12:34:56"
// ds1388.adjust(DateTime("Dec 26 2009", "12:34:56"));
DateTime adjusttime(ts);
api->getLogger()->logDebug(GwLog::LOG,"Adjust RTC time: %04d/%02d/%02d %02d:%02d:%02d",adjusttime.year(), adjusttime.month(), adjusttime.day(), adjusttime.hour(), adjusttime.minute(), adjusttime.second());
// Adjust RTC time as unix time value
ds1388.adjust(adjusttime);
}
}
}
// Send 1Wire data for all temperature sensors all 2s
if(millis() > starttime13 + 2000 && String(oneWireOn) == "DS18B20" && oneWire_ready == true){
starttime13 = millis();
float tempC;
ds18b20.requestTemperatures(); // Collect all temperature values (max.8)
for(int i=0;i<numberOfDevices; i++){
// Send only one 1Wire data per loop step (time reduction)
if(i == loopCounter % numberOfDevices){
if(ds18b20.getAddress(tempDeviceAddress, i)){
// Read temperature value in Celsius
tempC = ds18b20.getTempC(tempDeviceAddress);
}
// Send to NMEA200 bus for each sensor with instance number
if(!isnan(tempC)){
sensors.onewireTemp[i] = tempC; // Save values in SensorData
api->getLogger()->logDebug(GwLog::DEBUG,"DS18B20-%1d Temp: %.1f",i,tempC);
SetN2kPGN130316(N2kMsg, 0, i, N2kts_OutsideTemperature, CToKelvin(tempC), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
}
}
loopCounter++;
}
// If GPS not ready or installed then send RTC time on bus all 500ms
if(millis() > starttime12 + 500){
starttime12 = millis();
if(rtcOn == "DS1388" && RTC_ready == true && GPS_ready == false){
// Convert RTC time to Unix system time
// https://de.wikipedia.org/wiki/Unixzeit
const short daysOfYear[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
long unixtime = ds1388.now().get();
uint16_t year = ds1388.now().year();
uint8_t month = ds1388.now().month();
uint8_t hour = ds1388.now().hour();
uint8_t minute = ds1388.now().minute();
uint8_t second = ds1388.now().second();
uint8_t day = ds1388.now().day();
uint16_t switchYear = ((year-1)-1968)/4 - ((year-1)-1900)/100 + ((year-1)-1600)/400;
long daysAt1970 = (year-1970)*365 + switchYear + daysOfYear[month-1] + day-1;
// If switch year then add one day
if ( (month>2) && (year%4==0 && (year%100!=0 || year%400==0)) ){
daysAt1970 += 1;
}
double sysTime = (hour * 3600) + (minute * 60) + second;
if(!isnan(daysAt1970) && !isnan(sysTime)){
sensors.rtcYear = year; // Save values in SensorData
sensors.rtcMonth = month;
sensors.rtcDay = day;
sensors.rtcHour = hour;
sensors.rtcMinute = minute;
sensors.rtcSecond = second;
// api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",year, month, day, hour, minute, second);
// api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime);
SetN2kPGN126992(N2kMsg,0,daysAt1970,sysTime,N2ktimes_LocalCrystalClock);
api->sendN2kMessage(N2kMsg);
}
}
}
// Send supplay voltage value all 1s
if(millis() > starttime5 + 1000 && String(powsensor1) == "off"){
starttime5 = millis();
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20
sensors.batteryVoltage = sensors.batteryVoltage * vslope + voffset; // Calibration
// Save new data in average array
batV.reading(int(sensors.batteryVoltage * 100));
// Calculate the average values for different time lines from integer values
sensors.batteryVoltage10 = batV.getAvg(10) / 100.0;
sensors.batteryVoltage60 = batV.getAvg(60) / 100.0;
sensors.batteryVoltage300 = batV.getAvg(300) / 100.0;
// Send to NMEA200 bus
if(!isnan(sensors.batteryVoltage)){
SetN2kDCBatStatus(N2kMsg, 0, sensors.batteryVoltage, N2kDoubleNA, N2kDoubleNA, 1);
api->sendN2kMessage(N2kMsg);
}
}
// Send data from environment sensor all 2s
if(millis() > starttime6 + 2000){
starttime6 = millis();
unsigned char TempSource = 2; // Inside temperature
unsigned char PressureSource = 0; // Atmospheric pressure
unsigned char HumiditySource=0; // Inside humidity
if(envsensor == "BME280" && BME280_ready == true){
sensors.airTemperature = bme280.readTemperature();
sensors.airPressure = bme280.readPressure()/100;
sensors.airHumidity = bme280.readHumidity();
// Send to NMEA200 bus
if(!isnan(sensors.airTemperature)){
SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airHumidity)){
SetN2kPGN130313(N2kMsg, 0, 0,(tN2kHumiditySource) HumiditySource, sensors.airHumidity, N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airPressure)){
SetN2kPGN130314(N2kMsg, 0, 0, (tN2kPressureSource) mBarToPascal(PressureSource), sensors.airPressure);
api->sendN2kMessage(N2kMsg);
}
}
else if(envsensor == "BMP280" && BMP280_ready == true){
sensors.airTemperature = bmp280.readTemperature();
sensors.airPressure =bmp280.readPressure()/100;
// Send to NMEA200 bus
if(!isnan(sensors.airTemperature)){
SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airPressure)){
SetN2kPGN130314(N2kMsg, 0, 0, (tN2kPressureSource) mBarToPascal(PressureSource), sensors.airPressure);
api->sendN2kMessage(N2kMsg);
}
}
else if((envsensor == "BMP085" || envsensor == "BMP180") && BMP180_ready == true){
sensors.airTemperature = bmp085.readTemperature();
sensors.airPressure =bmp085.readPressure()/100;
// Send to NMEA200 bus
if(!isnan(sensors.airTemperature)){
SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airPressure)){
SetN2kPGN130314(N2kMsg, 0, 0, (tN2kPressureSource) mBarToPascal(PressureSource), sensors.airPressure);
api->sendN2kMessage(N2kMsg);
}
}
else if((envsensor == "SHT21" || envsensor == "HTU21") && SHT21_ready == true){
sensors.airHumidity = sht21.readCompensatedHumidity();
sensors.airTemperature = sht21.readTemperature();
// Send to NMEA200 bus
if(!isnan(sensors.airTemperature)){
SetN2kPGN130312(N2kMsg, 0, 0,(tN2kTempSource) TempSource, CToKelvin(sensors.airTemperature), N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
if(!isnan(sensors.airHumidity)){
SetN2kPGN130313(N2kMsg, 0, 0,(tN2kHumiditySource) HumiditySource, sensors.airHumidity, N2kDoubleNA);
api->sendN2kMessage(N2kMsg);
}
}
}
// Send rotation angle all 500ms
if(millis() > starttime7 + 500){
starttime7 = millis();
double rotationAngle=0;
if(String(rotsensor) == "AS5600" && AS5600_ready == true && as5600.detectMagnet() == 1){
rotationAngle = as5600.getRawAngle() * 0.087; // 0...4095 segments = 0.087 degree
// Offset correction
if(rotoffset >= 0){
rotationAngle = rotationAngle + rotoffset;
rotationAngle = int(rotationAngle) % 360;
}
else{
rotationAngle = rotationAngle + 360 + rotoffset;
rotationAngle = int(rotationAngle) % 360;
}
// Send to NMEA200 bus as rudder angle values
if(!isnan(rotationAngle) && String(rotfunction) == "Rudder"){
double rudder = rotationAngle - 180; // Center position is 180°
// Rudder limits to +/-45°
if(rudder < -45){
rudder = -45;
}
if(rudder > 45){
rudder = 45;
}
SetN2kRudder(N2kMsg, DegToRad(rudder), 0, N2kRDO_NoDirectionOrder, PI);
api->sendN2kMessage(N2kMsg);
}
// Send to NMEA200 bus as wind angle values
if(!isnan(rotationAngle) && String(rotfunction) == "Wind"){
SetN2kWindSpeed(N2kMsg, 1, 0, DegToRad(rotationAngle), N2kWind_Apprent);
api->sendN2kMessage(N2kMsg);
}
// Send to NMEA200 bus as trim angle values in [%]
if(!isnan(rotationAngle) && (String(rotfunction) == "Mast" || String(rotfunction) == "Keel" || String(rotfunction) == "Trim" || String(rotfunction) == "Boom")){
int trim = rotationAngle * 100 / 360; // 0...360° -> 0...100%
SetN2kTrimTab(N2kMsg, trim, trim);
api->sendN2kMessage(N2kMsg);
}
sensors.rotationAngle = DegToRad(rotationAngle); // Data take over to page
sensors.validRotAngle = true; // Valid true, magnet present
}
else{
sensors.rotationAngle = 0; // Center position 0°
sensors.validRotAngle = false; // Valid false, magnet missing
}
}
// Send battery power value all 1s
if(millis() > starttime8 + 1000 && (String(powsensor1) == "INA219" || String(powsensor1) == "INA226")){
starttime8 = millis();
if(String(powsensor1) == "INA226" && INA226_1_ready == true){
double voltage = ina226_1.getBusVoltage();
// Limiter for voltage average building
if(voltage < 0){
voltage = 0;
}
if(voltage > 30){
voltage = 30;
}
sensors.batteryVoltage = voltage;
sensors.batteryCurrent = ina226_1.getCurrent() * corrFactor;
// Eliminates bit jitter by zero current values
float factor = maxCurrent / 100;
if(sensors.batteryCurrent >= (-0.015 * factor) && sensors.batteryCurrent <= (0.015 * factor)){
sensors.batteryCurrent = 0;
}
// Save actual values in average arrays as integer values
batV.reading(int(sensors.batteryVoltage * 100));
batC.reading(int(sensors.batteryCurrent * 10));
// Calculate the average values for different time lines from integer values
sensors.batteryVoltage10 = batV.getAvg(10) / 100.0;
sensors.batteryVoltage60 = batV.getAvg(60) / 100.0;
sensors.batteryVoltage300 = batV.getAvg(300) / 100.0;
sensors.batteryCurrent10 = batC.getAvg(10) / 10.0;
sensors.batteryCurrent60 = batC.getAvg(60) / 10.0;
sensors.batteryCurrent300 = batC.getAvg(300) / 10.0;
sensors.batteryPower10 = sensors.batteryVoltage10 * sensors.batteryCurrent10;
sensors.batteryPower60 = sensors.batteryVoltage60 * sensors.batteryCurrent60;
sensors.batteryPower300 = sensors.batteryVoltage300 * sensors.batteryCurrent300;
// sensors.batteryPower = ina226_1.getPower() * corrFactor; // Real value
sensors.batteryPower = sensors.batteryVoltage * sensors.batteryCurrent; // Calculated power value (more stable)
}
// Send battery live data to NMEA200 bus
if(!isnan(sensors.batteryVoltage) && !isnan(sensors.batteryCurrent)){
SetN2kDCBatStatus(N2kMsg, 0, sensors.batteryVoltage, sensors.batteryCurrent, N2kDoubleNA, 1);
api->sendN2kMessage(N2kMsg);
}
}
// Send solar power value all 1s
if(millis() > starttime9 + 1000 && (String(powsensor2) == "INA219" || String(powsensor2) == "INA226")){
starttime9 = millis();
if(String(powsensor2) == "INA226" && INA226_2_ready == true){
double voltage = ina226_2.getBusVoltage();
// Limiter for voltage average building
if(voltage < 0){
voltage = 0;
}
if(voltage > 30){
voltage = 30;
}
sensors.solarVoltage = voltage;
sensors.solarCurrent = ina226_2.getCurrent() * corrFactor;
// Eliminates bit jitter by zero current values
float factor = maxCurrent / 100;
if(sensors.solarCurrent >= (-0.015 * factor) && sensors.solarCurrent <= (0.015 * factor)){
sensors.solarCurrent = 0;
}
// Calculate power value
sensors.solarPower = sensors.solarVoltage * sensors.solarCurrent; // more stable
}
// Send solar live data to NMEA200 bus
if(!isnan(sensors.solarVoltage) && !isnan(sensors.solarCurrent)){
SetN2kDCBatStatus(N2kMsg, 1, sensors.solarVoltage, sensors.solarCurrent, N2kDoubleNA, 1);
api->sendN2kMessage(N2kMsg);
}
}
// Send generator power value all 1s
if(millis() > starttime10 + 1000 && (String(powsensor3) == "INA219" || String(powsensor3) == "INA226")){
starttime10 = millis();
if(String(powsensor3) == "INA226" && INA226_3_ready == true){
double voltage = ina226_3.getBusVoltage();
// Limiter for voltage average building
if(voltage < 0){
voltage = 0;
}
if(voltage > 30){
voltage = 30;
}
sensors.generatorVoltage = voltage;
sensors.generatorCurrent = ina226_3.getCurrent() * corrFactor;
// Eliminates bit jitter by zero current values
float factor = maxCurrent / 100;
if(sensors.generatorCurrent >= (-0.015 * factor) && sensors.generatorCurrent <= (0.015 * factor)){
sensors.generatorCurrent = 0;
}
// Calculate power value
sensors.generatorPower = sensors.generatorVoltage * sensors.generatorCurrent; // more stable
}
// Send solar live data to NMEA200 bus
if(!isnan(sensors.generatorVoltage) && !isnan(sensors.generatorCurrent)){
SetN2kDCBatStatus(N2kMsg, 2, sensors.generatorVoltage, sensors.generatorCurrent, N2kDoubleNA, 1);
api->sendN2kMessage(N2kMsg);
}
}
shared->setSensorData(sensors);
}
vTaskDelete(NULL);
}
void createSensorTask(SharedData *shared){
xTaskCreate(sensorTask,"readSensors",10000,shared,3,NULL);
}
#endif

View File

@@ -1,29 +0,0 @@
#pragma once
#include "GwSynchronized.h"
#include "GwApi.h"
#include "freertos/semphr.h"
#include "Pagedata.h"
class SharedData{
private:
SemaphoreHandle_t locker;
SensorData sensors;
public:
GwApi *api=NULL;
SharedData(GwApi *api){
locker=xSemaphoreCreateMutex();
this->api=api;
}
void setSensorData(SensorData &values){
GWSYNCHRONIZED(&locker);
sensors=values;
}
SensorData getSensorData(){
GWSYNCHRONIZED(&locker);
return sensors;
}
};
void createSensorTask(SharedData *shared);

View File

@@ -1,54 +0,0 @@
#pragma once
#include "NMEA0183.h"
#include "GwNmea0183Msg.h"
class ObpNmea0183 : public tNMEA0183
{
public:
bool GetMessageCor(SNMEA0183Msg &NMEA0183Msg)
{
if (!IsOpen())
return false;
bool result = false;
while (port->available() > 0 && !result)
{
int NewByte = port->read();
if (NewByte == '$' || NewByte == '!')
{ // Message start
MsgInStarted = true;
MsgInPos = 0;
MsgInBuf[MsgInPos] = NewByte;
MsgInPos++;
}
else if (MsgInStarted)
{
MsgInBuf[MsgInPos] = NewByte;
if (NewByte == '*')
MsgCheckSumStartPos = MsgInPos;
MsgInPos++;
if (MsgCheckSumStartPos != SIZE_MAX and MsgCheckSumStartPos + 3 == MsgInPos)
{ // We have full checksum and so full message
MsgInBuf[MsgInPos] = 0; // add null termination
if (NMEA0183Msg.SetMessageCor(MsgInBuf))
{
NMEA0183Msg.SourceID = SourceID;
result = true;
}
MsgInStarted = false;
MsgInPos = 0;
MsgCheckSumStartPos = SIZE_MAX;
}
if (MsgInPos >= MAX_NMEA0183_MSG_BUF_LEN)
{ // Too may chars in message. Start from beginning
MsgInStarted = false;
MsgInPos = 0;
MsgCheckSumStartPos = SIZE_MAX;
}
}
}
return result;
}
};

View File

@@ -1,208 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageApparentWind : public Page
{
bool keylock = false; // Keylock
int16_t lp = 80; // Pointer length
public:
PageApparentWind(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageApparentWind");
}
// Key functions
virtual int handleKey(int key){
// Reduce instrument size
if(key == 2){ // Code for reduce
lp = lp - 10;
if(lp < 10){
lp = 10;
}
return 0; // Commit the key
}
// Enlarge instrument size
if(key == 5){ // Code for enlarge
lp = lp + 10;
if(lp > 80){
lp = 80;
}
return 0; // Commit the key
}
// Keylock function
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData)
{
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
static String svalue1old = "";
static String unit1old = "";
static String svalue2old = "";
static String unit2old = "";
// Get config data
String lengthformat = config->getString(config->lengthFormat);
// bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
// Get boat values for AWS
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
String name1 = bvalue1->getName().c_str(); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
double value1 = bvalue1->value; // Value as double in SI unit
// bool valid1 = bvalue1->valid; // Valid information
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
// Get boat values for AWD
GwApi::BoatValue *bvalue2 = pageData.values[1]; // First element in list (only one value by PageOneValue)
String name2 = bvalue2->getName().c_str(); // Value name
name2 = name2.substring(0, 6); // String length limit for value name
double value2 = bvalue2->value; // Value as double in SI unit
// bool valid2 = bvalue2->valid; // Valid information
String svalue2 = formatValue(bvalue2, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit2 = formatValue(bvalue2, commonData).unit; // Unit of value
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageApparentWind, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Show values AWS
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 50);
if(holdvalues == false){
getdisplay().print(name1); // Value name
getdisplay().print(": ");
getdisplay().print(svalue1); // Value
getdisplay().print(" ");
getdisplay().print(unit1); // Unit
}
else{
getdisplay().print(name1); // Value name
getdisplay().print(": ");
getdisplay().print(svalue1old); // Value old
getdisplay().print(" ");
getdisplay().print(unit1old); // Unit old
}
// Show values AWD
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 260);
if(holdvalues == false){
getdisplay().print(name2); // Value name
getdisplay().print(": ");
getdisplay().print(svalue2); // Value
getdisplay().print(" ");
getdisplay().print(unit2); // Unit
}
else{
getdisplay().print(name2); // Value name
getdisplay().print(": ");
getdisplay().print(svalue2old); // Value old
getdisplay().print(" ");
getdisplay().print(unit2old); // Unit old
}
// Draw wind pointer
static int16_t x0 = 200; // Center point
static int16_t y0 = 145;
static int16_t x1 = x0; // Start point for pointer
static int16_t y1 = y0;
static int16_t x2 = x0; // End point for pointer
static int16_t y2 = y0;
//Draw instrument
getdisplay().fillCircle(x0, y0, lp + 5, pixelcolor); // Black circle
getdisplay().fillCircle(x0, y0, lp + 1, bgcolor); // White circle
// Calculation end point of pointer
value2 = value2 - 3.14 / 2;
x1 = x0 + cos(value2) * lp * 0.6;
y1 = y0 + sin(value2) * lp * 0.6;
x2 = x0 + cos(value2) * lp;
y2 = y0 + sin(value2) * lp;
getdisplay().drawLine(x1, y1, x2, y2, pixelcolor);
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageApparentWind(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect (0 here)
* and will will provide the names of the fixed values we need
*/
PageDescription registerPageApparentWind(
"ApparentWind", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{"AWS","AWA"}, // Bus values we need in the page
true // Show display header on/off
);
#endif

View File

@@ -1,239 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageBME280 : public Page
{
bool keylock = false; // Keylock
public:
PageBME280(CommonData &comon){
comon.logger->logDebug(GwLog::LOG,"Show PageThreeValue");
}
virtual int handleKey(int key){
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData){
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
double value1 = 0;
double value2 = 0;
double value3 = 0;
String svalue1 = "";
String svalue2 = "";
String svalue3 = "";
// Get config data
String tempformat = config->getString(config->tempFormat);
bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
String useenvsensor = config->getString(config->useEnvSensor);
// Get sensor values #1
String name1 = "Temp"; // Value name
name1 = name1.substring(0, 6); // String length limit for value name
if(simulation == false){
value1 = commonData.data.airTemperature; // Value as double in SI unit
}
else{
value1 = 23.0 + float(random(0, 10)) / 10.0;
}
// Display data when sensor activated
if(String(useenvsensor) == "BME280"){
svalue1 = String(value1, 1); // Formatted value as string including unit conversion and switching decimal places
}
else{
svalue1 = "---";
}
String unit1 = "Deg C"; // Unit of value
// Get sensor values #2
String name2 = "Humid"; // Value name
name2 = name2.substring(0, 6); // String length limit for value name
if(simulation == false){
value2 = commonData.data.airHumidity; // Value as double in SI unit
}
else{
value2 = 43 + float(random(0, 4));
}
// Display data when sensor activated
if(String(useenvsensor) == "BME280"){
svalue2 = String(value2, 0); // Formatted value as string including unit conversion and switching decimal places
}
else{
svalue2 = "---";
}
String unit2 = "%"; // Unit of value
// Get sensor values #3
String name3 = "Press"; // Value name
name3 = name3.substring(0, 6); // String length limit for value name
if(simulation == false){
value3 = commonData.data.airPressure; // Value as double in SI unit
}
else{
value3 = 1006 + float(random(0, 5));
}
// Display data when sensor activated
if(String(useenvsensor) == "BME280"){
svalue3 = String(value3, 0); // Formatted value as string including unit conversion and switching decimal places
}
else{
svalue3 = "---";
}
String unit3 = "hPa"; // Unit of value
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
LOG_DEBUG(GwLog::LOG,"Drawing at PageBME280, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// ############### Value 1 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 55);
getdisplay().print(name1); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 90);
getdisplay().print(unit1); // Unit
// Switch font if format for any values
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 90);
// Show bus data
getdisplay().print(svalue1); // Real value as formated string
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 105, 400, 3, pixelcolor);
// ############### Value 2 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 145);
getdisplay().print(name2); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 180);
getdisplay().print(unit2); // Unit
// Switch font if format for any values
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 180);
// Show bus data
getdisplay().print(svalue2); // Real value as formated string
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 195, 400, 3, pixelcolor);
// ############### Value 3 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 235);
getdisplay().print(name3); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 270);
getdisplay().print(unit3); // Unit
// Switch font if format for any values
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 270);
// Show bus data
getdisplay().print(svalue3); // Real value as formated string
// ############### Key Layout ################
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageBME280(common);
}/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageBME280(
"BME280", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
true // Show display header on/off
);
#endif

View File

@@ -1,351 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageBattery : public Page
{
bool keylock = false; // Keylock
int average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s
public:
PageBattery(CommonData &comon){
comon.logger->logDebug(GwLog::LOG,"Show PageThreeValue");
}
virtual int handleKey(int key){
// Change average
if(key == 1){
average ++;
average = average % 4; // Modulo 4
return 0; // Commit the key
}
// Code for keylock
if(key == 11){
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData){
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Old values for hold function
double value1 = 0;
static String svalue1old = "";
static String unit1old = "";
double value2 = 0;
static String svalue2old = "";
static String unit2old = "";
double value3 = 0;
static String svalue3old = "";
static String unit3old = "";
// Get config data
String lengthformat = config->getString(config->lengthFormat);
// bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
String powsensor1 = config->getString(config->usePowSensor1);
bool simulation = config->getBool(config->useSimuData);
// Get voltage value
String name1 = "VBat"; // Value name
if(String(powsensor1) == "INA219" || String(powsensor1) == "INA226"){
// Switch average values
switch (average) {
case 0:
value1 = commonData.data.batteryVoltage; // Live data
break;
case 1:
value1 = commonData.data.batteryVoltage10; // Average 10s
break;
case 2:
value1 = commonData.data.batteryVoltage60; // Average 60s
break;
case 3:
value1 = commonData.data.batteryVoltage300; // Average 300s
break;
default:
value1 = commonData.data.batteryVoltage; // Default
break;
}
}
else{
if(simulation == true){
value1 = 12 + float(random(0, 5)) / 10; // Simulation data
}
}
String svalue1 = String(value1); // Formatted value as string including unit conversion and switching decimal places
String unit1 = "V"; // Unit of value
// Get current value
String name2 = "IBat"; // Value name
if(String(powsensor1) == "INA219" || String(powsensor1) == "INA226"){
switch (average) {
case 0:
value2 = commonData.data.batteryCurrent; // Live data
break;
case 1:
value2 = commonData.data.batteryCurrent10; // Average 10s
break;
case 2:
value2 = commonData.data.batteryCurrent60; // Average 60s
break;
case 3:
value2 = commonData.data.batteryCurrent300; // Average 300s
break;
default:
value2 = commonData.data.batteryCurrent; // Default
break;
}
}
else{
if(simulation == true){
value2 = 8 + float(random(0, 10)) / 10; // Simulation data
}
}
String svalue2 = String(value2); // Formatted value as string including unit conversion and switching decimal places
String unit2 = "A"; // Unit of value
// Get power value
String name3 = "PBat"; // Value name
if(String(powsensor1) == "INA219" || String(powsensor1) == "INA226"){
switch (average) {
case 0:
value3 = commonData.data.batteryPower; // Live data
break;
case 1:
value3 = commonData.data.batteryPower10; // Average 10s
break;
case 2:
value3 = commonData.data.batteryPower60; // Average 60s
break;
case 3:
value3 = commonData.data.batteryPower300; // Average 300s
break;
default:
value3 = commonData.data.batteryPower; // Default
break;
}
}
else{
if(simulation == true){
value3 = value1 * value2; // Simulation data
}
}
String svalue3 = String(value3); // Formatted value as string including unit conversion and switching decimal places
String unit3 = "W"; // Unit of value
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
LOG_DEBUG(GwLog::LOG,"Drawing at PageBattery, %s: %f, %s: %f, %s: %f, Avg: %d", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, average);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Show average settings
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
switch (average) {
case 0:
getdisplay().setCursor(60, 90);
getdisplay().print("Avg: 1s");
getdisplay().setCursor(60, 180);
getdisplay().print("Avg: 1s");
getdisplay().setCursor(60, 270);
getdisplay().print("Avg: 1s");
break;
case 1:
getdisplay().setCursor(60, 90);
getdisplay().print("Avg: 10s");
getdisplay().setCursor(60, 180);
getdisplay().print("Avg: 10s");
getdisplay().setCursor(60, 270);
getdisplay().print("Avg: 10s");
break;
case 2:
getdisplay().setCursor(60, 90);
getdisplay().print("Avg: 60s");
getdisplay().setCursor(60, 180);
getdisplay().print("Avg: 60s");
getdisplay().setCursor(60, 270);
getdisplay().print("Avg: 60s");
break;
case 3:
getdisplay().setCursor(60, 90);
getdisplay().print("Avg: 300s");
getdisplay().setCursor(60, 180);
getdisplay().print("Avg: 300s");
getdisplay().setCursor(60, 270);
getdisplay().print("Avg: 300s");
break;
default:
getdisplay().setCursor(60, 90);
getdisplay().print("Avg: 1s");
getdisplay().setCursor(60, 180);
getdisplay().print("Avg: 1s");
getdisplay().setCursor(60, 270);
getdisplay().print("Avg: 1s");
break;
}
// ############### Value 1 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 55);
getdisplay().print(name1); // Value name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 90);
getdisplay().print(unit1); // Unit
// Show value
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 90);
// Show bus data
if(String(powsensor1) != "off"){
getdisplay().print(value1,2); // Real value as formated string
}
else{
getdisplay().print("---"); // No sensor data (sensor is off)
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 105, 400, 3, pixelcolor);
// ############### Value 2 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 145);
getdisplay().print(name2); // Value name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 180);
getdisplay().print(unit2); // Unit
// Show value
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 180);
// Show bus data
if(String(powsensor1) != "off"){
getdisplay().print(value2,1); // Real value as formated string
}
else{
getdisplay().print("---"); // No sensor data (sensor is off)
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 195, 400, 3, pixelcolor);
// ############### Value 3 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 235);
getdisplay().print(name3); // Value name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 270);
getdisplay().print(unit3); // Unit
// Show value
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 270);
// Show bus data
if(String(powsensor1) != "off"){
getdisplay().print(value3,1); // Real value as formated string
}
else{
getdisplay().print("---"); // No sensor data (sensor is off)
}
// ############### Key Layout ################
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(10, 290);
getdisplay().print("[AVG]");
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageBattery(common);
}/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageBattery(
"Battery", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
true // Show display header on/off
);
#endif

View File

@@ -1,395 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
#include "movingAvg.h" // Lib for moving average building
class PageBattery2 : public Page
{
bool init = false; // Marker for init done
bool keylock = false; // Keylock
int average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s
bool trend = true; // Trend indicator [0|1], 0=off, 1=on
double raw = 0;
public:
PageBattery2(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageBattery2");
}
virtual int handleKey(int key){
// Change average
if(key == 1){
average ++;
average = average % 4; // Modulo 4
return 0; // Commit the key
}
// Trend indicator
if(key == 5){
trend = !trend;
return 0; // Commit the key
}
// Code for keylock
if(key == 11){
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData)
{
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Polynominal coefficients second order for battery energy level calculation
// index 0 = Pb, 1 = Gel, 2 = AGM, 3 = LiFePo4
float x0[4] = {+3082.5178, +1656.1571, +1316.8766, +14986.9336}; // Offset
float x1[4] = {-603.7478, -351.6503, -298.1454, -2432.1985}; // X
float x2[4] = {+29.0340, +17.9000, +15.8196, +98.6132}; // X²
int batPercentage = 0; // Battery level
float batRange = 0; // Range in hours
// Get config data
bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String batVoltage = config->getString(config->batteryVoltage);
int batCapacity = config->getInt(config->batteryCapacity);
String batType = config->getString(config->batteryType);
String backlightMode = config->getString(config->backlight);
String powerSensor = config->getString(config->usePowSensor1);
double value1 = 0; // Battery voltage
double value2 = 0; // Battery current
double value3 = 0; // Battery power consumption
double valueTrend = 0; // Average over 10 values
// Get voltage value
String name1 = "VBat";
// Create trend value
if(init == false){ // Load start values for first page run
valueTrend = commonData.data.batteryVoltage10;
init = true;
}
else{ // Reading trend value
valueTrend = commonData.data.batteryVoltage10;
}
// Get raw value for trend indicator
raw = commonData.data.batteryVoltage; // Live data
// Switch average values
switch (average) {
case 0:
value1 = commonData.data.batteryVoltage; // Live data
value2 = commonData.data.batteryCurrent;
value3 = commonData.data.batteryPower;
break;
case 1:
value1 = commonData.data.batteryVoltage10; // Average 10s
value2 = commonData.data.batteryCurrent10;
value3 = commonData.data.batteryPower10;
break;
case 2:
value1 = commonData.data.batteryVoltage60; // Average 60s
value2 = commonData.data.batteryCurrent60;
value3 = commonData.data.batteryPower60;
break;
case 3:
value1 = commonData.data.batteryVoltage300; // Average 300s
value2 = commonData.data.batteryCurrent300;
value3 = commonData.data.batteryPower300;
break;
default:
value1 = commonData.data.batteryVoltage; // Default
value2 = commonData.data.batteryCurrent;
value3 = commonData.data.batteryPower;
break;
}
bool valid1 = true;
// Battery energy level calculation
if(String(batType) == "Pb"){
batPercentage = (value1 * value1 * x2[0]) + (value1 * x1[0]) + x0[0];
}
if(String(batType) == "Gel"){
batPercentage = (value1 * value1 * x2[1]) + (value1 * x1[1]) + x0[1];
}
if(String(batType) == "AGM"){
batPercentage = (value1 * value1 * x2[2]) + (value1 * x1[2]) + x0[2];
}
if(String(batType) == "LiFePo4"){
batPercentage = (value1 * value1 * x2[3]) + (value1 * x1[3]) + x0[3];
}
// Limits for battery level
if(batPercentage < 0) batPercentage = 0;
if(batPercentage > 99) batPercentage = 99;
// Battery range calculation
if(value2 <= 0) value2 = 0.0000001; // Limiting current
batRange = batCapacity * batPercentage / 100 / value2;
// Limits for battery range
if(batRange < 0) batRange = 0;
if(batRange > 99) batRange = 99;
// Optical warning by limit violation
if(String(flashLED) == "Limit Violation"){
// Limits for Pb battery
if(String(batType) == "Pb" && (raw < 11.8 || raw > 14.8)){
setBlinkingLED(true);
}
if(String(batType) == "Pb" && (raw >= 11.8 && raw <= 14.8)){
setBlinkingLED(false);
setFlashLED(false);
}
// Limits for Gel battery
if(String(batType) == "Gel" && (raw < 11.8 || raw > 14.4)){
setBlinkingLED(true);
}
if(String(batType) == "Gel" && (raw >= 11.8 && raw <= 14.4)){
setBlinkingLED(false);
setFlashLED(false);
}
// Limits for AGM battery
if(String(batType) == "AGM" && (raw < 11.8 || raw > 14.7)){
setBlinkingLED(true);
}
if(String(batType) == "AGM" && (raw >= 11.8 && raw <= 14.7)){
setBlinkingLED(false);
setFlashLED(false);
}
// Limits for LiFePo4 battery
if(String(batType) == "LiFePo4" && (raw < 12.0 || raw > 14.6)){
setBlinkingLED(true);
}
if(String(batType) == "LiFePo4" && (raw >= 12.0 && raw <= 14.6)){
setBlinkingLED(false);
setFlashLED(false);
}
}
// Logging voltage value
LOG_DEBUG(GwLog::LOG,"Drawing at PageBattery2, Type:%s %s:=%f", batType.c_str(), name1.c_str(), raw);
// Draw page
//***********************************************************
// Clear display, set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(10, 65);
getdisplay().print("Bat.");
// Show batery type
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(90, 65);
getdisplay().print(batType);
// Show voltage type
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(10, 140);
int bvoltage = 0;
if(String(batVoltage) == "12V") bvoltage = 12;
else bvoltage = 24;
getdisplay().print(bvoltage);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("V");
// Show batery capacity
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(10, 200);
if(batCapacity <= 999) getdisplay().print(batCapacity, 0);
if(batCapacity > 999) getdisplay().print(float(batCapacity/1000.0), 1);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
if(batCapacity <= 999) getdisplay().print("Ah");
if(batCapacity > 999) getdisplay().print("kAh");
// Show info
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(10, 235);
getdisplay().print("Installed");
getdisplay().setCursor(10, 255);
getdisplay().print("Battery Type");
// Show battery with fill level
batteryGraphic(150, 45, batPercentage, pixelcolor, bgcolor);
// Show average settings
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(150, 145);
switch (average) {
case 0:
getdisplay().print("Avg: 1s");
break;
case 1:
getdisplay().print("Avg: 10s");
break;
case 2:
getdisplay().print("Avg: 60s");
break;
case 3:
getdisplay().print("Avg: 300s");
break;
default:
getdisplay().print("Avg: 1s");
break;
}
// Show fill level in percent
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(150, 200);
getdisplay().print(batPercentage);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("%");
// Show time to full discharge
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(150, 260);
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
if(batRange < 9.9) getdisplay().print(batRange, 1);
else getdisplay().print(batRange, 0);
}
else getdisplay().print("--");
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("h");
// Show sensor type info
String i2cAddr = "";
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(270, 60);
if(powerSensor == "off") getdisplay().print("Internal");
if(powerSensor == "INA219"){
getdisplay().print("INA219");
}
if(powerSensor == "INA226"){
getdisplay().print("INA226");
i2cAddr = " (0x" + String(INA226_I2C_ADDR1, HEX) + ")";
}
getdisplay().print(i2cAddr);
getdisplay().setCursor(270, 80);
getdisplay().print("Sensor Modul");
// Reading bus data or using simulation data
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(260, 140);
if(simulation == true){
if(batVoltage == "12V"){
value1 = 12.0;
}
if(batVoltage == "24V"){
value1 = 24.0;
}
value1 += float(random(0, 5)) / 10; // Simulation data
getdisplay().print(value1,1);
}
else{
// Check for valid real data, display also if hold values activated
if(valid1 == true || holdvalues == true){
// Resolution switching
if(value1 <= 9.9) getdisplay().print(value1, 2);
if(value1 > 9.9 && value1 <= 99.9)getdisplay().print(value1, 1);
if(value1 > 99.9) getdisplay().print(value1, 0);
}
else{
getdisplay().print("---"); // Missing bus data
}
}
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("V");
// Show actual current in A
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(260, 200);
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
if(value2 <= 9.9) getdisplay().print(value2, 2);
if(value2 > 9.9 && value2 <= 99.9)getdisplay().print(value2, 1);
if(value2 > 99.9) getdisplay().print(value2, 0);
}
else getdisplay().print("---");
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("A");
// Show actual consumption in W
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(260, 260);
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
if(value3 <= 9.9) getdisplay().print(value3, 2);
if(value3 > 9.9 && value3 <= 99.9)getdisplay().print(value3, 1);
if(value3 > 99.9) getdisplay().print(value3, 0);
}
else getdisplay().print("---");
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("W");
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(10, 290);
getdisplay().print("[AVG]");
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageBattery2(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect (0 here)
* and will will provide the names of the fixed values we need
*/
PageDescription registerPageBattery2(
"Battery2", // Name of page
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
true // Show display header on/off
);
#endif

View File

@@ -1,360 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageClock : public Page
{
bool keylock = false; // Keylock
public:
PageClock(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageClock");
}
// Key functions
virtual int handleKey(int key){
// Keylock function
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData)
{
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
static String svalue1old = "";
static String unit1old = "";
static String svalue2old = "";
static String unit2old = "";
static String svalue3old = "";
static String svalue4old = "";
double value1 = 0;
double value2 = 0;
// Get config data
String lengthformat = config->getString(config->lengthFormat);
bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
String stimezone = config->getString(config->timeZone);
double timezone = stimezone.toDouble();
// Get boat values for GPS time
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
String name1 = bvalue1->getName().c_str(); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
if(simulation == false){
value1 = bvalue1->value; // Value as double in SI unit
}
else{
value1 = 38160; // Simulation data for time value 11:36 in seconds
} // Other simulation data see OBP60Formater.cpp
bool valid1 = bvalue1->valid; // Valid information
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
if(valid1 == true){
svalue1old = svalue1; // Save old value
unit1old = unit1; // Save old unit
}
// Get boat values for GPS date
GwApi::BoatValue *bvalue2 = pageData.values[1]; // First element in list (only one value by PageOneValue)
String name2 = bvalue2->getName().c_str(); // Value name
name2 = name2.substring(0, 6); // String length limit for value name
value2 = bvalue2->value; // Value as double in SI unit
bool valid2 = bvalue2->valid; // Valid information
String svalue2 = formatValue(bvalue2, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit2 = formatValue(bvalue2, commonData).unit; // Unit of value
if(valid2 == true){
svalue2old = svalue2; // Save old value
unit2old = unit2; // Save old unit
}
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageClock, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Show values GPS date
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(10, 65);
if(holdvalues == false) getdisplay().print(svalue2); // Value
else getdisplay().print(svalue2old);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(10, 95);
getdisplay().print("Date"); // Name
// Horizintal separator left
getdisplay().fillRect(0, 149, 60, 3, pixelcolor);
// Show values GPS time
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(10, 250);
if(holdvalues == false) getdisplay().print(svalue1); // Value
else getdisplay().print(svalue1old);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(10, 220);
getdisplay().print("Time"); // Name
// Show values sunrise
String sunrise = "---";
if(valid1 == true && valid2 == true){
sunrise = String(commonData.sundata.sunriseHour) + ":" + String(commonData.sundata.sunriseMinute + 100).substring(1);
svalue3old = sunrise;
}
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(335, 65);
if(holdvalues == false) getdisplay().print(sunrise); // Value
else getdisplay().print(svalue3old);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(335, 95);
getdisplay().print("SunR"); // Name
// Horizintal separator right
getdisplay().fillRect(340, 149, 80, 3, pixelcolor);
// Show values sunset
String sunset = "---";
if(valid1 == true && valid2 == true){
sunset = String(commonData.sundata.sunsetHour) + ":" + String(commonData.sundata.sunsetMinute + 100).substring(1);
svalue4old = sunset;
}
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(335, 250);
if(holdvalues == false) getdisplay().print(sunset); // Value
else getdisplay().print(svalue4old);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(335, 220);
getdisplay().print("SunS"); // Name
//*******************************************************************************************
// Draw clock
int rInstrument = 110; // Radius of clock
float pi = 3.141592;
getdisplay().fillCircle(200, 150, rInstrument + 10, pixelcolor); // Outer circle
getdisplay().fillCircle(200, 150, rInstrument + 7, bgcolor); // Outer circle
for(int i=0; i<360; i=i+1)
{
// Scaling values
float x = 200 + (rInstrument-30)*sin(i/180.0*pi); // x-coordinate dots
float y = 150 - (rInstrument-30)*cos(i/180.0*pi); // y-coordinate cots
const char *ii = "";
switch (i)
{
case 0: ii="12"; break;
case 30 : ii=""; break;
case 60 : ii=""; break;
case 90 : ii="3"; break;
case 120 : ii=""; break;
case 150 : ii=""; break;
case 180 : ii="6"; break;
case 210 : ii=""; break;
case 240 : ii=""; break;
case 270 : ii="9"; break;
case 300 : ii=""; break;
case 330 : ii=""; break;
default: break;
}
// Print text centered on position x, y
int16_t x1, y1; // Return values of getTextBounds
uint16_t w, h; // Return values of getTextBounds
getdisplay().getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
getdisplay().setCursor(x-w/2, y+h/2);
if(i % 30 == 0){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().print(ii);
}
// Draw sub scale with dots
float sinx = 0;
float cosx = 0;
if(i % 6 == 0){
float x1c = 200 + rInstrument*sin(i/180.0*pi);
float y1c = 150 - rInstrument*cos(i/180.0*pi);
getdisplay().fillCircle((int)x1c, (int)y1c, 2, pixelcolor);
sinx=sin(i/180.0*pi);
cosx=cos(i/180.0*pi);
}
// Draw sub scale with lines (two triangles)
if(i % 30 == 0){
float dx=2; // Line thickness = 2*dx+1
float xx1 = -dx;
float xx2 = +dx;
float yy1 = -(rInstrument-10);
float yy2 = -(rInstrument+10);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),pixelcolor);
getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),
200+(int)(cosx*xx2-sinx*yy2),150+(int)(sinx*xx2+cosx*yy2),pixelcolor);
}
}
// Print Unit in clock
getdisplay().setTextColor(textcolor);
if(holdvalues == false){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(175, 110);
getdisplay().print(unit2); // Unit
}
else{
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(175, 110);
getdisplay().print(unit2old); // Unit
}
// Clock values
double hour = 0;
double minute = 0;
value1 = value1 + int(timezone*3600);
if (value1 > 86400) {value1 = value1 - 86400;}
if (value1 < 0) {value1 = value1 + 86400;}
hour = (value1 / 3600.0);
if(hour > 12) hour = hour - 12.0;
// minute = (hour - int(hour)) * 3600.0 / 60.0; // Analog minute pointer smoth moving
minute = int((hour - int(hour)) * 3600.0 / 60.0); // Jumping minute pointer from minute to minute
LOG_DEBUG(GwLog::DEBUG,"... PageClock, value1: %f hour: %f minute:%f", value1, hour, minute);
// Draw hour pointer
float startwidth = 8; // Start width of pointer
if(valid1 == true || holdvalues == true || simulation == true){
float sinx=sin(hour * 30.0 * pi / 180); // Hour
float cosx=cos(hour * 30.0 * pi / 180);
// Normal pointer
// Pointer as triangle with center base 2*width
float xx1 = -startwidth;
float xx2 = startwidth;
float yy1 = -startwidth;
float yy2 = -(rInstrument * 0.5);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2),pixelcolor);
// Inverted pointer
// Pointer as triangle with center base 2*width
float endwidth = 2; // End width of pointer
float ix1 = endwidth;
float ix2 = -endwidth;
float iy1 = -(rInstrument * 0.5);
float iy2 = -endwidth;
getdisplay().fillTriangle(200+(int)(cosx*ix1-sinx*iy1),150+(int)(sinx*ix1+cosx*iy1),
200+(int)(cosx*ix2-sinx*iy1),150+(int)(sinx*ix2+cosx*iy1),
200+(int)(cosx*0-sinx*iy2),150+(int)(sinx*0+cosx*iy2),pixelcolor);
}
// Draw minute pointer
startwidth = 8; // Start width of pointer
if(valid1 == true || holdvalues == true || simulation == true){
float sinx=sin(minute * 6.0 * pi / 180); // Minute
float cosx=cos(minute * 6.0 * pi / 180);
// Normal pointer
// Pointer as triangle with center base 2*width
float xx1 = -startwidth;
float xx2 = startwidth;
float yy1 = -startwidth;
float yy2 = -(rInstrument - 15);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2),pixelcolor);
// Inverted pointer
// Pointer as triangle with center base 2*width
float endwidth = 2; // End width of pointer
float ix1 = endwidth;
float ix2 = -endwidth;
float iy1 = -(rInstrument - 15);
float iy2 = -endwidth;
getdisplay().fillTriangle(200+(int)(cosx*ix1-sinx*iy1),150+(int)(sinx*ix1+cosx*iy1),
200+(int)(cosx*ix2-sinx*iy1),150+(int)(sinx*ix2+cosx*iy1),
200+(int)(cosx*0-sinx*iy2),150+(int)(sinx*0+cosx*iy2),pixelcolor);
}
// Center circle
getdisplay().fillCircle(200, 150, startwidth + 6, bgcolor);
getdisplay().fillCircle(200, 150, startwidth + 4, pixelcolor);
//*******************************************************************************************
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageClock(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect (0 here)
* and will will provide the names of the fixed values we need
*/
PageDescription registerPageClock(
"Clock", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{"GPST", "GPSD"}, // Bus values we need in the page
true // Show display header on/off
);
#endif

View File

@@ -1,308 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageDST810 : public Page
{
bool keylock = false; // Keylock
public:
PageDST810(CommonData &comon){
comon.logger->logDebug(GwLog::LOG,"Show PageDST810");
}
virtual int handleKey(int key){
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData){
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Old values for hold function
static String svalue1old = "";
static String unit1old = "";
static String svalue2old = "";
static String unit2old = "";
static String svalue3old = "";
static String unit3old = "";
static String svalue4old = "";
static String unit4old = "";
// Get config data
String lengthformat = config->getString(config->lengthFormat);
// bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
// Get boat values #1
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
String name1 = xdrDelete(bvalue1->getName()); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
double value1 = bvalue1->value; // Value as double in SI unit
bool valid1 = bvalue1->valid; // Valid information
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
// Get boat values #2
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
String name2 = xdrDelete(bvalue2->getName()); // Value name
name2 = name2.substring(0, 6); // String length limit for value name
double value2 = bvalue2->value; // Value as double in SI unit
bool valid2 = bvalue2->valid; // Valid information
String svalue2 = formatValue(bvalue2, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit2 = formatValue(bvalue2, commonData).unit; // Unit of value
// Get boat values #3
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
String name3 = xdrDelete(bvalue3->getName()); // Value name
name3 = name3.substring(0, 6); // String length limit for value name
double value3 = bvalue3->value; // Value as double in SI unit
bool valid3 = bvalue3->valid; // Valid information
String svalue3 = formatValue(bvalue3, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit3 = formatValue(bvalue3, commonData).unit; // Unit of value
// Get boat values #4
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
String name4 = xdrDelete(bvalue4->getName()); // Value name
name4 = name4.substring(0, 6); // String length limit for value name
double value4 = bvalue4->value; // Value as double in SI unit
bool valid4 = bvalue4->valid; // Valid information
String svalue4 = formatValue(bvalue4, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit4 = formatValue(bvalue4, commonData).unit; // Unit of value
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageDST810, %s: %f, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// ############### Value 1 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 55);
getdisplay().print("Depth"); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 90);
if(holdvalues == false){
getdisplay().print(unit1); // Unit
}
else{
getdisplay().print(unit1old);
}
// Set font
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 90);
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue1); // Real value as formated string
}
else{
getdisplay().print(svalue1old); // Old value as formated string
}
if(valid1 == true){
svalue1old = svalue1; // Save the old value
unit1old = unit1; // Save the old unit
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 105, 400, 3, pixelcolor);
// ############### Value 2 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 145);
getdisplay().print("Speed"); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 180);
if(holdvalues == false){
getdisplay().print(unit2); // Unit
}
else{
getdisplay().print(unit2old);
}
// Setfont
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 180);
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue2); // Real value as formated string
}
else{
getdisplay().print(svalue2old); // Old value as formated string
}
if(valid2 == true){
svalue2old = svalue2; // Save the old value
unit2old = unit2; // Save the old unit
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 195, 400, 3, pixelcolor);
// ############### Value 3 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 220);
getdisplay().print("Log"); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(20, 240);
if(holdvalues == false){
getdisplay().print(unit3); // Unit
}
else{
getdisplay().print(unit3old);
}
// Set font
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(80, 270);
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue3); // Real value as formated string
}
else{
getdisplay().print(svalue3old); // Old value as formated string
}
if(valid3 == true){
svalue3old = svalue3; // Save the old value
unit3old = unit3; // Save the old unit
}
// ############### Vertical Line ################
// Vertical line 3 pix
getdisplay().fillRect(200, 195, 3, 75, pixelcolor);
// ############### Value 4 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(220, 220);
getdisplay().print("Temp"); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(220, 240);
if(holdvalues == false){
getdisplay().print(unit4); // Unit
}
else{
getdisplay().print(unit4old);
}
// Set font
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(280, 270);
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue4); // Real value as formated string
}
else{
getdisplay().print(svalue4old); // Old value as formated string
}
if(valid4 == true){
svalue4old = svalue4; // Save the old value
unit4old = unit4; // Save the old unit
}
// ############### Key Layout ################
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageDST810(common);
}/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageDST810(
"DST810", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{"DBT","STW","Log","WTemp"}, // Bus values we need in the page
true // Show display header on/off
);
#endif

View File

@@ -1,347 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageFourValues : public Page
{
bool keylock = false; // Keylock
public:
PageFourValues(CommonData &comon){
comon.logger->logDebug(GwLog::LOG,"Show PageFourValues");
}
virtual int handleKey(int key){
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData){
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Old values for hold function
static String svalue1old = "";
static String unit1old = "";
static String svalue2old = "";
static String unit2old = "";
static String svalue3old = "";
static String unit3old = "";
static String svalue4old = "";
static String unit4old = "";
// Get config data
String lengthformat = config->getString(config->lengthFormat);
// bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
// Get boat values #1
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
String name1 = xdrDelete(bvalue1->getName()); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
double value1 = bvalue1->value; // Value as double in SI unit
bool valid1 = bvalue1->valid; // Valid information
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
// Get boat values #2
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
String name2 = xdrDelete(bvalue2->getName()); // Value name
name2 = name2.substring(0, 6); // String length limit for value name
double value2 = bvalue2->value; // Value as double in SI unit
bool valid2 = bvalue2->valid; // Valid information
String svalue2 = formatValue(bvalue2, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit2 = formatValue(bvalue2, commonData).unit; // Unit of value
// Get boat values #3
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
String name3 = xdrDelete(bvalue3->getName()); // Value name
name3 = name3.substring(0, 6); // String length limit for value name
double value3 = bvalue3->value; // Value as double in SI unit
bool valid3 = bvalue3->valid; // Valid information
String svalue3 = formatValue(bvalue3, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit3 = formatValue(bvalue3, commonData).unit; // Unit of value
// Get boat values #4
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
String name4 = xdrDelete(bvalue4->getName()); // Value name
name4 = name4.substring(0, 6); // String length limit for value name
double value4 = bvalue4->value; // Value as double in SI unit
bool valid4 = bvalue4->valid; // Valid information
String svalue4 = formatValue(bvalue4, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit4 = formatValue(bvalue4, commonData).unit; // Unit of value
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageFourValues, %s: %f, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// ############### Value 1 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().setCursor(20, 45);
getdisplay().print(name1); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(20, 65);
if(holdvalues == false){
getdisplay().print(unit1); // Unit
}
else{
getdisplay().print(unit1old);
}
// Switch font if format for any values
if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(120, 55);
}
else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(150, 58);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(180, 65);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue1); // Real value as formated string
}
else{
getdisplay().print(svalue1old); // Old value as formated string
}
if(valid1 == true){
svalue1old = svalue1; // Save the old value
unit1old = unit1; // Save the old unit
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 80, 400, 3, pixelcolor);
// ############### Value 2 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().setCursor(20, 113);
getdisplay().print(name2); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(20, 133);
if(holdvalues == false){
getdisplay().print(unit2); // Unit
}
else{
getdisplay().print(unit2old);
}
// Switch font if format for any values
if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(120, 123);
}
else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(150, 123);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(180, 133);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue2); // Real value as formated string
}
else{
getdisplay().print(svalue2old); // Old value as formated string
}
if(valid2 == true){
svalue2old = svalue2; // Save the old value
unit2old = unit2; // Save the old unit
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 146, 400, 3, pixelcolor);
// ############### Value 3 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().setCursor(20, 181);
getdisplay().print(name3); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(20, 201);
if(holdvalues == false){
getdisplay().print(unit3); // Unit
}
else{
getdisplay().print(unit3old);
}
// Switch font if format for any values
if(bvalue3->getFormat() == "formatLatitude" || bvalue3->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(120, 191);
}
else if(bvalue3->getFormat() == "formatTime" || bvalue3->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(150, 191);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(180, 201);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue3); // Real value as formated string
}
else{
getdisplay().print(svalue3old); // Old value as formated string
}
if(valid3 == true){
svalue3old = svalue3; // Save the old value
unit3old = unit3; // Save the old unit
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 214, 400, 3, pixelcolor);
// ############### Value 4 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().setCursor(20, 249);
getdisplay().print(name4); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(20, 269);
if(holdvalues == false){
getdisplay().print(unit4); // Unit
}
else{
getdisplay().print(unit4old);
}
// Switch font if format for any values
if(bvalue4->getFormat() == "formatLatitude" || bvalue4->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(120, 259);
}
else if(bvalue4->getFormat() == "formatTime" || bvalue4->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(150, 259);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(180, 269);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue4); // Real value as formated string
}
else{
getdisplay().print(svalue4old); // Old value as formated string
}
if(valid4 == true){
svalue4old = svalue4; // Save the old value
unit4old = unit4; // Save the old unit
}
// ############### Key Layout ################
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageFourValues(common);
}/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageFourValues(
"FourValues", // Page name
createPage, // Action
4, // Number of bus values depends on selection in Web configuration
true // Show display header on/off
);
#endif

View File

@@ -1,347 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageFourValues2 : public Page
{
bool keylock = false; // Keylock
public:
PageFourValues2(CommonData &comon){
comon.logger->logDebug(GwLog::LOG,"Show PageFourValues2");
}
virtual int handleKey(int key){
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData){
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Old values for hold function
static String svalue1old = "";
static String unit1old = "";
static String svalue2old = "";
static String unit2old = "";
static String svalue3old = "";
static String unit3old = "";
static String svalue4old = "";
static String unit4old = "";
// Get config data
String lengthformat = config->getString(config->lengthFormat);
// bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
// Get boat values #1
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
String name1 = xdrDelete(bvalue1->getName()); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
double value1 = bvalue1->value; // Value as double in SI unit
bool valid1 = bvalue1->valid; // Valid information
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
// Get boat values #2
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
String name2 = xdrDelete(bvalue2->getName()); // Value name
name2 = name2.substring(0, 6); // String length limit for value name
double value2 = bvalue2->value; // Value as double in SI unit
bool valid2 = bvalue2->valid; // Valid information
String svalue2 = formatValue(bvalue2, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit2 = formatValue(bvalue2, commonData).unit; // Unit of value
// Get boat values #3
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
String name3 = xdrDelete(bvalue3->getName()); // Value name
name3 = name3.substring(0, 6); // String length limit for value name
double value3 = bvalue3->value; // Value as double in SI unit
bool valid3 = bvalue3->valid; // Valid information
String svalue3 = formatValue(bvalue3, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit3 = formatValue(bvalue3, commonData).unit; // Unit of value
// Get boat values #4
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
String name4 = xdrDelete(bvalue4->getName()); // Value name
name4 = name4.substring(0, 6); // String length limit for value name
double value4 = bvalue4->value; // Value as double in SI unit
bool valid4 = bvalue4->valid; // Valid information
String svalue4 = formatValue(bvalue4, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit4 = formatValue(bvalue4, commonData).unit; // Unit of value
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageFourValues2, %s: %f, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// ############### Value 1 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 55);
getdisplay().print(name1); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 90);
if(holdvalues == false){
getdisplay().print(unit1); // Unit
}
else{
getdisplay().print(unit1old);
}
// Switch font if format for any values
if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(100, 90);
}
else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(180, 77);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 90);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue1); // Real value as formated string
}
else{
getdisplay().print(svalue1old); // Old value as formated string
}
if(valid1 == true){
svalue1old = svalue1; // Save the old value
unit1old = unit1; // Save the old unit
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 105, 400, 3, pixelcolor);
// ############### Value 2 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 145);
getdisplay().print(name2); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 180);
if(holdvalues == false){
getdisplay().print(unit2); // Unit
}
else{
getdisplay().print(unit2old);
}
// Switch font if format for any values
if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(100, 180);
}
else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(180, 158);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 180);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue2); // Real value as formated string
}
else{
getdisplay().print(svalue2old); // Old value as formated string
}
if(valid2 == true){
svalue2old = svalue2; // Save the old value
unit2old = unit2; // Save the old unit
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 195, 400, 3, pixelcolor);
// ############### Value 3 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 220);
getdisplay().print(name3); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(20, 240);
if(holdvalues == false){
getdisplay().print(unit3); // Unit
}
else{
getdisplay().print(unit3old);
}
// Switch font if format for any values
if(bvalue3->getFormat() == "formatLatitude" || bvalue3->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(50, 240);
}
else if(bvalue3->getFormat() == "formatTime" || bvalue3->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(100, 240);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(80, 270);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue3); // Real value as formated string
}
else{
getdisplay().print(svalue3old); // Old value as formated string
}
if(valid3 == true){
svalue3old = svalue3; // Save the old value
unit3old = unit3; // Save the old unit
}
// ############### Vertical Line ################
// Vertical line 3 pix
getdisplay().fillRect(200, 195, 3, 75, pixelcolor);
// ############### Value 4 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(220, 220);
getdisplay().print(name4); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(220, 240);
if(holdvalues == false){
getdisplay().print(unit4); // Unit
}
else{
getdisplay().print(unit4old);
}
// Switch font if format for any values
if(bvalue4->getFormat() == "formatLatitude" || bvalue4->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(250, 240);
}
else if(bvalue4->getFormat() == "formatTime" || bvalue4->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(300, 240);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(280, 270);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue4); // Real value as formated string
}
else{
getdisplay().print(svalue4old); // Old value as formated string
}
if(valid4 == true){
svalue4old = svalue4; // Save the old value
unit4old = unit4; // Save the old unit
}
// ############### Key Layout ################
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageFourValues2(common);
}/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageFourValues2(
"FourValues2", // Page name
createPage, // Action
4, // Number of bus values depends on selection in Web configuration
true // Show display header on/off
);
#endif

View File

@@ -1,267 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
#include "movingAvg.h" // Lib for moving average building
class PageGenerator : public Page
{
bool init = false; // Marker for init done
bool keylock = false; // Keylock
public:
PageGenerator(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageGenerator");
}
virtual int handleKey(int key){
// Code for keylock
if(key == 11){
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData)
{
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Get config data
bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String batVoltage = config->getString(config->batteryVoltage);
int genPower = config->getInt(config->genPower);
String backlightMode = config->getString(config->backlight);
String powerSensor = config->getString(config->usePowSensor3);
double value1 = 0; // Solar voltage
double value2 = 0; // Solar current
double value3 = 0; // Solar output power
double valueTrend = 0; // Average over 10 values
int genPercentage = 0; // Power generator load
// Get voltage value
String name1 = "VGen";
// Get raw value for trend indicator
if(powerSensor != "off"){
value1 = commonData.data.generatorVoltage; // Use voltage from external sensor
}
else{
value1 = commonData.data.batteryVoltage; // Use internal voltage sensor
}
value2 = commonData.data.generatorCurrent;
value3 = commonData.data.generatorPower;
genPercentage = value3 * 100 / (double)genPower; // Load value
// Limits for battery level
if(genPercentage < 0) genPercentage = 0;
if(genPercentage > 99) genPercentage = 99;
bool valid1 = true;
// Optical warning by limit violation
if(String(flashLED) == "Limit Violation"){
// Over voltage
if(value1 > 14.8 && batVoltage == "12V"){
setBlinkingLED(true);
}
if(value1 <= 14.8 && batVoltage == "12V"){
setBlinkingLED(false);
}
if(value1 > 29.6 && batVoltage == "24V"){
setBlinkingLED(true);
}
if(value1 <= 29.6 && batVoltage == "24V"){
setBlinkingLED(false);
}
}
// Logging voltage value
LOG_DEBUG(GwLog::LOG,"Drawing at PageGenerator, Type:%iW %s:=%f", genPower, name1.c_str(), value1);
// Draw page
//***********************************************************
// Clear display, set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(10, 65);
getdisplay().print("Power");
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(12, 82);
getdisplay().print("Generator");
// Show voltage type
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(10, 140);
int bvoltage = 0;
if(String(batVoltage) == "12V") bvoltage = 12;
else bvoltage = 24;
getdisplay().print(bvoltage);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("V");
// Show solar power
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(10, 200);
if(genPower <= 999) getdisplay().print(genPower, 0);
if(genPower > 999) getdisplay().print(float(genPower/1000.0), 1);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
if(genPower <= 999) getdisplay().print("W");
if(genPower > 999) getdisplay().print("kW");
// Show info
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(10, 235);
getdisplay().print("Installed");
getdisplay().setCursor(10, 255);
getdisplay().print("Power Modul");
// Show generator
generatorGraphic(200, 95, pixelcolor, bgcolor);
// Show load level in percent
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(150, 200);
getdisplay().print(genPercentage);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("%");
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(150, 235);
getdisplay().print("Load");
// Show sensor type info
String i2cAddr = "";
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(270, 60);
if(powerSensor == "off") getdisplay().print("Internal");
if(powerSensor == "INA219"){
getdisplay().print("INA219");
i2cAddr = " (0x" + String(INA219_I2C_ADDR3, HEX) + ")";
}
if(powerSensor == "INA226"){
getdisplay().print("INA226");
i2cAddr = " (0x" + String(INA226_I2C_ADDR3, HEX) + ")";
}
getdisplay().print(i2cAddr);
getdisplay().setCursor(270, 80);
getdisplay().print("Sensor Modul");
// Reading bus data or using simulation data
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(260, 140);
if(simulation == true){
if(batVoltage == "12V"){
value1 = 12.0;
}
if(batVoltage == "24V"){
value1 = 24.0;
}
value1 += float(random(0, 5)) / 10; // Simulation data
getdisplay().print(value1,1);
}
else{
// Check for valid real data, display also if hold values activated
if(valid1 == true || holdvalues == true){
// Resolution switching
if(value1 <= 9.9) getdisplay().print(value1, 2);
if(value1 > 9.9 && value1 <= 99.9)getdisplay().print(value1, 1);
if(value1 > 99.9) getdisplay().print(value1, 0);
}
else{
getdisplay().print("---"); // Missing bus data
}
}
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("V");
// Show actual current in A
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(260, 200);
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
if(value2 <= 9.9) getdisplay().print(value2, 2);
if(value2 > 9.9 && value2 <= 99.9)getdisplay().print(value2, 1);
if(value2 > 99.9) getdisplay().print(value2, 0);
}
else getdisplay().print("---");
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("A");
// Show actual consumption in W
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(260, 260);
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
if(value3 <= 9.9) getdisplay().print(value3, 2);
if(value3 > 9.9 && value3 <= 99.9)getdisplay().print(value3, 1);
if(value3 > 99.9) getdisplay().print(value3, 0);
}
else getdisplay().print("---");
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("W");
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageGenerator(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect (0 here)
* and will will provide the names of the fixed values we need
*/
PageDescription registerPageGenerator(
"Generator", // Name of page
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
true // Show display header on/off
);
#endif

View File

@@ -1,267 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageKeelPosition : public Page
{
bool keylock = false; // Keylock
public:
PageKeelPosition(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageKeelPosition");
}
// Key functions
virtual int handleKey(int key){
// Keylock function
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData)
{
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
double value1 = 0;
double value1old = 0;
// Get config data
String lengthformat = config->getString(config->lengthFormat);
bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
String rotsensor = config->getString(config->useRotSensor);
String rotfunction = config->getString(config->rotFunction);
// Get boat values for Keel position
bool valid1 = commonData.data.validRotAngle; // Valid information
if(simulation == false && rotsensor == "AS5600" && rotfunction == "Keel"){
value1 = commonData.data.rotationAngle; // Raw value without unit convertion
}
else{
value1 = 0;
}
if(simulation == true){
value1 = (170 + float(random(0, 40)) / 10.0) * 2 * PI / 360; // Simulation data in radiant
}
String unit1 = "Deg"; // Unit of value
if(valid1 == true){
value1old = value1; // Save old value
}
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
LOG_DEBUG(GwLog::LOG,"Drawing at PageKeelPosition, Keel:%f", value1);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
//*******************************************************************************************
// Draw KeelPosition
int rInstrument = 110; // Radius of KeelPosition
float pi = 3.141592;
getdisplay().fillCircle(200, 150, rInstrument + 10, pixelcolor); // Outer circle
getdisplay().fillCircle(200, 150, rInstrument + 7, bgcolor); // Outer circle
getdisplay().fillRect(0, 30, 400, 122, bgcolor); // Delete half top circle
for(int i=90; i<=270; i=i+10)
{
// Scaling values
float x = 200 + (rInstrument-30)*sin(i/180.0*pi); // x-coordinate dots
float y = 150 - (rInstrument-30)*cos(i/180.0*pi); // y-coordinate cots
const char *ii = " ";
switch (i)
{
case 0: ii=" "; break; // Use a blank for a empty scale value
case 30 : ii=" "; break;
case 60 : ii=" "; break;
case 90 : ii="45"; break;
case 120 : ii="30"; break;
case 150 : ii="15"; break;
case 180 : ii="0"; break;
case 210 : ii="15"; break;
case 240 : ii="30"; break;
case 270 : ii="45"; break;
case 300 : ii=" "; break;
case 330 : ii=" "; break;
default: break;
}
// Print text centered on position x, y
int16_t x1, y1; // Return values of getTextBounds
uint16_t w, h; // Return values of getTextBounds
getdisplay().getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
getdisplay().setCursor(x-w/2, y+h/2);
if(i % 30 == 0){
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().print(ii);
}
// Draw sub scale with dots
float x1c = 200 + rInstrument*sin(i/180.0*pi);
float y1c = 150 - rInstrument*cos(i/180.0*pi);
getdisplay().fillCircle((int)x1c, (int)y1c, 2, pixelcolor);
float sinx=sin(i/180.0*pi);
float cosx=cos(i/180.0*pi);
// Draw sub scale with lines (two triangles)
if(i % 30 == 0){
float dx=2; // Line thickness = 2*dx+1
float xx1 = -dx;
float xx2 = +dx;
float yy1 = -(rInstrument-10);
float yy2 = -(rInstrument+10);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),pixelcolor);
getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),
200+(int)(cosx*xx2-sinx*yy2),150+(int)(sinx*xx2+cosx*yy2),pixelcolor);
}
}
// Angle limits to +/-45° (Attention: 180° offset!)
if(value1 < (3 * PI / 4)){
value1 = 3 * PI / 4;
}
if(value1 > (5 * PI / 4)){
value1 = 5 * PI / 4;
}
if(holdvalues == true && valid1 == false){
value1 = value1old;
}
// Calculate keel position
value1 = (value1 * 2) + PI;
// Draw keel position pointer
float startwidth = 8; // Start width of pointer
if((rotsensor == "AS5600" && rotfunction == "Keel" && (valid1 == true || holdvalues == true)) || simulation == true){
float sinx=sin(value1);
float cosx=cos(value1);
// Normal pointer
// Pointer as triangle with center base 2*width
float xx1 = -startwidth;
float xx2 = startwidth;
float yy1 = -startwidth;
float yy2 = -(rInstrument * 0.6);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2),pixelcolor);
// Inverted pointer
// Pointer as triangle with center base 2*width
float endwidth = 2; // End width of pointer
float ix1 = endwidth;
float ix2 = -endwidth;
float iy1 = -(rInstrument * 0.6);
float iy2 = -endwidth;
getdisplay().fillTriangle(200+(int)(cosx*ix1-sinx*iy1),150+(int)(sinx*ix1+cosx*iy1),
200+(int)(cosx*ix2-sinx*iy1),150+(int)(sinx*ix2+cosx*iy1),
200+(int)(cosx*0-sinx*iy2),150+(int)(sinx*0+cosx*iy2),pixelcolor);
// Draw counterweight
getdisplay().fillCircle(200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2), 5, pixelcolor);
}
// Center circle
getdisplay().fillCircle(200, 140, startwidth + 22, bgcolor);
getdisplay().fillCircle(200, 140, startwidth + 20, pixelcolor); // Boat circle
getdisplay().fillRect(200 - 30, 140 - 30, 2 * 30, 30, bgcolor); // Delete half top of boat circle
getdisplay().fillRect(150, 150, 100, 4, pixelcolor); // Water line
// Print label
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().setCursor(100, 70);
getdisplay().print("Keel Position"); // Label
if((rotsensor == "AS5600" && rotfunction == "Keel" && (valid1 == true || holdvalues == true)) || simulation == true){
// Print Unit of keel position
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(175, 110);
getdisplay().print(unit1); // Unit
}
else{
// Print Unit of keel position
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(145, 110);
getdisplay().print("No sensor data"); // Info missing sensor
}
//*******************************************************************************************
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageKeelPosition(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect (0 here)
* and will will provide the names of the fixed values we need
*/
PageDescription registerPageKeelPosition(
"KeelPosition", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{}, // Bus values we need in the page
true // Show display header on/off
);
#endif

View File

@@ -1,160 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageOneValue : public Page{
bool keylock = false; // Keylock
public:
PageOneValue(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageOneValue");
}
virtual int handleKey(int key){
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData){
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Old values for hold function
static String svalue1old = "";
static String unit1old = "";
// Get config data
String lengthformat = config->getString(config->lengthFormat);
// bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
// Get boat values
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
String name1 = xdrDelete(bvalue1->getName()); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
double value1 = bvalue1->value; // Value as double in SI unit
bool valid1 = bvalue1->valid; // Valid information
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageOneValue, %s: %f", name1.c_str(), value1);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
/// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold32pt7b);
getdisplay().setCursor(20, 100);
getdisplay().print(name1); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(270, 100);
if(holdvalues == false){
getdisplay().print(unit1); // Unit
}
else{
getdisplay().print(unit1old);
}
// Switch font if format for any values
if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 180);
}
else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold32pt7b);
getdisplay().setCursor(20, 200);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic60pt7b);
getdisplay().setCursor(20, 240);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue1); // Real value as formated string
}
else{
getdisplay().print(svalue1old); // Old value as formated string
}
if(valid1 == true){
svalue1old = svalue1; // Save the old value
unit1old = unit1; // Save the old unit
}
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page* createPage(CommonData &common){
return new PageOneValue(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageOneValue(
"OneValue", // Page name
createPage, // Action
1, // Number of bus values depends on selection in Web configuration
true // Show display header on/off
);
#endif

View File

@@ -1,360 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageRollPitch : public Page
{
bool keylock = false; // Keylock
public:
PageRollPitch(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageRollPitch");
}
// Key functions
virtual int handleKey(int key){
// Keylock function
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData)
{
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
double value1 = 0;
double value2 = 0;
String svalue1 = "";
String svalue1old = "";
String svalue2 = "";
String svalue2old = "";
// Get config data
String lengthformat = config->getString(config->lengthFormat);
bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
int rolllimit = config->getInt(config->rollLimit);
String roffset = config->getString(config->rollOffset);
double rolloffset = roffset.toFloat()/360*(2*PI);
String poffset = config->getString(config->pitchOffset);
double pitchoffset = poffset.toFloat()/360*(2*PI);
// Get boat values for roll
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (xdrRoll)
String name1 = xdrDelete(bvalue1->getName()); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
bool valid1 = bvalue1->valid; // Valid information
if(valid1 == true){
value1 = bvalue1->value + rolloffset; // Raw value for pitch
}
else{
if(simulation == true){
value1 = (20 + float(random(0, 50)) / 10.0)/360*2*PI;
}
else{
value1 = 0;
}
}
if(value1/(2*PI)*360 > -10 && value1/(2*PI)*360 < 10){
svalue1 = String(value1/(2*PI)*360,1); // Convert raw value to string
}
else{
svalue1 = String(value1/(2*PI)*360,0);
}
// Get boat values for pitch
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (xdrPitch)
String name2 = xdrDelete(bvalue2->getName()); // Value name
name2 = name2.substring(0, 6); // String length limit for value name
bool valid2 = bvalue2->valid; // Valid information
if(valid2 == true){
value2 = bvalue2->value + pitchoffset; // Raw value for pitch
}
else{
if(simulation == true){
value2 = (float(random(-5, 5)))/360*2*PI;
}
else{
value2 = 0;
}
}
if(value2/(2*PI)*360 > -10 && value2/(2*PI)*360 < 10){
svalue2 = String(value2/(2*PI)*360,1); // Convert raw value to string
}
else{
svalue2 = String(value2/(2*PI)*360,0);
}
// Optical warning by limit violation
if(String(flashLED) == "Limit Violation"){
// Limits for roll
if(value1*360/(2*PI) >= -1*rolllimit && value1*360/(2*PI) <= rolllimit){
setBlinkingLED(false);
setFlashLED(false);
}
else{
setBlinkingLED(true);
}
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageRollPitch, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Show roll limit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(10, 65);
getdisplay().print(rolllimit); // Value
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(10, 95);
getdisplay().print("Limit"); // Name
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(10, 115);
getdisplay().print("DEG");
// Horizintal separator left
getdisplay().fillRect(0, 149, 60, 3, pixelcolor);
// Show roll value
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(10, 270);
if(holdvalues == false) getdisplay().print(svalue1); // Value
else getdisplay().print(svalue1old);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(10, 220);
getdisplay().print(name1); // Name
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(10, 190);
getdisplay().print("Deg");
// Horizintal separator right
getdisplay().fillRect(340, 149, 80, 3, pixelcolor);
// Show pitch value
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(295, 270);
if(holdvalues == false) getdisplay().print(svalue2); // Value
else getdisplay().print(svalue2old);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(335, 220);
getdisplay().print(name2); // Name
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(335, 190);
getdisplay().print("Deg");
//*******************************************************************************************
// Draw instrument
int rInstrument = 100; // Radius of instrument
float pi = 3.141592;
getdisplay().fillCircle(200, 150, rInstrument + 10, pixelcolor); // Outer circle
getdisplay().fillCircle(200, 150, rInstrument + 7, bgcolor); // Outer circle
for(int i=0; i<360; i=i+10)
{
// Only scaling +/- 60 degrees
if((i >= 0 && i <= 60) || (i >= 300 && i <= 360)){
// Scaling values
float x = 200 + (rInstrument+25)*sin(i/180.0*pi); // x-coordinate dots
float y = 150 - (rInstrument+25)*cos(i/180.0*pi); // y-coordinate cots
const char *ii = "";
switch (i)
{
case 0: ii="0"; break;
case 20 : ii="20"; break;
case 40 : ii="40"; break;
case 60 : ii="60"; break;
case 300 : ii="60"; break;
case 320 : ii="40"; break;
case 340 : ii="20"; break;
default: break;
}
// Print text centered on position x, y
int16_t x1, y1; // Return values of getTextBounds
uint16_t w, h; // Return values of getTextBounds
getdisplay().getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
getdisplay().setCursor(x-w/2, y+h/2);
if(i % 20 == 0){
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().print(ii);
}
// Draw sub scale with dots
float x1c = 200 + rInstrument*sin(i/180.0*pi);
float y1c = 150 - rInstrument*cos(i/180.0*pi);
getdisplay().fillCircle((int)x1c, (int)y1c, 2, pixelcolor);
float sinx=sin(i/180.0*pi);
float cosx=cos(i/180.0*pi);
// Draw sub scale with lines (two triangles)
if(i % 20 == 0){
float dx=2; // Line thickness = 2*dx+1
float xx1 = -dx;
float xx2 = +dx;
float yy1 = -(rInstrument-10);
float yy2 = -(rInstrument+10);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),pixelcolor);
getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),
200+(int)(cosx*xx2-sinx*yy2),150+(int)(sinx*xx2+cosx*yy2),pixelcolor);
}
}
}
// Draw mast position pointer
float startwidth = 8; // Start width of pointer
// value1 = (2 * pi ) - value1; // Mirror coordiante system for pointer, keel and boat
if(valid1 == true || holdvalues == true || simulation == true){
float sinx=sin(value1 + pi);
float cosx=cos(value1 + pi);
// Normal pointer
// Pointer as triangle with center base 2*width
float xx1 = -startwidth;
float xx2 = startwidth;
float yy1 = -startwidth;
float yy2 = -(rInstrument * 0.7);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2),pixelcolor);
// Inverted pointer
// Pointer as triangle with center base 2*width
float endwidth = 2; // End width of pointer
float ix1 = endwidth;
float ix2 = -endwidth;
float iy1 = -(rInstrument * 0.7);
float iy2 = -endwidth;
getdisplay().fillTriangle(200+(int)(cosx*ix1-sinx*iy1),150+(int)(sinx*ix1+cosx*iy1),
200+(int)(cosx*ix2-sinx*iy1),150+(int)(sinx*ix2+cosx*iy1),
200+(int)(cosx*0-sinx*iy2),150+(int)(sinx*0+cosx*iy2),pixelcolor);
// Draw counterweight
getdisplay().fillCircle(200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2), 5, pixelcolor);
}
// Center circle
getdisplay().fillCircle(200, 150, startwidth + 22, bgcolor);
getdisplay().fillCircle(200, 150, startwidth + 20, pixelcolor); // Boat circle
int x0 = 200;
int y0 = 150;
int x1 = x0 + 50*cos(value1);
int y1 = y0 + 50*sin(value1);
int x2 = x0 + 50*cos(value1 - pi/2);
int y2 = y0 + 50*sin(value1 - pi/2);
getdisplay().fillTriangle(x0, y0, x1, y1, x2, y2, bgcolor); // Clear half top side of boat circle (right triangle)
x1 = x0 + 50*cos(value1 + pi);
y1 = y0 + 50*sin(value1 + pi);
getdisplay().fillTriangle(x0, y0, x1, y1, x2, y2, bgcolor); // Clear half top side of boat circle (left triangle)
getdisplay().fillRect(150, 160, 100, 4, pixelcolor); // Water line
// Draw roll pointer
startwidth = 4; // Start width of pointer
if(valid1 == true || holdvalues == true || simulation == true){
float sinx=sin(value1); // Roll
float cosx=cos(value1);
// Normal pointer
// Pointer as triangle with center base 2*width
float xx1 = -startwidth;
float xx2 = startwidth;
float yy1 = -startwidth;
float yy2 = -(rInstrument - 15);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2),pixelcolor);
// Inverted pointer
// Pointer as triangle with center base 2*width
float endwidth = 2; // End width of pointer
float ix1 = endwidth;
float ix2 = -endwidth;
float iy1 = -(rInstrument - 15);
float iy2 = -endwidth;
getdisplay().fillTriangle(200+(int)(cosx*ix1-sinx*iy1),150+(int)(sinx*ix1+cosx*iy1),
200+(int)(cosx*ix2-sinx*iy1),150+(int)(sinx*ix2+cosx*iy1),
200+(int)(cosx*0-sinx*iy2),150+(int)(sinx*0+cosx*iy2),pixelcolor);
}
else{
// Print sensor info
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(145, 200);
getdisplay().print("No sensor data"); // Info missing sensor
}
//*******************************************************************************************
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageRollPitch(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect (0 here)
* and will will provide the names of the fixed values we need
*/
PageDescription registerPageRollPitch(
"RollPitch", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{"xdrRoll", "xdrPitch"},// Bus values we need in the page
true // Show display header on/off
);
#endif

View File

@@ -1,266 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageRudderPosition : public Page
{
bool keylock = false; // Keylock
public:
PageRudderPosition(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageRudderPosition");
}
// Key functions
virtual int handleKey(int key){
// Keylock function
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData)
{
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
static String unit1old = "";
double value1 = 0.1;
double value1old = 0.1;
// Get config data
String lengthformat = config->getString(config->lengthFormat);
bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
// Get boat values for rudder position
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list
String name1 = bvalue1->getName().c_str(); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
value1 = bvalue1->value; // Raw value without unit convertion
bool valid1 = bvalue1->valid; // Valid information
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
if(valid1 == true){
value1old = value1; // Save old value
unit1old = unit1; // Save old unit
}
if(simulation == true){
value1 = (3 + float(random(0, 50)) / 10.0)/360*2*PI;
unit1 = "Deg";
}
else{
value1 = 0;
}
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageRudderPosition, %s:%f", name1.c_str(), value1);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
//*******************************************************************************************
// Draw RudderPosition
int rInstrument = 110; // Radius of RudderPosition
float pi = 3.141592;
getdisplay().fillCircle(200, 150, rInstrument + 10, pixelcolor); // Outer circle
getdisplay().fillCircle(200, 150, rInstrument + 7, bgcolor); // Outer circle
getdisplay().fillRect(0, 30, 400, 122, bgcolor); // Delete half top circle
for(int i=90; i<=270; i=i+10)
{
// Scaling values
float x = 200 + (rInstrument-30)*sin(i/180.0*pi); // x-coordinate dots
float y = 150 - (rInstrument-30)*cos(i/180.0*pi); // y-coordinate cots
const char *ii = " ";
switch (i)
{
case 0: ii=" "; break; // Use a blank for a empty scale value
case 30 : ii=" "; break;
case 60 : ii=" "; break;
case 90 : ii="45"; break;
case 120 : ii="30"; break;
case 150 : ii="15"; break;
case 180 : ii="0"; break;
case 210 : ii="15"; break;
case 240 : ii="30"; break;
case 270 : ii="45"; break;
case 300 : ii=" "; break;
case 330 : ii=" "; break;
default: break;
}
// Print text centered on position x, y
int16_t x1, y1; // Return values of getTextBounds
uint16_t w, h; // Return values of getTextBounds
getdisplay().getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
getdisplay().setCursor(x-w/2, y+h/2);
if(i % 30 == 0){
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().print(ii);
}
// Draw sub scale with dots
float x1c = 200 + rInstrument*sin(i/180.0*pi);
float y1c = 150 - rInstrument*cos(i/180.0*pi);
getdisplay().fillCircle((int)x1c, (int)y1c, 2, pixelcolor);
float sinx=sin(i/180.0*pi);
float cosx=cos(i/180.0*pi);
// Draw sub scale with lines (two triangles)
if(i % 30 == 0){
float dx=2; // Line thickness = 2*dx+1
float xx1 = -dx;
float xx2 = +dx;
float yy1 = -(rInstrument-10);
float yy2 = -(rInstrument+10);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),pixelcolor);
getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),
200+(int)(cosx*xx2-sinx*yy2),150+(int)(sinx*xx2+cosx*yy2),pixelcolor);
}
}
// Print label
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().setCursor(80, 70);
getdisplay().print("Rudder Position"); // Label
// Print Unit in RudderPosition
if(valid1 == true || simulation == true){
if(holdvalues == false){
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(175, 110);
getdisplay().print(unit1); // Unit
}
else{
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(175, 110);
getdisplay().print(unit1old); // Unit
}
}
else{
// Print Unit of keel position
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(145, 110);
getdisplay().print("No sensor data"); // Info missing sensor
}
// Calculate rudder position
if(holdvalues == true && valid1 == false){
value1 = 2 * pi - ((value1old * 2) + pi);
}
else{
value1 = 2 * pi - ((value1 * 2) + pi);
}
// Draw rudder position pointer
float startwidth = 8; // Start width of pointer
if(valid1 == true || holdvalues == true || simulation == true){
float sinx=sin(value1);
float cosx=cos(value1);
// Normal pointer
// Pointer as triangle with center base 2*width
float xx1 = -startwidth;
float xx2 = startwidth;
float yy1 = -startwidth;
float yy2 = -(rInstrument * 0.5);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2),pixelcolor);
// Inverted pointer
// Pointer as triangle with center base 2*width
float endwidth = 2; // End width of pointer
float ix1 = endwidth;
float ix2 = -endwidth;
float iy1 = -(rInstrument * 0.5);
float iy2 = -endwidth;
getdisplay().fillTriangle(200+(int)(cosx*ix1-sinx*iy1),150+(int)(sinx*ix1+cosx*iy1),
200+(int)(cosx*ix2-sinx*iy1),150+(int)(sinx*ix2+cosx*iy1),
200+(int)(cosx*0-sinx*iy2),150+(int)(sinx*0+cosx*iy2),pixelcolor);
}
// Center circle
getdisplay().fillCircle(200, 150, startwidth + 6, bgcolor);
getdisplay().fillCircle(200, 150, startwidth + 4, pixelcolor);
//*******************************************************************************************
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageRudderPosition(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect (0 here)
* and will will provide the names of the fixed values we need
*/
PageDescription registerPageRudderPosition(
"RudderPosition", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{"RPOS"}, // Bus values we need in the page
true // Show display header on/off
);
#endif

View File

@@ -1,264 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
#include "movingAvg.h" // Lib for moving average building
class PageSolar : public Page
{
bool init = false; // Marker for init done
bool keylock = false; // Keylock
public:
PageSolar(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageSolar");
}
virtual int handleKey(int key){
// Code for keylock
if(key == 11){
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData)
{
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Get config data
bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String batVoltage = config->getString(config->batteryVoltage);
int solPower = config->getInt(config->solarPower);
String backlightMode = config->getString(config->backlight);
String powerSensor = config->getString(config->usePowSensor2);
double value1 = 0; // Solar voltage
double value2 = 0; // Solar current
double value3 = 0; // Solar output power
double valueTrend = 0; // Average over 10 values
int solPercentage = 0; // Solar load
// Get voltage value
String name1 = "VSol";
// Get raw value for trend indicator
if(powerSensor != "off"){
value1 = commonData.data.solarVoltage; // Use voltage from external sensor
}
else{
value1 = commonData.data.batteryVoltage; // Use internal voltage sensor
}
value2 = commonData.data.solarCurrent;
value3 = commonData.data.solarPower;
solPercentage = value3 * 100 / (double)solPower; // Load value
// Limits for battery level
if(solPercentage < 0) solPercentage = 0;
if(solPercentage > 99) solPercentage = 99;
bool valid1 = true;
// Optical warning by limit violation
if(String(flashLED) == "Limit Violation"){
// Over voltage
if(value1 > 14.8 && batVoltage == "12V"){
setBlinkingLED(true);
}
if(value1 <= 14.8 && batVoltage == "12V"){
setBlinkingLED(false);
}
if(value1 > 29.6 && batVoltage == "24V"){
setBlinkingLED(true);
}
if(value1 <= 29.6 && batVoltage == "24V"){
setBlinkingLED(false);
}
}
// Logging voltage value
LOG_DEBUG(GwLog::LOG,"Drawing at PageSolar, Type:%iW %s:=%f", solPower, name1.c_str(), value1);
// Draw page
//***********************************************************
// Clear display, set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(10, 65);
getdisplay().print("Solar");
// Show voltage type
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(10, 140);
int bvoltage = 0;
if(String(batVoltage) == "12V") bvoltage = 12;
else bvoltage = 24;
getdisplay().print(bvoltage);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("V");
// Show solar power
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(10, 200);
if(solPower <= 999) getdisplay().print(solPower, 0);
if(solPower > 999) getdisplay().print(float(solPower/1000.0), 1);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
if(solPower <= 999) getdisplay().print("W");
if(solPower > 999) getdisplay().print("kW");
// Show info
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(10, 235);
getdisplay().print("Installed");
getdisplay().setCursor(10, 255);
getdisplay().print("Solar Modul");
// Show solar panel
solarGraphic(150, 45, pixelcolor, bgcolor);
// Show load level in percent
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(150, 200);
getdisplay().print(solPercentage);
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("%");
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(150, 235);
getdisplay().print("Load");
// Show sensor type info
String i2cAddr = "";
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(270, 60);
if(powerSensor == "off") getdisplay().print("Internal");
if(powerSensor == "INA219"){
getdisplay().print("INA219");
i2cAddr = " (0x" + String(INA219_I2C_ADDR2, HEX) + ")";
}
if(powerSensor == "INA226"){
getdisplay().print("INA226");
i2cAddr = " (0x" + String(INA226_I2C_ADDR2, HEX) + ")";
}
getdisplay().print(i2cAddr);
getdisplay().setCursor(270, 80);
getdisplay().print("Sensor Modul");
// Reading bus data or using simulation data
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(260, 140);
if(simulation == true){
if(batVoltage == "12V"){
value1 = 12.0;
}
if(batVoltage == "24V"){
value1 = 24.0;
}
value1 += float(random(0, 5)) / 10; // Simulation data
getdisplay().print(value1,1);
}
else{
// Check for valid real data, display also if hold values activated
if(valid1 == true || holdvalues == true){
// Resolution switching
if(value1 <= 9.9) getdisplay().print(value1, 2);
if(value1 > 9.9 && value1 <= 99.9)getdisplay().print(value1, 1);
if(value1 > 99.9) getdisplay().print(value1, 0);
}
else{
getdisplay().print("---"); // Missing bus data
}
}
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("V");
// Show actual current in A
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(260, 200);
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
if(value2 <= 9.9) getdisplay().print(value2, 2);
if(value2 > 9.9 && value2 <= 99.9)getdisplay().print(value2, 1);
if(value2 > 99.9) getdisplay().print(value2, 0);
}
else getdisplay().print("---");
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("A");
// Show actual consumption in W
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(260, 260);
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
if(value3 <= 9.9) getdisplay().print(value3, 2);
if(value3 > 9.9 && value3 <= 99.9)getdisplay().print(value3, 1);
if(value3 > 99.9) getdisplay().print(value3, 0);
}
else getdisplay().print("---");
getdisplay().setFont(&Ubuntu_Bold16pt7b);
getdisplay().print("W");
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageSolar(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect (0 here)
* and will will provide the names of the fixed values we need
*/
PageDescription registerPageSolar(
"Solar", // Name of page
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
true // Show display header on/off
);
#endif

View File

@@ -1,285 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageThreeValues : public Page
{
bool keylock = false; // Keylock
public:
PageThreeValues(CommonData &comon){
comon.logger->logDebug(GwLog::LOG,"Show PageThreeValue");
}
virtual int handleKey(int key){
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData){
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Old values for hold function
static String svalue1old = "";
static String unit1old = "";
static String svalue2old = "";
static String unit2old = "";
static String svalue3old = "";
static String unit3old = "";
// Get config data
String lengthformat = config->getString(config->lengthFormat);
// bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
// Get boat values #1
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
String name1 = xdrDelete(bvalue1->getName()); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
double value1 = bvalue1->value; // Value as double in SI unit
bool valid1 = bvalue1->valid; // Valid information
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
// Get boat values #2
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
String name2 = xdrDelete(bvalue2->getName()); // Value name
name2 = name2.substring(0, 6); // String length limit for value name
double value2 = bvalue2->value; // Value as double in SI unit
bool valid2 = bvalue2->valid; // Valid information
String svalue2 = formatValue(bvalue2, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit2 = formatValue(bvalue2, commonData).unit; // Unit of value
// Get boat values #3
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
String name3 = xdrDelete(bvalue3->getName()); // Value name
name3 = name3.substring(0, 6); // String length limit for value name
double value3 = bvalue3->value; // Value as double in SI unit
bool valid3 = bvalue3->valid; // Valid information
String svalue3 = formatValue(bvalue3, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit3 = formatValue(bvalue3, commonData).unit; // Unit of value
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageThreeValues, %s: %f, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
/// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// ############### Value 1 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 55);
getdisplay().print(name1); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 90);
if(holdvalues == false){
getdisplay().print(unit1); // Unit
}
else{
getdisplay().print(unit1old);
}
// Switch font if format for any values
if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(50, 90);
}
else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(170, 68);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 90);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue1); // Real value as formated string
}
else{
getdisplay().print(svalue1old); // Old value as formated string
}
if(valid1 == true){
svalue1old = svalue1; // Save the old value
unit1old = unit1; // Save the old unit
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 105, 400, 3, pixelcolor);
// ############### Value 2 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 145);
getdisplay().print(name2); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 180);
if(holdvalues == false){
getdisplay().print(unit2); // Unit
}
else{
getdisplay().print(unit2old);
}
// Switch font if format for any values
if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(50, 180);
}
else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(170, 158);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 180);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue2); // Real value as formated string
}
else{
getdisplay().print(svalue2old); // Old value as formated string
}
if(valid2 == true){
svalue2old = svalue2; // Save the old value
unit2old = unit2; // Save the old unit
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 195, 400, 3, pixelcolor);
// ############### Value 3 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 235);
getdisplay().print(name3); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 270);
if(holdvalues == false){
getdisplay().print(unit3); // Unit
}
else{
getdisplay().print(unit3old);
}
// Switch font if format for any values
if(bvalue3->getFormat() == "formatLatitude" || bvalue3->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(50, 270);
}
else if(bvalue3->getFormat() == "formatTime" || bvalue3->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(170, 248);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
getdisplay().setCursor(180, 270);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue3); // Real value as formated string
}
else{
getdisplay().print(svalue3old); // Old value as formated string
}
if(valid3 == true){
svalue3old = svalue3; // Save the old value
unit3old = unit3; // Save the old unit
}
// ############### Key Layout ################
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageThreeValues(common);
}/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageThreeValues(
"ThreeValues", // Page name
createPage, // Action
3, // Number of bus values depends on selection in Web configuration
true // Show display header on/off
);
#endif

View File

@@ -1,225 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageTwoValues : public Page
{
bool keylock = false; // Keylock
public:
PageTwoValues(CommonData &comon){
comon.logger->logDebug(GwLog::LOG,"Show PageTwoValue");
}
virtual int handleKey(int key){
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData){
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Old values for hold function
static String svalue1old = "";
static String unit1old = "";
static String svalue2old = "";
static String unit2old = "";
// Get config data
String lengthformat = config->getString(config->lengthFormat);
// bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
// Get boat values #1
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
String name1 = xdrDelete(bvalue1->getName()); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
double value1 = bvalue1->value; // Value as double in SI unit
bool valid1 = bvalue1->valid; // Valid information
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
// Get boat values #2
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
String name2 = xdrDelete(bvalue2->getName()); // Value name
name2 = name2.substring(0, 6); // String length limit for value name
double value2 = bvalue2->value; // Value as double in SI unit
bool valid2 = bvalue2->valid; // Valid information
String svalue2 = formatValue(bvalue2, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit2 = formatValue(bvalue2, commonData).unit; // Unit of value
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageTwoValues, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// ############### Value 1 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 80);
getdisplay().print(name1); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 130);
if(holdvalues == false){
getdisplay().print(unit1); // Unit
}
else{
getdisplay().print(unit1old);
}
// Switch font if format for any values
if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(50, 130);
}
else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(170, 105);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic42pt7b);
getdisplay().setCursor(180, 130);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue1); // Real value as formated string
}
else{
getdisplay().print(svalue1old); // Old value as formated string
}
if(valid1 == true){
svalue1old = svalue1; // Save the old value
unit1old = unit1; // Save the old unit
}
// ############### Horizontal Line ################
// Horizontal line 3 pix
getdisplay().fillRect(0, 145, 400, 3, pixelcolor);
// ############### Value 2 ################
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(20, 190);
getdisplay().print(name2); // Page name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(20, 240);
if(holdvalues == false){
getdisplay().print(unit2); // Unit
}
else{
getdisplay().print(unit2old);
}
// Switch font if format for any values
if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(50, 240);
}
else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(170, 215);
}
else{
getdisplay().setFont(&DSEG7Classic_BoldItalic42pt7b);
getdisplay().setCursor(180, 240);
}
// Show bus data
if(holdvalues == false){
getdisplay().print(svalue2); // Real value as formated string
}
else{
getdisplay().print(svalue2old); // Old value as formated string
}
if(valid2 == true){
svalue2old = svalue2; // Save the old value
unit2old = unit2; // Save the old unit
}
// ############### Key Layout ################
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageTwoValues(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageTwoValues(
"TwoValues", // Page name
createPage, // Action
2, // Number of bus values depends on selection in Web configuration
true // Show display header on/off
);
#endif

View File

@@ -1,287 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
#include "movingAvg.h" // Lib for moving average building
class PageVoltage : public Page
{
bool init = false; // Marker for init done
bool keylock = false; // Keylock
int average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s
bool trend = true; // Trend indicator [0|1], 0=off, 1=on
double raw = 0;
public:
PageVoltage(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageVoltage");
}
virtual int handleKey(int key){
// Change average
if(key == 1){
average ++;
average = average % 4; // Modulo 4
return 0; // Commit the key
}
// Trend indicator
if(key == 5){
trend = !trend;
return 0; // Commit the key
}
// Code for keylock
if(key == 11){
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData)
{
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Get config data
bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String batVoltage = config->getString(config->batteryVoltage);
String batType = config->getString(config->batteryType);
String backlightMode = config->getString(config->backlight);
double value1 = 0;
double valueTrend = 0; // Average over 10 values
// Get voltage value
String name1 = "VBat";
// Create trend value
if(init == false){ // Load start values for first page run
valueTrend = commonData.data.batteryVoltage10;
init = true;
}
else{ // Reading trend value
valueTrend = commonData.data.batteryVoltage10;
}
// Get raw value for trend indicator
raw = commonData.data.batteryVoltage; // Live data
// Switch average values
switch (average) {
case 0:
value1 = commonData.data.batteryVoltage; // Live data
break;
case 1:
value1 = commonData.data.batteryVoltage10; // Average 10s
break;
case 2:
value1 = commonData.data.batteryVoltage60; // Average 60s
break;
case 3:
value1 = commonData.data.batteryVoltage300; // Average 300s
break;
default:
value1 = commonData.data.batteryVoltage; // Default
break;
}
bool valid1 = true;
// Optical warning by limit violation
if(String(flashLED) == "Limit Violation"){
// Limits for Pb battery
if(String(batType) == "Pb" && (raw < 11.8 || raw > 14.8)){
setBlinkingLED(true);
}
if(String(batType) == "Pb" && (raw >= 11.8 && raw <= 14.8)){
setBlinkingLED(false);
setFlashLED(false);
}
// Limits for Gel battery
if(String(batType) == "Gel" && (raw < 11.8 || raw > 14.4)){
setBlinkingLED(true);
}
if(String(batType) == "Gel" && (raw >= 11.8 && raw <= 14.4)){
setBlinkingLED(false);
setFlashLED(false);
}
// Limits for AGM battery
if(String(batType) == "AGM" && (raw < 11.8 || raw > 14.7)){
setBlinkingLED(true);
}
if(String(batType) == "AGM" && (raw >= 11.8 && raw <= 14.7)){
setBlinkingLED(false);
setFlashLED(false);
}
// Limits for LiFePo4 battery
if(String(batType) == "LiFePo4" && (raw < 12.0 || raw > 14.6)){
setBlinkingLED(true);
}
if(String(batType) == "LiFePo4" && (raw >= 12.0 && raw <= 14.6)){
setBlinkingLED(false);
setFlashLED(false);
}
}
// Logging voltage value
if (raw == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageVoltage, Type:%s %s:=%f", batType, name1.c_str(), raw);
// Draw page
//***********************************************************
// Clear display, set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Show name
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold32pt7b);
getdisplay().setCursor(20, 100);
getdisplay().print(name1); // Value name
// Show unit
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold20pt7b);
getdisplay().setCursor(270, 100);
getdisplay().print("V");
// Show batery type
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(295, 100);
getdisplay().print(batType);
// Show average settings
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(320, 100);
switch (average) {
case 0:
getdisplay().print("Avg: 1s");
break;
case 1:
getdisplay().print("Avg: 10s");
break;
case 2:
getdisplay().print("Avg: 60s");
break;
case 3:
getdisplay().print("Avg: 300s");
break;
default:
getdisplay().print("Avg: 1s");
break;
}
// Reading bus data or using simulation data
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic60pt7b);
getdisplay().setCursor(20, 240);
if(simulation == true){
if(batVoltage == "12V"){
value1 = 12.0;
}
if(batVoltage == "24V"){
value1 = 24.0;
}
value1 += float(random(0, 5)) / 10; // Simulation data
getdisplay().print(value1,1);
}
else{
// Check for valid real data, display also if hold values activated
if(valid1 == true || holdvalues == true){
// Resolution switching
if(value1 < 10){
getdisplay().print(value1,2);
}
if(value1 >= 10 && value1 < 100){
getdisplay().print(value1,1);
}
if(value1 >= 100){
getdisplay().print(value1,0);
}
}
else{
getdisplay().print("---"); // Missing bus data
}
}
// Trend indicator
// Show trend indicator
if(trend == true){
getdisplay().fillRect(310, 240, 40, 120, bgcolor); // Clear area
getdisplay().fillRect(315, 183, 35, 4, textcolor); // Draw separator
if(int(raw * 10) > int(valueTrend * 10)){
displayTrendHigh(320, 174, 11, textcolor); // Show high indicator
}
if(int(raw * 10) < int(valueTrend * 10)){
displayTrendLow(320, 195, 11, textcolor); // Show low indicator
}
}
// No trend indicator
else{
getdisplay().fillRect(310, 240, 40, 120, bgcolor); // Clear area
}
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(10, 290);
getdisplay().print("[AVG]");
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
getdisplay().setCursor(293, 290);
getdisplay().print("[TRD]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageVoltage(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect (0 here)
* and will will provide the names of the fixed values we need
*/
PageDescription registerPageVoltage(
"Voltage", // Name of page
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
true // Show display header on/off
);
#endif

View File

@@ -1,63 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageWhite : public Page{
bool keylock = false; // Keylock
public:
PageWhite(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageWhite");
}
virtual void displayPage(CommonData &commonData, PageData &pageData){
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
// Get config data
String flashLED = config->getString(config->flashLED);
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
LOG_DEBUG(GwLog::LOG,"Drawing at PageWhite");
// Draw page
//***********************************************************
// Set background color
int bgcolor = GxEPD_WHITE;
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page* createPage(CommonData &common){
return new PageWhite(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect
* this will be number of BoatValue pointers in pageData.values
*/
PageDescription registerPageWhite(
"WhitePage", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
false // Show display header on/off
);
#endif

View File

@@ -1,412 +0,0 @@
#ifdef BOARD_OBP60S3
#include "Pagedata.h"
#include "OBP60Extensions.h"
class PageWindRose : public Page
{
bool keylock = false; // Keylock
int16_t lp = 80; // Pointer length
public:
PageWindRose(CommonData &common){
common.logger->logDebug(GwLog::LOG,"Show PageWindRose");
}
// Key functions
virtual int handleKey(int key){
// Keylock function
if(key == 11){ // Code for keylock
keylock = !keylock; // Toggle keylock
return 0; // Commit the key
}
return key;
}
virtual void displayPage(CommonData &commonData, PageData &pageData)
{
GwConfigHandler *config = commonData.config;
GwLog *logger=commonData.logger;
static String svalue1old = "";
static String unit1old = "";
static String svalue2old = "";
static String unit2old = "";
static String svalue3old = "";
static String unit3old = "";
static String svalue4old = "";
static String unit4old = "";
static String svalue5old = "";
static String unit5old = "";
static String svalue6old = "";
static String unit6old = "";
// Get config data
String lengthformat = config->getString(config->lengthFormat);
bool simulation = config->getBool(config->useSimuData);
String displaycolor = config->getString(config->displaycolor);
bool holdvalues = config->getBool(config->holdvalues);
String flashLED = config->getString(config->flashLED);
String backlightMode = config->getString(config->backlight);
// Get boat values for AWA
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
String name1 = xdrDelete(bvalue1->getName()); // Value name
name1 = name1.substring(0, 6); // String length limit for value name
double value1 = bvalue1->value; // Value as double in SI unit
bool valid1 = bvalue1->valid; // Valid information
value1 = formatValue(bvalue1, commonData).value;// Format only nesaccery for simulation data for pointer
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
if(valid1 == true){
svalue1old = svalue1; // Save old value
unit1old = unit1; // Save old unit
}
// Get boat values for AWS
GwApi::BoatValue *bvalue2 = pageData.values[1]; // First element in list (only one value by PageOneValue)
String name2 = xdrDelete(bvalue2->getName()); // Value name
name2 = name2.substring(0, 6); // String length limit for value name
double value2 = bvalue2->value; // Value as double in SI unit
bool valid2 = bvalue2->valid; // Valid information
String svalue2 = formatValue(bvalue2, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit2 = formatValue(bvalue2, commonData).unit; // Unit of value
if(valid2 == true){
svalue2old = svalue2; // Save old value
unit2old = unit2; // Save old unit
}
// Get boat values TWD
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
String name3 = xdrDelete(bvalue3->getName()); // Value name
name3 = name3.substring(0, 6); // String length limit for value name
double value3 = bvalue3->value; // Value as double in SI unit
bool valid3 = bvalue3->valid; // Valid information
String svalue3 = formatValue(bvalue3, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit3 = formatValue(bvalue3, commonData).unit; // Unit of value
if(valid3 == true){
svalue3old = svalue3; // Save old value
unit3old = unit3; // Save old unit
}
// Get boat values TWS
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
String name4 = xdrDelete(bvalue4->getName()); // Value name
name4 = name4.substring(0, 6); // String length limit for value name
double value4 = bvalue4->value; // Value as double in SI unit
bool valid4 = bvalue4->valid; // Valid information
String svalue4 = formatValue(bvalue4, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit4 = formatValue(bvalue4, commonData).unit; // Unit of value
if(valid4 == true){
svalue4old = svalue4; // Save old value
unit4old = unit4; // Save old unit
}
// Get boat values DBT
GwApi::BoatValue *bvalue5 = pageData.values[4]; // Second element in list (only one value by PageOneValue)
String name5 = xdrDelete(bvalue5->getName()); // Value name
name5 = name5.substring(0, 6); // String length limit for value name
double value5 = bvalue5->value; // Value as double in SI unit
bool valid5 = bvalue5->valid; // Valid information
String svalue5 = formatValue(bvalue5, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit5 = formatValue(bvalue5, commonData).unit; // Unit of value
if(valid5 == true){
svalue5old = svalue5; // Save old value
unit5old = unit5; // Save old unit
}
// Get boat values STW
GwApi::BoatValue *bvalue6 = pageData.values[5]; // Second element in list (only one value by PageOneValue)
String name6 = xdrDelete(bvalue6->getName()); // Value name
name6 = name6.substring(0, 6); // String length limit for value name
double value6 = bvalue6->value; // Value as double in SI unit
bool valid6 = bvalue6->valid; // Valid information
String svalue6 = formatValue(bvalue6, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
String unit6 = formatValue(bvalue6, commonData).unit; // Unit of value
if(valid6 == true){
svalue6old = svalue6; // Save old value
unit6old = unit6; // Save old unit
}
// Optical warning by limit violation (unused)
if(String(flashLED) == "Limit Violation"){
setBlinkingLED(false);
setFlashLED(false);
}
// Logging boat values
if (bvalue1 == NULL) return;
LOG_DEBUG(GwLog::LOG,"Drawing at PageWindRose, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3, name4.c_str(), value4, name5.c_str(), value5, name6.c_str(), value6);
// Draw page
//***********************************************************
// Set background color and text color
int textcolor = GxEPD_BLACK;
int pixelcolor = GxEPD_BLACK;
int bgcolor = GxEPD_WHITE;
if(displaycolor == "Normal"){
textcolor = GxEPD_BLACK;
pixelcolor = GxEPD_BLACK;
bgcolor = GxEPD_WHITE;
}
else{
textcolor = GxEPD_WHITE;
pixelcolor = GxEPD_WHITE;
bgcolor = GxEPD_BLACK;
}
// Set display in partial refresh mode
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
// Show values AWA
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(10, 65);
getdisplay().print(svalue1); // Value
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(10, 95);
getdisplay().print(name1); // Name
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(10, 115);
getdisplay().print(" ");
if(holdvalues == false){
getdisplay().print(unit1); // Unit
}
else{
getdisplay().print(unit1old); // Unit
}
// Horizintal separator left
getdisplay().fillRect(0, 149, 60, 3, pixelcolor);
// Show values AWS
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(10, 270);
getdisplay().print(svalue2); // Value
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(10, 220);
getdisplay().print(name2); // Name
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(10, 190);
getdisplay().print(" ");
if(holdvalues == false){
getdisplay().print(unit2); // Unit
}
else{
getdisplay().print(unit2old); // Unit
}
// Show values TWD
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(295, 65);
if(valid3 == true){
getdisplay().print(abs(value3 * 360 / PI), 0); // Value
}
else{
getdisplay().print("---"); // Value
}
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(335, 95);
getdisplay().print(name3); // Name
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(335, 115);
getdisplay().print(" ");
if(holdvalues == false){
getdisplay().print(unit3); // Unit
}
else{
getdisplay().print(unit3old); // Unit
}
// Horizintal separator right
getdisplay().fillRect(340, 149, 80, 3, pixelcolor);
// Show values TWS
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
getdisplay().setCursor(295, 270);
getdisplay().print(svalue4); // Value
getdisplay().setFont(&Ubuntu_Bold12pt7b);
getdisplay().setCursor(335, 220);
getdisplay().print(name4); // Name
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(335, 190);
getdisplay().print(" ");
if(holdvalues == false){
getdisplay().print(unit4); // Unit
}
else{
getdisplay().print(unit4old); // Unit
}
//*******************************************************************************************
// Draw wind rose
int rInstrument = 110; // Radius of grafic instrument
float pi = 3.141592;
getdisplay().fillCircle(200, 150, rInstrument + 10, pixelcolor); // Outer circle
getdisplay().fillCircle(200, 150, rInstrument + 7, bgcolor); // Outer circle
getdisplay().fillCircle(200, 150, rInstrument - 10, pixelcolor); // Inner circle
getdisplay().fillCircle(200, 150, rInstrument - 13, bgcolor); // Inner circle
for(int i=0; i<360; i=i+10)
{
// Scaling values
float x = 200 + (rInstrument-30)*sin(i/180.0*pi); // x-coordinate dots
float y = 150 - (rInstrument-30)*cos(i/180.0*pi); // y-coordinate cots
const char *ii = "";
switch (i)
{
case 0: ii="0"; break;
case 30 : ii="30"; break;
case 60 : ii="60"; break;
case 90 : ii="90"; break;
case 120 : ii="120"; break;
case 150 : ii="150"; break;
case 180 : ii="180"; break;
case 210 : ii="210"; break;
case 240 : ii="240"; break;
case 270 : ii="270"; break;
case 300 : ii="300"; break;
case 330 : ii="330"; break;
default: break;
}
// Print text centered on position x, y
int16_t x1, y1; // Return values of getTextBounds
uint16_t w, h; // Return values of getTextBounds
getdisplay().getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
getdisplay().setCursor(x-w/2, y+h/2);
if(i % 30 == 0){
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().print(ii);
}
// Draw sub scale with dots
float x1c = 200 + rInstrument*sin(i/180.0*pi);
float y1c = 150 - rInstrument*cos(i/180.0*pi);
getdisplay().fillCircle((int)x1c, (int)y1c, 2, pixelcolor);
float sinx=sin(i/180.0*pi);
float cosx=cos(i/180.0*pi);
// Draw sub scale with lines (two triangles)
if(i % 30 == 0){
float dx=2; // Line thickness = 2*dx+1
float xx1 = -dx;
float xx2 = +dx;
float yy1 = -(rInstrument-10);
float yy2 = -(rInstrument+10);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),pixelcolor);
getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*xx1-sinx*yy2),150+(int)(sinx*xx1+cosx*yy2),
200+(int)(cosx*xx2-sinx*yy2),150+(int)(sinx*xx2+cosx*yy2),pixelcolor);
}
}
// Draw wind pointer
float startwidth = 8; // Start width of pointer
if(valid2 == true || holdvalues == true || simulation == true){
float sinx=sin(value1); // Wind direction
float cosx=cos(value1);
// Normal pointer
// Pointer as triangle with center base 2*width
float xx1 = -startwidth;
float xx2 = startwidth;
float yy1 = -startwidth;
float yy2 = -(rInstrument-15);
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2),pixelcolor);
// Inverted pointer
// Pointer as triangle with center base 2*width
float endwidth = 2; // End width of pointer
float ix1 = endwidth;
float ix2 = -endwidth;
float iy1 = -(rInstrument-15);
float iy2 = -endwidth;
getdisplay().fillTriangle(200+(int)(cosx*ix1-sinx*iy1),150+(int)(sinx*ix1+cosx*iy1),
200+(int)(cosx*ix2-sinx*iy1),150+(int)(sinx*ix2+cosx*iy1),
200+(int)(cosx*0-sinx*iy2),150+(int)(sinx*0+cosx*iy2),pixelcolor);
}
// Center circle
getdisplay().fillCircle(200, 150, startwidth + 6, bgcolor);
getdisplay().fillCircle(200, 150, startwidth + 4, pixelcolor);
//*******************************************************************************************
// Show values DBT
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b);
getdisplay().setCursor(160, 200);
getdisplay().print(svalue5); // Value
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(190, 215);
getdisplay().print(" ");
if(holdvalues == false){
getdisplay().print(unit5); // Unit
}
else{
getdisplay().print(unit5old); // Unit
}
// Show values STW
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b);
getdisplay().setCursor(160, 130);
getdisplay().print(svalue6); // Value
getdisplay().setFont(&Ubuntu_Bold8pt7b);
getdisplay().setCursor(190, 90);
getdisplay().print(" ");
if(holdvalues == false){
getdisplay().print(unit6); // Unit
}
else{
getdisplay().print(unit6old); // Unit
}
// Key Layout
getdisplay().setTextColor(textcolor);
getdisplay().setFont(&Ubuntu_Bold8pt7b);
if(keylock == false){
getdisplay().setCursor(130, 290);
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
if(String(backlightMode) == "Control by Key"){ // Key for illumination
getdisplay().setCursor(343, 290);
getdisplay().print("[ILUM]");
}
}
else{
getdisplay().setCursor(130, 290);
getdisplay().print(" [ Keylock active ]");
}
// Update display
getdisplay().nextPage(); // Partial update (fast)
};
};
static Page *createPage(CommonData &common){
return new PageWindRose(common);
}
/**
* with the code below we make this page known to the PageTask
* we give it a type (name) that can be selected in the config
* we define which function is to be called
* and we provide the number of user parameters we expect (0 here)
* and will will provide the names of the fixed values we need
*/
PageDescription registerPageWindRose(
"WindRose", // Page name
createPage, // Action
0, // Number of bus values depends on selection in Web configuration
{"AWA", "AWS", "TWD", "TWS", "DBT", "STW"}, // Bus values we need in the page
true // Show display header on/off
);
#endif

View File

@@ -1,124 +0,0 @@
#pragma once
#include <Arduino.h>
#include "GwApi.h"
#include <functional>
#include <vector>
typedef std::vector<GwApi::BoatValue *> ValueList;
typedef struct{
String pageName;
//the values will always contain the user defined values first
ValueList values;
} PageData;
// Sensor data structure (only for extended sensors, not for NMEA bus sensors)
typedef struct{
int actpage = 0;
int maxpage = 0;
double batteryVoltage = 0;
double batteryCurrent = 0;
double batteryPower = 0;
double batteryVoltage10 = 0; // Sliding average over 10 values
double batteryCurrent10 = 0;
double batteryPower10 = 0;
double batteryVoltage60 = 0; // Sliding average over 60 values
double batteryCurrent60 = 0;
double batteryPower60 = 0;
double batteryVoltage300 = 0; // Sliding average over 300 values
double batteryCurrent300 = 0;
double batteryPower300 = 0;
double solarVoltage = 0;
double solarCurrent = 0;
double solarPower = 0;
double generatorVoltage = 0;
double generatorCurrent = 0;
double generatorPower = 0;
double airTemperature = 0;
double airHumidity = 0;
double airPressure = 0;
double onewireTemp[8] = {0,0,0,0,0,0,0,0};
double rotationAngle = 0; // Rotation angle in radiant
bool validRotAngle = false; // Valid flag magnet present for rotation sensor
int rtcYear = 0; // UTC time
int rtcMonth = 0;
int rtcDay = 0;
int rtcHour = 0;
int rtcMinute = 0;
int rtcSecond = 0;
int sunsetHour = 0;
int sunsetMinute = 0;
int sunriseHour = 0;
int sunriseMinute = 0;
bool sunDown = true;
} SensorData;
typedef struct{
int sunsetHour = 0;
int sunsetMinute = 0;
int sunriseHour = 0;
int sunriseMinute = 0;
bool sunDown = true;
} SunData;
typedef struct{
GwApi::Status status;
GwLog *logger=NULL;
GwConfigHandler *config=NULL;
SensorData data;
SunData sundata;
GwApi::BoatValue *time=NULL;
GwApi::BoatValue *date=NULL;
} CommonData;
//a base class that all pages must inherit from
class Page{
public:
virtual void displayPage(CommonData &commonData, PageData &pageData)=0;
virtual void displayNew(CommonData &commonData, PageData &pageData){}
//return -1 if handled by the page
virtual int handleKey(int key){return key;}
};
typedef std::function<Page* (CommonData &)> PageFunction;
typedef std::vector<String> StringList;
/**
* a class that describes a page
* it contains the name (type)
* the number of expected user defined boat Values
* and a list of boatValue names that are fixed
* for each page you define a variable of this type
* and add this to registerAllPages in the obp60task
*/
class PageDescription{
public:
String pageName;
int userParam=0;
StringList fixedParam;
PageFunction creator;
bool header=true;
PageDescription(String name, PageFunction creator,int userParam,StringList fixedParam,bool header=true){
this->pageName=name;
this->userParam=userParam;
this->fixedParam=fixedParam;
this->creator=creator;
this->header=header;
}
PageDescription(String name, PageFunction creator,int userParam,bool header=true){
this->pageName=name;
this->userParam=userParam;
this->creator=creator;
this->header=header;
}
};
// Structure for formated boat values
typedef struct{
double value;
String svalue;
String unit;
} FormatedData;
// Formater for boat values
FormatedData formatValue(GwApi::BoatValue *value, CommonData &commondata);

View File

@@ -1,516 +0,0 @@
// A library for handling real-time clocks, dates, etc.
// 2010-02-04 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php
// 2012-11-08 RAM methods - idreammicro.com
// 2012-11-14 SQW/OUT methods - idreammicro.com
// 2012-01-12 DS1388 support
// 2013-08-29 ENERGIA MSP430 support
// 2023-11-24 Return value for begin() to RTC presence check - NoWa
#include <Wire.h>
// Energia support
#ifndef ENERGIA
// #include <avr/pgmspace.h>
#else
#define pgm_read_word(data) *data
#define pgm_read_byte(data) *data
#define PROGMEM
#endif
#include "RTClib.h"
#include <Arduino.h>
////////////////////////////////////////////////////////////////////////////////
// utility code, some of this could be exposed in the DateTime API if needed
static const uint8_t daysInMonth [] PROGMEM = {
31,28,31,30,31,30,31,31,30,31,30,31
};
// number of days since 2000/01/01, valid for 2001..2099
static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) {
if (y >= 2000)
y -= 2000;
uint16_t days = d;
for (uint8_t i = 1; i < m; ++i)
days += pgm_read_byte(daysInMonth + i - 1);
if (m > 2 && y % 4 == 0)
++days;
return days + 365 * y + (y + 3) / 4 - 1;
}
static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) {
return ((days * 24L + h) * 60 + m) * 60 + s;
}
////////////////////////////////////////////////////////////////////////////////
// DateTime implementation - ignores time zones and DST changes
// NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second
DateTime::DateTime (long t) {
ss = t % 60;
t /= 60;
mm = t % 60;
t /= 60;
hh = t % 24;
uint16_t days = t / 24;
uint8_t leap;
for (yOff = 0; ; ++yOff) {
leap = yOff % 4 == 0;
if (days < 365 + leap)
break;
days -= 365 + leap;
}
for (m = 1; ; ++m) {
uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1);
if (leap && m == 2)
++daysPerMonth;
if (days < daysPerMonth)
break;
days -= daysPerMonth;
}
d = days + 1;
}
DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) {
if (year >= 2000)
year -= 2000;
yOff = year;
m = month;
d = day;
hh = hour;
mm = min;
ss = sec;
}
static uint8_t conv2d(const char* p) {
uint8_t v = 0;
if ('0' <= *p && *p <= '9')
v = *p - '0';
return 10 * v + *++p - '0';
}
// A convenient constructor for using "the compiler's time":
// DateTime now (__DATE__, __TIME__);
// NOTE: using PSTR would further reduce the RAM footprint
DateTime::DateTime (const char* date, const char* time) {
// sample input: date = "Dec 26 2009", time = "12:34:56"
yOff = conv2d(date + 9);
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
switch (date[0]) {
case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break;
case 'F': m = 2; break;
case 'A': m = date[2] == 'r' ? 4 : 8; break;
case 'M': m = date[2] == 'r' ? 3 : 5; break;
case 'S': m = 9; break;
case 'O': m = 10; break;
case 'N': m = 11; break;
case 'D': m = 12; break;
}
d = conv2d(date + 4);
hh = conv2d(time);
mm = conv2d(time + 3);
ss = conv2d(time + 6);
}
uint8_t DateTime::dayOfWeek() const {
uint16_t day = get() / SECONDS_PER_DAY;
return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
}
long DateTime::get() const {
uint16_t days = date2days(yOff, m, d);
return time2long(days, hh, mm, ss);
}
////////////////////////////////////////////////////////////////////////////////
// RTC_DS1307 implementation
void RTC_DS1307::adjust(const DateTime& dt) {
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write((byte) 0);
Wire.write(bin2bcd(dt.second()));
Wire.write(bin2bcd(dt.minute()));
Wire.write(bin2bcd(dt.hour()));
Wire.write(bin2bcd(0));
Wire.write(bin2bcd(dt.day()));
Wire.write(bin2bcd(dt.month()));
Wire.write(bin2bcd(dt.year() - 2000));
Wire.write((byte) 0);
Wire.endTransmission();
}
DateTime RTC_DS1307::now() {
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write((byte) 0);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
uint8_t ss = bcd2bin(Wire.read());
uint8_t mm = bcd2bin(Wire.read());
uint8_t hh = bcd2bin(Wire.read());
Wire.read();
uint8_t d = bcd2bin(Wire.read());
uint8_t m = bcd2bin(Wire.read());
uint16_t y = bcd2bin(Wire.read()) + 2000;
return DateTime (y, m, d, hh, mm, ss);
}
void RTC_DS1307::setSqwOutLevel(uint8_t level) {
uint8_t value = (level == LOW) ? 0x00 : (1 << RTC_DS1307__OUT);
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(DS1307_CONTROL_REGISTER);
Wire.write(value);
Wire.endTransmission();
}
void RTC_DS1307::setSqwOutSignal(Frequencies frequency) {
uint8_t value = (1 << RTC_DS1307__SQWE);
switch (frequency)
{
case Frequency_1Hz:
// Nothing to do.
break;
case Frequency_4096Hz:
value |= (1 << RTC_DS1307__RS0);
break;
case Frequency_8192Hz:
value |= (1 << RTC_DS1307__RS1);
break;
case Frequency_32768Hz:
default:
value |= (1 << RTC_DS1307__RS1) | (1 << RTC_DS1307__RS0);
break;
}
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(DS1307_CONTROL_REGISTER);
Wire.write(value);
Wire.endTransmission();
}
uint8_t RTC_DS1307::readByteInRam(uint8_t address) {
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(address);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 1);
uint8_t data = Wire.read();
Wire.endTransmission();
return data;
}
void RTC_DS1307::readBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data) {
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(address);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, (int)length);
for (uint8_t i = 0; i < length; i++) {
p_data[i] = Wire.read();
}
Wire.endTransmission();
}
void RTC_DS1307::writeByteInRam(uint8_t address, uint8_t data) {
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(address);
Wire.write(data);
Wire.endTransmission();
}
void RTC_DS1307::writeBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data) {
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write(address);
for (uint8_t i = 0; i < length; i++) {
Wire.write(p_data[i]);
}
Wire.endTransmission();
}
uint8_t RTC_DS1307::isrunning(void) {
Wire.beginTransmission(DS1307_ADDRESS);
Wire.write((byte) 0);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 1);
uint8_t ss = Wire.read();
return !(ss>>7);
}
////////////////////////////////////////////////////////////////////////////////
// DS 1388 implementation
void RTC_DS1388::adjust(const DateTime& dt) {
Wire.beginTransmission(DS1388_ADDRESS);
Wire.write((byte) 0);
Wire.write(bin2bcd(0)); // hundreds of seconds 0x00
Wire.write(bin2bcd(dt.second())); // 0x01
Wire.write(bin2bcd(dt.minute())); // 0x02
Wire.write(bin2bcd(dt.hour())); // 0x03
Wire.write(bin2bcd(0)); // 0x04
Wire.write(bin2bcd(dt.day())); // 0x05
Wire.write(bin2bcd(dt.month())); // 0x06
Wire.write(bin2bcd(dt.year() - 2000)); // 0x07
Wire.endTransmission();
Wire.beginTransmission(DS1388_ADDRESS);
Wire.write((byte) 0x0b);
Wire.write((byte) 0x00); //clear the 'time is invalid ' flag bit (OSF)
Wire.endTransmission();
}
DateTime RTC_DS1388::now() {
Wire.beginTransmission(DS1388_ADDRESS);
Wire.write((byte) 0);
Wire.endTransmission();
Wire.requestFrom(DS1388_ADDRESS, 8);
uint8_t hs = bcd2bin(Wire.read() & 0x7F); // hundreds of seconds
uint8_t ss = bcd2bin(Wire.read() & 0x7F);
uint8_t mm = bcd2bin(Wire.read());
uint8_t hh = bcd2bin(Wire.read());
Wire.read();
uint8_t d = bcd2bin(Wire.read());
uint8_t m = bcd2bin(Wire.read());
uint16_t y = bcd2bin(Wire.read()) + 2000;
return DateTime (y, m, d, hh, mm, ss);
}
uint8_t RTC_DS1388::isrunning() {
Wire.beginTransmission(DS1388_ADDRESS);
Wire.write((byte)0x0b);
Wire.endTransmission();
Wire.requestFrom(DS1388_ADDRESS, 1);
uint8_t ss = Wire.read();
return !(ss>>7); //OSF flag bit
}
void RTC_DS1388::EEPROMWrite(int pos, uint8_t c) {
uint8_t rel_pos = pos % 256;
if(pos > 255){
Wire.beginTransmission(DS1388_ADDRESS | DS1388_EEPROM_1);
} else {
Wire.beginTransmission(DS1388_ADDRESS | DS1388_EEPROM_0);
}
// Set address
Wire.write((byte)rel_pos);
// Wite data
Wire.write((byte)c);
Wire.endTransmission();
#if defined(__MSP430G2553__)
delay(10); // Needed on MSP430 !!
#endif
}
uint8_t RTC_DS1388::EEPROMRead(int pos) {
uint8_t rel_pos = pos % 256;
if(pos > 255){
Wire.beginTransmission(DS1388_ADDRESS | DS1388_EEPROM_1);
} else {
Wire.beginTransmission(DS1388_ADDRESS | DS1388_EEPROM_0);
}
// Set address
Wire.write((byte)rel_pos);
Wire.endTransmission(true); // Stay open
// Request one byte
if(pos > 255){
Wire.requestFrom(DS1388_ADDRESS | DS1388_EEPROM_1, 1);
} else {
Wire.requestFrom(DS1388_ADDRESS | DS1388_EEPROM_0, 1);
}
uint8_t c = Wire.read();
#if defined(__MSP430G2553__)
delay(10); // Needed on MSP430 !!
#endif
return c;
}
///////////////////////////////////////////////////////////////////////////////
// RTC_PCF8563 implementation
// contributed by @mariusster, see http://forum.jeelabs.net/comment/1902
void RTC_PCF8563::adjust(const DateTime& dt) {
Wire.beginTransmission(PCF8563_ADDRESS);
Wire.write((byte) 0);
Wire.write((byte) 0x0); // control/status1
Wire.write((byte) 0x0); // control/status2
Wire.write(bin2bcd(dt.second())); // set seconds
Wire.write(bin2bcd(dt.minute())); // set minutes
Wire.write(bin2bcd(dt.hour())); // set hour
Wire.write(bin2bcd(dt.day())); // set day
Wire.write((byte) 0x01); // set weekday
Wire.write(bin2bcd(dt.month())); // set month, century to 1
Wire.write(bin2bcd(dt.year() - 2000)); // set year to 00-99
Wire.write((byte) 0x80); // minute alarm value reset to 00
Wire.write((byte) 0x80); // hour alarm value reset to 00
Wire.write((byte) 0x80); // day alarm value reset to 00
Wire.write((byte) 0x80); // weekday alarm value reset to 00
Wire.write((byte) 0x0); // set freqout 0= 32768khz, 1= 1hz
Wire.write((byte) 0x0); // timer off
Wire.endTransmission();
}
DateTime RTC_PCF8563::now() {
Wire.beginTransmission(PCF8563_ADDRESS);
Wire.write(PCF8563_SEC_ADDR);
Wire.endTransmission();
Wire.requestFrom(PCF8563_ADDRESS, 7);
uint8_t ss = bcd2bin(Wire.read() & 0x7F);
uint8_t mm = bcd2bin(Wire.read() & 0x7F);
uint8_t hh = bcd2bin(Wire.read() & 0x3F);
uint8_t d = bcd2bin(Wire.read() & 0x3F);
Wire.read();
uint8_t m = bcd2bin(Wire.read()& 0x1F);
uint16_t y = bcd2bin(Wire.read()) + 2000;
return DateTime (y, m, d, hh, mm, ss);
}
///////////////////////////////////////////////////////////////////////////////
// RTC_BQ32000 implementation
void RTC_BQ32000::adjust(const DateTime& dt) {
Wire.beginTransmission(BQ32000_ADDRESS);
Wire.write((byte) 0);
Wire.write(bin2bcd(dt.second()));
Wire.write(bin2bcd(dt.minute()));
Wire.write(bin2bcd(dt.hour()));
Wire.write(bin2bcd(0));
Wire.write(bin2bcd(dt.day()));
Wire.write(bin2bcd(dt.month()));
Wire.write(bin2bcd(dt.year() - 2000));
Wire.endTransmission();
}
DateTime RTC_BQ32000::now() {
Wire.beginTransmission(BQ32000_ADDRESS);
Wire.write((byte) 0);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
uint8_t ss = bcd2bin(Wire.read());
uint8_t mm = bcd2bin(Wire.read());
uint8_t hh = bcd2bin(Wire.read());
Wire.read();
uint8_t d = bcd2bin(Wire.read());
uint8_t m = bcd2bin(Wire.read());
uint16_t y = bcd2bin(Wire.read()) + 2000;
return DateTime (y, m, d, hh, mm, ss);
}
void RTC_BQ32000::setIRQ(uint8_t state) {
/* Set IRQ square wave output state: 0=disabled, 1=1Hz, 2=512Hz.
*/
uint8_t reg, value;
if (state) {
// Setting the frequency is a bit complicated on the BQ32000:
Wire.beginTransmission(BQ32000_ADDRESS);
Wire.write(BQ32000_SFKEY1);
Wire.write(BQ32000_SFKEY1_VAL);
Wire.write(BQ32000_SFKEY2_VAL);
Wire.write((state == 1) ? BQ32000_FTF_1HZ : BQ32000_FTF_512HZ);
Wire.endTransmission();
}
value = readRegister(BQ32000_CAL_CFG1);
value = (!state) ? value & ~(1<<BQ32000__FT) : value | (1<<BQ32000__FT);
writeRegister(BQ32000_CAL_CFG1, value);
}
void RTC_BQ32000::setIRQLevel(uint8_t level) {
/* Set IRQ output level when IRQ square wave output is disabled to
* LOW or HIGH.
*/
uint8_t value;
// The IRQ active level bit is in the same register as the calibration
// settings, so we preserve its current state:
value = readRegister(BQ32000_CAL_CFG1);
value = (!level) ? value & ~(1<<BQ32000__OUT) : value | (1<<BQ32000__OUT);
writeRegister(BQ32000_CAL_CFG1, value);
}
void RTC_BQ32000::setCalibration(int8_t value) {
/* Sets the calibration value to given value in the range -31 - 31, which
* corresponds to -126ppm - +63ppm; see table 13 in th BQ32000 datasheet.
*/
uint8_t val;
if (value > 31) value = 31;
if (value < -31) value = -31;
val = (uint8_t) (value < 0) ? -value | (1<<BQ32000__CAL_S) : value;
val |= readRegister(BQ32000_CAL_CFG1) & ~0x3f;
writeRegister(BQ32000_CAL_CFG1, val);
}
void RTC_BQ32000::setCharger(int state) {
/* If using a super capacitor instead of a battery for backup power, use this
* method to set the state of the trickle charger: 0=disabled, 1=low-voltage
* charge, 2=high-voltage charge. In low-voltage charge mode, the super cap is
* charged through a diode with a voltage drop of about 0.5V, so it will charge
* up to VCC-0.5V. In high-voltage charge mode the diode is bypassed and the super
* cap will be charged up to VCC (make sure the charge voltage does not exceed your
* super cap's voltage rating!!).
*/
// First disable charger regardless of state (prevents it from
// possible starting up in the high voltage mode when the low
// voltage mode is requested):
uint8_t value;
writeRegister(BQ32000_TCH2, 0);
if (state <= 0 || state > 2) return;
value = BQ32000_CHARGE_ENABLE;
if (state == 2) {
// High voltage charge enable:
value |= (1 << BQ32000__TCFE);
}
writeRegister(BQ32000_CFG2, value);
// Now enable charger:
writeRegister(BQ32000_TCH2, 1 << BQ32000__TCH2_BIT);
}
uint8_t RTC_BQ32000::readRegister(uint8_t address) {
/* Read and return the value in the register at the given address.
*/
Wire.beginTransmission(BQ32000_ADDRESS);
Wire.write((byte) address);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 1);
// Get register state:
return Wire.read();
}
uint8_t RTC_BQ32000::writeRegister(uint8_t address, uint8_t value) {
/* Write the given value to the register at the given address.
*/
Wire.beginTransmission(BQ32000_ADDRESS);
Wire.write(address);
Wire.write(value);
Wire.endTransmission();
}
uint8_t RTC_BQ32000::isrunning() {
return !(readRegister(0x0)>>7);
}
////////////////////////////////////////////////////////////////////////////////
// RTC_Millis implementation
long RTC_Millis::offset = 0;
void RTC_Millis::adjust(const DateTime& dt) {
offset = dt.get() - millis() / 1000;
}
DateTime RTC_Millis::now() {
return offset + millis() / 1000;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,201 +0,0 @@
// A library for handling real-time clocks, dates, etc.
// 2010-02-04 <jc@wippler.nl> http://opensource.org/licenses/mit-license.php
// 2012-11-08 RAM methods - idreammicro.com
// 2012-11-14 SQW/OUT methods - idreammicro.com
// 2023-11-24 Return value for begin() to RTC presence check - NoWa
// DS1307
#define DS1307_ADDRESS 0x68
#define DS1307_CONTROL_REGISTER 0x07
#define DS1307_RAM_REGISTER 0x08
// DS1307 Control register bits.
#define RTC_DS1307__RS0 0x00
#define RTC_DS1307__RS1 0x01
#define RTC_DS1307__SQWE 0x04
#define RTC_DS1307__OUT 0x07
// DS1388
#define DS1388_ADDRESS 0x68
// DS1388 Control register bits
#define DS1388_EEPROM_0 0x01
#define DS1388_EEPROM_1 0x02
// PCF8563
#define PCF8563_ADDRESS 0x51
#define PCF8563_SEC_ADDR 0x02
// BQ32000
#define BQ32000_ADDRESS 0x68
// BQ32000 register addresses:
#define BQ32000_CAL_CFG1 0x07
#define BQ32000_TCH2 0x08
#define BQ32000_CFG2 0x09
#define BQ32000_SFKEY1 0x20
#define BQ32000_SFKEY2 0x21
#define BQ32000_SFR 0x22
// BQ32000 config bits:
#define BQ32000__OUT 0x07 // CAL_CFG1 - IRQ active state
#define BQ32000__FT 0x06 // CAL_CFG1 - IRQ square wave enable
#define BQ32000__CAL_S 0x05 // CAL_CFG1 - Calibration sign
#define BQ32000__TCH2_BIT 0x05 // TCH2 - Trickle charger switch 2
#define BQ32000__TCFE 0x06 // CFG2 - Trickle FET control
// BQ32000 config values:
#define BQ32000_CHARGE_ENABLE 0x05 // CFG2 - Trickle charger switch 1 enable
#define BQ32000_SFKEY1_VAL 0x5E
#define BQ32000_SFKEY2_VAL 0xC7
#define BQ32000_FTF_1HZ 0x01
#define BQ32000_FTF_512HZ 0x00
#define SECONDS_PER_DAY 86400L
// Simple general-purpose date/time class (no TZ / DST / leap second handling!)
class DateTime {
public:
DateTime (long t =0);
DateTime (uint16_t year, uint8_t month, uint8_t day,
uint8_t hour =0, uint8_t min =0, uint8_t sec =0);
DateTime (const char* date, const char* time);
uint16_t year() const { return 2000 + yOff; }
uint8_t month() const { return m; }
uint8_t day() const { return d; }
uint8_t hour() const { return hh; }
uint8_t minute() const { return mm; }
uint8_t second() const { return ss; }
uint8_t dayOfWeek() const;
// 32-bit times as seconds since 1/1/2000
long get() const;
protected:
uint8_t yOff, m, d, hh, mm, ss;
};
// RTC based on the DS1307 chip connected via I2C and the Wire library
class RTC_DS1307 {
public:
// SQW/OUT frequencies.
enum Frequencies
{
Frequency_1Hz,
Frequency_4096Hz,
Frequency_8192Hz,
Frequency_32768Hz
};
static bool begin() {
Wire.beginTransmission(DS1307_ADDRESS);
return (Wire.endTransmission() == 0);
}
static void adjust(const DateTime& dt);
static DateTime now();
static uint8_t isrunning();
// SQW/OUT functions.
void setSqwOutLevel(uint8_t level);
void setSqwOutSignal(Frequencies frequency);
// RAM registers read/write functions. Address locations 08h to 3Fh.
// Max length = 56 bytes.
static uint8_t readByteInRam(uint8_t address);
static void readBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data);
static void writeByteInRam(uint8_t address, uint8_t data);
static void writeBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data);
// utility functions
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
};
// DS1388 version
class RTC_DS1388 {
public:
static bool begin() {
Wire.beginTransmission(DS1388_ADDRESS);
return (Wire.endTransmission() == 0);
};
static void adjust(const DateTime& dt);
static DateTime now();
static uint8_t isrunning();
// EEPROM
static void EEPROMWrite(int pos, uint8_t c);
static uint8_t EEPROMRead(int pos);
// utility functions
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
};
// RTC based on the PCF8563 chip connected via I2C and the Wire library
// contributed by @mariusster, see http://forum.jeelabs.net/comment/1902
class RTC_PCF8563 {
public:
static bool begin() {
Wire.beginTransmission(PCF8563_ADDRESS);
return (Wire.endTransmission() == 0);
}
static void adjust(const DateTime& dt);
static DateTime now();
// utility functions
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
};
// TI BQ32000 I2C RTC
class RTC_BQ32000 {
public:
static bool begin() {
Wire.beginTransmission(BQ32000_ADDRESS);
return (Wire.endTransmission() == 0);
}
static void adjust(const DateTime& dt);
static DateTime now();
static uint8_t isrunning();
static void setIRQ(uint8_t state);
/* Set IRQ output state: 0=disabled, 1=1Hz, 2=512Hz.
*/
static void setIRQLevel(uint8_t level);
/* Set IRQ output active state to LOW or HIGH.
*/
static void setCalibration(int8_t value);
/* Sets the calibration value to given value in the range -31 - 31, which
* corresponds to -126ppm - +63ppm; see table 13 in th BQ32000 datasheet.
*/
static void setCharger(int state);
/* If using a super capacitor instead of a battery for backup power, use this
method to set the state of the trickle charger: 0=disabled, 1=low-voltage
charge, 2=high-voltage charge. In low-voltage charge mode, the super cap is
charged through a diode with a voltage drop of about 0.5V, so it will charge
up to VCC-0.5V. In high-voltage charge mode the diode is bypassed and the super
cap will be charged up to VCC (make sure the charge voltage does not exceed your
super cap's voltage rating!!). */
// utility functions:
static uint8_t readRegister(uint8_t address);
static uint8_t writeRegister(uint8_t address, uint8_t value);
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
};
// RTC using the internal millis() clock, has to be initialized before use
// NOTE: this clock won't be correct once the millis() timer rolls over (>49d?)
class RTC_Millis {
public:
static void begin(const DateTime& dt) { adjust(dt); }
static void adjust(const DateTime& dt);
static DateTime now();
protected:
static long offset;
};

Some files were not shown because too many files have changed in this diff Show More