Compare commits
18 Commits
cf7ef8d849
...
175f525bcd
Author | SHA1 | Date |
---|---|---|
![]() |
175f525bcd | |
![]() |
ba6c1038af | |
![]() |
cbe06f65be | |
![]() |
e7d5ada610 | |
![]() |
38f1d5de44 | |
![]() |
93402841cb | |
|
f0cc5d9966 | |
![]() |
9dc857056b | |
![]() |
c202554c5c | |
![]() |
df81e6e443 | |
|
097111c270 | |
|
bdfaf3c886 | |
![]() |
26e551c616 | |
![]() |
0cfaf1e793 | |
![]() |
ea9a2ff9c4 | |
![]() |
f116e41964 | |
![]() |
c85e575378 | |
![]() |
922247ed4a |
|
@ -19,8 +19,8 @@
|
|||
"flash_mode": "qio",
|
||||
"hwids": [
|
||||
[
|
||||
"0x303A",
|
||||
"0x1001"
|
||||
"0x1A86",
|
||||
"0x7523"
|
||||
]
|
||||
],
|
||||
"mcu": "esp32s3",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
|
@ -141,12 +141,12 @@ void deepSleep(CommonData &common){
|
|||
getdisplay().print("Sleep Mode");
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||
getdisplay().setCursor(65, 175);
|
||||
getdisplay().print("For wakeup press key and wait 5s");
|
||||
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
|
||||
esp_deep_sleep_start(); // Deep Sleep with weakup via touch pin
|
||||
}
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
|
@ -166,7 +166,7 @@ void deepSleep(CommonData &common){
|
|||
getdisplay().print("Sleep Mode");
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||
getdisplay().setCursor(65, 175);
|
||||
getdisplay().print("For wakeup press wheel and wait 5s");
|
||||
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
|
||||
|
@ -341,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);
|
||||
|
@ -392,13 +388,37 @@ void displayHeader(CommonData &commonData, GwApi::BoatValue *date, GwApi::BoatVa
|
|||
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
|
||||
|
||||
// Heartbeat as dot
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold32pt7b);
|
||||
getdisplay().setCursor(205, 14);
|
||||
getdisplay().print(heartbeat ? "." : " ");
|
||||
heartbeat = !heartbeat;
|
||||
// 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);
|
||||
drawTextCenter(211, 9, String(commonData.data.actpage));
|
||||
heartbeat = !heartbeat;
|
||||
|
||||
// Date and time
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
|
@ -442,17 +462,16 @@ void displayFooter(CommonData &commonData) {
|
|||
// 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);
|
||||
getdisplay().drawLine(commonData.keydata[1].x-10, top, commonData.keydata[1].x+10, top, commonData.fgcolor);
|
||||
getdisplay().drawLine(commonData.keydata[2].x-10, top, commonData.keydata[2].x+10, top, commonData.fgcolor);
|
||||
getdisplay().drawLine(commonData.keydata[4].x-10, top, commonData.keydata[4].x+10, top, commonData.fgcolor);
|
||||
getdisplay().drawLine(commonData.keydata[5].x-10, top, commonData.keydata[5].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
|
||||
getdisplay().drawLine(commonData.keydata[0].x + commonData.keydata[0].w, top, commonData.keydata[0].x + commonData.keydata[0].w, bottom, commonData.fgcolor);
|
||||
getdisplay().drawLine(commonData.keydata[1].x + commonData.keydata[1].w, top, commonData.keydata[1].x + commonData.keydata[1].w, bottom, commonData.fgcolor);
|
||||
getdisplay().drawLine(commonData.keydata[3].x + commonData.keydata[3].w, top, commonData.keydata[3].x + commonData.keydata[3].w, bottom, commonData.fgcolor);
|
||||
getdisplay().drawLine(commonData.keydata[4].x + commonData.keydata[4].w, top, commonData.keydata[4].x + commonData.keydata[4].w, bottom, commonData.fgcolor);
|
||||
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) {
|
||||
|
@ -476,9 +495,6 @@ void displayFooter(CommonData &commonData) {
|
|||
}
|
||||
}
|
||||
}
|
||||
// Current page number in a small box
|
||||
getdisplay().drawRect(190, 280, 23, 19, commonData.fgcolor);
|
||||
drawTextCenter(200, 289, String(commonData.data.actpage));
|
||||
} else {
|
||||
getdisplay().setCursor(65, 295);
|
||||
getdisplay().print("Press 1 and 6 fast to unlock keys");
|
||||
|
|
|
@ -100,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);
|
||||
|
@ -160,6 +160,46 @@ static std::map<String, unsigned char *> iconmap = {
|
|||
{"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
|
||||
|
|
|
@ -277,8 +277,8 @@ void initKeys(CommonData &commonData) {
|
|||
starttime = millis(); // Start key pressed
|
||||
keycodeold = keycode;
|
||||
}
|
||||
// If key pressed longer than 200ms
|
||||
if(millis() > starttime + 200 && keycode == keycodeold) {
|
||||
// If key pressed longer than 100ms
|
||||
if(millis() > starttime + 100 && keycode == keycodeold) {
|
||||
if (use_syspage and keycode == 3) {
|
||||
keystatus = 12;
|
||||
} else {
|
||||
|
|
|
@ -89,11 +89,11 @@ void sensorTask(void *param){
|
|||
double vslope = (api->getConfig()->getConfigItem(api->getConfig()->vSlope,true)->asString()).toFloat();
|
||||
if(String(powsensor1) == "off"){
|
||||
#ifdef VOLTAGE_SENSOR
|
||||
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
|
||||
float rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
|
||||
#else
|
||||
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
|
||||
float rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
|
||||
#endif
|
||||
sensors.batteryVoltage = sensors.batteryVoltage * vslope + voffset; // Calibration
|
||||
sensors.batteryVoltage = rawVoltage * vslope + voffset; // Calibration
|
||||
#ifdef LIPO_ACCU_1200
|
||||
sensors.BatteryChargeStatus = 0; // Set to discharging
|
||||
sensors.batteryLevelLiPo = 0; // Level 0...100%
|
||||
|
@ -468,20 +468,20 @@ void sensorTask(void *param){
|
|||
if(millis() > starttime5 + 1000 && String(powsensor1) == "off"){
|
||||
starttime5 = millis();
|
||||
#ifdef VOLTAGE_SENSOR
|
||||
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
|
||||
float rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
|
||||
#else
|
||||
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
|
||||
float rawVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
|
||||
#endif
|
||||
sensors.batteryVoltage = sensors.batteryVoltage * vslope + voffset; // Calibration
|
||||
#ifdef LIPO_ACCU_1200
|
||||
if(sensors.batteryVoltage > 4.1){
|
||||
sensors.BatteryChargeStatus = 1; // Charging active
|
||||
}
|
||||
else{
|
||||
sensors.BatteryChargeStatus = 0; // Discharging
|
||||
}
|
||||
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.batteryVoltage * sensors.batteryVoltage * 174.9513 + sensors.batteryVoltage * 1147,7686 + 1868.5120;
|
||||
sensors.batteryLevelLiPo = sensors.batteryVoltage60 * 203.8312 -738.1635;
|
||||
// Limiter
|
||||
if(sensors.batteryLevelLiPo > 100){
|
||||
sensors.batteryLevelLiPo = 100;
|
||||
|
@ -489,18 +489,39 @@ void sensorTask(void *param){
|
|||
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
|
||||
// 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;
|
||||
#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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -95,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
|
||||
|
@ -112,7 +113,7 @@ class Page{
|
|||
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 = "";
|
||||
|
|
|
@ -609,10 +609,10 @@
|
|||
"label": "Undervoltage",
|
||||
"type": "boolean",
|
||||
"default": "false",
|
||||
"description": "Switch off device if voltage drops below 9V [on|off]",
|
||||
"description": "Switch off device if LiPo voltage drops below 3.65V [on|off]",
|
||||
"category": "OBP40 Hardware",
|
||||
"capabilities": {
|
||||
"obp40": "false"
|
||||
"obp40":"true"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
@ -78,7 +78,7 @@ void OBP60Init(GwApi *api){
|
|||
}
|
||||
|
||||
#ifdef BOARD_OBP40S3
|
||||
//String sdcard = config->getConfigItem(config->useSDCard, true)->asString();
|
||||
// String sdcard = config->getConfigItem(config->useSDCard, true)->asString();
|
||||
String sdcard = "on";
|
||||
if (sdcard == "on") {
|
||||
SPIClass SD_SPI = SPIClass(HSPI);
|
||||
|
@ -309,37 +309,35 @@ void registerAllPages(PageList &list){
|
|||
|
||||
// Undervoltage detection for shutdown display
|
||||
void underVoltageDetection(GwApi *api, CommonData &common){
|
||||
float actVoltage = 0;
|
||||
float minVoltage = 0;
|
||||
// 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
|
||||
#if defined VOLTAGE_SENSOR && defined LIPO_ACCU_1200
|
||||
actVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.53) * 2; // Vin = 1/2 for OBP40
|
||||
minVoltage = 3.65; // Absolut minimum volatge for 3,7V LiPo accu
|
||||
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
|
||||
actVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
|
||||
minVoltage = MIN_VOLTAGE;
|
||||
float actVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20 for OBP60
|
||||
float minVoltage = MIN_VOLTAGE;
|
||||
#endif
|
||||
actVoltage = actVoltage * vslope + voffset;
|
||||
if(actVoltage < minVoltage){
|
||||
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().setFullWindow(); // Set full Refresh
|
||||
//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 press reset");
|
||||
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
|
||||
|
@ -352,7 +350,7 @@ 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);
|
||||
|
@ -415,7 +413,8 @@ void OBP60Task(GwApi *api){
|
|||
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 = config->getBool(config->systemPage);
|
||||
bool syspage_enabled = true;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
|
@ -556,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();
|
||||
|
|
Loading…
Reference in New Issue