mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2026-10-07 07:25:14 +02:00
Compare commits
62
Commits
master
..
caf833e6ac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
caf833e6ac | ||
|
|
b2e67880d3 | ||
|
|
a8cf34343f | ||
|
|
c00a0ecbed | ||
|
|
a16ee74b32 | ||
|
|
601d56ee49 | ||
|
|
9a04029cb4 | ||
|
|
22e3ca3875 | ||
|
|
8e72537286 | ||
|
|
494acbf0d0 | ||
|
|
d7251eeb8a | ||
|
|
c4406fd009 | ||
|
|
0097a1eb1e | ||
|
|
c932724473 | ||
|
|
672a3843d1 | ||
|
|
1e0acf2a8f | ||
|
|
63ae42588f | ||
|
|
cba21574cb | ||
|
|
fbe6c1a9a5 | ||
|
|
ae9334236b | ||
|
|
318a218470 | ||
|
|
c6df6eac56 | ||
|
|
4513f9d7b0 | ||
|
|
2749f25d15 | ||
|
|
992348ce92 | ||
|
|
8695d3eeb5 | ||
|
|
54b4954797 | ||
|
|
1ada6e5a82 | ||
|
|
15ca3614ba | ||
|
|
e5ca2a3a3d | ||
|
|
cf305e9f5a | ||
|
|
f823dadc6b | ||
|
|
2d47702627 | ||
|
|
15674543b6 | ||
|
|
0dd6b7c9cf | ||
|
|
cbc0c09d65 | ||
|
|
1d05c2b5d4 | ||
|
|
38bdc4f577 | ||
|
|
b8a31f2280 | ||
|
|
7cff3e62e6 | ||
|
|
39966098cc | ||
|
|
11a061d5a2 | ||
|
|
4600cb7228 | ||
|
|
e89d1ac62e | ||
|
|
6fb5e01969 | ||
|
|
5c731bc662 | ||
|
|
25c2742f5b | ||
|
|
6479c7d711 | ||
|
|
e287bfa72e | ||
|
|
5a652e2c19 | ||
|
|
5081f3a684 | ||
|
|
7de226b447 | ||
|
|
f6e2fa7806 | ||
|
|
d5b0af3b19 | ||
|
|
aed389f3b2 | ||
|
|
32ba4a64ed | ||
|
|
7edd201daa | ||
|
|
f4d88f1b8b | ||
|
|
08cd2ad4b1 | ||
|
|
b50d82eff0 | ||
|
|
6ae4e195d6 | ||
|
|
c5e346f4eb |
@@ -6,3 +6,4 @@
|
||||
generated/*
|
||||
lib/generated
|
||||
webinstall/token.php
|
||||
*~
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"partitions": "default_16MB.csv",
|
||||
"memory_type": "qio_opi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": [
|
||||
"-DBOARD_HAS_PSRAM",
|
||||
"-DARDUINO_ESP32S3_DEV",
|
||||
"-DARDUINO_USB_MODE=1",
|
||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||
"-DARDUINO_RUNNING_CORE=1",
|
||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
||||
],
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "qio",
|
||||
"hwids": [
|
||||
[
|
||||
"0x303A",
|
||||
"0x1001"
|
||||
]
|
||||
],
|
||||
"mcu": "esp32s3",
|
||||
"variant": "obp70s3"
|
||||
},
|
||||
"connectivity": [
|
||||
"bluetooth",
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"default_tool": "esp-builtin",
|
||||
"onboard_tools": [
|
||||
"esp-builtin"
|
||||
],
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf"
|
||||
],
|
||||
"name": "OBP70 ESP32-S3-N16R8 16 MB QD, 8 MB PSRAM)",
|
||||
"upload": {
|
||||
"flash_size": "16MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 16777216,
|
||||
"use_1200bps_touch": true,
|
||||
"wait_for_upload_port": true,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://open-boat-projects.org/en/diy-multifunktionsdisplay-obp-60/",
|
||||
"vendor": "Open Boat Projects"
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
#define _GWAPI_H
|
||||
#include "GwMessage.h"
|
||||
#include "N2kMsg.h"
|
||||
#include "Nmea2kTwai.h"
|
||||
#include "N2kDeviceList.h"
|
||||
#include "NMEA0183Msg.h"
|
||||
#include "GWConfig.h"
|
||||
#include "GwBoatData.h"
|
||||
@@ -23,6 +25,7 @@ class GwApi{
|
||||
bool formatSet=false;
|
||||
public:
|
||||
double value=0;
|
||||
String svalue="";
|
||||
bool valid=false;
|
||||
int source=-1;
|
||||
bool changed=false; //will be set by getBoatDataValues
|
||||
@@ -222,6 +225,8 @@ class GwApi{
|
||||
* accessing boat data must only be executed from within the main thread
|
||||
* you need to use the request pattern as shown in GwExampleTask.cpp
|
||||
*/
|
||||
virtual Nmea2kTwai *getNMEA2000()=0;
|
||||
virtual tN2kDeviceList *getN2kDeviceList()=0;
|
||||
virtual GwBoatData *getBoatData()=0;
|
||||
virtual ~GwApi(){}
|
||||
};
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
#include <GwJsonDocument.h>
|
||||
#include <ArduinoJson/Json/TextFormatter.hpp>
|
||||
#include "GWConfig.h"
|
||||
#define GWTYPE_DOUBLE 1
|
||||
#define GWTYPE_UINT32 2
|
||||
#define GWTYPE_UINT16 3
|
||||
#define GWTYPE_INT16 4
|
||||
#define GWTYPE_USER 100
|
||||
|
||||
class GwBoatItemTypes
|
||||
{
|
||||
@@ -15,7 +10,9 @@ public:
|
||||
static int getType(const uint16_t &x) { return GWTYPE_UINT16; }
|
||||
static int getType(const int16_t &x) { return GWTYPE_INT16; }
|
||||
static int getType(const double &x) { return GWTYPE_DOUBLE; }
|
||||
static int getType(const String &x) { return GWTYPE_STRING; }
|
||||
static int getType(const GwSatInfoList &x) { return GWTYPE_USER + 1; }
|
||||
static int getType(const GwAisTargetList &x) { return GWTYPE_USER + 1; }
|
||||
};
|
||||
|
||||
bool GwBoatItemBase::isValid(unsigned long now) const
|
||||
@@ -252,6 +249,10 @@ static void writeToString(GwTextWriter *writer, const int16_t &value)
|
||||
{
|
||||
writer->writeInteger(value);
|
||||
}
|
||||
static void writeToString(GwTextWriter *writer, String value)
|
||||
{
|
||||
writer->writeString(value.c_str());
|
||||
}
|
||||
static void writeToString(GwTextWriter *writer, GwSatInfoList &value)
|
||||
{
|
||||
writer->writeInteger(value.getNumSats());
|
||||
@@ -288,6 +289,8 @@ template class GwBoatItem<double>;
|
||||
template class GwBoatItem<uint32_t>;
|
||||
template class GwBoatItem<uint16_t>;
|
||||
template class GwBoatItem<int16_t>;
|
||||
template class GwBoatItem<String>;
|
||||
|
||||
void GwSatInfoList::houseKeeping(unsigned long ts)
|
||||
{
|
||||
if (ts == 0)
|
||||
@@ -301,6 +304,7 @@ void GwSatInfoList::houseKeeping(unsigned long ts)
|
||||
}),
|
||||
sats.end());
|
||||
}
|
||||
|
||||
void GwSatInfoList::update(GwSatInfo entry, unsigned long validTill)
|
||||
{
|
||||
entry.validTill = validTill;
|
||||
@@ -343,6 +347,63 @@ void GwBoatDataSatList::toJsonDoc(GwJsonDocument *doc, unsigned long minTime)
|
||||
GwBoatItem<GwSatInfoList>::toJsonDoc(doc, minTime);
|
||||
}
|
||||
|
||||
void GwAisTargetList::houseKeeping(unsigned long ts)
|
||||
{
|
||||
if (ts == 0) {
|
||||
ts = millis();
|
||||
}
|
||||
targets.erase(
|
||||
std::remove_if(
|
||||
targets.begin(),
|
||||
targets.end(),
|
||||
[ts, this](const GwAisTarget &target) {
|
||||
return target.validTill < ts;
|
||||
}
|
||||
),
|
||||
targets.end()
|
||||
);
|
||||
}
|
||||
|
||||
void GwAisTargetList::update(GwAisTarget target, unsigned long validTill)
|
||||
{
|
||||
target.validTill = validTill;
|
||||
for (auto it = targets.begin(); it != targets.end(); it++) {
|
||||
if (it->mmsi == target.mmsi) {
|
||||
*it = target;
|
||||
houseKeeping();
|
||||
return;
|
||||
}
|
||||
}
|
||||
houseKeeping();
|
||||
targets.push_back(target);
|
||||
}
|
||||
|
||||
GwBoatDataAisList::GwBoatDataAisList(String name, String formatInfo, GwBoatItemBase::TOType toType, GwBoatItemMap *map) : GwBoatItem<GwAisTargetList>(name, formatInfo, toType, map) {}
|
||||
|
||||
bool GwBoatDataAisList::update(GwAisTarget target, int source)
|
||||
{
|
||||
unsigned long now = millis();
|
||||
if (isValid(now))
|
||||
{
|
||||
//priority handling
|
||||
//sources with lower ids will win
|
||||
//and we will not overwrite their value
|
||||
if (lastUpdateSource < source)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
lastUpdateSource = source;
|
||||
uls(now);
|
||||
data.update(target, now+invalidTime);
|
||||
return true;
|
||||
}
|
||||
void GwBoatDataAisList::toJsonDoc(GwJsonDocument *doc, unsigned long minTime)
|
||||
{
|
||||
data.houseKeeping();
|
||||
GwBoatItem<GwAisTargetList>::toJsonDoc(doc, minTime);
|
||||
}
|
||||
|
||||
GwBoatData::GwBoatData(GwLog *logger, GwConfigHandler *cfg)
|
||||
{
|
||||
this->logger = logger;
|
||||
@@ -512,6 +573,11 @@ bool convertToJson(const GwSatInfoList &si, JsonVariant &variant)
|
||||
return variant.set(si.getNumSats());
|
||||
}
|
||||
|
||||
bool convertToJson(const GwAisTargetList &si, JsonVariant &variant)
|
||||
{
|
||||
return variant.set(si.getNumTargets());
|
||||
}
|
||||
|
||||
#ifdef _UNDEF
|
||||
#include <ArduinoJson/Json/TextFormatter.hpp>
|
||||
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
#define GW_BOAT_VALUE_LEN 32
|
||||
#define GWSC(name) static constexpr const char* name=#name
|
||||
|
||||
#define GWTYPE_DOUBLE 1
|
||||
#define GWTYPE_UINT32 2
|
||||
#define GWTYPE_UINT16 3
|
||||
#define GWTYPE_INT16 4
|
||||
#define GWTYPE_STRING 5
|
||||
#define GWTYPE_USER 100
|
||||
|
||||
//see https://github.com/wellenvogel/esp32-nmea2000/issues/44
|
||||
//factor to convert from N2k/SI rad/s to current NMEA rad/min
|
||||
#define ROT_WA_FACTOR 60
|
||||
@@ -58,6 +65,7 @@ class GwBoatItemBase{
|
||||
GWSC(formatRot);
|
||||
GWSC(formatDate);
|
||||
GWSC(formatTime);
|
||||
GWSC(formatName);
|
||||
protected:
|
||||
int type;
|
||||
unsigned long lastSet=0;
|
||||
@@ -92,6 +100,7 @@ class GwBoatItemBase{
|
||||
virtual int getLastSource(){return lastUpdateSource;}
|
||||
virtual void refresh(unsigned long ts=0){uls(ts);}
|
||||
virtual double getDoubleValue()=0;
|
||||
virtual String getStringValue()=0;
|
||||
String getName(){return name;}
|
||||
const String & getFormat() const{return format;}
|
||||
virtual void setInvalidTime(GwConfigHandler *cfg);
|
||||
@@ -120,7 +129,17 @@ template<class T> class GwBoatItem : public GwBoatItemBase{
|
||||
if (! isValid(millis())) return defaultv;
|
||||
return data;
|
||||
}
|
||||
virtual double getDoubleValue(){return (double)data;}
|
||||
virtual double getDoubleValue(){
|
||||
if constexpr (std::is_same<T, String>::value) {
|
||||
return 0.0; // TODO any better ideas?
|
||||
} else {
|
||||
return (double)data;
|
||||
}
|
||||
}
|
||||
virtual String getStringValue(){
|
||||
return (String)data;
|
||||
}
|
||||
|
||||
virtual void fillString();
|
||||
virtual void toJsonDoc(GwJsonDocument *doc, unsigned long minTime);
|
||||
virtual int getLastSource(){return lastUpdateSource;}
|
||||
@@ -177,6 +196,55 @@ public:
|
||||
|
||||
};
|
||||
|
||||
class GwAisTarget {
|
||||
public:
|
||||
uint32_t mmsi;
|
||||
char callsign[8];
|
||||
char name[21];
|
||||
uint8_t vesseltype;
|
||||
double lat;
|
||||
double lon;
|
||||
float length;
|
||||
float beam;
|
||||
float sog;
|
||||
float cog;
|
||||
unsigned long validTill;
|
||||
};
|
||||
|
||||
class GwAisTargetList {
|
||||
public:
|
||||
static const GwBoatItemBase::TOType toType=GwBoatItemBase::TOType::ais;
|
||||
std::vector<GwAisTarget> targets;
|
||||
void houseKeeping(unsigned long ts=0);
|
||||
void update(GwAisTarget target, unsigned long validTill);
|
||||
int getNumTargets() const {
|
||||
return targets.size();
|
||||
}
|
||||
GwAisTarget *getAt(int idx){
|
||||
if (idx >= 0 && idx < targets.size()) return &targets.at(idx);
|
||||
return NULL;
|
||||
}
|
||||
operator double(){ return getNumTargets();}
|
||||
};
|
||||
|
||||
class GwBoatDataAisList : public GwBoatItem<GwAisTargetList> {
|
||||
public:
|
||||
GwBoatDataAisList(String name, String formatInfo, GwBoatItemBase::TOType toType, GwBoatItemMap *map = NULL);
|
||||
bool update(GwAisTarget target, int source);
|
||||
virtual void toJsonDoc(GwJsonDocument *doc, unsigned long minTime);
|
||||
GwAisTarget *getAt(int idx) {
|
||||
if (! isValid()) return NULL;
|
||||
return data.getAt(idx);
|
||||
}
|
||||
int getNumTargets(){
|
||||
if (! isValid()) return 0;
|
||||
return data.getNumTargets();
|
||||
}
|
||||
virtual double getDoubleValue(){
|
||||
return (double)(data.getNumTargets());
|
||||
}
|
||||
};
|
||||
|
||||
class GwBoatItemNameProvider
|
||||
{
|
||||
public:
|
||||
@@ -235,7 +303,9 @@ class GwBoatData{
|
||||
GWBOATDATA(double,XTE,formatXte) // cross track error
|
||||
GWBOATDATA(double,WPLat,formatLatitude) // waypoint latitude
|
||||
GWBOATDATA(double,WPLon,formatLongitude) // waypoint longitude
|
||||
GWBOATDATA(String,WPName,formatName) // waypoint name
|
||||
GWSPECBOATDATA(GwBoatDataSatList,SatInfo,GwSatInfoList::toType,formatFixed0);
|
||||
GWSPECBOATDATA(GwBoatDataAisList,AisTarget,GwAisTargetList::toType,formatFixed0);
|
||||
public:
|
||||
GwBoatData(GwLog *logger, GwConfigHandler *cfg);
|
||||
~GwBoatData();
|
||||
|
||||
@@ -79,7 +79,7 @@ GwUpdate::GwUpdate(GwLog *log, GwWebServer *webserver, PasswordChecker ckr)
|
||||
}
|
||||
if (!param->hasError())
|
||||
{
|
||||
AsyncWebParameter *hash=request->getParam("_hash");
|
||||
const AsyncWebParameter *hash=request->getParam("_hash");
|
||||
if (! hash){
|
||||
hash=request->getParam("_hash",true);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ void sendEmbeddedFile(String name,String contentType,AsyncWebServerRequest *requ
|
||||
std::map<String,EmbeddedFile*>::iterator it=embeddedFiles.find(name);
|
||||
if (it != embeddedFiles.end()){
|
||||
EmbeddedFile* found=it->second;
|
||||
AsyncWebServerResponse *response=request->beginResponse_P(200,contentType,found->start,found->len);
|
||||
AsyncWebServerResponse *response=request->beginResponse(200, contentType, found->start, found->len);
|
||||
response->addHeader(F("Content-Encoding"), F("gzip"));
|
||||
request->send(response);
|
||||
}
|
||||
|
||||
+7
-11
@@ -106,7 +106,7 @@ bool GwWifi::connectInternal(){
|
||||
if (wifiClient->asBoolean()){
|
||||
clientIsConnected=false;
|
||||
LOG_DEBUG(GwLog::LOG,"creating wifiClient ssid=%s",wifiSSID->asString().c_str());
|
||||
// CRITICAL SECTION: WiFi-Operationen müssen serialisiert werden
|
||||
// CRITICAL SECTION: WiFi operations has to be serialized
|
||||
if (!acquireMutex()){
|
||||
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex timeout in connectInternal");
|
||||
return false;
|
||||
@@ -143,7 +143,6 @@ void GwWifi::loop(){
|
||||
|
||||
delay(300);
|
||||
|
||||
if (!apActive) {
|
||||
if (acquireMutex()){
|
||||
esp_err_t stopErr=esp_wifi_stop();
|
||||
releaseMutex();
|
||||
@@ -168,9 +167,6 @@ void GwWifi::loop(){
|
||||
else{
|
||||
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex timeout in loop (start)");
|
||||
}
|
||||
} else {
|
||||
connectInternal();
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
@@ -193,10 +189,10 @@ void GwWifi::loop(){
|
||||
}
|
||||
|
||||
bool GwWifi::clientConnected(){
|
||||
// CRITICAL SECTION: WiFi.status() muss geschützt werden
|
||||
// CRITICAL SECTION: WiFi.status() has to be protected
|
||||
if (!acquireMutex()){
|
||||
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex timeout in clientConnected");
|
||||
return false; // Conservative: nehme an, nicht verbunden
|
||||
return false; // conservative: assume not connected
|
||||
}
|
||||
bool result = WiFi.status() == WL_CONNECTED;
|
||||
releaseMutex();
|
||||
@@ -204,7 +200,7 @@ bool GwWifi::clientConnected(){
|
||||
};
|
||||
|
||||
bool GwWifi::connectClient(){
|
||||
// CRITICAL SECTION: Disconnect und Connect müssen atomar sein
|
||||
// CRITICAL SECTION: disconnect and connect has to be atomar
|
||||
if (!acquireMutex()){
|
||||
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex timeout in connectClient");
|
||||
return false;
|
||||
@@ -215,15 +211,15 @@ bool GwWifi::connectClient(){
|
||||
}
|
||||
|
||||
bool GwWifi::connectClientAsync(){
|
||||
// Non-blocking version: Versuche Mutex zu nehmen, gib aber sofort auf
|
||||
// Ideal für Tasks, die nicht blockieren dürfen
|
||||
// Non-blocking version: Try to get Mutex but give up immediately
|
||||
// Ideal for tasks which should not block
|
||||
if (wifiMutex==nullptr){
|
||||
LOG_DEBUG(GwLog::ERROR,"GwWifi: mutex not initialized in connectClientAsync");
|
||||
return false;
|
||||
}
|
||||
if (xSemaphoreTake(wifiMutex, 0)!=pdTRUE){
|
||||
LOG_DEBUG(GwLog::LOG,"GwWifi: connectClientAsync skipped - WiFi busy");
|
||||
return false; // WiFi ist aktuell busy, versuche es später nochmal
|
||||
return false; // WiFiis busy, try again later
|
||||
}
|
||||
WiFi.disconnect();
|
||||
xSemaphoreGive(wifiMutex);
|
||||
|
||||
@@ -355,6 +355,7 @@ private:
|
||||
AppendN2kRouteWPInfo(n2kMsg,destinationId,rmb.destID,rmb.latitude,rmb.longitude);
|
||||
send(n2kMsg,msg.sourceId);
|
||||
}
|
||||
boatData->WPName->update(String(rmb.destID), msg.sourceId);
|
||||
}
|
||||
void convertRMC(const SNMEA0183Msg &msg)
|
||||
{
|
||||
|
||||
@@ -9,6 +9,7 @@ static const int TIMEOUT_OFFLINE=256; //# of timeouts to consider offline
|
||||
Nmea2kTwai::Nmea2kTwai(gpio_num_t _TxPin, gpio_num_t _RxPin, unsigned long recP, unsigned long logP):
|
||||
tNMEA2000(),RxPin(_RxPin),TxPin(_TxPin)
|
||||
{
|
||||
pN2kDeviceList = new tN2kDeviceList(this);
|
||||
if (RxPin < 0 || TxPin < 0){
|
||||
disabled=true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef _NMEA2KTWAI_H
|
||||
#define _NMEA2KTWAI_H
|
||||
#include "NMEA2000.h"
|
||||
#include "N2kDeviceList.h"
|
||||
#include "GwTimer.h"
|
||||
|
||||
class Nmea2kTwai : public tNMEA2000{
|
||||
@@ -26,6 +27,7 @@ class Nmea2kTwai : public tNMEA2000{
|
||||
STATE state=ST_ERROR;
|
||||
} Status;
|
||||
Status getStatus();
|
||||
tN2kDeviceList *getDeviceList(){return pN2kDeviceList;}
|
||||
unsigned long getLastRecoveryStart(){return lastRecoveryStart;}
|
||||
void loop();
|
||||
static const char * stateStr(const STATE &st);
|
||||
@@ -58,6 +60,7 @@ class Nmea2kTwai : public tNMEA2000{
|
||||
GwIntervalRunner timers;
|
||||
bool disabled=false;
|
||||
unsigned long lastRecoveryStart=0;
|
||||
tN2kDeviceList *pN2kDeviceList;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,14 +0,0 @@
|
||||
Changes to original project (wellenvogel)
|
||||
|
||||
* esp32-nmea2000-obp60/gwwifi/GwWifi.cpp
|
||||
- any fixes for reconnect handling
|
||||
* GWStatisticsw.h
|
||||
- changed time source for log messages
|
||||
* esp32-nmea2000-obp60/platformio.ini
|
||||
- change to newer versions for AsyncTCP and AsyncWebServer (better handling for bad WiFi connections)
|
||||
|
||||
From AsyncTCP-esphome @ 2.0.1
|
||||
ottowinter/ESPAsyncWebServer-esphome@2.0.1
|
||||
|
||||
To AsyncTCP-esphome @ 2.1.1
|
||||
ottowinter/ESPAsyncWebServer-esphome@3.4.0
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
dir="$1"
|
||||
|
||||
total=0
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
lines=$(wc -l < "$file")
|
||||
echo "$file : $lines"
|
||||
total=$((total + lines))
|
||||
done < <(find "$dir" \( -name "*.c" -o -name "*.cpp" -o -name "*.h" \) -type f -print0)
|
||||
|
||||
echo "-----------------------"
|
||||
echo "Over all files: $total"
|
||||
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
Menu system for online configuration
|
||||
*/
|
||||
#include "ConfigMenu.h"
|
||||
|
||||
ConfigMenuItem::ConfigMenuItem(String itemtype, String itemlabel, uint16_t itemval, String itemunit) {
|
||||
if (! (itemtype == "int" or itemtype == "bool")) {
|
||||
valtype = "int";
|
||||
} else {
|
||||
valtype = itemtype;
|
||||
}
|
||||
label = itemlabel;
|
||||
min = 0;
|
||||
max = std::numeric_limits<uint16_t>::max();
|
||||
value = itemval;
|
||||
unit = itemunit;
|
||||
}
|
||||
|
||||
void ConfigMenuItem::setRange(uint16_t valmin, uint16_t valmax, std::vector<uint16_t> valsteps) {
|
||||
min = valmin;
|
||||
max = valmax;
|
||||
steps = valsteps;
|
||||
};
|
||||
|
||||
bool ConfigMenuItem::checkRange(uint16_t checkval) {
|
||||
return (checkval >= min) and (checkval <= max);
|
||||
}
|
||||
|
||||
String ConfigMenuItem::getLabel() {
|
||||
return label;
|
||||
};
|
||||
|
||||
uint16_t ConfigMenuItem::getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
bool ConfigMenuItem::setValue(uint16_t newval) {
|
||||
if (valtype == "int") {
|
||||
if (newval >= min and newval <= max) {
|
||||
value = newval;
|
||||
return true;
|
||||
}
|
||||
return false; // out of range
|
||||
} else if (valtype == "bool") {
|
||||
value = (newval != 0) ? 1 : 0;
|
||||
return true;
|
||||
}
|
||||
return false; // invalid type
|
||||
};
|
||||
|
||||
void ConfigMenuItem::incValue() {
|
||||
// increase value by step
|
||||
if (valtype == "int") {
|
||||
if (value + step < max) {
|
||||
value += step;
|
||||
} else {
|
||||
value = max;
|
||||
}
|
||||
} else if (valtype == "bool") {
|
||||
value = !value;
|
||||
}
|
||||
};
|
||||
|
||||
void ConfigMenuItem::decValue() {
|
||||
// decrease value by step
|
||||
if (valtype == "int") {
|
||||
if (value - step > min) {
|
||||
value -= step;
|
||||
} else {
|
||||
value = min;
|
||||
}
|
||||
} else if (valtype == "bool") {
|
||||
value = !value;
|
||||
}
|
||||
};
|
||||
|
||||
String ConfigMenuItem::getUnit() {
|
||||
return unit;
|
||||
}
|
||||
|
||||
uint16_t ConfigMenuItem::getStep() {
|
||||
return step;
|
||||
}
|
||||
|
||||
void ConfigMenuItem::setStep(uint16_t newstep) {
|
||||
if (std::find(steps.begin(), steps.end(), newstep) == steps.end()) {
|
||||
return; // invalid step: not in list of possible steps
|
||||
}
|
||||
step = newstep;
|
||||
}
|
||||
|
||||
int8_t ConfigMenuItem::getPos() {
|
||||
return position;
|
||||
};
|
||||
|
||||
void ConfigMenuItem::setPos(int8_t newpos) {
|
||||
position = newpos;
|
||||
};
|
||||
|
||||
String ConfigMenuItem::getType() {
|
||||
return valtype;
|
||||
}
|
||||
|
||||
ConfigMenu::ConfigMenu(String menutitle, uint16_t menu_x, uint16_t menu_y) {
|
||||
title = menutitle;
|
||||
x = menu_x;
|
||||
y = menu_y;
|
||||
};
|
||||
|
||||
ConfigMenuItem* ConfigMenu::addItem(String key, String label, String valtype, uint16_t val, String valunit) {
|
||||
if (items.find(key) != items.end()) {
|
||||
// duplicate keys not allowed
|
||||
return nullptr;
|
||||
}
|
||||
ConfigMenuItem *itm = new ConfigMenuItem(valtype, label, val, valunit);
|
||||
items.insert(std::pair<String, ConfigMenuItem*>(key, itm));
|
||||
// Append key to index, index starting with 0
|
||||
int8_t ix = items.size() - 1;
|
||||
index[ix] = key;
|
||||
itm->setPos(ix);
|
||||
return itm;
|
||||
};
|
||||
|
||||
void ConfigMenu::setItemDimension(uint16_t itemwidth, uint16_t itemheight) {
|
||||
w = itemwidth;
|
||||
h = itemheight;
|
||||
};
|
||||
|
||||
void ConfigMenu::setItemActive(String key) {
|
||||
if (items.find(key) != items.end()) {
|
||||
activeitem = items[key]->getPos();
|
||||
} else {
|
||||
activeitem = -1;
|
||||
}
|
||||
};
|
||||
|
||||
int8_t ConfigMenu::getActiveIndex() {
|
||||
return activeitem;
|
||||
}
|
||||
|
||||
ConfigMenuItem* ConfigMenu::getActiveItem() {
|
||||
if (activeitem < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return items[index[activeitem]];
|
||||
};
|
||||
|
||||
ConfigMenuItem* ConfigMenu::getItemByIndex(uint8_t ix) {
|
||||
if (ix > index.size() - 1) {
|
||||
return nullptr;
|
||||
}
|
||||
return items[index[ix]];
|
||||
};
|
||||
|
||||
ConfigMenuItem* ConfigMenu::getItemByKey(String key) {
|
||||
if (items.find(key) == items.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return items[key];
|
||||
};
|
||||
|
||||
uint8_t ConfigMenu::getItemCount() {
|
||||
return items.size();
|
||||
};
|
||||
|
||||
void ConfigMenu::goPrev() {
|
||||
if (activeitem == 0) {
|
||||
activeitem = items.size() - 1;
|
||||
} else {
|
||||
activeitem--;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigMenu::goNext() {
|
||||
if (activeitem == items.size() - 1) {
|
||||
activeitem = 0;
|
||||
} else {
|
||||
activeitem++;
|
||||
}
|
||||
}
|
||||
|
||||
Point ConfigMenu::getXY() {
|
||||
return {static_cast<double>(x), static_cast<double>(y)};
|
||||
}
|
||||
|
||||
Rect ConfigMenu::getRect() {
|
||||
return {static_cast<double>(x), static_cast<double>(y),
|
||||
static_cast<double>(w), static_cast<double>(h)};
|
||||
}
|
||||
|
||||
Rect ConfigMenu::getItemRect(int8_t index) {
|
||||
return {static_cast<double>(x), static_cast<double>(y + index * h),
|
||||
static_cast<double>(w), static_cast<double>(h)};
|
||||
}
|
||||
|
||||
void ConfigMenu::setCallback(void (*callback)()) {
|
||||
fptrCallback = callback;
|
||||
}
|
||||
|
||||
void ConfigMenu::storeValues() {
|
||||
if (fptrCallback) {
|
||||
fptrCallback();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "Graphics.h" // for Point and Rect
|
||||
|
||||
class ConfigMenuItem {
|
||||
private:
|
||||
String label;
|
||||
uint16_t value;
|
||||
String unit;
|
||||
String valtype; // "int" | "bool"
|
||||
uint16_t min;
|
||||
uint16_t max;
|
||||
std::vector<uint16_t> steps;
|
||||
uint16_t step;
|
||||
int8_t position; // counted fom 0
|
||||
|
||||
public:
|
||||
ConfigMenuItem(String itemtype, String itemlabel, uint16_t itemval, String itemunit);
|
||||
void setRange(uint16_t valmin, uint16_t valmax, std::vector<uint16_t> steps);
|
||||
bool checkRange(uint16_t checkval);
|
||||
String getLabel();
|
||||
uint16_t getValue();
|
||||
bool setValue(uint16_t newval);
|
||||
void incValue();
|
||||
void decValue();
|
||||
String getUnit();
|
||||
uint16_t getStep();
|
||||
void setStep(uint16_t newstep);
|
||||
int8_t getPos();
|
||||
void setPos(int8_t newpos);
|
||||
String getType();
|
||||
};
|
||||
|
||||
class ConfigMenu {
|
||||
private:
|
||||
String title;
|
||||
std::map <String,ConfigMenuItem*> items;
|
||||
std::map <uint8_t,String> index;
|
||||
int8_t activeitem = -1; // refers to position of item
|
||||
uint16_t x;
|
||||
uint16_t y;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
void (*fptrCallback)();
|
||||
|
||||
public:
|
||||
ConfigMenu(String title, uint16_t menu_x, uint16_t menu_y);
|
||||
ConfigMenuItem* addItem(String key, String label, String valtype, uint16_t val, String valunit);
|
||||
void setItemDimension(uint16_t itemwidth, uint16_t itemheight);
|
||||
int8_t getActiveIndex();
|
||||
void setItemActive(String key);
|
||||
ConfigMenuItem* getActiveItem();
|
||||
ConfigMenuItem* getItemByIndex(uint8_t index);
|
||||
ConfigMenuItem* getItemByKey(String key);
|
||||
uint8_t getItemCount();
|
||||
void goPrev();
|
||||
void goNext();
|
||||
Point getXY();
|
||||
Rect getRect();
|
||||
Rect getItemRect(int8_t index);
|
||||
void setCallback(void (*callback)());
|
||||
void storeValues();
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
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.py and run it to auto-generate the relevant section of config.json
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#include <FreeRTOS.h>
|
||||
#include "LedSpiTask.h"
|
||||
#include "GwHardware.h"
|
||||
@@ -50,7 +51,7 @@ Color setBrightness(const Color &color,uint8_t brightness){
|
||||
|
||||
uint16_t br255=brightness*255;
|
||||
br255=br255/100;
|
||||
//Very simple for now
|
||||
//very simple for now
|
||||
Color rt=color;
|
||||
rt.g=mulcolor(rt.g,br255);
|
||||
rt.b=mulcolor(rt.b,br255);
|
||||
@@ -85,12 +86,12 @@ static size_t ledsToBuffer(int numLeds,const Color *leds,uint8_t *buffer){
|
||||
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);
|
||||
logger->logDebug(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);
|
||||
logger->logDebug(GwLog::ERROR, "unable to set gpio level for %d: %d", pin, (int)err);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -116,7 +117,7 @@ bool prepareSpi(GwLog *logger,spi_host_device_t bus,spi_device_handle_t *device)
|
||||
};
|
||||
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",
|
||||
logger->logDebug(GwLog::ERROR, "unable to initialize SPI bus %d,mosi=%d, error=%d",
|
||||
(int)bus, -1, (int)err);
|
||||
return false;
|
||||
}
|
||||
@@ -135,7 +136,7 @@ bool prepareSpi(GwLog *logger,spi_host_device_t bus,spi_device_handle_t *device)
|
||||
};
|
||||
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",
|
||||
logger->logDebug(GwLog::ERROR, "unable to add device to SPI bus %d,mosi=%d, error=%d",
|
||||
(int)bus, -1, (int)err);
|
||||
return false;
|
||||
}
|
||||
@@ -143,7 +144,7 @@ bool prepareSpi(GwLog *logger,spi_host_device_t bus,spi_device_handle_t *device)
|
||||
//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",
|
||||
logger->logDebug(GwLog::ERROR,"unable to acquire SPI bus %d,mosi=%d, error=%d",
|
||||
(int)bus, -1, (int)err);
|
||||
return false;
|
||||
}
|
||||
@@ -174,7 +175,7 @@ bool sendToLeds(GwLog *logger, uint8_t pin, int numLeds, Color *leds, spi_host_d
|
||||
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);
|
||||
logger->logDebug(GwLog::ERROR, "unable to allocate %d bytes of DMA buffer", (int)bufferSize);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -195,12 +196,12 @@ bool sendToLeds(GwLog *logger, uint8_t pin, int numLeds, Color *leds, spi_host_d
|
||||
int64_t end = esp_timer_get_time();
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
LOG_DEBUG(GwLog::ERROR, "unable to send led data: %d", (int)ret);
|
||||
logger->logDebug(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);
|
||||
logger->logDebug(GwLog::DEBUG, "successfully send led data for %d leds, %lld us", numLeds, end - now);
|
||||
}
|
||||
if (ownsBuffer)
|
||||
{
|
||||
@@ -213,7 +214,7 @@ bool sendToLeds(GwLog *logger, uint8_t pin, int numLeds, Color *leds, spi_host_d
|
||||
void handleSpiLeds(void *param){
|
||||
LedTaskData *taskData=(LedTaskData*)param;
|
||||
GwLog *logger=taskData->api->getLogger();
|
||||
LOG_DEBUG(GwLog::ERROR,"spi led task initialized");
|
||||
logger->logDebug(GwLog::ERROR, "spi led task initialized");
|
||||
spi_host_device_t bus=SPI3_HOST;
|
||||
bool spiValid=false;
|
||||
LOG_DEBUG(GwLog::ERROR, "SpiLed task started");
|
||||
@@ -235,14 +236,14 @@ void handleSpiLeds(void *param){
|
||||
LedInterface newLeds=taskData->getLedData();
|
||||
if (first || current.backlightChanged(newLeds) || current.flasChanged(newLeds)){
|
||||
first=false;
|
||||
LOG_DEBUG(GwLog::ERROR,"handle SPI leds");
|
||||
logger->logDebug(GwLog::ERROR, "handle SPI leds");
|
||||
if (current.backlightChanged(newLeds) || first){
|
||||
LOG_DEBUG(GwLog::ERROR,"setting backlight r=%02d,g=%02d,b=%02d",
|
||||
logger->logDebug(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",
|
||||
logger->logDebug(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);
|
||||
}
|
||||
@@ -254,5 +255,10 @@ void handleSpiLeds(void *param){
|
||||
}
|
||||
|
||||
void createSpiLedTask(LedTaskData *param) {
|
||||
xTaskCreate(handleSpiLeds,"handleLeds",4000,param,3,NULL);
|
||||
TaskHandle_t xHandle = NULL;
|
||||
GwLog *logger = param->api->getLogger();
|
||||
esp_err_t err = xTaskCreate(handleSpiLeds, "handleLeds", configMINIMAL_STACK_SIZE + 2048, param, 3, &xHandle);
|
||||
if (err != pdPASS) {
|
||||
logger->logDebug(GwLog::ERROR, "Failed to create spiled task! (err=%d)", err);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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,};
|
||||
@@ -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,};
|
||||
+240
-455
File diff suppressed because it is too large
Load Diff
+56
-654
@@ -1,27 +1,14 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#ifndef _OBP60EXTENSIONPORT_H
|
||||
#define _OBP60EXTENSIONPORT_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "OBP60Hardware.h"
|
||||
#include "OBP60Formatter.h"
|
||||
#include "LedSpiTask.h"
|
||||
#include "Graphics.h"
|
||||
#include <GxEPD2_BW.h> // GxEPD2 lib for b/w E-Ink displays
|
||||
#include <GxEPD2_BW.h> // E-paper lib V2
|
||||
#include <Adafruit_FRAM_I2C.h> // I2C FRAM
|
||||
#include <math.h>
|
||||
|
||||
#ifdef TFT_DISPLAY
|
||||
#if !defined(TFT_320x480_ST7796) && !defined(TFT_320x480_ILI9488)
|
||||
#error "TFT_DISPLAY requires one panel type: TFT_320x480_ST7796 or TFT_320x480_ILI9488"
|
||||
#endif
|
||||
#if defined(TFT_320x480_ST7796) && defined(TFT_320x480_ILI9488)
|
||||
#error "Select exactly one TFT panel type: TFT_320x480_ST7796 or TFT_320x480_ILI9488"
|
||||
#endif
|
||||
#include <LovyanGFX.hpp> // TFT LCD lib for 320x480 color displays
|
||||
#undef GxEPD_WHITE
|
||||
#define GxEPD_WHITE TFT_WHITE // Replacement color for white on TFT (OBPHardware.h)
|
||||
#undef GxEPD_BLACK
|
||||
#define GxEPD_BLACK TFT_BLACK // Replacement color for black on TFT (OBPHardware.h)
|
||||
#endif
|
||||
|
||||
#ifdef BOARD_OBP40S3
|
||||
#include "esp_vfs_fat.h"
|
||||
@@ -45,9 +32,6 @@
|
||||
#define FRAM_BAROGRAPH_START 0x0400
|
||||
#define FRAM_BAROGRAPH_END 0x13FF
|
||||
|
||||
#define PI 3.1415926535897932384626433832795
|
||||
#define EARTH_RADIUS 6371000.0
|
||||
|
||||
extern Adafruit_FRAM_I2C fram;
|
||||
extern bool hasFRAM;
|
||||
extern bool hasSDCard;
|
||||
@@ -55,9 +39,9 @@ extern bool hasSDCard;
|
||||
extern sdmmc_card_t *sdcard;
|
||||
#endif
|
||||
|
||||
extern bool heartbeat;
|
||||
|
||||
// Fonts declarations for display (#includes see OBP60Extensions.cpp)
|
||||
extern const GFXfont DSEG7Classic_BoldItalic10pt7b;
|
||||
extern const GFXfont DSEG7Classic_BoldItalic12pt7b;
|
||||
extern const GFXfont DSEG7Classic_BoldItalic16pt7b;
|
||||
extern const GFXfont DSEG7Classic_BoldItalic20pt7b;
|
||||
extern const GFXfont DSEG7Classic_BoldItalic26pt7b;
|
||||
@@ -71,646 +55,28 @@ extern const GFXfont Ubuntu_Bold16pt8b;
|
||||
extern const GFXfont Ubuntu_Bold20pt8b;
|
||||
extern const GFXfont Ubuntu_Bold32pt8b;
|
||||
extern const GFXfont Atari16px;
|
||||
extern const GFXfont IBM8x8px;
|
||||
extern const GFXfont Atari6px;
|
||||
|
||||
// Global functions
|
||||
#ifdef DISPLAY_GDEW042T2
|
||||
GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> & getdisplay();
|
||||
typedef GxEPD2_BW<GxEPD2_420, GxEPD2_420::HEIGHT> gxepd2display;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> & getdisplay();
|
||||
typedef GxEPD2_BW<GxEPD2_420_GDEY042T81, GxEPD2_420_GDEY042T81::HEIGHT> gxepd2display;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_GYE042A87
|
||||
GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay();
|
||||
typedef GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> gxepd2display;
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_SE0420NQ04
|
||||
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay();
|
||||
#endif
|
||||
|
||||
#ifdef TFT_DISPLAY
|
||||
// LovyanGFX based display wrapper for TFT panels
|
||||
class LGFX : public lgfx::LGFX_Device {
|
||||
public:
|
||||
lgfx::Bus_SPI _bus_instance;
|
||||
|
||||
#ifdef TFT_320x480_ST7796
|
||||
LGFX(void) {
|
||||
{
|
||||
auto cfg = _bus_instance.config();
|
||||
cfg.spi_host = SPI2_HOST;
|
||||
cfg.spi_mode = 0;
|
||||
cfg.freq_write = 80000000; // High speed ST7796
|
||||
cfg.freq_read = 16000000;
|
||||
cfg.pin_sclk = OBP_SPI_CLK;
|
||||
cfg.pin_mosi = OBP_SPI_DIN;
|
||||
cfg.pin_miso = -1;
|
||||
cfg.pin_dc = OBP_SPI_DC;
|
||||
_bus_instance.config(cfg);
|
||||
_panel_instance.setBus(&_bus_instance);
|
||||
}
|
||||
{
|
||||
auto cfg = _panel_instance.config();
|
||||
cfg.pin_cs = OBP_SPI_CS;
|
||||
cfg.pin_rst = OBP_SPI_RST;
|
||||
cfg.pin_busy = -1;
|
||||
cfg.panel_width = 320; // Native width resolution
|
||||
cfg.panel_height = 480; // Native hight resolution
|
||||
cfg.offset_x = 0; // No panel offset: full framebuffer mapping
|
||||
cfg.offset_y = 0; // No panel offset: full framebuffer mapping
|
||||
cfg.offset_rotation = 3; // Rotate display content conter clock wise 90 deg ST7796
|
||||
cfg.dummy_read_pixel = 8;
|
||||
cfg.dummy_read_bits = 1;
|
||||
cfg.memory_width = 320;
|
||||
cfg.memory_height = 480;
|
||||
// cfg.pwm_control not available in this LovyanGFX version
|
||||
cfg.invert = false;
|
||||
cfg.rgb_order = false;
|
||||
cfg.dlen_16bit = false;
|
||||
cfg.bus_shared = true;
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
// No dedicated TFT PWM backlight pin configured on this board.
|
||||
// Keep backlight handling outside LovyanGFX to avoid LEDC init on invalid GPIO.
|
||||
setPanel(&_panel_instance);
|
||||
// Match Adafruit GFX cursor semantics: y coordinate is text baseline.
|
||||
setTextDatum(textdatum_t::baseline_left);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TFT_320x480_ILI9488
|
||||
LGFX(void) {
|
||||
{
|
||||
auto cfg = _bus_instance.config();
|
||||
cfg.spi_host = SPI2_HOST;
|
||||
cfg.spi_mode = 0;
|
||||
cfg.freq_write = 40000000; // Slow speed ILI9488
|
||||
cfg.freq_read = 16000000;
|
||||
cfg.pin_sclk = OBP_SPI_CLK;
|
||||
cfg.pin_mosi = OBP_SPI_DIN;
|
||||
cfg.pin_miso = -1;
|
||||
cfg.pin_dc = OBP_SPI_DC;
|
||||
_bus_instance.config(cfg);
|
||||
_panel_instance.setBus(&_bus_instance);
|
||||
}
|
||||
{
|
||||
auto cfg = _panel_instance.config();
|
||||
cfg.pin_cs = OBP_SPI_CS;
|
||||
cfg.pin_rst = OBP_SPI_RST;
|
||||
cfg.pin_busy = -1;
|
||||
cfg.panel_width = 320; // Native width resolution
|
||||
cfg.panel_height = 480; // Native hight resolution
|
||||
cfg.offset_x = 0; // No panel offset: full framebuffer mapping
|
||||
cfg.offset_y = 0; // No panel offset: full framebuffer mapping
|
||||
cfg.offset_rotation = 1; // Rotate display content clock wise 90 deg ILI9488
|
||||
cfg.dummy_read_pixel = 8;
|
||||
cfg.dummy_read_bits = 1;
|
||||
cfg.memory_width = 320;
|
||||
cfg.memory_height = 480;
|
||||
// cfg.pwm_control not available in this LovyanGFX version
|
||||
cfg.invert = false;
|
||||
cfg.rgb_order = false;
|
||||
cfg.dlen_16bit = false;
|
||||
cfg.bus_shared = true;
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
// No dedicated TFT PWM backlight pin configured on this board.
|
||||
// Keep backlight handling outside LovyanGFX to avoid LEDC init on invalid GPIO.
|
||||
setPanel(&_panel_instance);
|
||||
// Match Adafruit GFX cursor semantics: y coordinate is text baseline.
|
||||
setTextDatum(textdatum_t::baseline_left);
|
||||
}
|
||||
#endif
|
||||
|
||||
// compatibility helpers --------------------------------------------------
|
||||
using lgfx::LGFX_Device::setFont;
|
||||
void setFont(const lgfx::IFont* font) {
|
||||
_currentAdfFont = nullptr;
|
||||
lgfx::LGFX_Device::setFont(font);
|
||||
}
|
||||
// Adafruit GFX fonts support on TFT via LovyanGFX bridge
|
||||
void setFont(const GFXfont *font) {
|
||||
if (font == nullptr) {
|
||||
_currentAdfFont = nullptr;
|
||||
lgfx::LGFX_Device::setFont(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (font->glyph == nullptr || font->bitmap == nullptr || font->last < font->first) {
|
||||
_currentAdfFont = nullptr;
|
||||
lgfx::LGFX_Device::setFont(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint16_t glyphCount = static_cast<uint16_t>(font->last - font->first + 1);
|
||||
if (glyphCount == 0) {
|
||||
lgfx::LGFX_Device::setFont(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_adfGlyphCount != glyphCount || _adfGlyphBridge == nullptr) {
|
||||
if (_adfGlyphBridge != nullptr) {
|
||||
free(_adfGlyphBridge);
|
||||
_adfGlyphBridge = nullptr;
|
||||
_adfGlyphCount = 0;
|
||||
}
|
||||
_adfGlyphBridge = static_cast<lgfx::GFXglyph*>(malloc(sizeof(lgfx::GFXglyph) * glyphCount));
|
||||
if (_adfGlyphBridge == nullptr) {
|
||||
lgfx::LGFX_Device::setFont(nullptr);
|
||||
return;
|
||||
}
|
||||
_adfGlyphCount = glyphCount;
|
||||
}
|
||||
|
||||
for (uint16_t index = 0; index < glyphCount; ++index) {
|
||||
_adfGlyphBridge[index].bitmapOffset = font->glyph[index].bitmapOffset;
|
||||
_adfGlyphBridge[index].width = font->glyph[index].width;
|
||||
_adfGlyphBridge[index].height = font->glyph[index].height;
|
||||
_adfGlyphBridge[index].xAdvance = font->glyph[index].xAdvance;
|
||||
_adfGlyphBridge[index].xOffset = font->glyph[index].xOffset;
|
||||
_adfGlyphBridge[index].yOffset = font->glyph[index].yOffset;
|
||||
}
|
||||
|
||||
_adfFontBridge = lgfx::GFXfont(
|
||||
const_cast<uint8_t*>(font->bitmap),
|
||||
_adfGlyphBridge,
|
||||
font->first,
|
||||
font->last,
|
||||
font->yAdvance
|
||||
);
|
||||
_currentAdfFont = font;
|
||||
lgfx::LGFX_Device::setFont(&_adfFontBridge);
|
||||
}
|
||||
|
||||
void getTextBounds(const String &txt, int16_t x, int16_t y,
|
||||
int16_t *x0, int16_t *y0,
|
||||
uint16_t *w, uint16_t *h) {
|
||||
if (w == nullptr || h == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (_currentAdfFont == nullptr || txt.length() == 0) {
|
||||
*w = textWidth(txt);
|
||||
*h = fontHeight();
|
||||
if (x0) *x0 = x;
|
||||
if (y0) *y0 = y - static_cast<int16_t>(*h);
|
||||
return;
|
||||
}
|
||||
|
||||
const float sx = getTextSizeX();
|
||||
const float sy = getTextSizeY();
|
||||
|
||||
int32_t cursorX = x;
|
||||
int32_t cursorY = y;
|
||||
int32_t minX = 0;
|
||||
int32_t minY = 0;
|
||||
int32_t maxX = 0;
|
||||
int32_t maxY = 0;
|
||||
bool hasPixel = false;
|
||||
|
||||
for (size_t i = 0; i < txt.length(); ++i) {
|
||||
char c = txt[i];
|
||||
if (c == '\r') continue;
|
||||
if (c == '\n') {
|
||||
cursorX = x;
|
||||
cursorY += static_cast<int32_t>(_currentAdfFont->yAdvance * sy);
|
||||
continue;
|
||||
}
|
||||
if (c < _currentAdfFont->first || c > _currentAdfFont->last) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const GFXglyph* glyph = &_currentAdfFont->glyph[static_cast<uint16_t>(c) - _currentAdfFont->first];
|
||||
const int32_t gw = static_cast<int32_t>(glyph->width * sx);
|
||||
const int32_t gh = static_cast<int32_t>(glyph->height * sy);
|
||||
const int32_t gx1 = cursorX + static_cast<int32_t>(glyph->xOffset * sx);
|
||||
const int32_t gy1 = cursorY + static_cast<int32_t>(glyph->yOffset * sy);
|
||||
|
||||
if (gw > 0 && gh > 0) {
|
||||
const int32_t gx2 = gx1 + gw - 1;
|
||||
const int32_t gy2 = gy1 + gh - 1;
|
||||
if (!hasPixel) {
|
||||
minX = gx1; minY = gy1; maxX = gx2; maxY = gy2;
|
||||
hasPixel = true;
|
||||
} else {
|
||||
if (gx1 < minX) minX = gx1;
|
||||
if (gy1 < minY) minY = gy1;
|
||||
if (gx2 > maxX) maxX = gx2;
|
||||
if (gy2 > maxY) maxY = gy2;
|
||||
}
|
||||
}
|
||||
cursorX += static_cast<int32_t>(glyph->xAdvance * sx);
|
||||
}
|
||||
|
||||
if (hasPixel) {
|
||||
if (x0) *x0 = static_cast<int16_t>(minX);
|
||||
if (y0) *y0 = static_cast<int16_t>(minY);
|
||||
*w = static_cast<uint16_t>(maxX - minX + 1);
|
||||
*h = static_cast<uint16_t>(maxY - minY + 1);
|
||||
} else {
|
||||
if (x0) *x0 = x;
|
||||
if (y0) *y0 = y;
|
||||
*w = 0;
|
||||
*h = 0;
|
||||
}
|
||||
}
|
||||
// E-Ink interface compatibility
|
||||
void setFullWindow() { /* no-op on TFT */ }
|
||||
|
||||
// Runtime panel offset control for TFT panels
|
||||
void setPanelOffset(int16_t x, int16_t y) {
|
||||
auto cfg = _panel_instance.config();
|
||||
cfg.offset_x = x;
|
||||
cfg.offset_y = y;
|
||||
_panel_instance.config(cfg);
|
||||
}
|
||||
|
||||
void getPanelOffset(int16_t &x, int16_t &y) {
|
||||
auto cfg = _panel_instance.config();
|
||||
x = cfg.offset_x;
|
||||
y = cfg.offset_y;
|
||||
}
|
||||
|
||||
private:
|
||||
lgfx::GFXfont _adfFontBridge { nullptr, nullptr, 0, 0, 0 };
|
||||
lgfx::GFXglyph* _adfGlyphBridge = nullptr;
|
||||
uint16_t _adfGlyphCount = 0;
|
||||
const GFXfont* _currentAdfFont = nullptr;
|
||||
#if defined(TFT_320x480_ST7796)
|
||||
lgfx::Panel_ST7796 _panel_instance;
|
||||
#elif defined(TFT_320x480_ILI9488)
|
||||
lgfx::Panel_ILI9488 _panel_instance;
|
||||
#endif
|
||||
};
|
||||
|
||||
class LGFXCanvas : public lgfx::LGFX_Sprite {
|
||||
public:
|
||||
explicit LGFXCanvas(lgfx::LGFX_Device* parent = nullptr) : lgfx::LGFX_Sprite(parent) {}
|
||||
|
||||
using lgfx::LGFX_Sprite::setFont;
|
||||
void setFont(const GFXfont *font) {
|
||||
if (font == nullptr) {
|
||||
_currentAdfFont = nullptr;
|
||||
lgfx::LGFX_Sprite::setFont(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (font->glyph == nullptr || font->bitmap == nullptr || font->last < font->first) {
|
||||
_currentAdfFont = nullptr;
|
||||
lgfx::LGFX_Sprite::setFont(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
const uint16_t glyphCount = static_cast<uint16_t>(font->last - font->first + 1);
|
||||
if (glyphCount == 0) {
|
||||
lgfx::LGFX_Sprite::setFont(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_adfGlyphCount != glyphCount || _adfGlyphBridge == nullptr) {
|
||||
if (_adfGlyphBridge != nullptr) {
|
||||
free(_adfGlyphBridge);
|
||||
_adfGlyphBridge = nullptr;
|
||||
_adfGlyphCount = 0;
|
||||
}
|
||||
_adfGlyphBridge = static_cast<lgfx::GFXglyph*>(malloc(sizeof(lgfx::GFXglyph) * glyphCount));
|
||||
if (_adfGlyphBridge == nullptr) {
|
||||
lgfx::LGFX_Sprite::setFont(nullptr);
|
||||
return;
|
||||
}
|
||||
_adfGlyphCount = glyphCount;
|
||||
}
|
||||
|
||||
for (uint16_t index = 0; index < glyphCount; ++index) {
|
||||
_adfGlyphBridge[index].bitmapOffset = font->glyph[index].bitmapOffset;
|
||||
_adfGlyphBridge[index].width = font->glyph[index].width;
|
||||
_adfGlyphBridge[index].height = font->glyph[index].height;
|
||||
_adfGlyphBridge[index].xAdvance = font->glyph[index].xAdvance;
|
||||
_adfGlyphBridge[index].xOffset = font->glyph[index].xOffset;
|
||||
_adfGlyphBridge[index].yOffset = font->glyph[index].yOffset;
|
||||
}
|
||||
|
||||
_adfFontBridge = lgfx::GFXfont(
|
||||
const_cast<uint8_t*>(font->bitmap),
|
||||
_adfGlyphBridge,
|
||||
font->first,
|
||||
font->last,
|
||||
font->yAdvance
|
||||
);
|
||||
_currentAdfFont = font;
|
||||
lgfx::LGFX_Sprite::setFont(&_adfFontBridge);
|
||||
}
|
||||
|
||||
void getTextBounds(const String &txt, int16_t x, int16_t y,
|
||||
int16_t *x0, int16_t *y0,
|
||||
uint16_t *w, uint16_t *h) {
|
||||
if (w == nullptr || h == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (_currentAdfFont == nullptr || txt.length() == 0) {
|
||||
*w = textWidth(txt);
|
||||
*h = fontHeight();
|
||||
if (x0) *x0 = x;
|
||||
if (y0) *y0 = y - static_cast<int16_t>(*h);
|
||||
return;
|
||||
}
|
||||
|
||||
const float sx = getTextSizeX();
|
||||
const float sy = getTextSizeY();
|
||||
|
||||
int32_t cursorX = x;
|
||||
int32_t cursorY = y;
|
||||
int32_t minX = 0;
|
||||
int32_t minY = 0;
|
||||
int32_t maxX = 0;
|
||||
int32_t maxY = 0;
|
||||
bool hasPixel = false;
|
||||
|
||||
for (size_t i = 0; i < txt.length(); ++i) {
|
||||
char c = txt[i];
|
||||
if (c == '\r') continue;
|
||||
if (c == '\n') {
|
||||
cursorX = x;
|
||||
cursorY += static_cast<int32_t>(_currentAdfFont->yAdvance * sy);
|
||||
continue;
|
||||
}
|
||||
if (c < _currentAdfFont->first || c > _currentAdfFont->last) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const GFXglyph* glyph = &_currentAdfFont->glyph[static_cast<uint16_t>(c) - _currentAdfFont->first];
|
||||
const int32_t gw = static_cast<int32_t>(glyph->width * sx);
|
||||
const int32_t gh = static_cast<int32_t>(glyph->height * sy);
|
||||
const int32_t gx1 = cursorX + static_cast<int32_t>(glyph->xOffset * sx);
|
||||
const int32_t gy1 = cursorY + static_cast<int32_t>(glyph->yOffset * sy);
|
||||
|
||||
if (gw > 0 && gh > 0) {
|
||||
const int32_t gx2 = gx1 + gw - 1;
|
||||
const int32_t gy2 = gy1 + gh - 1;
|
||||
if (!hasPixel) {
|
||||
minX = gx1; minY = gy1; maxX = gx2; maxY = gy2;
|
||||
hasPixel = true;
|
||||
} else {
|
||||
if (gx1 < minX) minX = gx1;
|
||||
if (gy1 < minY) minY = gy1;
|
||||
if (gx2 > maxX) maxX = gx2;
|
||||
if (gy2 > maxY) maxY = gy2;
|
||||
}
|
||||
}
|
||||
cursorX += static_cast<int32_t>(glyph->xAdvance * sx);
|
||||
}
|
||||
|
||||
if (hasPixel) {
|
||||
if (x0) *x0 = static_cast<int16_t>(minX);
|
||||
if (y0) *y0 = static_cast<int16_t>(minY);
|
||||
*w = static_cast<uint16_t>(maxX - minX + 1);
|
||||
*h = static_cast<uint16_t>(maxY - minY + 1);
|
||||
} else {
|
||||
if (x0) *x0 = x;
|
||||
if (y0) *y0 = y;
|
||||
*w = 0;
|
||||
*h = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void setFullWindow() { /* no-op on TFT */ }
|
||||
|
||||
private:
|
||||
lgfx::GFXfont _adfFontBridge { nullptr, nullptr, 0, 0, 0 };
|
||||
lgfx::GFXglyph* _adfGlyphBridge = nullptr;
|
||||
uint16_t _adfGlyphCount = 0;
|
||||
const GFXfont* _currentAdfFont = nullptr;
|
||||
};
|
||||
|
||||
LGFXCanvas & getdisplay();
|
||||
LGFX & getpaneldisplay();
|
||||
LGFXCanvas & getscaleddisplay();
|
||||
bool initDisplayShadowBuffer();
|
||||
bool initDisplayScaleBuffer(uint16_t width, uint16_t height);
|
||||
typedef GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> gxepd2display;
|
||||
#endif
|
||||
extern gxepd2display *epd;
|
||||
|
||||
// Page display return values
|
||||
#define PAGE_OK 0 // all ok, do nothing
|
||||
#define PAGE_UPDATE 1 // page wants display to update
|
||||
#define PAGE_HIBERNATE 2 // page wants displey to hibernate
|
||||
|
||||
#ifdef TFT_DISPLAY
|
||||
#ifndef OBP_TFT_ENABLE_SCALING
|
||||
#define OBP_TFT_ENABLE_SCALING 1
|
||||
#endif
|
||||
|
||||
#ifndef OBP_TFT_SCALE_ANTIALIAS
|
||||
#define OBP_TFT_SCALE_ANTIALIAS 1
|
||||
#endif
|
||||
|
||||
#if OBP_TFT_SCALE_ANTIALIAS
|
||||
inline uint16_t lerpRgb565(uint16_t c0, uint16_t c1, uint16_t w8) {
|
||||
const uint16_t r0 = (c0 >> 11) & 0x1F;
|
||||
const uint16_t g0 = (c0 >> 5) & 0x3F;
|
||||
const uint16_t b0 = c0 & 0x1F;
|
||||
|
||||
const uint16_t r1 = (c1 >> 11) & 0x1F;
|
||||
const uint16_t g1 = (c1 >> 5) & 0x3F;
|
||||
const uint16_t b1 = c1 & 0x1F;
|
||||
|
||||
const uint16_t r = static_cast<uint16_t>(r0 + ((static_cast<int32_t>(r1) - r0) * w8 + 128) / 256);
|
||||
const uint16_t g = static_cast<uint16_t>(g0 + ((static_cast<int32_t>(g1) - g0) * w8 + 128) / 256);
|
||||
const uint16_t b = static_cast<uint16_t>(b0 + ((static_cast<int32_t>(b1) - b0) * w8 + 128) / 256);
|
||||
|
||||
return static_cast<uint16_t>((r << 11) | (g << 5) | b);
|
||||
}
|
||||
|
||||
inline uint16_t sampleBilinearRgb565(LGFXCanvas& src, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t wx, uint16_t wy) {
|
||||
const uint16_t c00 = src.readPixel(x0, y0);
|
||||
const uint16_t c10 = src.readPixel(x1, y0);
|
||||
const uint16_t c01 = src.readPixel(x0, y1);
|
||||
const uint16_t c11 = src.readPixel(x1, y1);
|
||||
|
||||
const uint16_t top = lerpRgb565(c00, c10, wx);
|
||||
const uint16_t bot = lerpRgb565(c01, c11, wx);
|
||||
return lerpRgb565(top, bot, wy);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Draw monochrome bitmap on both E-Ink and TFT displays
|
||||
// supports various packing and bit orders; optional runtime conversion for TFT
|
||||
inline void drawMonochromeBitmap(
|
||||
int16_t x, int16_t y,
|
||||
const uint8_t *bmp,
|
||||
int16_t w, int16_t h,
|
||||
uint16_t color,
|
||||
bool vertical=false, // true: bytes run vertically (each byte 8 pixels down)
|
||||
bool lsbFirst=false, // true: least significant bit = left/top pixel
|
||||
bool mirrorX=false) // true: bytes run right-to-left within each row
|
||||
{
|
||||
#ifdef TFT_DISPLAY
|
||||
// TFT converts per‑pixel
|
||||
int bytesPerRow = (w + 7) / 8;
|
||||
for (int yy = 0; yy < h; yy++) {
|
||||
for (int xx = 0; xx < w; xx++) {
|
||||
int byteIdx;
|
||||
int bitIdx;
|
||||
if (vertical) {
|
||||
// vertical packing: column-major bytes
|
||||
int col = mirrorX ? (w - 1 - xx) : xx;
|
||||
byteIdx = col * ((h + 7) / 8) + (yy / 8);
|
||||
bitIdx = yy % 8;
|
||||
} else {
|
||||
// horizontal packing: row-major bytes
|
||||
int col = mirrorX ? (w - 1 - xx) : xx;
|
||||
byteIdx = yy * bytesPerRow + (col / 8);
|
||||
bitIdx = col % 8;
|
||||
}
|
||||
uint8_t b = bmp[byteIdx];
|
||||
bool pix;
|
||||
if (lsbFirst) {
|
||||
pix = b & (1 << bitIdx);
|
||||
} else {
|
||||
pix = b & (1 << (7 - bitIdx));
|
||||
}
|
||||
if (pix) {
|
||||
getdisplay().drawPixel(x + xx, y + yy, color);
|
||||
}
|
||||
}
|
||||
if ((yy & 0x0F) == 0) {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
#else
|
||||
// E‑Paper: just hand over to driver (expects MSB‑first horizontal)
|
||||
getdisplay().drawBitmap(x, y, bmp, w, h, color);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// Display wrapper functions for E-Ink/TFT compatibility
|
||||
|
||||
// generic bitmap draw that accepts 1‑bit data; TFT version
|
||||
// forwards to drawMonochromeBitmap whereas EPD uses native drawBitmap
|
||||
inline void displayDrawBitmap(int16_t x, int16_t y,
|
||||
const uint8_t *bmp,
|
||||
int16_t w, int16_t h,
|
||||
uint16_t color) {
|
||||
#ifdef TFT_DISPLAY
|
||||
drawMonochromeBitmap(x, y, bmp, w, h, color);
|
||||
#else
|
||||
getdisplay().drawBitmap(x, y, bmp, w, h, color);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void displayFirstPage() {
|
||||
#ifdef TFT_DISPLAY
|
||||
initDisplayShadowBuffer();
|
||||
#else
|
||||
getdisplay().firstPage();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void displayNextPage() {
|
||||
#ifdef TFT_DISPLAY
|
||||
if (initDisplayShadowBuffer()) {
|
||||
LGFXCanvas &src = getdisplay();
|
||||
LGFX &dst = getpaneldisplay();
|
||||
|
||||
const uint16_t srcW = GxEPD_WIDTH;
|
||||
const uint16_t srcH = GxEPD_HEIGHT;
|
||||
const uint16_t dstW = static_cast<uint16_t>(dst.width());
|
||||
const uint16_t dstH = static_cast<uint16_t>(dst.height());
|
||||
|
||||
#if !OBP_TFT_ENABLE_SCALING
|
||||
const uint16_t drawX = static_cast<uint16_t>((dstW > srcW) ? ((dstW - srcW) / 2U) : 0U);
|
||||
const uint16_t drawY = static_cast<uint16_t>((dstH > srcH) ? ((dstH - srcH) / 2U) : 0U);
|
||||
src.pushSprite(drawX, drawY);
|
||||
#else
|
||||
|
||||
const uint16_t targetH = (dstH < 320U) ? dstH : 320U;
|
||||
const uint32_t scaledW32 = (static_cast<uint32_t>(srcW) * targetH + (srcH / 2U)) / srcH;
|
||||
const uint16_t targetW = static_cast<uint16_t>((scaledW32 < dstW) ? scaledW32 : dstW);
|
||||
|
||||
const uint16_t drawX = static_cast<uint16_t>((dstW - targetW) / 2U);
|
||||
const uint16_t drawY = static_cast<uint16_t>((dstH - targetH) / 2U);
|
||||
|
||||
const uint16_t borderColor = src.readPixel(0, 0);
|
||||
if (initDisplayScaleBuffer(dstW, dstH)) {
|
||||
LGFXCanvas &scaled = getscaleddisplay();
|
||||
scaled.fillScreen(borderColor);
|
||||
|
||||
for (uint16_t y = 0; y < targetH; ++y) {
|
||||
const uint32_t syfp = (targetH > 1)
|
||||
? (static_cast<uint32_t>(y) * (srcH - 1) * 256U) / (targetH - 1)
|
||||
: 0;
|
||||
const uint16_t sy0 = static_cast<uint16_t>(syfp >> 8);
|
||||
const uint16_t sy1 = (sy0 + 1 < srcH) ? static_cast<uint16_t>(sy0 + 1) : sy0;
|
||||
const uint16_t wy = static_cast<uint16_t>(syfp & 0xFFU);
|
||||
|
||||
for (uint16_t x = 0; x < targetW; ++x) {
|
||||
const uint32_t sxfp = (targetW > 1)
|
||||
? (static_cast<uint32_t>(x) * (srcW - 1) * 256U) / (targetW - 1)
|
||||
: 0;
|
||||
const uint16_t sx0 = static_cast<uint16_t>(sxfp >> 8);
|
||||
const uint16_t sx1 = (sx0 + 1 < srcW) ? static_cast<uint16_t>(sx0 + 1) : sx0;
|
||||
|
||||
#if OBP_TFT_SCALE_ANTIALIAS
|
||||
const uint16_t wx = static_cast<uint16_t>(sxfp & 0xFFU);
|
||||
const uint16_t color = sampleBilinearRgb565(src, sx0, sy0, sx1, sy1, wx, wy);
|
||||
#else
|
||||
const uint16_t color = src.readPixel(sx0, sy0);
|
||||
#endif
|
||||
|
||||
scaled.drawPixel(drawX + x, drawY + y, color);
|
||||
}
|
||||
if ((y & 0x0F) == 0) {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
|
||||
scaled.pushSprite(0, 0);
|
||||
} else {
|
||||
src.pushSprite(drawX, drawY);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
getdisplay().nextPage();
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void displaySetPartialWindow(uint16_t x, uint16_t y, uint16_t w, uint16_t h) {
|
||||
#ifdef TFT_DISPLAY
|
||||
// TFT LCD doesn't use partial windows
|
||||
(void)x; (void)y; (void)w; (void)h;
|
||||
#else
|
||||
getdisplay().setPartialWindow(x, y, w, h);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void displaySetFullWindow() {
|
||||
#ifdef TFT_DISPLAY
|
||||
// TFT LCD doesn't need setFullWindow()
|
||||
#else
|
||||
getdisplay().setFullWindow();
|
||||
#endif
|
||||
}
|
||||
|
||||
// replacement for getTextBounds that works with both EPD and TFT
|
||||
inline void displayGetTextBounds(const String &txt, int16_t x, int16_t y,
|
||||
int16_t *x0, int16_t *y0,
|
||||
uint16_t *w, uint16_t *h, const bool dsegAdjust = false) {
|
||||
String str = txt;
|
||||
// make sure that we always have a char with max size at last position for boundary test
|
||||
// for monotype italic DSEG7 font to avoid text wobbling
|
||||
if (dsegAdjust && str.length() > 0 && isDigit(str[str.length() - 1])) {
|
||||
str.setCharAt(str.length() - 1, '8');
|
||||
}
|
||||
#ifdef TFT_DISPLAY
|
||||
getdisplay().getTextBounds(str, x, y, x0, y0, w, h);
|
||||
#else
|
||||
getdisplay().getTextBounds(str, x, y, x0, y0, w, h);
|
||||
#endif
|
||||
}
|
||||
|
||||
void fillPoly4(const std::vector<Point>& p4, uint16_t color);
|
||||
void drawPoly(const std::vector<Point>& points, uint16_t color);
|
||||
|
||||
@@ -738,19 +104,17 @@ 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
|
||||
String xdrDelete(String input, uint8_t maxlen = 0); // Delete xdr prefix from string and optional limit length
|
||||
|
||||
int16_t drawTextCenter(int16_t cx, int16_t cy, String text, bool dsegAdjust = false);
|
||||
void drawTextCenter(int16_t cx, int16_t cy, String text);
|
||||
void drawButtonCenter(int16_t cx, int16_t cy, int8_t sx, int8_t sy, String text, uint16_t fg, uint16_t bg, bool inverted);
|
||||
int16_t drawTextRalign(int16_t x, int16_t y, const String& text, bool dsegAdjust = false);
|
||||
void drawTextRalign(int16_t x, int16_t y, String text);
|
||||
void drawTextBoxed(Rect box, String text, uint16_t fg, uint16_t bg, bool inverted, bool border);
|
||||
void printBoatValue(GwApi::BoatValue *bValue, CommonData &commondata, const int16_t x, const int16_t y, const int8_t align, const int8_t fontSize, const bool smallDecs = false);
|
||||
void printBoatValue(const String &sBoatValue, const int16_t x, const int16_t y, const int8_t align, const int8_t fontSize, const bool smallDecs = false);
|
||||
|
||||
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
|
||||
void displayHeader(CommonData &commonData, bool symbolmode, GwApi::BoatValue *date, GwApi::BoatValue *time, GwApi::BoatValue *hdop); // Draw display header
|
||||
void displayFooter(CommonData &commonData);
|
||||
void displayAlarm(CommonData &commonData);
|
||||
|
||||
@@ -802,24 +166,62 @@ 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 };
|
||||
|
||||
// Header symbols
|
||||
|
||||
static unsigned char ap_bits[] PROGMEM= {
|
||||
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 = {
|
||||
static unsigned char gps_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 unsigned char nmea_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0x22, 0x21, 0x26, 0x33, 0x26, 0x33, 0x2a, 0x2d, 0x32, 0x2d,
|
||||
0x32, 0x21, 0x22, 0x21, 0x00, 0x00, 0x3c, 0x0c, 0x04, 0x0c, 0x04, 0x12,
|
||||
0x3c, 0x12, 0x04, 0x1e, 0x04, 0x21, 0x3c, 0x21 };
|
||||
|
||||
static unsigned char n2k_bits[] PROGMEM = {
|
||||
0xe0, 0x07, 0x18, 0x18, 0x04, 0x20, 0x02, 0x40, 0x32, 0x4c, 0x31, 0x8c,
|
||||
0x01, 0x80, 0x81, 0x81, 0x81, 0x81, 0x01, 0x80, 0x31, 0x8c, 0x32, 0x4c,
|
||||
0x02, 0x40, 0x04, 0x20, 0x98, 0x19, 0xe0, 0x07 };
|
||||
|
||||
static unsigned char tcp_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0xe0, 0x03, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0xe0, 0x03,
|
||||
0x80, 0x00, 0x80, 0x00, 0xff, 0xff, 0x08, 0x10, 0x08, 0x10, 0x3e, 0x7c,
|
||||
0x22, 0x44, 0x22, 0x44, 0x22, 0x44, 0x3e, 0x7c };
|
||||
|
||||
static unsigned char usb_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0x92, 0x39, 0x52, 0x4a, 0x52, 0x48, 0x92, 0x39, 0x12, 0x4a,
|
||||
0x52, 0x4a, 0x8c, 0x39, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x04, 0x20,
|
||||
0xf4, 0x2f, 0x04, 0x20, 0xf8, 0x1f, 0x00, 0x00 };
|
||||
|
||||
static unsigned char sdcard_bits[] PROGMEM = {
|
||||
0xf8, 0x07, 0x0c, 0x08, 0x04, 0x08, 0xc4, 0x09, 0x24, 0x1a, 0xe4, 0x13,
|
||||
0x04, 0x20, 0x24, 0x21, 0xa4, 0x12, 0x44, 0x12, 0x04, 0x20, 0x04, 0x20,
|
||||
0xc4, 0x23, 0x34, 0x2c, 0xd8, 0x1b, 0x00, 0x00 };
|
||||
|
||||
static unsigned char bluetooth_bits[] PROGMEM = {
|
||||
0x00, 0x00, 0x22, 0x21, 0x26, 0x33, 0x26, 0x33, 0x2a, 0x2d, 0x32, 0x2d,
|
||||
0x32, 0x21, 0x22, 0x21, 0x00, 0x00, 0x3c, 0x0c, 0x04, 0x0c, 0x04, 0x12,
|
||||
0x3c, 0x12, 0x04, 0x1e, 0x04, 0x21, 0x3c, 0x21 };
|
||||
|
||||
static std::map<String, unsigned char *> iconmap = {
|
||||
{"LEFT", left_bits},
|
||||
{"RIGHT", right_bits},
|
||||
{"LOCK", lock_bits},
|
||||
{"PLUS", plus_bits},
|
||||
{"MINUS", minus_bits},
|
||||
{"DISH", dish_bits},
|
||||
{"AP", ap_bits}
|
||||
{"GPS", gps_bits},
|
||||
{"AP", ap_bits},
|
||||
{"0183", nmea_bits},
|
||||
{"N2K", n2k_bits},
|
||||
{"TCP", tcp_bits},
|
||||
{"USB", usb_bits},
|
||||
{"SDCARD", sdcard_bits},
|
||||
{"BLUE", bluetooth_bits}
|
||||
};
|
||||
|
||||
// Battery
|
||||
|
||||
+195
-231
@@ -3,111 +3,91 @@
|
||||
#include <Arduino.h>
|
||||
#include "GwApi.h"
|
||||
#include "Pagedata.h"
|
||||
#include "OBPDataOperations.h"
|
||||
#include "OBP60Formatter.h"
|
||||
|
||||
// ToDo
|
||||
// simulation data
|
||||
// hold values by missing data
|
||||
|
||||
String formatDate(String fmttype, uint16_t year, uint8_t month, uint8_t day) {
|
||||
char buffer[12];
|
||||
if (fmttype == "GB") {
|
||||
snprintf(buffer, 12, "%02d/%02d/%04d", day , month, year);
|
||||
}
|
||||
else if (fmttype == "US") {
|
||||
snprintf(buffer, 12, "%02d/%02d/%04d", month, day, year);
|
||||
}
|
||||
else if (fmttype == "ISO") {
|
||||
snprintf(buffer, 12, "%04d-%02d-%02d", year, month, day);
|
||||
}
|
||||
else {
|
||||
snprintf(buffer, 12, "%02d.%02d.%04d", day, month, year);
|
||||
}
|
||||
return String(buffer);
|
||||
Formatter::Formatter(GwConfigHandler *config) {
|
||||
// Load configuration values
|
||||
// TODO do not use strings but enums, see header file
|
||||
stimeZone = config->getString(config->timeZone);
|
||||
timeZone = stimeZone.toDouble();
|
||||
lengthFormat = config->getString(config->lengthFormat);
|
||||
distanceFormat = config->getString(config->distanceFormat);
|
||||
speedFormat = config->getString(config->speedFormat);
|
||||
windspeedFormat = config->getString(config->windspeedFormat);
|
||||
tempFormat = config->getString(config->tempFormat);
|
||||
dateFormat = config->getString(config->dateFormat);
|
||||
dateFmt = getDateFormat(dateFormat);
|
||||
usesimudata = config->getBool(config->useSimuData);
|
||||
precision = config->getString(config->valueprecision);
|
||||
|
||||
if (precision == "1") {
|
||||
fmt_dec_1 = "%3.1f";
|
||||
fmt_dec_10 = "%3.0f";
|
||||
fmt_dec_100 = "%3.0f";
|
||||
} else {
|
||||
fmt_dec_1 = "%3.2f";
|
||||
fmt_dec_10 = "%3.1f";
|
||||
fmt_dec_100 = "%3.0f";
|
||||
}
|
||||
|
||||
String formatTime(char fmttype, uint8_t hour, uint8_t minute, uint8_t second) {
|
||||
// fmttype: s: with seconds, m: only minutes
|
||||
char buffer[10];
|
||||
if (fmttype == 'm') {
|
||||
snprintf(buffer, 10, "%02d:%02d", hour , minute);
|
||||
}
|
||||
else {
|
||||
snprintf(buffer, 10, "%02d:%02d:%02d", hour, minute, second);
|
||||
}
|
||||
return String(buffer);
|
||||
}
|
||||
|
||||
String formatLatitude(double lat) {
|
||||
float degree = abs(int(lat));
|
||||
float minute = abs((lat - int(lat)) * 60);
|
||||
return String(degree, 0) + "\x90 " + String(minute, 4) + "' " + ((lat > 0) ? "N" : "S");
|
||||
fmtType Formatter::stringToFormat(const char* formatStr) {
|
||||
auto it = formatMap.find(formatStr);
|
||||
if (it != formatMap.end()) {
|
||||
return it->second;
|
||||
}
|
||||
return fmtType::XDR_G; // generic as default
|
||||
}
|
||||
|
||||
String formatLongitude(double lon) {
|
||||
float degree = abs(int(lon));
|
||||
float minute = abs((lon - int(lon)) * 60);
|
||||
return String(degree, 0) + "\x90 " + String(minute, 4) + "' " + ((lon > 0) ? "E" : "W");
|
||||
fmtDate Formatter::getDateFormat(String sformat) {
|
||||
if (sformat == "DE") {
|
||||
return fmtDate::DE;
|
||||
}
|
||||
if (sformat == "GB") {
|
||||
return fmtDate::GB;
|
||||
}
|
||||
if (sformat == "US") {
|
||||
return fmtDate::US;
|
||||
}
|
||||
return fmtDate::ISO; // default
|
||||
}
|
||||
|
||||
// Convert and format boat value from SI to user defined format
|
||||
// generates random simulation data; can be deselected to use conversion+formatting function even in simulation mode
|
||||
// String setPrecision - overrides precision setting from config; if not set, use config setting
|
||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool ignoreSimuDataSetting, String setPrecision) {
|
||||
fmtTime Formatter::getTimeFormat(String sformat) {
|
||||
if (sformat == "MMHH") {
|
||||
return fmtTime::MMHH;
|
||||
}
|
||||
if (sformat == "MMHHSS") {
|
||||
return fmtTime::MMHHSS;
|
||||
}
|
||||
return fmtTime::MMHH; // default
|
||||
}
|
||||
|
||||
FormattedData Formatter::formatValue(GwApi::BoatValue *value, CommonData &commondata, bool ignoreSimuDataSetting) {
|
||||
GwLog *logger = commondata.logger;
|
||||
FormattedData result;
|
||||
static int dayoffset = 0;
|
||||
double rawvalue = 0;
|
||||
|
||||
bool simulation;
|
||||
if (ignoreSimuDataSetting) {
|
||||
simulation = false; // ignore user setting for simulation data; we want to format the boat value passed to this function
|
||||
} else {
|
||||
simulation = usesimudata; // use setting from configuration
|
||||
}
|
||||
|
||||
result.cvalue = value->value;
|
||||
|
||||
// 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]
|
||||
String precision = commondata.config->getString(commondata.config->valueprecision); // [1|2]
|
||||
bool usesimudata = commondata.config->getBool(commondata.config->useSimuData); // [on|off]
|
||||
|
||||
if (setPrecision == "1" || setPrecision == "2") {
|
||||
precision = setPrecision; // override precision setting from config
|
||||
}
|
||||
if (ignoreSimuDataSetting){
|
||||
usesimudata = false; // ignore user setting for simulation data; we want to format the boat value passed to this function
|
||||
}
|
||||
|
||||
// If boat value not valid
|
||||
if (! value->valid && !usesimudata){
|
||||
result.svalue = "---";
|
||||
if (! value->valid && !simulation){
|
||||
result.svalue = placeholder;
|
||||
return result;
|
||||
}
|
||||
|
||||
const char* fmt_dec_1;
|
||||
const char* fmt_dec_10;
|
||||
const char* fmt_dec_100;
|
||||
double limit_dec_10;
|
||||
double limit_dec_100;
|
||||
if (precision == "1") {
|
||||
//All values are displayed using a DSEG7* font. In this font, ' ' is a very short space, and '.' takes up no space at all.
|
||||
//For a space that is as long as a number, '!' is used. For details see https://www.keshikan.net/fonts-e.html
|
||||
|
||||
fmt_dec_1 = "!%1.1f"; // blank digit + 2 digit number, incl. 1 decimal
|
||||
fmt_dec_10 = "%3.1f"; // 3 digit number, incl. 1 decimal
|
||||
fmt_dec_100 = "%3.0f"; // 3 digit number, no decimal
|
||||
limit_dec_10=9.95; // use fmt_dec_1 below this number to avoid formatting 9.96 as 10.0 instead of 10
|
||||
limit_dec_100=99.5;
|
||||
} else {
|
||||
fmt_dec_1 = "%3.2f";
|
||||
fmt_dec_10 = "%3.1f";
|
||||
fmt_dec_100 = "%3.0f";
|
||||
limit_dec_10=9.995;
|
||||
limit_dec_100=99.95;
|
||||
}
|
||||
|
||||
// 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];
|
||||
@@ -127,7 +107,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
tmElements_t parts;
|
||||
time_t tv=tNMEA0183Msg::daysToTime_t(value->value + dayoffset);
|
||||
tNMEA0183Msg::breakTime(tv,parts);
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
if (String(dateFormat) == "DE") {
|
||||
snprintf(buffer,bsize, "%02d.%02d.%04d", parts.tm_mday, parts.tm_mon+1, parts.tm_year+1900);
|
||||
}
|
||||
@@ -147,12 +127,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
else{
|
||||
snprintf(buffer, bsize, "01.01.2022");
|
||||
}
|
||||
if(timeZone == 0){
|
||||
result.unit = "UTC";
|
||||
}
|
||||
else{
|
||||
result.unit = "LOT";
|
||||
}
|
||||
result.unit = ((timeZone == 0) ? "UTC" : "LOT");
|
||||
}
|
||||
//########################################################
|
||||
else if(value->getFormat() == "formatTime"){
|
||||
@@ -166,7 +141,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
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) {
|
||||
if (simulation == false) {
|
||||
val = modf(timeInSeconds/3600.0, &inthr);
|
||||
val = modf(val*3600.0/60.0, &intmin);
|
||||
modf(val*60.0,&intsec);
|
||||
@@ -184,16 +159,11 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
result.cvalue = sec;
|
||||
lasttime = millis();
|
||||
}
|
||||
if(timeZone == 0){
|
||||
result.unit = "UTC";
|
||||
}
|
||||
else{
|
||||
result.unit = "LOT";
|
||||
}
|
||||
result.unit = ((timeZone == 0) ? "UTC" : "LOT");
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatFixed0"){
|
||||
if(usesimudata == false) {
|
||||
if(simulation == false) {
|
||||
snprintf(buffer, bsize, "%3.0f", value->value);
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -207,15 +177,15 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatCourse" || value->getFormat() == "formatWind"){
|
||||
double course = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
course = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else {
|
||||
course = M_PI_2 + float(random(-26, 26) / 100.0); // create random course/wind values with 90° +/- 15°
|
||||
course = M_PI_2 + float(random(-17, 17) / 100.0); // create random course/wind values with 90° +/- 10°
|
||||
rawvalue = course;
|
||||
}
|
||||
course = WindUtils::to360(course * RAD_TO_DEG); // Unit conversion form rad to deg
|
||||
course = course * 57.2958; // Unit conversion form rad to deg
|
||||
|
||||
// Format 3 numbers with prefix zero
|
||||
snprintf(buffer,bsize,"%03.0f",course);
|
||||
@@ -223,9 +193,9 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
result.cvalue = course;
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatKnots" && (value->getName() == "SOG" || value->getName() == "STW") || value->getName() == "DFT"){
|
||||
else if (value->getFormat() == "formatKnots" && (value->getName() == "SOG" || value->getName() == "STW")){
|
||||
double speed = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
speed = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -245,10 +215,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
speed = speed; // Unit conversion form m/s to m/s
|
||||
result.unit = "m/s";
|
||||
}
|
||||
if(speed < limit_dec_10) {
|
||||
if(speed < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, speed);
|
||||
}
|
||||
else if (speed < limit_dec_100) {
|
||||
else if (speed < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, speed);
|
||||
}
|
||||
else {
|
||||
@@ -259,7 +229,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatKnots" && (value->getName() == "AWS" || value->getName() == "TWS" || value->getName() == "MaxAws" || value->getName() == "MaxTws")){
|
||||
double speed = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
speed = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -325,10 +295,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
snprintf(buffer, bsize, "%2.0f", speed);
|
||||
}
|
||||
else{
|
||||
if (speed < limit_dec_10){
|
||||
if (speed < 10){
|
||||
snprintf(buffer, bsize, fmt_dec_1, speed);
|
||||
}
|
||||
else if (speed < limit_dec_100){
|
||||
else if (speed < 100){
|
||||
snprintf(buffer, bsize, fmt_dec_10, speed);
|
||||
}
|
||||
else {
|
||||
@@ -340,7 +310,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatRot"){
|
||||
double rotation = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
rotation = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -353,13 +323,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
if (rotation < -100){
|
||||
rotation = -99;
|
||||
}
|
||||
if (rotation > 100){
|
||||
else if (rotation > 100){
|
||||
rotation = 99;
|
||||
}
|
||||
if (rotation > -10 && rotation < 10){
|
||||
snprintf(buffer, bsize, "%3.2f", rotation);
|
||||
}
|
||||
if (rotation <= -10 || rotation >= 10){
|
||||
else {
|
||||
snprintf(buffer, bsize, "%3.0f", rotation);
|
||||
}
|
||||
result.cvalue = rotation;
|
||||
@@ -367,7 +337,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatDop"){
|
||||
double dop = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
dop = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -379,10 +349,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
if (dop > 99.9){
|
||||
dop = 99.9;
|
||||
}
|
||||
if (dop < limit_dec_10){
|
||||
if (dop < 10){
|
||||
snprintf(buffer, bsize, fmt_dec_1, dop);
|
||||
}
|
||||
else if(dop < limit_dec_100){
|
||||
else if(dop < 100){
|
||||
snprintf(buffer, bsize, fmt_dec_10, dop);
|
||||
}
|
||||
else {
|
||||
@@ -392,19 +362,14 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatLatitude"){
|
||||
if (usesimudata == false) {
|
||||
if (simulation == 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";
|
||||
}
|
||||
latdir = (lat > 0) ? "N" : "S";
|
||||
latitude = String(degree,0) + "\x90 " + String(minute,4) + "' " + latdir;
|
||||
result.unit = "";
|
||||
strcpy(buffer, latitude.c_str());
|
||||
@@ -417,19 +382,14 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatLongitude"){
|
||||
if (usesimudata == false) {
|
||||
if (simulation == 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";
|
||||
}
|
||||
londir = (lon > 0) ? "E" : "W";
|
||||
longitude = String(degree,0) + "\x90 " + String(minute,4) + "' " + londir;
|
||||
result.unit = "";
|
||||
strcpy(buffer, longitude.c_str());
|
||||
@@ -443,7 +403,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatDepth"){
|
||||
double depth = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
depth = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -452,16 +412,16 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
depth = rawvalue;
|
||||
}
|
||||
if(String(lengthFormat) == "ft"){
|
||||
depth = depth * 3.28084;
|
||||
depth = depth * 3.28084; // TODO use global defined factor
|
||||
result.unit = "ft";
|
||||
}
|
||||
else{
|
||||
result.unit = "m";
|
||||
}
|
||||
if (depth < limit_dec_10) {
|
||||
if (depth < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, depth);
|
||||
}
|
||||
else if (depth < limit_dec_100){
|
||||
else if (depth < 100){
|
||||
snprintf(buffer, bsize, fmt_dec_10, depth);
|
||||
}
|
||||
else {
|
||||
@@ -472,32 +432,28 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXte"){
|
||||
double xte = 0;
|
||||
if(usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
xte = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
rawvalue = 6.0 + float(random(0, 4));
|
||||
xte = rawvalue;
|
||||
}
|
||||
if(String(distanceFormat) == "km"){
|
||||
if (distanceFormat == "km") {
|
||||
xte = xte * 0.001;
|
||||
result.unit = "km";
|
||||
}
|
||||
else if(String(distanceFormat) == "nm"){
|
||||
xte = xte * 0.000539957;
|
||||
} else if (distanceFormat == "nm") {
|
||||
xte = xte * 0.000539957; // TODO use global defined factor
|
||||
result.unit = "nm";
|
||||
}
|
||||
else{;
|
||||
} else {
|
||||
result.unit = "m";
|
||||
}
|
||||
if (xte < 10) {
|
||||
snprintf(buffer, bsize, "%3.2f", xte);
|
||||
}
|
||||
if(xte >= 10 && xte < 100){
|
||||
} else if (xte < 100) {
|
||||
snprintf(buffer,bsize,"%3.1f",xte);
|
||||
}
|
||||
if(xte >= 100){
|
||||
else {
|
||||
snprintf(buffer, bsize, "%3.0f", xte);
|
||||
}
|
||||
result.cvalue = xte;
|
||||
@@ -505,7 +461,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "kelvinToC"){
|
||||
double temp = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
temp = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -515,19 +471,19 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
}
|
||||
if (String(tempFormat) == "C") {
|
||||
temp = temp - 273.15;
|
||||
result.unit = "Deg C";
|
||||
result.unit = "C";
|
||||
}
|
||||
else if (String(tempFormat) == "F") {
|
||||
temp = (temp - 273.15) * 9 / 5 + 32;
|
||||
result.unit = "Deg F";
|
||||
result.unit = "F";
|
||||
}
|
||||
else{
|
||||
result.unit = "K";
|
||||
}
|
||||
if(temp < limit_dec_10) {
|
||||
if (temp < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, temp);
|
||||
}
|
||||
else if (temp < limit_dec_100) {
|
||||
else if (temp < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, temp);
|
||||
}
|
||||
else {
|
||||
@@ -538,7 +494,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "mtr2nm"){
|
||||
double distance = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
distance = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -551,16 +507,16 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
result.unit = "km";
|
||||
}
|
||||
else if (String(distanceFormat) == "nm") {
|
||||
distance = distance * 0.000539957;
|
||||
distance = distance * 0.000539957; // TODO use global defined factor
|
||||
result.unit = "nm";
|
||||
}
|
||||
else {
|
||||
result.unit = "m";
|
||||
}
|
||||
if (distance < limit_dec_10){
|
||||
if (distance < 10){
|
||||
snprintf(buffer, bsize, fmt_dec_1, distance);
|
||||
}
|
||||
else if (distance < limit_dec_100){
|
||||
else if (distance < 100){
|
||||
snprintf(buffer, bsize, fmt_dec_10, distance);
|
||||
}
|
||||
else {
|
||||
@@ -574,7 +530,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:P:P"){
|
||||
double pressure = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
pressure = value->value;
|
||||
rawvalue = value->value;
|
||||
pressure = pressure / 100.0; // Unit conversion form Pa to hPa
|
||||
@@ -583,18 +539,14 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 968 + float(random(0, 10));
|
||||
pressure = rawvalue;
|
||||
}
|
||||
if (pressure < 999.5) {
|
||||
snprintf(buffer, bsize, "!%3.0f", pressure);
|
||||
} else {
|
||||
snprintf(buffer, bsize, "%4.0f", pressure);
|
||||
}
|
||||
result.unit = "hPa";
|
||||
result.cvalue = pressure;
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:P:B"){
|
||||
double pressure = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
pressure = value->value;
|
||||
rawvalue = value->value;
|
||||
pressure = pressure / 100.0; // Unit conversion form Pa to mBar
|
||||
@@ -603,18 +555,14 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = value->value;
|
||||
pressure = 968 + float(random(0, 10));
|
||||
}
|
||||
if (pressure < 999.5) {
|
||||
snprintf(buffer, bsize, "!%3.0f", pressure);
|
||||
} else {
|
||||
snprintf(buffer, bsize, "%4.0f", pressure);
|
||||
}
|
||||
result.unit = "mBar";
|
||||
result.cvalue = pressure;
|
||||
}
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:U:V"){
|
||||
double voltage = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
voltage = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -622,7 +570,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 12 + float(random(0, 30)) / 10.0;
|
||||
voltage = rawvalue;
|
||||
}
|
||||
if (voltage < limit_dec_10) {
|
||||
if (voltage < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, voltage);
|
||||
}
|
||||
else {
|
||||
@@ -634,7 +582,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:I:A"){
|
||||
double current = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
current = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -642,10 +590,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 8.2 + float(random(0, 50)) / 10.0;
|
||||
current = rawvalue;
|
||||
}
|
||||
if (current < limit_dec_10) {
|
||||
if (current < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, current);
|
||||
}
|
||||
else if(current < limit_dec_100) {
|
||||
else if(current < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, current);
|
||||
}
|
||||
else {
|
||||
@@ -657,7 +605,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:C:K"){
|
||||
double temperature = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
temperature = value->value - 273.15; // Convert K to C
|
||||
rawvalue = value->value - 273.15;
|
||||
}
|
||||
@@ -665,10 +613,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 21.8 + float(random(0, 50)) / 10.0;
|
||||
temperature = rawvalue;
|
||||
}
|
||||
if (temperature < limit_dec_10) {
|
||||
if (temperature < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, temperature);
|
||||
}
|
||||
else if (temperature < limit_dec_100) {
|
||||
else if (temperature < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, temperature);
|
||||
}
|
||||
else {
|
||||
@@ -680,7 +628,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:C:C"){
|
||||
double temperature = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
temperature = value->value; // Value in C
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -688,10 +636,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 21.8 + float(random(0, 50)) / 10.0;
|
||||
temperature = rawvalue;
|
||||
}
|
||||
if (temperature < limit_dec_10) {
|
||||
if (temperature < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, temperature);
|
||||
}
|
||||
else if(temperature < limit_dec_100) {
|
||||
else if(temperature < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, temperature);
|
||||
}
|
||||
else {
|
||||
@@ -703,7 +651,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:H:P"){
|
||||
double humidity = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
humidity = value->value; // Value in %
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -711,10 +659,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 41.3 + float(random(0, 50)) / 10.0;
|
||||
humidity = rawvalue;
|
||||
}
|
||||
if (humidity < limit_dec_10) {
|
||||
if (humidity < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, humidity);
|
||||
}
|
||||
else if(humidity < limit_dec_100) {
|
||||
else if(humidity < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, humidity);
|
||||
}
|
||||
else {
|
||||
@@ -726,7 +674,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:V:P"){
|
||||
double volume = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
volume = value->value; // Value in %
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -734,13 +682,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 85.8 + float(random(0, 50)) / 10.0;
|
||||
volume = rawvalue;
|
||||
}
|
||||
if (volume < limit_dec_10) {
|
||||
if (volume < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, volume);
|
||||
}
|
||||
else if (volume < limit_dec_100) {
|
||||
else if (volume < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, volume);
|
||||
}
|
||||
else if (volume >= limit_dec_100) {
|
||||
else if (volume >= 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_100, volume);
|
||||
}
|
||||
result.unit = "%";
|
||||
@@ -749,7 +697,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:V:M"){
|
||||
double volume = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
volume = value->value; // Value in l
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -757,10 +705,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 75.2 + float(random(0, 50)) / 10.0;
|
||||
volume = rawvalue;
|
||||
}
|
||||
if (volume < limit_dec_10) {
|
||||
if (volume < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, volume);
|
||||
}
|
||||
else if (volume < limit_dec_100) {
|
||||
else if (volume < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, volume);
|
||||
}
|
||||
else {
|
||||
@@ -772,7 +720,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:R:I"){
|
||||
double flow = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
flow = value->value; // Value in l/min
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -780,10 +728,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 7.5 + float(random(0, 20)) / 10.0;
|
||||
flow = rawvalue;
|
||||
}
|
||||
if (flow < limit_dec_10) {
|
||||
if (flow < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, flow);
|
||||
}
|
||||
else if (flow < limit_dec_100) {
|
||||
else if (flow < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, flow);
|
||||
}
|
||||
else {
|
||||
@@ -795,7 +743,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:G:"){
|
||||
double generic = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
generic = value->value;
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -803,10 +751,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 18.5 + float(random(0, 20)) / 10.0;
|
||||
generic = rawvalue;
|
||||
}
|
||||
if (generic < limit_dec_10) {
|
||||
if (generic < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, generic);
|
||||
}
|
||||
else if (generic < limit_dec_100) {
|
||||
else if (generic < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, generic);
|
||||
}
|
||||
else {
|
||||
@@ -818,7 +766,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:A:P"){
|
||||
double dplace = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
dplace = value->value; // Value in %
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -826,10 +774,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 55.3 + float(random(0, 20)) / 10.0;
|
||||
dplace = rawvalue;
|
||||
}
|
||||
if (dplace < limit_dec_10) {
|
||||
if (dplace < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, dplace);
|
||||
}
|
||||
else if (dplace < limit_dec_100) {
|
||||
else if (dplace < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, dplace);
|
||||
}
|
||||
else {
|
||||
@@ -841,7 +789,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if ((value->getFormat() == "formatXdr:A:D") || ((value->getFormat() == "formatXdr:A:rd"))){
|
||||
double angle = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
angle = value->value;
|
||||
angle = angle * 57.2958; // Unit conversion form rad to deg
|
||||
rawvalue = value->value;
|
||||
@@ -862,7 +810,7 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
//########################################################
|
||||
else if (value->getFormat() == "formatXdr:T:R"){
|
||||
double rpm = 0;
|
||||
if (usesimudata == false) {
|
||||
if (simulation == false) {
|
||||
rpm = value->value; // Value in rpm
|
||||
rawvalue = value->value;
|
||||
}
|
||||
@@ -870,10 +818,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
rawvalue = 2505 + random(0, 20);
|
||||
rpm = rawvalue;
|
||||
}
|
||||
if (rpm < limit_dec_10) {
|
||||
if (rpm < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, rpm);
|
||||
}
|
||||
else if (rpm < limit_dec_100) {
|
||||
else if (rpm < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, rpm);
|
||||
}
|
||||
else {
|
||||
@@ -886,10 +834,10 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
// Default format
|
||||
//########################################################
|
||||
else {
|
||||
if (value->value < limit_dec_10) {
|
||||
if (value->value < 10) {
|
||||
snprintf(buffer, bsize, fmt_dec_1, value->value);
|
||||
}
|
||||
else if (value->value < limit_dec_100) {
|
||||
else if (value->value < 100) {
|
||||
snprintf(buffer, bsize, fmt_dec_10, value->value);
|
||||
}
|
||||
else {
|
||||
@@ -904,42 +852,13 @@ FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert and format boat value from SI to user defined format
|
||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata) {
|
||||
|
||||
return formatValue(value, commondata, false, String("-1")); // call <formatValue> with standard setting for simulation data and precision setting from config
|
||||
}
|
||||
|
||||
// Convert and format boat value from SI to user defined format with simulation data setting and precision setting from config
|
||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool ignoreSimuDataSetting) {
|
||||
|
||||
return formatValue(value, commondata, ignoreSimuDataSetting, String("-1"));
|
||||
}
|
||||
|
||||
// Convert and format boat value from SI to user defined format with standard setting for simulation data and specified precision
|
||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, String setPrecision) {
|
||||
|
||||
return formatValue(value, commondata, false, setPrecision);
|
||||
}
|
||||
|
||||
// Format double value from SI to user defined format and convert to string user defined precision setting
|
||||
String formatValue(const double &value, const String &vFormat, CommonData &commondata)
|
||||
{
|
||||
GwApi::BoatValue tmpBVal("dummy"); // temporary boat value for string formatter
|
||||
String sVal;
|
||||
|
||||
tmpBVal.setFormat(vFormat);
|
||||
tmpBVal.valid = true;
|
||||
tmpBVal.value = value;
|
||||
sVal = formatValue(&tmpBVal, commondata, false, String("-1")).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
if (sVal.length() > 0 && sVal[0] == '!') {
|
||||
sVal = sVal.substring(1); // cut leading "!" created at OBPFormatter; doesn't work for other fonts than 7SEG
|
||||
}
|
||||
return sVal;
|
||||
// Convert and format boat value from SI to user defined format (definition for compatibility purposes)
|
||||
FormattedData Formatter::formatValue(GwApi::BoatValue *value, CommonData &commondata) {
|
||||
return formatValue(value, commondata, false); // call <formatValue> with standard handling of user setting for simulation data
|
||||
}
|
||||
|
||||
// Helper method for conversion of any data value from SI to user defined format
|
||||
double convertValue(const double &value, const String &name, const String &format, CommonData &commondata)
|
||||
double Formatter::convertValue(const double &value, const String &name, const String &format, CommonData &commondata)
|
||||
{
|
||||
std::unique_ptr<GwApi::BoatValue> tmpBValue; // Temp variable to get converted data value from <OBP60Formatter::formatValue>
|
||||
double result; // data value converted to user defined target data format
|
||||
@@ -956,7 +875,7 @@ double convertValue(const double &value, const String &name, const String &forma
|
||||
}
|
||||
|
||||
// Helper method for conversion of any data value from SI to user defined format
|
||||
double convertValue(const double &value, const String &format, CommonData &commondata)
|
||||
double Formatter::convertValue(const double &value, const String &format, CommonData &commondata)
|
||||
{
|
||||
double result; // data value converted to user defined target data format
|
||||
|
||||
@@ -964,4 +883,49 @@ double convertValue(const double &value, const String &format, CommonData &commo
|
||||
return result;
|
||||
}
|
||||
|
||||
String formatDate(fmtDate fmttype, uint16_t year, uint8_t month, uint8_t day) {
|
||||
char buffer[12];
|
||||
if (fmttype == fmtDate::GB) {
|
||||
snprintf(buffer, 12, "%02d/%02d/%04d", day , month, year);
|
||||
}
|
||||
else if (fmttype == fmtDate::US) {
|
||||
snprintf(buffer, 12, "%02d/%02d/%04d", month, day, year);
|
||||
}
|
||||
else if (fmttype == fmtDate::ISO) {
|
||||
snprintf(buffer, 12, "%04d-%02d-%02d", year, month, day);
|
||||
}
|
||||
else if (fmttype == fmtDate::DE) {
|
||||
snprintf(buffer, 12, "%02d.%02d.%04d", day, month, year);
|
||||
} else {
|
||||
snprintf(buffer, 12, "%04d-%02d-%02d", year, month, day);
|
||||
}
|
||||
return String(buffer);
|
||||
}
|
||||
|
||||
String formatTime(fmtTime fmttype, uint8_t hour, uint8_t minute, uint8_t second) {
|
||||
char buffer[10];
|
||||
if (fmttype == fmtTime::MMHH) {
|
||||
snprintf(buffer, 10, "%02d:%02d", hour , minute);
|
||||
}
|
||||
else if (fmttype == fmtTime::MMHHSS) {
|
||||
snprintf(buffer, 10, "%02d:%02d:%02d", hour, minute, second);
|
||||
}
|
||||
else {
|
||||
snprintf(buffer, 10, "%02d%02d%02d", hour, minute, second);
|
||||
}
|
||||
return String(buffer);
|
||||
}
|
||||
|
||||
String formatLatitude(double lat) {
|
||||
float degree = abs(int(lat));
|
||||
float minute = abs((lat - int(lat)) * 60);
|
||||
return String(degree, 0) + "\x90 " + String(minute, 4) + "' " + ((lat > 0) ? "N" : "S");
|
||||
}
|
||||
|
||||
String formatLongitude(double lon) {
|
||||
float degree = abs(int(lon));
|
||||
float minute = abs((lon - int(lon)) * 60);
|
||||
return String(degree, 0) + "\x90 " + String(minute, 4) + "' " + ((lon > 0) ? "E" : "W");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#ifndef _OBP60FORMATTER_H
|
||||
#define _OBP60FORMATTER_H
|
||||
|
||||
#include "GwApi.h"
|
||||
#include "Pagedata.h"
|
||||
#include <unordered_map>
|
||||
|
||||
/*
|
||||
|
||||
XDR types
|
||||
A Angular displacement
|
||||
C Temperature
|
||||
D Linear displacement
|
||||
F Frequency
|
||||
G Generic
|
||||
H Humidity
|
||||
I Current
|
||||
L Salinity
|
||||
N Force
|
||||
P Pressure
|
||||
R Flow
|
||||
S Switch or valve
|
||||
T Tachometer
|
||||
U Voltage
|
||||
V Volume
|
||||
|
||||
XDR units
|
||||
A Ampere
|
||||
B Bar
|
||||
C Celsius
|
||||
D Degrees
|
||||
H Hertz
|
||||
I Liter per second?
|
||||
M Meter / Cubic meter
|
||||
N Newton
|
||||
P Percent
|
||||
R RPM
|
||||
V Volt
|
||||
|
||||
*/
|
||||
|
||||
enum class fmtType {
|
||||
// Formatter names as defined in BoatItemBase
|
||||
COURSE,
|
||||
KNOTS,
|
||||
WIND,
|
||||
LATITUDE,
|
||||
LONGITUDE,
|
||||
XTE,
|
||||
FIXED0,
|
||||
DEPTH,
|
||||
DOP, // dilution of precision
|
||||
ROT,
|
||||
DATE,
|
||||
TIME,
|
||||
NAME,
|
||||
|
||||
kelvinToC, // TODO not a format but conversion
|
||||
mtr2nm, // TODO not a format but conversion
|
||||
|
||||
// XDR Formatter names
|
||||
XDR_PP, // pressure percent
|
||||
XDR_PB, // pressure bar
|
||||
XDR_UV, // voltage volt
|
||||
XDR_IA, // current ampere
|
||||
XDR_CK, // temperature kelvin
|
||||
XDR_CC, // temperature celsius
|
||||
XDR_HP, // humidity percent
|
||||
XDR_VP, // volume percent
|
||||
XDR_VM, // volume cubic meters
|
||||
XDR_RI, // flow liter per second?
|
||||
XDR_G, // generic
|
||||
XDR_AP, // angle percent
|
||||
XDR_AD, // angle degrees
|
||||
XDR_TR // tachometer rpm
|
||||
};
|
||||
|
||||
// Hint: String is not supported
|
||||
static std::unordered_map<const char*, fmtType> formatMap PROGMEM = {
|
||||
{"formatCourse", fmtType::COURSE},
|
||||
{"formatKnots", fmtType::KNOTS},
|
||||
{"formatWind", fmtType::WIND},
|
||||
{"formatLatitude", fmtType::LATITUDE},
|
||||
{"formatLongitude", fmtType::LONGITUDE},
|
||||
{"formatXte", fmtType::XTE},
|
||||
{"formatFixed0", fmtType::FIXED0},
|
||||
{"formatDepth", fmtType::DEPTH},
|
||||
{"formatDop", fmtType::DOP},
|
||||
{"formatRot", fmtType::ROT},
|
||||
{"formatDate", fmtType::DATE},
|
||||
{"formatTime", fmtType::TIME},
|
||||
{"formatName", fmtType::NAME},
|
||||
{"kelvinToC", fmtType::kelvinToC},
|
||||
{"mtr2nm", fmtType::mtr2nm},
|
||||
{"formatXdr:P:P", fmtType::XDR_PP},
|
||||
{"formatXdr:P:B", fmtType::XDR_PB},
|
||||
{"formatXdr:U:V", fmtType::XDR_UV},
|
||||
{"formatXdr:I:A", fmtType::XDR_IA},
|
||||
{"formatXdr:C:K", fmtType::XDR_CK},
|
||||
{"formatXdr:C:C", fmtType::XDR_CC},
|
||||
{"formatXdr:H:P", fmtType::XDR_HP},
|
||||
{"formatXdr:V:P", fmtType::XDR_VP},
|
||||
{"formatXdr:V:M", fmtType::XDR_VM},
|
||||
{"formatXdr:R:I", fmtType::XDR_RI},
|
||||
{"formatXdr:G:", fmtType::XDR_G},
|
||||
{"formatXdr:A:P", fmtType::XDR_AP},
|
||||
{"formatXdr:A:D", fmtType::XDR_AD},
|
||||
{"formatXdr:T:R", fmtType::XDR_TR}
|
||||
};
|
||||
|
||||
// Possible formats as scoped enums
|
||||
enum class fmtDate {DE, GB, US, ISO};
|
||||
enum class fmtTime {MMHH, MMHHSS};
|
||||
enum class fmtLength {METER, FEET, FATHOM, CABLE};
|
||||
enum class fmtDepth {METER, FEET, FATHOM};
|
||||
enum class fmtWind {KMH, MS, KN, BFT};
|
||||
enum class fmtCourse {DEG, RAD};
|
||||
enum class fmtRot {DEGS, RADS};
|
||||
enum class fmtXte {M, KM, NM, CABLE};
|
||||
enum class fmtPress {PA, BAR};
|
||||
enum class fmtTemp {KELVIN, CELSUIS, FAHRENHEIT};
|
||||
|
||||
// Conversion factors
|
||||
#define CONV_M_FT 3.2808399 // meter too feet
|
||||
#define CONV_M_FM 0.5468 // meter to fathom
|
||||
#define CONV_M_CBL 0.0053961182483768 // meter to cable
|
||||
#define CONV_CBL_FT 608 // cable to feet
|
||||
#define CONV_FM_FT 6 // fathom to feet
|
||||
|
||||
// Structure for formatted boat values
|
||||
typedef struct {
|
||||
double value; // SI value of boat data value
|
||||
double cvalue; // value converted to target unit
|
||||
String svalue; // value converted to target unit and formatted
|
||||
String unit; // target value unit
|
||||
} FormattedData;
|
||||
|
||||
// Formatter for boat values
|
||||
class Formatter {
|
||||
private:
|
||||
String stimeZone = "0";
|
||||
double timeZone = 0.0; // [UTC -14.00...+12.00]
|
||||
String lengthFormat = "m"; // [m|ft]
|
||||
String distanceFormat = "nm"; // [m|km|nm]
|
||||
String speedFormat = "kn"; // [m/s|km/h|kn]
|
||||
String windspeedFormat = "kn"; // [m/s|km/h|kn|bft]
|
||||
String tempFormat = "C"; // [K|°C|°F]
|
||||
String dateFormat = "ISO"; // [DE|GB|US|ISO]
|
||||
fmtDate dateFmt;
|
||||
bool usesimudata = false; // [on|off]
|
||||
|
||||
String precision = "2"; // [1|2]
|
||||
const char* fmt_dec_1;
|
||||
const char* fmt_dec_10;
|
||||
const char* fmt_dec_100;
|
||||
|
||||
public:
|
||||
Formatter(GwConfigHandler *config);
|
||||
fmtType stringToFormat(const char* formatStr);
|
||||
fmtDate getDateFormat(String sformat);
|
||||
fmtTime getTimeFormat(String sformat);
|
||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool ignoreSimuDataSetting);
|
||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata);
|
||||
double convertValue(const double &value, const String &name, const String &format, CommonData &commondata);
|
||||
double convertValue(const double &value, const String &format, CommonData &commondata);
|
||||
String placeholder = "---";
|
||||
};
|
||||
|
||||
// Standard format functions without class and overhead
|
||||
String formatDate(fmtDate fmttype, uint16_t year, uint8_t month, uint8_t day);
|
||||
String formatTime(fmtTime fmttype, uint8_t hour, uint8_t minute, uint8_t second);
|
||||
String formatLatitude(double lat);
|
||||
String formatLongitude(double lon);
|
||||
|
||||
#endif
|
||||
@@ -1,11 +1,11 @@
|
||||
// General hardware definitions
|
||||
// CAN and RS485 bus pin definitions see obp60task.h
|
||||
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP70S3
|
||||
#if defined HARDWARE_V20 || HARDWARE_V21
|
||||
// Direction pin for RS485 NMEA0183
|
||||
#define OBP_DIRECTION_PIN 18
|
||||
// I2C
|
||||
#define I2C_SPEED 10000UL // 100kHz clock speed on I2C bus
|
||||
#define I2C_SPEED 10000UL // 10kHz clock speed on I2C bus
|
||||
#define I2C_SPEED_LOW 1000UL // 10kHz clock speed on I2C bus for external bus
|
||||
#define OBP_I2C_SDA 47
|
||||
#define OBP_I2C_SCL 21
|
||||
@@ -34,21 +34,15 @@
|
||||
#define PCF8574_I2C_ADDR1 0x20 // First digital out module
|
||||
// FRAM (e.g. MB85RC256V)
|
||||
#define FRAM_I2C_ADDR 0x50
|
||||
// SPI (E-paper display, TFT display Extern Bus)
|
||||
// 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 OBP_TFT_OFFSET_X 10 // ST7796, ILI9488 operating x-offset for centered 400x300 content
|
||||
#define OBP_TFT_OFFSET_Y -20 // ST7796, ILI9488 operating y-offset for centered 400x300 content
|
||||
#define TFT_BLACK 0x0109 // Replacement color for black on TFT (RGB565)
|
||||
#define TFT_WHITE 0xFFFF // Replacement color for white on TFT (RGB565)
|
||||
#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 GxEPD_WIDTH 400 // Display width
|
||||
#define GxEPD_HEIGHT 300 // Display height
|
||||
|
||||
// GPS (NEO-6M, NEO-M8N, ATGM336H)
|
||||
#define OBP_GPS_RX 2
|
||||
@@ -127,8 +121,6 @@
|
||||
#define OBP_SPI_DIN 11
|
||||
#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 GxEPD_WIDTH 400 // Display width
|
||||
#define GxEPD_HEIGHT 300 // Display height
|
||||
// SPI SD-Card
|
||||
#define SD_SPI_CS GPIO_NUM_10
|
||||
#define SD_SPI_MOSI GPIO_NUM_40
|
||||
|
||||
@@ -26,20 +26,20 @@ void qrWiFi(String ssid, String passwd, uint16_t fgcolor, uint16_t bgcolor){
|
||||
// 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, fgcolor);
|
||||
epd->fillRect(box_x, box_y, box_s, box_s, fgcolor);
|
||||
} else {
|
||||
getdisplay().fillRect(box_x, box_y, box_s, box_s, bgcolor);
|
||||
epd->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_Bold32pt8b);
|
||||
getdisplay().setTextColor(fgcolor);
|
||||
getdisplay().setCursor(140, 285);
|
||||
getdisplay().print("WiFi");
|
||||
displayNextPage(); // Full Refresh
|
||||
epd->setFont(&Ubuntu_Bold32pt8b);
|
||||
epd->setTextColor(fgcolor);
|
||||
epd->setCursor(140, 285);
|
||||
epd->print("WiFi");
|
||||
epd->nextPage(); // Full Refresh
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+131
-189
@@ -1,4 +1,6 @@
|
||||
#include "OBP60Formatter.h"
|
||||
#include "OBPDataOperations.h"
|
||||
//#include "BoatDataCalibration.h" // Functions lib for data instance calibration
|
||||
|
||||
// --- Class CalibrationData ---------------
|
||||
CalibrationData::CalibrationData(GwLog* log)
|
||||
@@ -107,6 +109,7 @@ void CalibrationData::readConfig(GwConfigHandler* config)
|
||||
LOG_DEBUG(GwLog::LOG, "Calibration data type added: %s, offset: %f, slope: %f, smoothing: %f", instance.c_str(),
|
||||
calibrationMap[instance].offset, calibrationMap[instance].slope, calibrationMap[instance].smooth);
|
||||
}
|
||||
// LOG_DEBUG(GwLog::LOG, "All calibration data read");
|
||||
}
|
||||
|
||||
// Handle calibrationMap and calibrate all boat data values
|
||||
@@ -153,7 +156,8 @@ bool CalibrationData::calibrateInstance(GwApi::BoatValue* boatDataValue)
|
||||
|
||||
if (format == "formatWind") { // instance is of type angle
|
||||
dataValue = (dataValue * slope) + offset;
|
||||
dataValue = WindUtils::to2PI(dataValue); // wind angle data is stored in [0..2PI] format
|
||||
// dataValue = WindUtils::toPI(dataValue);
|
||||
dataValue = WindUtils::to2PI(dataValue); // we should call <toPI> for format of [-180..180], but pages cannot display negative values properly yet
|
||||
|
||||
} else if (format == "formatCourse") { // instance is of type direction
|
||||
dataValue = (dataValue * slope) + offset;
|
||||
@@ -166,6 +170,7 @@ bool CalibrationData::calibrateInstance(GwApi::BoatValue* boatDataValue)
|
||||
dataValue = (dataValue * slope) + offset;
|
||||
}
|
||||
|
||||
|
||||
boatDataValue->value = dataValue; // update boat data value with calibrated value
|
||||
calibrationMap[instance].value = dataValue; // store the calibrated value in the list
|
||||
calibrationMap[instance].isCalibrated = true;
|
||||
@@ -207,107 +212,108 @@ bool CalibrationData::smoothInstance(GwApi::BoatValue* boatDataValue)
|
||||
calibrationMap[instance].value = dataValue; // store the smoothed value in the list
|
||||
calibrationMap[instance].isCalibrated = true;
|
||||
|
||||
// LOG_DEBUG(GwLog::DEBUG, "BoatDataCalibration: %s: smooth: %f, oldValue: %f, result: %f", instance.c_str(), smoothFactor, oldValue, calibrationMap[instance].value);
|
||||
|
||||
return true;
|
||||
}
|
||||
// --- End Class CalibrationData ---------------
|
||||
|
||||
// --- Class HstryBuf ---------------
|
||||
HstryBuf::HstryBuf(const String& name, const int size, BoatValueList* boatValues, const bool smooth, GwLog* log)
|
||||
HstryBuf::HstryBuf(const String& name, int size, BoatValueList* boatValues, GwLog* log)
|
||||
: logger(log)
|
||||
, smoothing(smooth)
|
||||
, boatDataName(name)
|
||||
{
|
||||
hstryBuf.resize(size);
|
||||
boatValue = boatValues->findValueOrCreate(name);
|
||||
}
|
||||
|
||||
void HstryBuf::init(const String& format, int updFreq, double mltplr, double minVal, double maxVal)
|
||||
void HstryBuf::init(const String& format, int updFreq, int mltplr, double minVal, double maxVal)
|
||||
{
|
||||
hstryBuf.setMetaData(boatDataName, format, updFreq, mltplr, minVal, maxVal);
|
||||
hstryMin = minVal;
|
||||
hstryMax = maxVal;
|
||||
bufUpdateTime = 0;
|
||||
if (!boatValue->valid) {
|
||||
boatValue->setFormat(format);
|
||||
boatValue->value = std::numeric_limits<double>::max(); // mark current value invalid
|
||||
}
|
||||
|
||||
isTypeAngle = format == "formatCourse" || format == "formatWind" || format == "formatRot";
|
||||
// initialize correct variant of buffer for averaging history data
|
||||
if (smoothing) {
|
||||
if (isTypeAngle) {
|
||||
chrtAvgAngle.begin();
|
||||
} else {
|
||||
chrtAvg.begin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HstryBuf::add(const double value)
|
||||
void HstryBuf::add(double value)
|
||||
{
|
||||
double bufVal = value;
|
||||
|
||||
if (value >= hstryMin && value <= hstryMax) {
|
||||
|
||||
if (smoothing) {
|
||||
if (isTypeAngle) {
|
||||
bufVal = chrtAvgAngle.reading(value);
|
||||
} else {
|
||||
bufVal = chrtAvg.reading(value);
|
||||
hstryBuf.add(value);
|
||||
// LOG_DEBUG(GwLog::DEBUG, "HstryBuf::add: name: %s, value: %.3f", hstryBuf.getName(), value);
|
||||
}
|
||||
}
|
||||
|
||||
hstryBuf.add(bufVal);
|
||||
// LOG_DEBUG(GwLog::DEBUG, "HstryBuf::add: name: %s, value: %.3f, value buffer: %.3f", hstryBuf.getName(), value, hstryBuf.getLast());
|
||||
}
|
||||
}
|
||||
|
||||
void HstryBuf::handle(const bool useSimuData, CommonData& common)
|
||||
void HstryBuf::handle(bool useSimuData, CommonData& common)
|
||||
{
|
||||
if ((millis() - bufUpdateTime) >= hstryBuf.getUpdFreq()) {
|
||||
|
||||
bufUpdateTime = millis();
|
||||
|
||||
if (boatValue->valid) {
|
||||
add(boatValue->value);
|
||||
|
||||
} else if (useSimuData) { // add simulated value to history buffer
|
||||
// GwApi::BoatValue* tmpBVal;
|
||||
std::unique_ptr<GwApi::BoatValue> tmpBVal; // Temp variable to get formatted and converted data value from OBP60Formatter
|
||||
tmpBVal = std::unique_ptr<GwApi::BoatValue>(new GwApi::BoatValue(boatDataName)); // create temporary boat value for retrieval of simulation value
|
||||
|
||||
// create temporary boat value for calibration purposes and retrieval of simulation value
|
||||
// tmpBVal = new GwApi::BoatValue(boatDataName.c_str());
|
||||
tmpBVal = std::unique_ptr<GwApi::BoatValue>(new GwApi::BoatValue(boatDataName));
|
||||
tmpBVal->setFormat(boatValue->getFormat());
|
||||
tmpBVal->value = boatValue->value;
|
||||
tmpBVal->valid = boatValue->valid;
|
||||
double simSIValue = formatValue(tmpBVal.get(), common).value; // simulated value is generated at <formatValue>; here: retreive SI value
|
||||
|
||||
if (boatValue->valid) {
|
||||
// Calibrate boat value before adding it to history buffer
|
||||
//calibrationData.calibrateInstance(tmpBVal.get(), logger);
|
||||
//add(tmpBVal->value);
|
||||
add(boatValue->value);
|
||||
|
||||
} else if (useSimuData) { // add simulated value to history buffer
|
||||
double simSIValue = common.fmt->formatValue(tmpBVal.get(), common).value; // simulated value is generated at <formatValue>; here: retreive SI value
|
||||
add(simSIValue);
|
||||
} else {
|
||||
// TODO: add invalid (DBL_MAX) value; this will mark periods of missing data in buffer together with a timestamp
|
||||
}
|
||||
// here we will add invalid (DBL_MAX) value; this will mark periods of missing data in buffer together with a timestamp
|
||||
}
|
||||
}
|
||||
// --- End Class HstryBuf ---------------
|
||||
|
||||
// --- Class HstryBuffers ---------------
|
||||
HstryBuffers::HstryBuffers(const int size, BoatValueList* boatValues, GwLog* log)
|
||||
HstryBuffers::HstryBuffers(int size, BoatValueList* boatValues, GwLog* log)
|
||||
: size(size)
|
||||
, boatValueList(boatValues)
|
||||
, logger(log) { };
|
||||
, logger(log)
|
||||
{
|
||||
|
||||
// collect boat values for true wind calculation
|
||||
// should all have been already created at true wind object initialization
|
||||
// potentially to be moved to history buffer handling
|
||||
awaBVal = boatValueList->findValueOrCreate("AWA");
|
||||
hdtBVal = boatValueList->findValueOrCreate("HDT");
|
||||
hdmBVal = boatValueList->findValueOrCreate("HDM");
|
||||
varBVal = boatValueList->findValueOrCreate("VAR");
|
||||
cogBVal = boatValueList->findValueOrCreate("COG");
|
||||
sogBVal = boatValueList->findValueOrCreate("SOG");
|
||||
awdBVal = boatValueList->findValueOrCreate("AWD");
|
||||
}
|
||||
|
||||
// Create history buffer for boat data type
|
||||
void HstryBuffers::addBuffer(const String& name, const bool smooth)
|
||||
void HstryBuffers::addBuffer(const String& name)
|
||||
{
|
||||
if (HstryBuffers::getBuffer(name) != nullptr) { // buffer for this data type already exists
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = bufferParams.find(name);
|
||||
if (it == bufferParams.end() && !name.startsWith("xdr")) { // requested boat data type is not supported in list of <bufferParams>
|
||||
// we take any "XDR" type, though
|
||||
if (bufferParams.find(name) == bufferParams.end()) { // requested boat data type is not supported in list of <bufferParams>
|
||||
return;
|
||||
}
|
||||
|
||||
// create buffer only; initialization with metadata can only be done later after boat data have been updated first time
|
||||
hstryBuffers[name] = std::unique_ptr<HstryBuf>(new HstryBuf(name, size, boatValueList, smooth, logger));
|
||||
hstryBuffers[name] = std::unique_ptr<HstryBuf>(new HstryBuf(name, size, boatValueList, logger));
|
||||
|
||||
LOG_DEBUG(GwLog::LOG, "HstryBuffers: new buffer added: name: %s", name);
|
||||
// Initialize metadata for buffer
|
||||
String valueFormat = bufferParams[name].format; // Data format of boat data type
|
||||
// String valueFormat = boatValueList->findValueOrCreate(name)->getFormat().c_str(); // Unfortunately, format is not yet available during system initialization
|
||||
int hstryUpdFreq = bufferParams[name].hstryUpdFreq; // Update frequency for history buffers in ms
|
||||
int mltplr = bufferParams[name].mltplr; // default multiplier which transforms original <double> value into buffer type format
|
||||
double bufferMinVal = bufferParams[name].bufferMinVal; // Min value for this history buffer
|
||||
double bufferMaxVal = bufferParams[name].bufferMaxVal; // Max value for this history buffer
|
||||
|
||||
hstryBuffers[name]->init(valueFormat, hstryUpdFreq, mltplr, bufferMinVal, bufferMaxVal);
|
||||
LOG_DEBUG(GwLog::DEBUG, "HstryBuffers: new buffer added: name: %s, format: %s, multiplier: %d, min value: %.2f, max value: %.2f", name, valueFormat, mltplr, bufferMinVal, bufferMaxVal);
|
||||
}
|
||||
|
||||
// Handle all registered history buffers
|
||||
@@ -315,35 +321,6 @@ void HstryBuffers::handleHstryBufs(bool useSimuData, CommonData& common)
|
||||
{
|
||||
for (auto& bufMap : hstryBuffers) {
|
||||
auto& buf = bufMap.second;
|
||||
|
||||
if (!buf->hasMetaData()) { // meta data initialization for buffer has not been done before
|
||||
|
||||
String valueFormat = boatValueList->findValueOrCreate(buf->boatDataName)->getFormat().c_str();
|
||||
// LOG_DEBUG(GwLog::DEBUG, "HstryBuffers: value name: %s, format: %s", boatValueList->findValueOrCreate(buf->boatDataName)->getName().c_str(), valueFormat);
|
||||
|
||||
if (!valueFormat.isEmpty()) {
|
||||
String lookupKey = buf->boatDataName;
|
||||
if (buf->boatDataName.startsWith("xdr")) { // current boat data is of type "XDR"
|
||||
lookupKey = valueFormat;
|
||||
}
|
||||
auto it = bufferParams.find(lookupKey);
|
||||
if (it == bufferParams.end()) { // requested boat data type is not supported in list of <bufferParams>
|
||||
return;
|
||||
}
|
||||
HistoryParams params = it->second; // this is the metadata for the new buffer
|
||||
|
||||
int hstryUpdFreq = params.hstryUpdFreq; // Update frequency for history buffers in ms
|
||||
double mltplr = params.mltplr; // default multiplier which transforms original <double> value into buffer type format
|
||||
double bufferMinVal = params.bufferMinVal; // Min value for this history buffer
|
||||
double bufferMaxVal = params.bufferMaxVal; // Max value for this history buffer
|
||||
|
||||
hstryBuffers[buf->boatDataName]->init(valueFormat, hstryUpdFreq, mltplr, bufferMinVal, bufferMaxVal);
|
||||
buf->metaDataDefined = true;
|
||||
LOG_DEBUG(GwLog::LOG, "HstryBuffers::handleBufs: metadata added: name: %s, format: %s, frequency: %d, multiplier: %f, min value: %.2f, max value: %.2f", buf->boatDataName, valueFormat, hstryUpdFreq,
|
||||
mltplr, bufferMinVal, bufferMaxVal);
|
||||
}
|
||||
}
|
||||
|
||||
buf->handle(useSimuData, common);
|
||||
}
|
||||
}
|
||||
@@ -353,9 +330,8 @@ RingBuffer<uint16_t>* HstryBuffers::getBuffer(const String& name)
|
||||
auto it = hstryBuffers.find(name);
|
||||
if (it != hstryBuffers.end()) {
|
||||
return &it->second->hstryBuf;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
// --- End Class HstryBuffers ---------------
|
||||
|
||||
@@ -421,73 +397,56 @@ void WindUtils::addPolar(const double* phi1, const double* r1,
|
||||
toPol(&x1, &y1, phi, r);
|
||||
}
|
||||
|
||||
void WindUtils::calcTwdSA(const double* AWA, const double* AWS, const double* AWD, const double* CTW, const double* STW, const double* HDT,
|
||||
double* TWA, double* TWS, double* TWD)
|
||||
void WindUtils::calcTwdSA(const double* AWA, const double* AWS,
|
||||
const double* CTW, const double* STW, const double* HDT,
|
||||
double* TWD, double* TWS, double* TWA, double* AWD)
|
||||
{
|
||||
*AWD = *AWA + *HDT;
|
||||
*AWD = to2PI(*AWD);
|
||||
double stw = -*STW;
|
||||
addPolar(AWD, AWS, CTW, &stw, TWD, TWS);
|
||||
|
||||
// Normalize to [0..2PI]
|
||||
// Normalize TWD to [0..360°] (2PI) and TWA to [-180..180] (PI)
|
||||
*TWD = to2PI(*TWD);
|
||||
*TWA = to2PI(*TWD - *HDT); // for internal storage we normalize wind angle to [0..2PI], as well
|
||||
*TWA = toPI(*TWD - *HDT);
|
||||
}
|
||||
|
||||
// calculate HDT from either HDM + VAR, HDM only, or COG
|
||||
bool WindUtils::calcHDT(const double* hdmVal, const double* varVal, const double* cogVal, const double* sogVal, double* hdtVal)
|
||||
double WindUtils::calcHDT(const double* hdmVal, const double* varVal, const double* cogVal, const double* sogVal)
|
||||
{
|
||||
double hdt;
|
||||
double minSogVal = 0.1; // SOG below this value (m/s) is assumed to be data noise from GPS sensor
|
||||
|
||||
if (*hdmVal != DBL_MAX) {
|
||||
hdt = *hdmVal + (*varVal != DBL_MAX ? *varVal : 0.0); // Use corrected HDM if HDT is not available (or just HDM if VAR is not available)
|
||||
hdt = to2PI(hdt);
|
||||
} else if (*cogVal != DBL_MAX && *sogVal >= minSogVal) {
|
||||
hdt = *cogVal; // Use COG as fallback if HDT and HDM are not available, and SOG is not data noise
|
||||
} else {
|
||||
hdt = DBL_MAX; // Cannot calculate HDT without valid HDM or HDM+VAR or COG
|
||||
}
|
||||
|
||||
return hdt;
|
||||
}
|
||||
|
||||
bool WindUtils::calcWinds(const double* awaVal, const double* awsVal,
|
||||
const double* cogVal, const double* stwVal, const double* sogVal, const double* hdtVal,
|
||||
const double* hdmVal, const double* varVal, double* twdVal, double* twsVal, double* twaVal, double* awdVal)
|
||||
{
|
||||
double stw, hdt, ctw;
|
||||
double twd, tws, twa, awd;
|
||||
double minSogVal = 0.1; // SOG below this value (m/s) is assumed to be data noise from GPS sensor
|
||||
|
||||
if (*hdtVal != DBL_MAX) {
|
||||
// HDT already available-> nothing to do
|
||||
return true;
|
||||
}
|
||||
|
||||
if (*hdmVal != DBL_MAX) {
|
||||
*hdtVal = *hdmVal + (*varVal != DBL_MAX ? *varVal : 0.0); // Use corrected HDM if HDT is not available (or just HDM if VAR is not available)
|
||||
*hdtVal = to2PI(*hdtVal);
|
||||
} else if (*cogVal != DBL_MAX && *sogVal >= minSogVal) {
|
||||
*hdtVal = *cogVal; // Use COG as fallback if HDT and HDM are not available, and SOG is not data noise
|
||||
hdt = *hdtVal; // Use HDT if available
|
||||
} else {
|
||||
*hdtVal = DBL_MAX; // Cannot calculate HDT without valid HDM or HDM+VAR or COG
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// calculate wind direction (either TWD or AWD) from wind angle (TWA or AWA) and HDT
|
||||
bool WindUtils::calcWD(const double* waVal, const double* hdtVal, double* wdVal)
|
||||
{
|
||||
if (*waVal != DBL_MAX && *hdtVal != DBL_MAX) {
|
||||
*wdVal = *waVal + *hdtVal;
|
||||
*wdVal = to2PI(*wdVal);
|
||||
} else {
|
||||
*wdVal = DBL_MAX; // Cannot calculate wind direction WD without valid wind angle WA and HDT
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// calculate full set of true winds (TWA, TWS, TWD) apparent winds and more data
|
||||
bool WindUtils::calcTrueWinds(const double* awaVal, const double* awsVal, const double* awd,
|
||||
const double* cogVal, const double* stwVal, const double* sogVal, const double* hdtVal,
|
||||
double* twaVal, double* twsVal, double* twdVal)
|
||||
{
|
||||
double stw, ctw;
|
||||
double twd, tws, twa;
|
||||
double minSogVal = 0.1; // SOG below this value (m/s) is assumed to be data noise from GPS sensor
|
||||
|
||||
if ((*awaVal == DBL_MAX) || (*awsVal == DBL_MAX)) {
|
||||
// Cannot calculate true winds at all without valid AWA, AWS
|
||||
return false;
|
||||
hdt = calcHDT(hdmVal, varVal, cogVal, sogVal);
|
||||
}
|
||||
|
||||
if (*cogVal != DBL_MAX && *sogVal >= minSogVal) { // if SOG is data noise, we don't trust COG
|
||||
|
||||
ctw = *cogVal; // Use COG for CTW if available
|
||||
} else {
|
||||
ctw = *hdtVal; // 2nd approximation for CTW; HDT must exist if we reach this part of code
|
||||
ctw = hdt; // 2nd approximation for CTW; hdt must exist if we reach this part of the code
|
||||
}
|
||||
|
||||
if (*stwVal != DBL_MAX) {
|
||||
@@ -498,34 +457,28 @@ bool WindUtils::calcTrueWinds(const double* awaVal, const double* awsVal, const
|
||||
// If STW and SOG are not available, we cannot calculate true wind
|
||||
return false;
|
||||
}
|
||||
// LOG_DEBUG(GwLog::DEBUG, "WindUtils:calcWinds: HDT: %.1f, CTW %.1f, STW %.1f", hdt, ctw, stw);
|
||||
|
||||
calcTwdSA(awaVal, awsVal, awd, &ctw, &stw, hdtVal, &twa, &tws, &twd);
|
||||
*twaVal = twa;
|
||||
*twsVal = tws;
|
||||
if ((*awaVal == DBL_MAX) || (*awsVal == DBL_MAX)) {
|
||||
// Cannot calculate true wind without valid AWA, AWS; other checks are done earlier
|
||||
return false;
|
||||
} else {
|
||||
calcTwdSA(awaVal, awsVal, &ctw, &stw, &hdt, &twd, &tws, &twa, &awd);
|
||||
*twdVal = twd;
|
||||
*twsVal = tws;
|
||||
*twaVal = twa;
|
||||
*awdVal = awd;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set max wind speed
|
||||
void WindUtils::setMaxWs(GwApi::BoatValue* wsMaxValue, const double* wsVal)
|
||||
{
|
||||
static double maxWs = 0.0; // maintain own maxTWS value in obp user task; core gateway would reset MaxTWS obp boat value if true wind data is not available
|
||||
|
||||
if (*wsVal != DBL_MAX && *wsVal > maxWs) {
|
||||
maxWs = *wsVal;
|
||||
}
|
||||
|
||||
if (maxWs > 0.0 && maxWs >= wsMaxValue->value) {
|
||||
wsMaxValue->value = maxWs; // overwrite core gateway value each second again with own user task value if that value is larger
|
||||
wsMaxValue->valid = true;
|
||||
}
|
||||
};
|
||||
|
||||
// Calculate true wind data and add to obp60task boat data list
|
||||
bool WindUtils::handleWinds(bool calcWinds)
|
||||
bool WindUtils::addWinds()
|
||||
{
|
||||
double twd, tws, twa, awd, hdt;
|
||||
bool twCalculated = false;
|
||||
bool awdCalculated = false;
|
||||
|
||||
double awaVal = awaBVal->valid ? awaBVal->value : DBL_MAX;
|
||||
double awsVal = awsBVal->valid ? awsBVal->value : DBL_MAX;
|
||||
@@ -535,60 +488,49 @@ bool WindUtils::handleWinds(bool calcWinds)
|
||||
double hdtVal = hdtBVal->valid ? hdtBVal->value : DBL_MAX;
|
||||
double hdmVal = hdmBVal->valid ? hdmBVal->value : DBL_MAX;
|
||||
double varVal = varBVal->valid ? varBVal->value : DBL_MAX;
|
||||
double twaVal = twaBVal->valid ? twaBVal->value : DBL_MAX;
|
||||
double twsVal = twsBVal->valid ? twsBVal->value : DBL_MAX;
|
||||
//LOG_DEBUG(GwLog::DEBUG, "WindUtils:addWinds: AWA %.1f, AWS %.1f, COG %.1f, STW %.1f, SOG %.2f, HDT %.1f, HDM %.1f, VAR %.1f", awaBVal->value * RAD_TO_DEG, awsBVal->value * 3.6 / 1.852,
|
||||
// cogBVal->value * RAD_TO_DEG, stwBVal->value * 3.6 / 1.852, sogBVal->value * 3.6 / 1.852, hdtBVal->value * RAD_TO_DEG, hdmBVal->value * RAD_TO_DEG, varBVal->value * RAD_TO_DEG);
|
||||
|
||||
if (calcHDT(&hdmVal, &varVal, &cogVal, &sogVal, &hdtVal)) {
|
||||
hdtBVal->value = hdtVal;
|
||||
hdtBVal->valid = true;
|
||||
} else {
|
||||
// determination of HDT was not possible due to missing prerequisite data
|
||||
hdtBVal->valid = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// calculate AWD if it does not exist yet and AWA is available
|
||||
if (!awdBVal->valid) {
|
||||
if (calcWD(&awaVal, &hdtVal, &awd)) {
|
||||
awdBVal->value = awd;
|
||||
awdBVal->valid = true;
|
||||
} else {
|
||||
awdBVal->valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate TWD if it does not exist yet and TWA is available
|
||||
// Check if TWD can be calculated from TWA and HDT/HDM
|
||||
if (twaBVal->valid) {
|
||||
if (!twdBVal->valid) {
|
||||
if (calcWD(&twaVal, &hdtVal, &twd)) {
|
||||
if (hdtVal != DBL_MAX) {
|
||||
hdt = hdtVal; // Use HDT if available
|
||||
} else {
|
||||
hdt = calcHDT(&hdmVal, &varVal, &cogVal, &sogVal);
|
||||
}
|
||||
twd = twaBVal->value + hdt;
|
||||
twd = to2PI(twd);
|
||||
twdBVal->value = twd;
|
||||
twdBVal->valid = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
twdBVal->valid = false;
|
||||
}
|
||||
}
|
||||
// Calculate true winds and AWD; if true winds exist, use at least AWD calculation
|
||||
twCalculated = calcWinds(&awaVal, &awsVal, &cogVal, &stwVal, &sogVal, &hdtVal, &hdmVal, &varVal, &twd, &tws, &twa, &awd);
|
||||
|
||||
if (!calcWinds) { // don't calculate true winds from apparent winds if not set in configuration
|
||||
return twCalculated;
|
||||
}
|
||||
|
||||
if (!twaBVal->valid || !twsBVal->valid || !twdBVal->valid) {
|
||||
// calculate true winds at least one of three true wind values does not exist
|
||||
twCalculated = calcTrueWinds(&awaVal, &awsVal, &awd, &cogVal, &stwVal, &sogVal, &hdtVal, &twa, &tws, &twd);
|
||||
if (twCalculated) { // Replace values only, if successfully calculated and not already available
|
||||
if (!twaBVal->valid) {
|
||||
twaBVal->value = twa;
|
||||
twaBVal->valid = true;
|
||||
if (!twdBVal->valid) {
|
||||
twdBVal->value = twd;
|
||||
twdBVal->valid = true;
|
||||
}
|
||||
if (!twsBVal->valid) {
|
||||
twsBVal->value = tws;
|
||||
twsBVal->valid = true;
|
||||
}
|
||||
if (!twdBVal->valid) {
|
||||
twdBVal->value = twd;
|
||||
twdBVal->valid = true;
|
||||
if (!twaBVal->valid) {
|
||||
//twaBVal->value = twa;
|
||||
twaBVal->value = to2PI(twa); // convert to [0..360], because pages cannot display negative values properly yet
|
||||
twaBVal->valid = true;
|
||||
}
|
||||
if (!awdBVal->valid) {
|
||||
awdBVal->value = awd;
|
||||
awdBVal->valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// LOG_DEBUG(GwLog::DEBUG, "WindUtils:addWinds: twCalculated %d, TWD %.1f, TWA %.1f, TWS %.2f kn, AWD: %.1f", twCalculated, twdBVal->value * RAD_TO_DEG,
|
||||
// twaBVal->value * RAD_TO_DEG, twsBVal->value * 3.6 / 1.852, awdBVal->value * RAD_TO_DEG);
|
||||
|
||||
return twCalculated;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "OBPRingBuffer.h"
|
||||
#include "Pagedata.h"
|
||||
#include "obp60task.h"
|
||||
#include "movingAvg.h"
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -20,7 +19,7 @@ private:
|
||||
} tCalibrationData;
|
||||
|
||||
std::unordered_map<std::string, tCalibrationData> calibrationMap; // list of calibration data instances
|
||||
std::unordered_map<std::string, double> lastValue; // array for last smoothed value of boat data values
|
||||
std::unordered_map<std::string, double> lastValue; // array for last smoothed values of boat data values
|
||||
GwLog* logger;
|
||||
|
||||
static constexpr int8_t MAX_CALIBRATION_DATA = 4; // maximum number of calibration data instances
|
||||
@@ -33,138 +32,108 @@ public:
|
||||
bool smoothInstance(GwApi::BoatValue* boatDataValue); // Smooth single boat data value
|
||||
};
|
||||
|
||||
// Class for a single history buffer of boat values
|
||||
class HstryBuf {
|
||||
private:
|
||||
RingBuffer<uint16_t> hstryBuf; // Circular buffer to store history values
|
||||
movingAvg<double> chrtAvg {6}; // Store average of the last 6 chart values if chart gradient shall be smoothed
|
||||
movingAvgAngle<double> chrtAvgAngle {6}; // Store average of the last 6 chart values (angle data) if chart gradient shall be smoothed
|
||||
String boatDataName;
|
||||
double hstryMin;
|
||||
double hstryMax;
|
||||
bool metaDataDefined = false;
|
||||
bool smoothing = false;
|
||||
bool isTypeAngle = false;
|
||||
unsigned long bufUpdateTime;
|
||||
GwApi::BoatValue* boatValue;
|
||||
GwLog* logger;
|
||||
|
||||
friend class HstryBuffers;
|
||||
|
||||
public:
|
||||
HstryBuf(const String& name, const int size, BoatValueList* boatValues, const bool smooth, GwLog* log);
|
||||
bool hasMetaData() const { return metaDataDefined; };
|
||||
void init(const String& format, int updFreq, double mltplr, double minVal, double maxVal);
|
||||
HstryBuf(const String& name, int size, BoatValueList* boatValues, GwLog* log);
|
||||
void init(const String& format, int updFreq, int mltplr, double minVal, double maxVal);
|
||||
void add(double value);
|
||||
void handle(bool useSimuData, CommonData& common);
|
||||
};
|
||||
|
||||
// Manage list of history buffers for supported boat data; used by boat data charts
|
||||
class HstryBuffers {
|
||||
private:
|
||||
std::map<String, std::unique_ptr<HstryBuf>> hstryBuffers;
|
||||
int size; // size of all history buffers
|
||||
BoatValueList* boatValueList;
|
||||
GwLog* logger;
|
||||
GwApi::BoatValue *awaBVal, *hdtBVal, *hdmBVal, *varBVal, *cogBVal, *sogBVal, *awdBVal; // boat values for true wind calculation
|
||||
|
||||
struct HistoryParams {
|
||||
int hstryUpdFreq; // update frequency of history buffer (documentation only)
|
||||
double mltplr; // specifies actual value precision being storable:
|
||||
// [10000: 0 - 6.5535 | 1000: 0 - 65.535 | 100: 0 - 655.35 | 10: 0 - 6553.5 | 1: 0 - 65535 | 0.1: 0 - 655350]
|
||||
int mltplr; // specifies actual value precision being storable:
|
||||
// [10000: 0 - 6.5535 | 1000: 0 - 65.535 | 100: 0 - 650.35 | 10: 0 - 6503.5
|
||||
double bufferMinVal; // minimum valid data value
|
||||
double bufferMaxVal; // maximum valid data value
|
||||
String format; // format of data type
|
||||
};
|
||||
|
||||
// Define buffer parameters for supported boat data type
|
||||
std::map<String, HistoryParams> bufferParams = {
|
||||
{ "AWA", { 1000, 10000, 0.0, M_TWOPI } },
|
||||
{ "AWD", { 1000, 10000, 0.0, M_TWOPI } },
|
||||
{ "AWS", { 1000, 1000, 0.0, 65.0 } },
|
||||
{ "COG", { 1000, 10000, 0.0, M_TWOPI } },
|
||||
{ "DBK", { 1000, 100, 0.0, 650.0 } },
|
||||
{ "DBS", { 1000, 100, 0.0, 650.0 } },
|
||||
{ "DBT", { 1000, 100, 0.0, 650.0 } },
|
||||
{ "DPT", { 1000, 100, 0.0, 650.0 } },
|
||||
{ "HDM", { 1000, 10000, 0.0, M_TWOPI } },
|
||||
{ "HDT", { 1000, 10000, 0.0, M_TWOPI } },
|
||||
{ "ROT", { 1000, 10000, -M_PI / 180.0 * 99.0, M_PI / 180.0 * 99.0 } }, // min/max is -/+ 99 degrees for "rate of turn"
|
||||
{ "SOG", { 1000, 1000, 0.0, 65.0 } },
|
||||
{ "STW", { 1000, 1000, 0.0, 65.0 } },
|
||||
{ "TWA", { 1000, 10000, 0.0, M_TWOPI } },
|
||||
{ "TWD", { 1000, 10000, 0.0, M_TWOPI } },
|
||||
{ "TWS", { 1000, 1000, 0.0, 65.0 } },
|
||||
{ "WTemp", { 1000, 100, 263.15, 403.15 } }, // water temp [-10..130] °C
|
||||
{ "formatXdr:C:K", { 1000, 100, 223.15, 423.15 } }, // temperature [-50..150] deg celsius
|
||||
{ "formatXdr:P:B", { 60000, 1000, 0, 65.0 } }, // pressure [0..65] bar
|
||||
{ "formatXdr:P:P", { 60000, 0.1, 0, 650000 } }, // pressure [0..6500] hPa
|
||||
{ "formatXdr:H:P", { 1000, 100, 0, 100 } }, // humidity [0..100] percent
|
||||
{ "formatXdr:I:A", { 1000, 100, 0, 650.0 } }, // current [0..650] amperes
|
||||
{ "formatXdr:U:V", { 1000, 1000, 0, 65.0 } }, // voltage [0..65] volts
|
||||
{ "formatXdr:T:R", { 1000, 1, 0, 30000 } }, // tachometer [0..30000] rpm
|
||||
{ "formatXdr:V:L", { 10000, 100, 0, 650 } }, // volume [0..650] litres
|
||||
{ "formatXdr:V:M", { 10000, 10000, 0, 6.50 } }, // volume [0..6.5] m^3
|
||||
{ "AWA", { 1000, 10000, 0.0, M_TWOPI, "formatWind" } },
|
||||
{ "AWD", { 1000, 10000, 0.0, M_TWOPI, "formatCourse" } },
|
||||
{ "AWS", { 1000, 1000, 0.0, 65.0, "formatKnots" } },
|
||||
{ "COG", { 1000, 10000, 0.0, M_TWOPI, "formatCourse" } },
|
||||
{ "DBS", { 1000, 100, 0.0, 650.0, "formatDepth" } },
|
||||
{ "DBT", { 1000, 100, 0.0, 650.0, "formatDepth" } },
|
||||
{ "DPT", { 1000, 100, 0.0, 650.0, "formatDepth" } },
|
||||
{ "HDM", { 1000, 10000, 0.0, M_TWOPI, "formatCourse" } },
|
||||
{ "HDT", { 1000, 10000, 0.0, M_TWOPI, "formatCourse" } },
|
||||
{ "ROT", { 1000, 10000, -M_PI / 180.0 * 99.0, M_PI / 180.0 * 99.0, "formatRot" } }, // min/max is -/+ 99 degrees for "rate of turn"
|
||||
{ "SOG", { 1000, 1000, 0.0, 65.0, "formatKnots" } },
|
||||
{ "STW", { 1000, 1000, 0.0, 65.0, "formatKnots" } },
|
||||
{ "TWA", { 1000, 10000, 0.0, M_TWOPI, "formatWind" } },
|
||||
{ "TWD", { 1000, 10000, 0.0, M_TWOPI, "formatCourse" } },
|
||||
{ "TWS", { 1000, 1000, 0.0, 65.0, "formatKnots" } },
|
||||
{ "WTemp", { 1000, 100, 233.0, 650.0, "kelvinToC" } } // [-50..376] °C
|
||||
};
|
||||
|
||||
public:
|
||||
HstryBuffers(int size, BoatValueList* boatValues, GwLog* log);
|
||||
void addBuffer(const String& name, const bool smooth);
|
||||
void addBuffer(const String& name);
|
||||
void handleHstryBufs(bool useSimuData, CommonData& common);
|
||||
RingBuffer<uint16_t>* getBuffer(const String& name);
|
||||
};
|
||||
|
||||
class WindUtils {
|
||||
private:
|
||||
GwApi::BoatValue *twaBVal, *twsBVal, *twdBVal, *maxtwsBVal;
|
||||
GwApi::BoatValue *awaBVal, *awsBVal, *awdBVal;
|
||||
GwApi::BoatValue *cogBVal, *stwBVal, *sogBVal, *hdtBVal, *hdmBVal, *varBVal;
|
||||
double twd, tws, twa, awd;
|
||||
GwApi::BoatValue *twaBVal, *twsBVal, *twdBVal;
|
||||
GwApi::BoatValue *awaBVal, *awsBVal, *awdBVal, *cogBVal, *stwBVal, *sogBVal, *hdtBVal, *hdmBVal, *varBVal;
|
||||
static constexpr double DBL_MAX = std::numeric_limits<double>::max();
|
||||
GwLog* logger;
|
||||
|
||||
// specify missing data for boat value type AWD; AWD is not available in core gateway and need to be specified here
|
||||
void defineAWD() {
|
||||
awdBVal->setFormat("formatCourse");
|
||||
awdBVal->valid = false;
|
||||
}
|
||||
|
||||
public:
|
||||
WindUtils(BoatValueList* boatValues, GwLog* log)
|
||||
: logger(log)
|
||||
{
|
||||
twaBVal = boatValues->findValueOrCreate("TWA");
|
||||
twsBVal = boatValues->findValueOrCreate("TWS");
|
||||
maxtwsBVal = boatValues->findValueOrCreate("MaxTws");
|
||||
twdBVal = boatValues->findValueOrCreate("TWD");
|
||||
awaBVal = boatValues->findValueOrCreate("AWA");
|
||||
awsBVal = boatValues->findValueOrCreate("AWS");
|
||||
awdBVal = boatValues->findValueOrCreate("AWD");
|
||||
cogBVal = boatValues->findValueOrCreate("COG");
|
||||
stwBVal = boatValues->findValueOrCreate("STW");
|
||||
sogBVal = boatValues->findValueOrCreate("SOG");
|
||||
hdtBVal = boatValues->findValueOrCreate("HDT");
|
||||
hdmBVal = boatValues->findValueOrCreate("HDM");
|
||||
varBVal = boatValues->findValueOrCreate("VAR");
|
||||
|
||||
awdBVal = boatValues->findValueOrCreate("AWD");
|
||||
defineAWD();
|
||||
};
|
||||
|
||||
static double to2PI(double a);
|
||||
static double toPI(double a);
|
||||
static double to360(double a);
|
||||
static double to180(double a);
|
||||
|
||||
void toCart(const double* phi, const double* r, double* x, double* y);
|
||||
void toPol(const double* x, const double* y, double* phi, double* r);
|
||||
void addPolar(const double* phi1, const double* r1,
|
||||
const double* phi2, const double* r2,
|
||||
double* phi, double* r);
|
||||
void calcTwdSA(const double* AWA, const double* AWS, const double* AWD, const double* CTW, const double* STW, const double* HDT,
|
||||
double* TWA, double* TWS, double* TWD);
|
||||
bool calcHDT(const double* hdmVal, const double* varVal, const double* cogVal, const double* sogVal, double* hdtVal);
|
||||
bool calcWD(const double* waVal, const double* hdtVal, double* wdVal);
|
||||
bool calcTrueWinds(const double* awaVal, const double* awsVal, const double* awd,
|
||||
void calcTwdSA(const double* AWA, const double* AWS,
|
||||
const double* CTW, const double* STW, const double* HDT,
|
||||
double* TWD, double* TWS, double* TWA, double* AWD);
|
||||
static double calcHDT(const double* hdmVal, const double* varVal, const double* cogVal, const double* sogVal);
|
||||
bool calcWinds(const double* awaVal, const double* awsVal,
|
||||
const double* cogVal, const double* stwVal, const double* sogVal, const double* hdtVal,
|
||||
double* twdVal, double* twsVal, double* twaVal);
|
||||
void setMaxWs(GwApi::BoatValue *wsMaxValue, const double * wsVal);
|
||||
void setMaxWs() { setMaxWs(maxtwsBVal, &tws); };
|
||||
bool handleWinds(bool calcWinds);
|
||||
const double* hdmVal, const double* varVal, double* twdVal, double* twsVal, double* twaVal, double* awdVal);
|
||||
bool addWinds();
|
||||
};
|
||||
@@ -1,8 +1,9 @@
|
||||
#ifndef _OBP60FUNCTIONS_H
|
||||
#define _OBP60FUNCTIONS_H
|
||||
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
#include <Arduino.h>
|
||||
#include "OBP60Hardware.h"
|
||||
#include "OBP60Extensions.h" // for buzzer
|
||||
#include "OBPKeyboardTask.h"
|
||||
|
||||
// Global vars
|
||||
|
||||
@@ -58,9 +59,9 @@ void initKeys(CommonData &commonData) {
|
||||
commonData.keydata[5].h = height;
|
||||
}
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
#ifdef HARDWARE_V21
|
||||
// Keypad functions for original OBP60 hardware
|
||||
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
|
||||
int readKeypad(GwLog* logger, uint thSensitivity) {
|
||||
|
||||
// Touch sensor values
|
||||
// 35000 - Not touched
|
||||
@@ -286,6 +287,7 @@ void initKeys(CommonData &commonData) {
|
||||
}
|
||||
// Copy keycode
|
||||
keycodeold = keycode;
|
||||
// 100% Task-CPU RLY?
|
||||
while(readSensorpads() > 0){} // Wait for pad release
|
||||
delay(keydelay);
|
||||
}
|
||||
@@ -300,4 +302,40 @@ void initKeys(CommonData &commonData) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void keyboardTask(void *param) {
|
||||
|
||||
// params needed:
|
||||
// queue
|
||||
// logger
|
||||
// sensitivity
|
||||
// use_syspage for deep sleep activation
|
||||
|
||||
KbTaskData *data = (KbTaskData *)param;
|
||||
|
||||
int keycode = 0;
|
||||
data->logger->logDebug(GwLog::LOG, "Start keyboard task");
|
||||
|
||||
while (true) {
|
||||
#ifdef BOARD_OBP40S3
|
||||
keycode = readKeypad(data->logger, data->sensitivity, data->use_syspage);
|
||||
#else
|
||||
keycode = readKeypad(data->logger, data->sensitivity);
|
||||
#endif
|
||||
//send a key event
|
||||
if (keycode != 0) {
|
||||
xQueueSend(data->queue, &keycode, 0);
|
||||
data->logger->logDebug(GwLog::LOG,"kbtask: send keycode: %d", keycode);
|
||||
}
|
||||
delay(20); // 50Hz update rate (20ms)
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void createKeyboardTask(KbTaskData *param) {
|
||||
TaskHandle_t xHandle = NULL;
|
||||
if (xTaskCreate(keyboardTask, "keyboard", configMINIMAL_STACK_SIZE + 1024, param, configMAX_PRIORITIES-1, &xHandle) != pdPASS) {
|
||||
param->logger->logDebug(GwLog::ERROR, "Failed to create keyboard task!");
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
#include "GwLog.h"
|
||||
#include "Pagedata.h"
|
||||
|
||||
typedef struct {
|
||||
QueueHandle_t queue;
|
||||
GwLog* logger = nullptr;
|
||||
uint sensitivity = 100;
|
||||
#ifdef BOARD_OBP40S3
|
||||
bool use_syspage = true;
|
||||
#endif
|
||||
} KbTaskData;
|
||||
|
||||
void initKeys(CommonData &commonData);
|
||||
void createKeyboardTask(KbTaskData *param);
|
||||
@@ -45,9 +45,9 @@ private:
|
||||
size_t last; // Points to the last (newest) valid element
|
||||
size_t count; // Number of valid elements currently in buffer
|
||||
bool is_Full; // Indicates that all buffer elements are used and ringing is in use
|
||||
T NUMLIMIT_LOW; // internally lowest possible value of buffer of type <T>
|
||||
T NUMLIMIT_HIGH; // internally highest possible value of buffer of type <T>
|
||||
double BUFMIN_VAL, BUFMAX_VAL; // lowest/highest possible buffer value considering multiplier -> externally used
|
||||
T MIN_VAL; // lowest possible value of buffer of type <T>
|
||||
T MAX_VAL; // highest possible value of buffer of type <T> -> indicates invalid value in buffer
|
||||
double dblMIN_VAL, dblMAX_VAL; // MIN_VAL, MAX_VAL in double format
|
||||
mutable SemaphoreHandle_t bufLocker;
|
||||
|
||||
// metadata for buffer
|
||||
@@ -55,8 +55,8 @@ private:
|
||||
String dataFmt; // Format of boat data in buffer
|
||||
int updFreq; // Update frequency in milliseconds
|
||||
double mltplr; // Multiplier which transforms original <double> value into buffer type format
|
||||
double lowest; // low value range for boat data in this buffer; needs to be => BUFMIN_VAL
|
||||
double highest; // high value range for boat data in this buffer; needs to be < BUFMAX_VAL, since BUFMAX_VAL indicates invalid entries
|
||||
double smallest; // Value range of buffer: smallest value; needs to be => MIN_VAL
|
||||
double largest; // Value range of buffer: biggest value; needs to be < MAX_VAL, since MAX_VAL indicates invalid entries
|
||||
|
||||
void initCommon();
|
||||
|
||||
@@ -64,12 +64,10 @@ public:
|
||||
RingBuffer();
|
||||
RingBuffer(size_t size);
|
||||
void setMetaData(String name, String format, int updateFrequency, double multiplier, double minValue, double maxValue); // Set meta data for buffer
|
||||
void setFormat(String format); // Specify format of buffer
|
||||
bool getMetaData(String& name, String& format, int& updateFrequency, double& multiplier, double& minValue, double& maxValue); // Get meta data of buffer
|
||||
bool getMetaData(String& name, String& format);
|
||||
String getName() const; // Get buffer name
|
||||
String getFormat() const; // Get buffer data format
|
||||
int getUpdFreq() const; // Get buffer update frequency
|
||||
void add(const double& value); // Add a new value to buffer
|
||||
double get(size_t index) const; // Get value at specific position (0-based index from oldest to newest)
|
||||
double getFirst() const; // Get the first (oldest) value in buffer
|
||||
@@ -80,8 +78,6 @@ public:
|
||||
double getMax(size_t amount) const; // Get maximum value of the last <amount> values of buffer
|
||||
double getMid() const; // Get mid value between <min> and <max> value in buffer
|
||||
double getMid(size_t amount) const; // Get mid value between <min> and <max> value of the last <amount> values of buffer
|
||||
double getCircularMid() const; // Get mid value of circle (degree) values of buffer
|
||||
double getCircularMid(size_t amount) const; // Get mid value of circle (degree) values of the last <amount> values of buffer
|
||||
double getMedian() const; // Get the median value in buffer
|
||||
double getMedian(size_t amount) const; // Get the median value of the last <amount> values of buffer
|
||||
size_t getCapacity() const; // Get the buffer capacity (maximum size)
|
||||
|
||||
+110
-134
@@ -1,7 +1,24 @@
|
||||
#include "OBPRingBuffer.h"
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <cmath>
|
||||
|
||||
template <typename T>
|
||||
void RingBuffer<T>::initCommon()
|
||||
{
|
||||
MIN_VAL = std::numeric_limits<T>::lowest();
|
||||
MAX_VAL = std::numeric_limits<T>::max();
|
||||
dblMIN_VAL = static_cast<double>(MIN_VAL);
|
||||
dblMAX_VAL = static_cast<double>(MAX_VAL);
|
||||
dataName = "";
|
||||
dataFmt = "";
|
||||
updFreq = -1;
|
||||
mltplr = 1;
|
||||
smallest = dblMIN_VAL;
|
||||
largest = dblMAX_VAL;
|
||||
bufLocker = xSemaphoreCreateMutex();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
RingBuffer<T>::RingBuffer()
|
||||
: capacity(0)
|
||||
@@ -27,23 +44,7 @@ RingBuffer<T>::RingBuffer(size_t size)
|
||||
initCommon();
|
||||
|
||||
buffer.reserve(size);
|
||||
buffer.resize(size, NUMLIMIT_HIGH); // NUMLIMIT_HIGH indicate invalid values
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void RingBuffer<T>::initCommon()
|
||||
{
|
||||
NUMLIMIT_LOW = std::numeric_limits<T>::lowest();
|
||||
NUMLIMIT_HIGH = std::numeric_limits<T>::max();
|
||||
dataName = "";
|
||||
dataFmt = "";
|
||||
updFreq = -1;
|
||||
mltplr = 1;
|
||||
BUFMIN_VAL = static_cast<double>(NUMLIMIT_LOW);
|
||||
BUFMAX_VAL = static_cast<double>(NUMLIMIT_HIGH);
|
||||
lowest = BUFMIN_VAL;
|
||||
highest = BUFMAX_VAL;
|
||||
bufLocker = xSemaphoreCreateMutex();
|
||||
buffer.resize(size, MAX_VAL); // MAX_VAL indicate invalid values
|
||||
}
|
||||
|
||||
// Specify meta data of buffer content
|
||||
@@ -55,18 +56,8 @@ void RingBuffer<T>::setMetaData(String name, String format, int updateFrequency,
|
||||
dataFmt = format;
|
||||
updFreq = updateFrequency;
|
||||
mltplr = multiplier;
|
||||
BUFMIN_VAL = static_cast<double>(NUMLIMIT_LOW) / mltplr; // lowest possible buffer value; converted to external view
|
||||
BUFMAX_VAL = static_cast<double>(NUMLIMIT_HIGH) / mltplr; // highest possible buffer value; converted to external view
|
||||
lowest = std::max(BUFMIN_VAL, minValue); // low value range, set by user
|
||||
highest = std::min(std::nextafter(BUFMAX_VAL, -std::numeric_limits<double>::infinity()), maxValue); // high value range, set by user; maximum is 1 tick lower than BUFMAX_VAL
|
||||
}
|
||||
|
||||
// Specify format of buffer content
|
||||
template <typename T>
|
||||
void RingBuffer<T>::setFormat(String format)
|
||||
{
|
||||
GWSYNCHRONIZED(&bufLocker);
|
||||
dataFmt = format;
|
||||
smallest = std::max(dblMIN_VAL, minValue);
|
||||
largest = std::min(dblMAX_VAL, maxValue);
|
||||
}
|
||||
|
||||
// Get meta data of buffer content
|
||||
@@ -82,8 +73,8 @@ bool RingBuffer<T>::getMetaData(String& name, String& format, int& updateFrequen
|
||||
format = dataFmt;
|
||||
updateFrequency = updFreq;
|
||||
multiplier = mltplr;
|
||||
minValue = lowest;
|
||||
maxValue = highest;
|
||||
minValue = smallest;
|
||||
maxValue = largest;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -115,20 +106,13 @@ String RingBuffer<T>::getFormat() const
|
||||
return dataFmt;
|
||||
}
|
||||
|
||||
// Get buffer update frequency
|
||||
template <typename T>
|
||||
int RingBuffer<T>::getUpdFreq() const
|
||||
{
|
||||
return updFreq;
|
||||
}
|
||||
|
||||
// Add a new value to buffer
|
||||
template <typename T>
|
||||
void RingBuffer<T>::add(const double& value)
|
||||
{
|
||||
GWSYNCHRONIZED(&bufLocker);
|
||||
if (value < lowest || value > highest) {
|
||||
buffer[head] = NUMLIMIT_HIGH; // Store maximum buffer value if data value is out of range
|
||||
if (value < smallest || value > largest) {
|
||||
buffer[head] = MAX_VAL; // Store MAX_VAL if value is out of range
|
||||
} else {
|
||||
buffer[head] = static_cast<T>(std::round(value * mltplr));
|
||||
}
|
||||
@@ -152,11 +136,11 @@ double RingBuffer<T>::get(size_t index) const
|
||||
{
|
||||
GWSYNCHRONIZED(&bufLocker);
|
||||
if (isEmpty() || index < 0 || index >= count) {
|
||||
return BUFMAX_VAL;
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
|
||||
size_t realIndex = (first + index) % capacity;
|
||||
return static_cast<double>(buffer[realIndex] / mltplr); // is BUFMAX_VAL if value is invalid
|
||||
return static_cast<double>(buffer[realIndex] / mltplr);
|
||||
}
|
||||
|
||||
// Operator[] for convenient access (same as get())
|
||||
@@ -171,7 +155,7 @@ template <typename T>
|
||||
double RingBuffer<T>::getFirst() const
|
||||
{
|
||||
if (isEmpty()) {
|
||||
return BUFMAX_VAL;
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
return get(0);
|
||||
}
|
||||
@@ -181,7 +165,7 @@ template <typename T>
|
||||
double RingBuffer<T>::getLast() const
|
||||
{
|
||||
if (isEmpty()) {
|
||||
return BUFMAX_VAL;
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
return get(count - 1);
|
||||
}
|
||||
@@ -190,7 +174,19 @@ double RingBuffer<T>::getLast() const
|
||||
template <typename T>
|
||||
double RingBuffer<T>::getMin() const
|
||||
{
|
||||
return getMin(getCurrentSize());
|
||||
if (isEmpty()) {
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
|
||||
double minVal = dblMAX_VAL;
|
||||
double value;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
value = get(i);
|
||||
if (value < minVal && value != dblMAX_VAL) {
|
||||
minVal = value;
|
||||
}
|
||||
}
|
||||
return minVal;
|
||||
}
|
||||
|
||||
// Get minimum value of the last <amount> values of buffer
|
||||
@@ -198,16 +194,16 @@ template <typename T>
|
||||
double RingBuffer<T>::getMin(size_t amount) const
|
||||
{
|
||||
if (isEmpty() || amount <= 0) {
|
||||
return BUFMAX_VAL;
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
if (amount > count)
|
||||
amount = count;
|
||||
|
||||
double minVal = BUFMAX_VAL;
|
||||
double minVal = dblMAX_VAL;
|
||||
double value;
|
||||
for (size_t i = 0; i < amount; i++) {
|
||||
value = get(count - 1 - i);
|
||||
if (value < minVal && value != BUFMAX_VAL) {
|
||||
if (value < minVal && value != dblMAX_VAL) {
|
||||
minVal = value;
|
||||
}
|
||||
}
|
||||
@@ -218,7 +214,22 @@ double RingBuffer<T>::getMin(size_t amount) const
|
||||
template <typename T>
|
||||
double RingBuffer<T>::getMax() const
|
||||
{
|
||||
return getMax(getCurrentSize());
|
||||
if (isEmpty()) {
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
|
||||
double maxVal = dblMIN_VAL;
|
||||
double value;
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
value = get(i);
|
||||
if (value > maxVal && value != dblMAX_VAL) {
|
||||
maxVal = value;
|
||||
}
|
||||
}
|
||||
if (maxVal == dblMIN_VAL) { // no change of initial value -> buffer has only invalid values (MAX_VAL)
|
||||
maxVal = dblMAX_VAL;
|
||||
}
|
||||
return maxVal;
|
||||
}
|
||||
|
||||
// Get maximum value of the last <amount> values of buffer
|
||||
@@ -226,21 +237,21 @@ template <typename T>
|
||||
double RingBuffer<T>::getMax(size_t amount) const
|
||||
{
|
||||
if (isEmpty() || amount <= 0) {
|
||||
return BUFMAX_VAL;
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
if (amount > count)
|
||||
amount = count;
|
||||
|
||||
double maxVal = BUFMIN_VAL;
|
||||
double maxVal = dblMIN_VAL;
|
||||
double value;
|
||||
for (size_t i = 0; i < amount; i++) {
|
||||
value = get(count - 1 - i);
|
||||
if (value > maxVal && value != BUFMAX_VAL) {
|
||||
if (value > maxVal && value != dblMAX_VAL) {
|
||||
maxVal = value;
|
||||
}
|
||||
}
|
||||
if (maxVal == BUFMIN_VAL) { // no change of initial value -> buffer has only invalid values (BUFMAX_VAL)
|
||||
maxVal = BUFMAX_VAL;
|
||||
if (maxVal == dblMIN_VAL) { // no change of initial value -> buffer has only invalid values (MAX_VAL)
|
||||
maxVal = dblMAX_VAL;
|
||||
}
|
||||
return maxVal;
|
||||
}
|
||||
@@ -249,7 +260,11 @@ double RingBuffer<T>::getMax(size_t amount) const
|
||||
template <typename T>
|
||||
double RingBuffer<T>::getMid() const
|
||||
{
|
||||
return getMid(getCurrentSize());
|
||||
if (isEmpty()) {
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
|
||||
return (getMin() + getMax()) / 2;
|
||||
}
|
||||
|
||||
// Get mid value between <min> and <max> value of the last <amount> values of buffer
|
||||
@@ -257,7 +272,7 @@ template <typename T>
|
||||
double RingBuffer<T>::getMid(size_t amount) const
|
||||
{
|
||||
if (isEmpty() || amount <= 0) {
|
||||
return BUFMAX_VAL;
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
|
||||
if (amount > count)
|
||||
@@ -270,7 +285,29 @@ double RingBuffer<T>::getMid(size_t amount) const
|
||||
template <typename T>
|
||||
double RingBuffer<T>::getMedian() const
|
||||
{
|
||||
return getMedian(getCurrentSize());
|
||||
if (isEmpty()) {
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
|
||||
// Create a temporary vector with current valid elements
|
||||
std::vector<T> temp;
|
||||
temp.reserve(count);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
temp.push_back(get(i));
|
||||
}
|
||||
|
||||
// Sort to find median
|
||||
std::sort(temp.begin(), temp.end());
|
||||
|
||||
if (count % 2 == 1) {
|
||||
// Odd number of elements
|
||||
return static_cast<double>(temp[count / 2]);
|
||||
} else {
|
||||
// Even number of elements - return average of middle two
|
||||
// Note: For integer types, this truncates. For floating point, it's exact.
|
||||
return static_cast<double>((temp[count / 2 - 1] + temp[count / 2]) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Get the median value of the last <amount> values of buffer
|
||||
@@ -278,13 +315,13 @@ template <typename T>
|
||||
double RingBuffer<T>::getMedian(size_t amount) const
|
||||
{
|
||||
if (isEmpty() || amount <= 0) {
|
||||
return BUFMAX_VAL;
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
if (amount > count)
|
||||
amount = count;
|
||||
|
||||
// Create a temporary vector with current valid elements
|
||||
std::vector<double> temp;
|
||||
std::vector<T> temp;
|
||||
temp.reserve(amount);
|
||||
|
||||
for (size_t i = 0; i < amount; i++) {
|
||||
@@ -294,84 +331,16 @@ double RingBuffer<T>::getMedian(size_t amount) const
|
||||
// Sort to find median
|
||||
std::sort(temp.begin(), temp.end());
|
||||
|
||||
if (temp[0] == BUFMAX_VAL) { // 1st element of sorted vector is already BUFMAX_VAL -> only invalid entries in buffer, so we return invalid value
|
||||
return BUFMAX_VAL;
|
||||
}
|
||||
|
||||
if (amount % 2 == 1) {
|
||||
// Odd number of elements
|
||||
return temp[amount / 2];
|
||||
return static_cast<double>(temp[amount / 2]);
|
||||
} else {
|
||||
// Even number of elements - return average of middle two
|
||||
return (temp[amount / 2 - 1] + temp[amount / 2]) / 2;
|
||||
// Note: For integer types, this truncates. For floating point, it's exact.
|
||||
return static_cast<double>((temp[amount / 2 - 1] + temp[amount / 2]) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
// Get mid value of circle (degree) values of buffer
|
||||
template <typename T>
|
||||
double RingBuffer<T>::getCircularMid() const
|
||||
{
|
||||
return getCircularMid(getCurrentSize());
|
||||
}
|
||||
|
||||
// Get mid value of circle (degree) values of the last <amount> values of buffer
|
||||
template <typename T>
|
||||
double RingBuffer<T>::getCircularMid(size_t amount) const
|
||||
{
|
||||
if (isEmpty() || amount <= 0) {
|
||||
return BUFMAX_VAL;
|
||||
}
|
||||
if (amount > count)
|
||||
amount = count;
|
||||
|
||||
std::vector<double> a;
|
||||
// Create a temporary vector with current valid elements
|
||||
std::vector<double> temp;
|
||||
temp.reserve(amount);
|
||||
|
||||
for (size_t i = 0; i < amount; i++) {
|
||||
temp.push_back(get(count - 1 - i));
|
||||
}
|
||||
|
||||
// Sort to find largest gap
|
||||
std::sort(temp.begin(), temp.end());
|
||||
|
||||
if (temp[0] == BUFMAX_VAL) { // 1st element of sorted vector is already BUFMAX_VAL -> only invalid entries in buffer, so we return invalid value
|
||||
return BUFMAX_VAL;
|
||||
}
|
||||
|
||||
// Find the largest gap
|
||||
double largestGap = BUFMIN_VAL;
|
||||
std::size_t gapIndex = 0;
|
||||
|
||||
for (std::size_t i = 0; i < temp.size(); ++i)
|
||||
{
|
||||
std::size_t next = (i + 1) % temp.size();
|
||||
|
||||
double gap;
|
||||
if (next == 0)
|
||||
gap = (temp[0] + M_TWOPI) - temp[i];
|
||||
else
|
||||
gap = temp[next] - temp[i];
|
||||
|
||||
if (gap > largestGap)
|
||||
{
|
||||
largestGap = gap;
|
||||
gapIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
double start = temp[(gapIndex + 1) % temp.size()]; // Start of occupied arc = first angle after largest gap
|
||||
double arcWidth = M_TWOPI - largestGap; // Width of occupied arc
|
||||
arcWidth = start + arcWidth / 2.0;
|
||||
arcWidth = fmod(arcWidth, M_TWOPI);
|
||||
if (arcWidth < 0.0) {
|
||||
arcWidth += M_TWOPI;
|
||||
}
|
||||
|
||||
return arcWidth; // Midpoint of occupied arc
|
||||
}
|
||||
|
||||
// Get the buffer capacity (maximum size)
|
||||
template <typename T>
|
||||
size_t RingBuffer<T>::getCapacity() const
|
||||
@@ -418,14 +387,14 @@ bool RingBuffer<T>::isFull() const
|
||||
template <typename T>
|
||||
double RingBuffer<T>::getMinVal() const
|
||||
{
|
||||
return BUFMIN_VAL;
|
||||
return dblMIN_VAL;
|
||||
}
|
||||
|
||||
// Get highest possible value for buffer; used for unset/invalid buffer data
|
||||
template <typename T>
|
||||
double RingBuffer<T>::getMaxVal() const
|
||||
{
|
||||
return BUFMAX_VAL;
|
||||
return dblMAX_VAL;
|
||||
}
|
||||
|
||||
// Clear buffer
|
||||
@@ -454,14 +423,21 @@ void RingBuffer<T>::resize(size_t newSize)
|
||||
|
||||
buffer.clear();
|
||||
buffer.reserve(newSize);
|
||||
buffer.resize(newSize, NUMLIMIT_HIGH);
|
||||
buffer.resize(newSize, MAX_VAL);
|
||||
}
|
||||
|
||||
// Get all current values in native buffer format as a vector
|
||||
template <typename T>
|
||||
std::vector<double> RingBuffer<T>::getAllValues() const
|
||||
{
|
||||
return getAllValues(getCurrentSize());
|
||||
std::vector<double> result;
|
||||
result.reserve(count);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
result.push_back(get(i));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Get last <amount> values in native buffer format as a vector
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
#include <Adafruit_Sensor.h> // Adafruit Lib for sensors
|
||||
#include <Adafruit_BME280.h> // Adafruit Lib for BME280
|
||||
@@ -49,10 +50,8 @@ void sensorTask(void *param){
|
||||
|
||||
// Init sensor stuff
|
||||
bool oneWire_ready = false; // 1Wire initialized and ready to use
|
||||
bool iRTC_ready = false; // Software RTC 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 N2K_GPS_ready = false; // GPS time on N2K bus
|
||||
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
|
||||
@@ -66,8 +65,8 @@ void sensorTask(void *param){
|
||||
const int avgsize = 300;
|
||||
constexpr int arrayBatV{avgsize};
|
||||
constexpr int arrayBatC{avgsize};
|
||||
movingAvg<int> batV(arrayBatV);
|
||||
movingAvg<int> batC(arrayBatC);
|
||||
movingAvg batV(arrayBatV);
|
||||
movingAvg batC(arrayBatC);
|
||||
batV.begin();
|
||||
batC.begin();
|
||||
|
||||
@@ -371,7 +370,7 @@ void sensorTask(void *param){
|
||||
GwApi::BoatValue *hdop=new GwApi::BoatValue(GwBoatData::_HDOP);
|
||||
GwApi::BoatValue *valueList[]={gpsdays, gpsseconds, hdop};
|
||||
|
||||
// Internal iRTC with NTP init
|
||||
// Internal RTC with NTP init
|
||||
ESP32Time rtc(0);
|
||||
if (api->getConfig()->getString(api->getConfig()->timeSource) == "iRTC") {
|
||||
GwApi::Status status;
|
||||
@@ -384,7 +383,6 @@ void sensorTask(void *param){
|
||||
if (getLocalTime(&timeinfo)) {
|
||||
api->getLogger()->logDebug(GwLog::LOG,"NTP time: %04d-%02d-%02d %02d:%02d:%02d UTC", timeinfo.tm_year+1900, timeinfo.tm_mon+1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
|
||||
rtc.setTimeStruct(timeinfo);
|
||||
iRTC_ready = true;
|
||||
sensors.rtcValid = true;
|
||||
} else {
|
||||
api->getLogger()->logDebug(GwLog::LOG,"NTP time fetch failed!");
|
||||
@@ -403,7 +401,7 @@ void sensorTask(void *param){
|
||||
if (millis() > starttime0 + 100)
|
||||
{
|
||||
starttime0 = millis();
|
||||
// Send NMEA0183 GPS data on several bus systems (N2K an 0183) all 100ms
|
||||
// Send NMEA0183 GPS data on several bus systems all 100ms
|
||||
if (GPS_ready == true && hdop->value <= hdopAccuracy)
|
||||
{
|
||||
SNMEA0183Msg NMEA0183Msg;
|
||||
@@ -415,55 +413,9 @@ void sensorTask(void *param){
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
Time set logic for RTC and N2K
|
||||
###############################
|
||||
|
||||
iRTC = Software RTC updatetd with NTP via internet
|
||||
RTC = RTC chip on PCB
|
||||
GPS = GPS Receiver on PCB
|
||||
N2K = GPS time on N2K od 183 bus
|
||||
0 = device not ready
|
||||
1 = device ready
|
||||
X = independend
|
||||
() = source for set time N2K
|
||||
-> = set RTC via iRTC
|
||||
<- = set RTC via GPS
|
||||
|
||||
iRTC RTC GPS N2K
|
||||
0 0 0 (1)
|
||||
0 0 (1) X
|
||||
0 (1) 0 X
|
||||
0 1 <-(1) X
|
||||
(1) 0 0 X
|
||||
1 0 (1) X
|
||||
1 ->(1) 0 X
|
||||
1 1 <-(1) X
|
||||
|
||||
*/
|
||||
|
||||
// If RTC DS1388 ready, then copy iRTC and GPS data to RTC all 1 min
|
||||
if(millis() > starttime11 + 1*60*1000){
|
||||
// If RTC DS1388 ready, then copy GPS data to RTC all 5min
|
||||
if(millis() > starttime11 + 5*60*1000){
|
||||
starttime11 = millis();
|
||||
// Set RTC chip via iRTC (NTP)
|
||||
if(iRTC_ready == true && RTC_ready == true && GPS_ready == false){
|
||||
GwApi::Status status;
|
||||
api->getStatus(status);
|
||||
// Check WiFi connection
|
||||
if (status.wifiClientConnected) {
|
||||
sensors.rtcTime = rtc.getTimeStruct(); // Get time from software RTC (iRTC)
|
||||
DateTime now = DateTime(
|
||||
sensors.rtcTime.tm_year + 1900,
|
||||
sensors.rtcTime.tm_mon + 1,
|
||||
sensors.rtcTime.tm_mday,
|
||||
sensors.rtcTime.tm_hour,
|
||||
sensors.rtcTime.tm_min,
|
||||
sensors.rtcTime.tm_sec
|
||||
);
|
||||
ds1388.adjust(now);
|
||||
}
|
||||
}
|
||||
// Set RTC chip via internal GPS
|
||||
if(rtcOn == "DS1388" && RTC_ready == true && GPS_ready == true){
|
||||
api->getBoatDataValues(3,valueList);
|
||||
if(gpsdays->valid && gpsseconds->valid && hdop->valid){
|
||||
@@ -471,30 +423,38 @@ void sensorTask(void *param){
|
||||
// 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 via internal GPS: %04d/%02d/%02d %02d:%02d:%02d",adjusttime.year(), adjusttime.month(), adjusttime.day(), adjusttime.hour(), adjusttime.minute(), adjusttime.second());
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set RTC chip via N2K or 183 in case the internal GPS is off (only one time)
|
||||
if(N2K_GPS_ready == false && RTC_ready == true && GPS_ready == false){
|
||||
api->getBoatDataValues(3,valueList);
|
||||
if(gpsdays->valid && gpsseconds->valid && hdop->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 via N2K/183: %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);
|
||||
// N2K GPS time ready
|
||||
N2K_GPS_ready = true;
|
||||
// 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++;
|
||||
}
|
||||
|
||||
// Send RTC date and time to N2K all 500ms
|
||||
// Get current RTC date and time all 500ms
|
||||
if (millis() > starttime12 + 500) {
|
||||
starttime12 = millis();
|
||||
// Send date and time from RTC chip if GPS not ready
|
||||
@@ -523,36 +483,18 @@ void sensorTask(void *param){
|
||||
}
|
||||
// N2K sysTime is double in n2klib
|
||||
double sysTime = (dt.hour() * 3600) + (dt.minute() * 60) + dt.second();
|
||||
if(!isnan(daysAt1970) && !isnan(sysTime)){
|
||||
//api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon+1, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec);
|
||||
// WHY? isnan should always fail here
|
||||
//if(!isnan(daysAt1970) && !isnan(sysTime)){
|
||||
//api->getLogger()->logDebug(GwLog::LOG,"RTC time: %04d/%02d/%02d %02d:%02d:%02d",sensors.rtcTime.tm_year+1900,sensors.rtcTime.tm_mon, sensors.rtcTime.tm_mday, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec);
|
||||
//api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime);
|
||||
SetN2kPGN126992(N2kMsg,0,daysAt1970,sysTime,N2ktimes_LocalCrystalClock);
|
||||
api->sendN2kMessage(N2kMsg);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
// Send date and time from software RTC (iRTC)
|
||||
if (iRTC_ready == true && RTC_ready == false && GPS_ready == false) {
|
||||
} else if (sensors.rtcValid) {
|
||||
// use internal rtc feature
|
||||
sensors.rtcTime = rtc.getTimeStruct();
|
||||
|
||||
const short daysOfYear[12] = {0,31,59,90,120,151,181,212,243,273,304,334};
|
||||
int year = sensors.rtcTime.tm_year + 1900;
|
||||
int month = sensors.rtcTime.tm_mon;
|
||||
int day = sensors.rtcTime.tm_mday;
|
||||
uint16_t switchYear = ((year - 1) - 1968) / 4 - ((year - 1) - 1900) / 100 + ((year - 1) - 1600) / 400;
|
||||
long daysAt1970 = (year - 1970) * 365L + switchYear + daysOfYear[month] + day - 1;
|
||||
|
||||
// Leap day add if date is after Feb (i.e. month >= March)
|
||||
if (month >= 2 && (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) {
|
||||
daysAt1970 += 1;
|
||||
}
|
||||
double sysTime = sensors.rtcTime.tm_hour * 3600.0 + sensors.rtcTime.tm_min * 60.0 + sensors.rtcTime.tm_sec;
|
||||
//api->getLogger()->logDebug(GwLog::LOG, "iRTC time: %04d/%02d/%02d %02d:%02d:%02d", year, month + 1, day, sensors.rtcTime.tm_hour, sensors.rtcTime.tm_min, sensors.rtcTime.tm_sec);
|
||||
//api->getLogger()->logDebug(GwLog::LOG,"Send PGN126992: %10d %10d",daysAt1970, (uint16_t)sysTime);
|
||||
SetN2kPGN126992(N2kMsg, 0, daysAt1970, sysTime, N2ktimes_LocalCrystalClock);
|
||||
api->sendN2kMessage(N2kMsg);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Send 1Wire data for all temperature sensors to N2K all 2s
|
||||
@@ -652,6 +594,11 @@ void sensorTask(void *param){
|
||||
// Send data from environment sensor to N2K all 2s
|
||||
if(millis() > starttime6 + 2000){
|
||||
starttime6 = millis();
|
||||
|
||||
// DEBUG
|
||||
UBaseType_t stackfree = uxTaskGetStackHighWaterMark(NULL);
|
||||
api->getLogger()->logDebug(GwLog::LOG, "obpSensortask Stack=%d", stackfree);
|
||||
|
||||
unsigned char TempSource = 2; // Inside temperature
|
||||
unsigned char PressureSource = 0; // Atmospheric pressure
|
||||
unsigned char HumiditySource = 0; // Inside humidity
|
||||
@@ -869,8 +816,12 @@ void sensorTask(void *param){
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
|
||||
void createSensorTask(SharedData *shared) {
|
||||
xTaskCreate(sensorTask,"readSensors",10000,shared,3,NULL);
|
||||
TaskHandle_t xHandle = NULL;
|
||||
GwLog *logger = shared->api->getLogger();
|
||||
esp_err_t err = xTaskCreate(sensorTask, "readSensors", configMINIMAL_STACK_SIZE + 8192, shared, 3, &xHandle);
|
||||
if ( err != pdPASS) {
|
||||
logger->logDebug(GwLog::ERROR, "Failed to create sensor task! (err=%d)", err);
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
#include "GwSynchronized.h"
|
||||
#include "GwApi.h"
|
||||
|
||||
+215
-291
@@ -3,6 +3,14 @@
|
||||
#include "OBPDataOperations.h"
|
||||
#include "OBPRingBuffer.h"
|
||||
|
||||
std::map<String, ChartProps> Chart::dfltChrtDta = {
|
||||
{ "formatWind", { 60.0 * DEG_TO_RAD, 10.0 * DEG_TO_RAD } }, // default course range 60 degrees
|
||||
{ "formatCourse", { 60.0 * DEG_TO_RAD, 10.0 * DEG_TO_RAD } }, // default course range 60 degrees
|
||||
{ "formatKnots", { 7.71, 2.56 } }, // default speed range in m/s
|
||||
{ "formatDepth", { 15.0, 5.0 } }, // default depth range in m
|
||||
{ "kelvinToC", { 30.0, 5.0 } } // default temp range in °C/K
|
||||
};
|
||||
|
||||
// --- Class Chart ---------------
|
||||
|
||||
// Chart - object holding the actual chart, incl. data buffer and format definition
|
||||
@@ -10,8 +18,9 @@
|
||||
// <dfltRng> default range of chart, e.g. 30 = [0..30]
|
||||
// <common> common program data; required for logger and color data
|
||||
// <useSimuData> flag to indicate if simulation data is active
|
||||
Chart::Chart(RingBuffer<uint16_t>& dataBuf, CommonData& common, bool useSimuData)
|
||||
Chart::Chart(RingBuffer<uint16_t>& dataBuf, double dfltRng, CommonData& common, bool useSimuData)
|
||||
: dataBuf(dataBuf)
|
||||
, dfltRng(dfltRng)
|
||||
, commonData(&common)
|
||||
, useSimuData(useSimuData)
|
||||
{
|
||||
@@ -20,54 +29,30 @@ Chart::Chart(RingBuffer<uint16_t>& dataBuf, CommonData& common, bool useSimuData
|
||||
bgColor = commonData->bgcolor;
|
||||
|
||||
// display dimensions (avoid calling width()/height() on incomplete LGFX type)
|
||||
#ifdef TFT_DISPLAY
|
||||
dWidth = 480;
|
||||
dHeight = 320;
|
||||
#else
|
||||
dWidth = getdisplay().width();
|
||||
dHeight = getdisplay().height();
|
||||
#endif
|
||||
|
||||
init();
|
||||
};
|
||||
|
||||
Chart::~Chart()
|
||||
{
|
||||
}
|
||||
|
||||
bool Chart::init()
|
||||
{
|
||||
chrtMin = 0.0;
|
||||
chrtMax = 0.0;
|
||||
chrtMid = 0.0;
|
||||
chrtRng = 0.0;
|
||||
dWidth = epd->width();
|
||||
dHeight = epd->height();
|
||||
|
||||
dataBuf.getMetaData(dbName, dbFormat);
|
||||
dbMIN_VAL = dataBuf.getMinVal();
|
||||
dbMAX_VAL = dataBuf.getMaxVal();
|
||||
bufSize = dataBuf.getCapacity();
|
||||
// LOG_DEBUG(GwLog::DEBUG, "Chart Init: dbMIN_VAL: %.2f, dbMAX_VAL: %.2fd, bufSize: %d", dbMIN_VAL, dbMAX_VAL, bufSize);
|
||||
|
||||
// Initialize chart data format; shorter version of standard format indicator
|
||||
if (dbFormat == "formatCourse" || dbFormat == "formatWind") {
|
||||
if (dbFormat == "formatCourse" || dbFormat == "formatWind" || dbFormat == "formatRot") {
|
||||
chrtDataFmt = WIND; // Chart is showing data of course / wind <degree> format
|
||||
} else if (dbFormat == "formatRot") {
|
||||
chrtDataFmt = ROTATION; // Chart is showing data of rotational <degree> format
|
||||
} else if (dbFormat == "formatKnots") {
|
||||
chrtDataFmt = SPEED; // Chart is showing data of speed or windspeed format
|
||||
} else if (dbFormat == "formatDepth") {
|
||||
chrtDataFmt = DEPTH;
|
||||
chrtDataFmt = DEPTH; // Chart ist showing data of <depth> format
|
||||
} else if (dbFormat == "kelvinToC") {
|
||||
chrtDataFmt = TEMPERATURE;
|
||||
} else if (dbFormat.startsWith("formatXdr:P")) {
|
||||
chrtDataFmt = PRESSURE;
|
||||
} else if (dbFormat.startsWith("formatXdr:H")) {
|
||||
chrtDataFmt = HUMIDITY;
|
||||
chrtDataFmt = TEMPERATURE; // Chart ist showing data of <temp> format
|
||||
} else {
|
||||
chrtDataFmt = OTHER; // Chart is showing any other data format
|
||||
}
|
||||
|
||||
// "0" value is the same for any data format but for user defined temperature and pressure format
|
||||
// "0" value is the same for any data format but for user defined temperature format
|
||||
zeroValue = 0.0;
|
||||
if (chrtDataFmt == TEMPERATURE) {
|
||||
tempFormat = commonData->config->getString(commonData->config->tempFormat); // [K|°C|°F]
|
||||
@@ -78,8 +63,6 @@ bool Chart::init()
|
||||
} else if (tempFormat == "F") {
|
||||
zeroValue = 255.37;
|
||||
}
|
||||
} else if (chrtDataFmt == PRESSURE) {
|
||||
zeroValue = 98000.0; // typical low pressure area value
|
||||
}
|
||||
|
||||
// Read default range and range step for this chart type
|
||||
@@ -87,7 +70,7 @@ bool Chart::init()
|
||||
dfltRng = dfltChrtDta[dbFormat].range;
|
||||
rngStep = dfltChrtDta[dbFormat].step;
|
||||
} else {
|
||||
dfltRng = 10.0;
|
||||
dfltRng = 15.0;
|
||||
rngStep = 5.0;
|
||||
}
|
||||
|
||||
@@ -96,19 +79,14 @@ bool Chart::init()
|
||||
chrtMax = chrtMin + dfltRng;
|
||||
chrtMid = (chrtMin + chrtMax) / 2;
|
||||
chrtRng = dfltRng;
|
||||
recalcRngMid = true; // initialize <chrtMid> and chart borders on first chart display call
|
||||
allLeft = true;
|
||||
allRight = true;
|
||||
recalcRngMid = true; // initialize <chrtMid> and chart borders on first screen call
|
||||
|
||||
if (dbFormat.isEmpty()) { // data buffer may not exist yet, because boat data object is not available yet
|
||||
initValid = false; // chart object will get invalid data during initialization
|
||||
} else {
|
||||
initValid = true;
|
||||
}
|
||||
LOG_DEBUG(GwLog::DEBUG, "Chart Init: dWidth: %d, dHeight: %d, timAxis: %d, valAxis: %d, cRoot {x,y}: %d, %d, dbname: %s, rngStep: %.4f, chrtDataFmt: %d, initValid: %d",
|
||||
dWidth, dHeight, timAxis, valAxis, cRoot.x, cRoot.y, dbName, rngStep, chrtDataFmt, initValid);
|
||||
LOG_DEBUG(GwLog::DEBUG, "Chart Init: dWidth: %d, dHeight: %d, timAxis: %d, valAxis: %d, cRoot {x,y}: %d, %d, dbname: %s, rngStep: %.4f, chrtDataFmt: %d",
|
||||
dWidth, dHeight, timAxis, valAxis, cRoot.x, cRoot.y, dbName, rngStep, chrtDataFmt);
|
||||
};
|
||||
|
||||
return isValid();
|
||||
Chart::~Chart()
|
||||
{
|
||||
}
|
||||
|
||||
// Perform all actions to draw chart
|
||||
@@ -118,7 +96,7 @@ bool Chart::init()
|
||||
// <prntName>; print data name on horizontal half chart [true|false]
|
||||
// <showCurrValue>: print current boat data value [true|false]
|
||||
// <currValue>: current boat data value; used only for test on valid data
|
||||
void Chart::showChrt(const ChrtDir chrtDir, ChrtSize chrtSz, const int8_t chrtIntv, bool prntName, bool showCurrValue, GwApi::BoatValue currValue)
|
||||
void Chart::showChrt(char chrtDir, int8_t chrtSz, const int8_t chrtIntv, bool prntName, bool showCurrValue, GwApi::BoatValue currValue)
|
||||
{
|
||||
if (!setChartDimensions(chrtDir, chrtSz)) {
|
||||
return; // wrong chart dimension parameters
|
||||
@@ -133,74 +111,64 @@ void Chart::showChrt(const ChrtDir chrtDir, ChrtSize chrtSz, const int8_t chrtIn
|
||||
return;
|
||||
}
|
||||
|
||||
if (showCurrValue) {
|
||||
currValue.value = dataBuf.getLast(); // show latest value from history buffer; this should be the most current one
|
||||
if (showCurrValue) { // show latest value from history buffer; this should be the most current one
|
||||
currValue.value = dataBuf.getLast();
|
||||
currValue.valid = currValue.value != dbMAX_VAL;
|
||||
prntCurrValue(chrtDir, currValue);
|
||||
}
|
||||
}
|
||||
|
||||
// define dimensions and start points for chart
|
||||
bool Chart::setChartDimensions(const ChrtDir chrtDir, const ChrtSize chrtSz)
|
||||
bool Chart::setChartDimensions(const char direction, const int8_t size)
|
||||
{
|
||||
if ((chrtDir != HORIZONTAL && chrtDir != VERTICAL) || (chrtSz < 0 || chrtSz > 3)) {
|
||||
if ((direction != HORIZONTAL && direction != VERTICAL) || (size < 0 || size > 2)) {
|
||||
LOG_DEBUG(GwLog::ERROR, "obp60:setChartDimensions %s: wrong parameters", dataBuf.getName());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (chrtDir == HORIZONTAL) {
|
||||
if (direction == HORIZONTAL) {
|
||||
// horizontal chart timeline direction
|
||||
timAxis = dWidth - 1;
|
||||
switch (chrtSz) {
|
||||
case ChrtSize::FULL_SIZE:
|
||||
switch (size) {
|
||||
case 0:
|
||||
valAxis = dHeight - top - bottom;
|
||||
cRoot = { 0, top - 1 };
|
||||
break;
|
||||
case HALF_SIZE_LEFT_TOP:
|
||||
case 1:
|
||||
valAxis = (dHeight - top - bottom) / 2 - hGap;
|
||||
cRoot = { 0, top - 1 };
|
||||
break;
|
||||
case HALF_SIZE_RIGHT_BOTTOM:
|
||||
case 2:
|
||||
valAxis = (dHeight - top - bottom) / 2 - hGap;
|
||||
cRoot = { 0, top + (valAxis + hGap) + hGap - 1 };
|
||||
break;
|
||||
case TWO_THIRD_TOP:
|
||||
valAxis = (dHeight - top - bottom) * 0.667 - hGap;
|
||||
cRoot = { 0, top - 1 };
|
||||
break;
|
||||
default: // same as case 0; should never happen
|
||||
valAxis = dHeight - top - bottom;
|
||||
cRoot = { 0, top - 1 };
|
||||
}
|
||||
|
||||
} else {
|
||||
} else if (direction == VERTICAL) {
|
||||
// vertical chart timeline direction
|
||||
timAxis = dHeight - top - bottom;
|
||||
switch (chrtSz) {
|
||||
case FULL_SIZE:
|
||||
switch (size) {
|
||||
case 0:
|
||||
valAxis = dWidth - 1;
|
||||
cRoot = { 0, top - 1 };
|
||||
break;
|
||||
case HALF_SIZE_LEFT_TOP:
|
||||
case 1:
|
||||
valAxis = dWidth / 2 - vGap;
|
||||
cRoot = { 0, top - 1 };
|
||||
break;
|
||||
case HALF_SIZE_RIGHT_BOTTOM:
|
||||
case 2:
|
||||
valAxis = dWidth / 2 - vGap;
|
||||
cRoot = { dWidth / 2 + vGap, top - 1 };
|
||||
cRoot = { dWidth / 2 + vGap - 1, top - 1 };
|
||||
break;
|
||||
default: // same as case 0; should never happen
|
||||
valAxis = dWidth - 1;
|
||||
cRoot = { 0, top - 1 };
|
||||
}
|
||||
}
|
||||
// LOG_DEBUG(GwLog::DEBUG, "obp60:setChartDimensions %s: chrtDir: %c, size: %d, dWidth: %d, dHeight: %d, timAxis: %d, valAxis: %d, cRoot{%d, %d}, top: %d, bottom: %d, hGap: %d, vGap: %d",
|
||||
// dataBuf.getName(), chrtDir, size, dWidth, dHeight, timAxis, valAxis, cRoot.x, cRoot.y, top, bottom, hGap, vGap);
|
||||
//LOG_DEBUG(GwLog::DEBUG, "obp60:setChartDimensions %s: direction: %c, size: %d, dWidth: %d, dHeight: %d, timAxis: %d, valAxis: %d, cRoot{%d, %d}, top: %d, bottom: %d, hGap: %d, vGap: %d",
|
||||
// dataBuf.getName(), direction, size, dWidth, dHeight, timAxis, valAxis, cRoot.x, cRoot.y, top, bottom, hGap, vGap);
|
||||
return true;
|
||||
}
|
||||
|
||||
// draw chart
|
||||
void Chart::drawChrt(const ChrtDir chrtDir, const int8_t chrtIntv, GwApi::BoatValue& currValue)
|
||||
void Chart::drawChrt(const char chrtDir, const int8_t chrtIntv, GwApi::BoatValue& currValue)
|
||||
{
|
||||
double chrtScale; // Scale for data values in pixels per value
|
||||
|
||||
@@ -209,7 +177,7 @@ void Chart::drawChrt(const ChrtDir chrtDir, const int8_t chrtIntv, GwApi::BoatVa
|
||||
// LOG_DEBUG(GwLog::DEBUG, "Chart:drawChart: min: %.1f, mid: %.1f, max: %.1f, rng: %.1f", chrtMin, chrtMid, chrtMax, chrtRng);
|
||||
calcChrtBorders(chrtMin, chrtMid, chrtMax, chrtRng);
|
||||
chrtScale = double(valAxis) / chrtRng; // Chart scale: pixels per value step
|
||||
// LOG_DEBUG(GwLog::DEBUG, "Chart:drawChart: min: %.1f, mid: %.1f, max: %.1f, rng: %.1f, data valid: %d", chrtMin, chrtMid, chrtMax, chrtRng, currValue.valid);
|
||||
// LOG_DEBUG(GwLog::DEBUG, "Chart:drawChart: min: %.1f, mid: %.1f, max: %.1f, rng: %.1f", chrtMin, chrtMid, chrtMax, chrtRng);
|
||||
|
||||
// Do we have valid buffer data?
|
||||
if (dataBuf.getMax() == dbMAX_VAL) { // only <MAX_VAL> values in buffer -> no valid wind data available
|
||||
@@ -224,7 +192,7 @@ void Chart::drawChrt(const ChrtDir chrtDir, const int8_t chrtIntv, GwApi::BoatVa
|
||||
numNoData++;
|
||||
bufDataValid = true;
|
||||
|
||||
if (numNoData > THRESHOLD_NO_DATA * (dataBuf.getUpdFreq() / 1000)) { // If more than <THRESHOLD> invalid values in a row, flag for invalid data
|
||||
if (numNoData > THRESHOLD_NO_DATA) { // If more than 4 invalid values in a row, flag for invalid data
|
||||
bufDataValid = false;
|
||||
return;
|
||||
}
|
||||
@@ -239,15 +207,17 @@ void Chart::getBufferStartNSize(const int8_t chrtIntv)
|
||||
count = dataBuf.getCurrentSize();
|
||||
currIdx = dataBuf.getLastIdx();
|
||||
numAddedBufVals = (currIdx - lastAddedIdx + bufSize) % bufSize; // Number of values added to buffer since last display
|
||||
lastAddedIdx = currIdx;
|
||||
|
||||
if (chrtIntv != oldChrtIntv || count == 1) { // new data interval selected by user
|
||||
if (chrtIntv != oldChrtIntv || count == 1) {
|
||||
// new data interval selected by user; this is only x * 230 values instead of 240 seconds (4 minutes) per interval step
|
||||
numBufVals = min(count, (timAxis - MIN_FREE_VALUES) * chrtIntv); // keep free or release MIN_FREE_VALUES on chart for plotting of new values
|
||||
bufStart = max(0, count - numBufVals);
|
||||
lastAddedIdx = currIdx;
|
||||
oldChrtIntv = chrtIntv;
|
||||
|
||||
} else {
|
||||
numBufVals = numBufVals + numAddedBufVals;
|
||||
lastAddedIdx = currIdx;
|
||||
if (count == bufSize) {
|
||||
bufStart = max(0, bufStart - numAddedBufVals);
|
||||
}
|
||||
@@ -259,7 +229,6 @@ void Chart::calcChrtBorders(double& rngMin, double& rngMid, double& rngMax, doub
|
||||
{
|
||||
if (chrtDataFmt == WIND || chrtDataFmt == ROTATION) {
|
||||
|
||||
// calculate rngMid
|
||||
if (chrtDataFmt == ROTATION) {
|
||||
// if chart data is of type 'rotation', we want to have <rndMid> always to be '0'
|
||||
rngMid = 0;
|
||||
@@ -274,12 +243,22 @@ void Chart::calcChrtBorders(double& rngMin, double& rngMid, double& rngMax, doub
|
||||
if (recalcRngMid) {
|
||||
// Set rngMid
|
||||
|
||||
rngMid = dataBuf.getCircularMid(numBufVals);
|
||||
rngMid = dataBuf.getMid(numBufVals);
|
||||
|
||||
if (rngMid == dbMAX_VAL) {
|
||||
rngMid = 0;
|
||||
} else {
|
||||
rngMid = std::round(rngMid / rngStep) * rngStep; // round new center value to next <rngStep> value
|
||||
rngMid = std::round(rngMid / rngStep) * rngStep; // Set new center value; round to next <rngStep> value
|
||||
|
||||
// Check if range between 'min' and 'max' is > 180° or crosses '0'
|
||||
rngMin = dataBuf.getMin(numBufVals);
|
||||
rngMax = dataBuf.getMax(numBufVals);
|
||||
rng = (rngMax >= rngMin ? rngMax - rngMin : M_TWOPI - rngMin + rngMax);
|
||||
rng = std::max(rng, dfltRng); // keep at least default chart range
|
||||
|
||||
if (rng > M_PI) { // If wind range > 180°, adjust wndCenter to smaller wind range end
|
||||
rngMid = WindUtils::to2PI(rngMid + M_PI);
|
||||
}
|
||||
}
|
||||
recalcRngMid = false; // Reset flag for <rngMid> determination
|
||||
|
||||
@@ -290,11 +269,16 @@ void Chart::calcChrtBorders(double& rngMin, double& rngMid, double& rngMax, doub
|
||||
|
||||
// check and adjust range between left, mid, and right chart limit
|
||||
double halfRng = rng / 2.0; // we calculate with range between <rngMid> and edges
|
||||
double tmpRng = getCircularRng(rngMid, numBufVals);
|
||||
double tmpRng = getAngleRng(rngMid, numBufVals);
|
||||
tmpRng = (tmpRng == dbMAX_VAL ? 0 : std::ceil(tmpRng / rngStep) * rngStep);
|
||||
|
||||
// LOG_DEBUG(GwLog::DEBUG, "calcChrtBorders: tmpRng: %.1f°, halfRng: %.1f°", tmpRng * RAD_TO_DEG, halfRng * RAD_TO_DEG);
|
||||
|
||||
if (tmpRng > halfRng) { // expand chart range to new value
|
||||
halfRng = tmpRng;
|
||||
} else if (tmpRng + rngStep < halfRng) { // Contract chart range for higher resolution if possible
|
||||
}
|
||||
|
||||
else if (tmpRng + rngStep < halfRng) { // Contract chart range for higher resolution if possible
|
||||
halfRng = std::max(dfltRng / 2.0, tmpRng);
|
||||
}
|
||||
|
||||
@@ -303,6 +287,7 @@ void Chart::calcChrtBorders(double& rngMin, double& rngMid, double& rngMax, doub
|
||||
rngMax = WindUtils::to2PI(rngMax);
|
||||
|
||||
rng = halfRng * 2.0;
|
||||
|
||||
// LOG_DEBUG(GwLog::DEBUG, "calcChrtBorders: rngMin: %.1f°, rngMid: %.1f°, rngMax: %.1f°, tmpRng: %.1f°, rng: %.1f°, rngStep: %.1f°", rngMin * RAD_TO_DEG, rngMid * RAD_TO_DEG, rngMax * RAD_TO_DEG,
|
||||
// tmpRng * RAD_TO_DEG, rng * RAD_TO_DEG, rngStep * RAD_TO_DEG);
|
||||
|
||||
@@ -311,15 +296,8 @@ void Chart::calcChrtBorders(double& rngMin, double& rngMid, double& rngMax, doub
|
||||
double currMinVal = dataBuf.getMin(numBufVals);
|
||||
double currMaxVal = dataBuf.getMax(numBufVals);
|
||||
|
||||
if (currMinVal == dbMAX_VAL || currMaxVal == dbMAX_VAL) { // no valid data
|
||||
auto chkIsNaN = [](double& val) { if (std::isnan(val)) val = 0.0; }; // define inline function
|
||||
// range values can be undefined if boat data type has not been created at time of chart printing (e.g. XDR data types)
|
||||
// we set them to "0.0" then
|
||||
chkIsNaN(rngMin);
|
||||
chkIsNaN(rngMid);
|
||||
chkIsNaN(rngMax);
|
||||
chkIsNaN(rng);
|
||||
return;
|
||||
if (currMinVal == dbMAX_VAL || currMaxVal == dbMAX_VAL) {
|
||||
return; // no valid data
|
||||
}
|
||||
|
||||
// check if current chart border have to be adjusted
|
||||
@@ -342,13 +320,14 @@ void Chart::calcChrtBorders(double& rngMin, double& rngMid, double& rngMax, doub
|
||||
|
||||
rngMid = (rngMin + rngMax) / 2.0;
|
||||
rng = rngMax - rngMin;
|
||||
|
||||
// LOG_DEBUG(GwLog::DEBUG, "calcChrtRange-end: currMinVal: %.1f, currMaxVal: %.1f, rngMin: %.1f, rngMid: %.1f, rngMax: %.1f, rng: %.1f, rngStep: %.1f, zeroValue: %.1f, dbMIN_VAL: %.1f",
|
||||
// currMinVal, currMaxVal, rngMin, rngMid, rngMax, rng, rngStep, zeroValue, dbMIN_VAL);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw chart graph
|
||||
void Chart::drawChartLines(const ChrtDir chrtDir, const int8_t chrtIntv, const double chrtScale)
|
||||
void Chart::drawChartLines(const char direction, const int8_t chrtIntv, const double chrtScale)
|
||||
{
|
||||
double chrtVal; // Current data value
|
||||
Pos point, prevPoint; // current and previous chart point
|
||||
@@ -361,12 +340,14 @@ void Chart::drawChartLines(const ChrtDir chrtDir, const int8_t chrtIntv, const d
|
||||
chrtPrevVal = dbMAX_VAL;
|
||||
} else {
|
||||
|
||||
point = setChartPoint(i, chrtDir, chrtVal, chrtScale);
|
||||
// if (i >= (numBufVals / chrtIntv) - 5) // log chart data of x lines (adjust for test purposes)
|
||||
// LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %.2f, chrtMin: %.2f, {x,y} {%d,%d}", i, chrtVal, chrtMin, point.x, point.y);
|
||||
point = setCurrentChartPoint(i, direction, chrtVal, chrtScale);
|
||||
|
||||
// if (i >= (numBufVals / chrtIntv) - 5) // log chart data of 1 line (adjust for test purposes)
|
||||
// LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: i: %d, chrtVal: %.2f, chrtMin: %.2f, {x,y} {%d,%d}", i, chrtVal, chrtMin, x, y);
|
||||
|
||||
if ((i == 0) || (chrtPrevVal == dbMAX_VAL)) {
|
||||
prevPoint = point; // just a dot for 1st chart point or after some invalid values
|
||||
// just a dot for 1st chart point or after some invalid values
|
||||
prevPoint = point;
|
||||
|
||||
} else if (chrtDataFmt == WIND || chrtDataFmt == ROTATION) {
|
||||
// cross borders check for degree values; shift values to [-PI..0..PI]; when crossing borders, range is 2x PI degrees
|
||||
@@ -380,7 +361,7 @@ void Chart::drawChartLines(const ChrtDir chrtDir, const int8_t chrtIntv, const d
|
||||
// LOG_DEBUG(GwLog::DEBUG, "PageWindPlot Chart: crossedBorders: %d, chrtVal: %.2f, chrtPrevVal: %.2f", crossedBorders, chrtVal, chrtPrevVal);
|
||||
bool wrappingFromHighToLow = normCurrVal < normPrevVal; // Determine which edge we're crossing
|
||||
|
||||
if (chrtDir == HORIZONTAL) {
|
||||
if (direction == HORIZONTAL) {
|
||||
int ySplit = wrappingFromHighToLow ? (cRoot.y + valAxis) : cRoot.y;
|
||||
drawBoldLine(prevPoint.x, prevPoint.y, point.x, ySplit);
|
||||
prevPoint.y = wrappingFromHighToLow ? cRoot.y : (cRoot.y + valAxis);
|
||||
@@ -391,19 +372,10 @@ void Chart::drawChartLines(const ChrtDir chrtDir, const int8_t chrtIntv, const d
|
||||
prevPoint.x = wrappingFromHighToLow ? cRoot.x : (cRoot.x + valAxis);
|
||||
}
|
||||
}
|
||||
|
||||
// test position of chart point against chart middle; ignore first values which we don't show next time anyway
|
||||
if (i > MIN_FREE_VALUES) {
|
||||
double d = WindUtils::toPI(chrtVal - chrtMid);
|
||||
if (d > 0) // point is right of mid point
|
||||
allLeft = false;
|
||||
if (d < 0) // point is left of mid point
|
||||
allRight = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (chrtDataFmt == DEPTH) {
|
||||
if (chrtDir == HORIZONTAL) { // horizontal chart
|
||||
if (direction == HORIZONTAL) { // horizontal chart
|
||||
drawBoldLine(point.x, point.y, point.x, cRoot.y + valAxis);
|
||||
} else { // vertical chart
|
||||
drawBoldLine(point.x, point.y, cRoot.x + valAxis, point.y);
|
||||
@@ -420,36 +392,31 @@ void Chart::drawChartLines(const ChrtDir chrtDir, const int8_t chrtIntv, const d
|
||||
if (i >= timAxis - 1) {
|
||||
oldChrtIntv = 0; // force reset of buffer start and number of values to show in next display loop
|
||||
|
||||
if (chrtDataFmt == WIND) {
|
||||
if (allLeft || allRight || chrtRng == M_TWOPI) { // check if we should recalculate chart axis middle value
|
||||
if (chrtDataFmt == WIND) { // degree of course or wind
|
||||
recalcRngMid = true;
|
||||
}
|
||||
// LOG_DEBUG(GwLog::DEBUG, "OBPcharts: WIND chart end: timAxis: %d, i: %d, bufStart: %d, numBufVals: %d, recalcRngCntr: %d, allLeft: %d, allRight: %d", timAxis, i, bufStart,
|
||||
// numBufVals, recalcRngMid, allLeft, allRight);
|
||||
allLeft = true; // reset marker for all left/right chart points
|
||||
allRight = true;
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot: chart end: timAxis: %d, i: %d, bufStart: %d, numBufVals: %d, recalcRngCntr: %d", timAxis, i, bufStart, numBufVals, recalcRngMid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
taskYIELD(); // we run for 50-150ms, so we want to be polite to other tasks with same priority
|
||||
taskYIELD(); // we run for 50-150ms; be polite to other tasks with same priority
|
||||
}
|
||||
}
|
||||
|
||||
// Set current chart point to draw
|
||||
Pos Chart::setChartPoint(const int i, const ChrtDir chrtDir, const double chrtVal, const double chrtScale)
|
||||
Pos Chart::setCurrentChartPoint(const int i, const char direction, const double chrtVal, const double chrtScale)
|
||||
{
|
||||
Pos currentPoint;
|
||||
|
||||
if (chrtDir == HORIZONTAL) {
|
||||
if (direction == HORIZONTAL) {
|
||||
currentPoint.x = cRoot.x + i; // Position in chart area
|
||||
|
||||
if (chrtDataFmt == WIND || chrtDataFmt == ROTATION) { // degree type value
|
||||
currentPoint.y = cRoot.y + static_cast<int>((WindUtils::to2PI(chrtVal - chrtMin) * chrtScale) + 0.5); // calculate chart point and round
|
||||
} else if (chrtDataFmt == WIND || chrtDataFmt == ROTATION || chrtDataFmt == DEPTH) { // print low values at bottom
|
||||
currentPoint.y = cRoot.y + static_cast<int>(((chrtVal - chrtMin) * chrtScale) + 0.5); // calculate chart point and round
|
||||
} else { // any other data format
|
||||
} else if (chrtDataFmt == SPEED or chrtDataFmt == TEMPERATURE) { // speed or temperature data format -> print low values at bottom
|
||||
currentPoint.y = cRoot.y + valAxis - static_cast<int>(((chrtVal - chrtMin) * chrtScale) + 0.5); // calculate chart point and round
|
||||
} else { // any other data format
|
||||
currentPoint.y = cRoot.y + static_cast<int>(((chrtVal - chrtMin) * chrtScale) + 0.5); // calculate chart point and round
|
||||
}
|
||||
|
||||
} else { // vertical chart
|
||||
@@ -466,94 +433,88 @@ Pos Chart::setChartPoint(const int i, const ChrtDir chrtDir, const double chrtVa
|
||||
}
|
||||
|
||||
// chart time axis label + lines
|
||||
void Chart::drawChrtTimeAxis(const ChrtDir chrtDir, const ChrtSize chrtSz, const int8_t chrtIntv)
|
||||
void Chart::drawChrtTimeAxis(const char chrtDir, const int8_t chrtSz, const int8_t chrtIntv)
|
||||
{
|
||||
int axSlots, intv, i, timeRng;
|
||||
float axSlots, intv, i;
|
||||
char sTime[6];
|
||||
int tOffset;
|
||||
int timeRng = chrtIntv * 4; // chart time interval: [1] 4 min., [2] 8 min., [3] 12 min., [4] 16 min., [8] 32 min.
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setTextColor(fgColor);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setTextColor(fgColor);
|
||||
|
||||
intv = 60; // print axis label each 60 pixels = seconds
|
||||
axSlots = timAxis / intv; // number of axis labels; value will be truncated to full number
|
||||
axSlots = 5; // number of axis labels
|
||||
intv = timAxis / (axSlots - 1); // minutes per chart axis interval (interval is 1 less than axSlots)
|
||||
i = timeRng; // Chart axis label start at -32, -16, -12, ... minutes
|
||||
|
||||
if (chrtDir == HORIZONTAL) {
|
||||
getdisplay().fillRect(0, cRoot.y, dWidth, 2, fgColor);
|
||||
epd->fillRect(0, cRoot.y, dWidth, 2, fgColor);
|
||||
|
||||
i = axSlots * chrtIntv * -1; // current minute label
|
||||
// LOG_DEBUG(GwLog::DEBUG, "Chart::drawChrtTimeAxis: intv: %d, axSlots: %d, timAxis: %d, chrtIntv: %d", intv, axSlots, timAxis, chrtIntv);
|
||||
for (int j = intv; j < timAxis - 1; j += intv) { // fill time axis with values but keep area free on right hand side for value label
|
||||
for (float j = 0; j < timAxis - 1; j += intv) { // fill time axis with values but keep area free on right hand side for value label
|
||||
|
||||
// draw text with appropriate offset
|
||||
tOffset = j == 0 ? 13 : -4;
|
||||
snprintf(sTime, sizeof(sTime), "%d", i);
|
||||
int tOffset = j == 0 ? 13 : -4;
|
||||
snprintf(sTime, sizeof(sTime), "-%.0f", i);
|
||||
drawTextCenter(cRoot.x + j + tOffset, cRoot.y - 8, sTime);
|
||||
getdisplay().drawLine(cRoot.x + j, cRoot.y, cRoot.x + j, cRoot.y + 5, fgColor); // draw short vertical time mark
|
||||
epd->drawLine(cRoot.x + j, cRoot.y, cRoot.x + j, cRoot.y + 5, fgColor); // draw short vertical time mark
|
||||
|
||||
i += chrtIntv;
|
||||
i -= chrtIntv;
|
||||
}
|
||||
|
||||
} else { // vertical chart
|
||||
|
||||
i = chrtIntv * -1; // current minute label
|
||||
for (float j = intv; j < timAxis - 1; j += intv) { // don't print time label at upper and lower end of time axis
|
||||
|
||||
snprintf(sTime, sizeof(sTime), "%d", i);
|
||||
getdisplay().drawLine(cRoot.x, cRoot.y + j, cRoot.x + valAxis - 2, cRoot.y + j, fgColor); // Grid line
|
||||
i -= chrtIntv; // we start not at top chart position
|
||||
snprintf(sTime, sizeof(sTime), "-%.0f", i);
|
||||
epd->drawLine(cRoot.x, cRoot.y + j, cRoot.x + valAxis, cRoot.y + j, fgColor); // Grid line
|
||||
|
||||
if (chrtSz == FULL_SIZE) { // full size chart
|
||||
getdisplay().fillRect(0, cRoot.y + j - 9, 32, 15, bgColor); // clear small area to remove potential chart lines
|
||||
getdisplay().setCursor((4 - strlen(sTime)) * 7, cRoot.y + j + 3); // time value; print left screen; value right-formated
|
||||
getdisplay().printf("%s", sTime); // time value
|
||||
} else if (chrtSz == HALF_SIZE_RIGHT_BOTTOM) { // half size chart; right side
|
||||
epd->fillRect(0, cRoot.y + j - 9, 32, 15, bgColor); // clear small area to remove potential chart lines
|
||||
epd->setCursor((4 - strlen(sTime)) * 7, cRoot.y + j + 3); // time value; print left screen; value right-formated
|
||||
epd->printf("%s", sTime); // Range value
|
||||
} else if (chrtSz == HALF_SIZE_RIGHT) { // half size chart; right side
|
||||
drawTextCenter(dWidth / 2, cRoot.y + j, sTime); // time value; print mid screen
|
||||
}
|
||||
i -= chrtIntv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// chart value axis labels + lines
|
||||
void Chart::drawChrtValAxis(const ChrtDir chrtDir, const ChrtSize chrtSz, const bool prntName)
|
||||
void Chart::drawChrtValAxis(const char chrtDir, const int8_t chrtSz, bool prntName)
|
||||
{
|
||||
const GFXfont* font;
|
||||
// constexpr bool NO_LABEL = false;
|
||||
// constexpr bool LABEL = true;
|
||||
constexpr bool NO_LABEL = false;
|
||||
constexpr bool LABEL = true;
|
||||
|
||||
getdisplay().setTextColor(fgColor);
|
||||
epd->setTextColor(fgColor);
|
||||
|
||||
if (chrtDir == HORIZONTAL) {
|
||||
|
||||
if (chrtSz == FULL_SIZE) {
|
||||
|
||||
if (prntName) {
|
||||
// print buffer data name on left hand side of time axis (max. size 5 characters)
|
||||
font = &Ubuntu_Bold12pt8b;
|
||||
getdisplay().setFont(font);
|
||||
getdisplay().fillRect(cRoot.x + timAxis - 57, cRoot.y + 2, 58, 20, bgColor); // clear small area to remove potential chart lines
|
||||
String name = xdrDelete(dbName); // Value name
|
||||
drawTextRalign(cRoot.x + timAxis - 1, cRoot.y + 19, name.substring(0, 5));
|
||||
}
|
||||
|
||||
// print buffer data name on right hand side of time axis (max. size 5 characters)
|
||||
epd->setFont(font);
|
||||
drawTextRalign(cRoot.x + timAxis, cRoot.y - 3, dbName.substring(0, 5));
|
||||
|
||||
if (chrtDataFmt == WIND) {
|
||||
prntHorizChartThreeValueAxisLabel(font);
|
||||
return;
|
||||
}
|
||||
|
||||
// for any other data formats print multiple axis value lines on full charts
|
||||
font = &Ubuntu_Bold10pt8b;
|
||||
prntHorizChartMultiValueAxisLabel(font);
|
||||
return;
|
||||
|
||||
} else { // half size chart -> just print edge values + middle chart line
|
||||
|
||||
font = &Ubuntu_Bold10pt8b;
|
||||
|
||||
if (prntName) {
|
||||
// print buffer data name on right hand side of time axis (max. size 6 characters)
|
||||
getdisplay().setFont(font);
|
||||
getdisplay().fillRect(cRoot.x + timAxis - 57, cRoot.y + 2, 58, 16, bgColor); // clear small area to remove potential chart lines
|
||||
String name = xdrDelete(dbName); // Value name
|
||||
drawTextRalign(cRoot.x + timAxis - 1, cRoot.y + 16, name.substring(0, 6));
|
||||
// print buffer data name on right hand side of time axis (max. size 5 characters)
|
||||
epd->setFont(font);
|
||||
drawTextRalign(cRoot.x + timAxis, cRoot.y - 3, dbName.substring(0, 5));
|
||||
}
|
||||
|
||||
prntHorizChartThreeValueAxisLabel(font);
|
||||
@@ -562,67 +523,53 @@ void Chart::drawChrtValAxis(const ChrtDir chrtDir, const ChrtSize chrtSz, const
|
||||
|
||||
} else { // vertical chart
|
||||
|
||||
if (prntName) {
|
||||
if (chrtSz == FULL_SIZE) {
|
||||
font = &Ubuntu_Bold12pt8b;
|
||||
epd->setFont(font); // use larger font
|
||||
drawTextRalign(cRoot.x + (valAxis * 0.42), cRoot.y - 2, dbName.substring(0, 6)); // print buffer data name (max. size 5 characters)
|
||||
|
||||
} else {
|
||||
font = &Ubuntu_Bold10pt8b;
|
||||
}
|
||||
getdisplay().setFont(font);
|
||||
String name = xdrDelete(dbName); // Value name
|
||||
drawTextRalign(cRoot.x + (valAxis * 0.42), cRoot.y - 2, name.substring(0, 6)); // print buffer data name (max. size 6 characters)
|
||||
}
|
||||
|
||||
font = &Ubuntu_Bold10pt8b;
|
||||
}
|
||||
|
||||
prntVerticChartThreeValueAxisLabel(font);
|
||||
}
|
||||
}
|
||||
|
||||
// Print current data value
|
||||
void Chart::prntCurrValue(const ChrtDir chrtDir, GwApi::BoatValue& currValue)
|
||||
void Chart::prntCurrValue(const char direction, GwApi::BoatValue& currValue)
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
static constexpr bool smallDecimals = true; // print data value always with small decimals
|
||||
const int xPosVal = (direction == HORIZONTAL) ? cRoot.x + (timAxis / 2) - 56 : cRoot.x + 32;
|
||||
const int yPosVal = (direction == HORIZONTAL) ? cRoot.y + valAxis - 7 : cRoot.y + timAxis - 7;
|
||||
|
||||
const int xPosVal = (chrtDir == HORIZONTAL) ? cRoot.x + (timAxis / 2) - 74 : cRoot.x + 31;
|
||||
const int yPosVal = (chrtDir == HORIZONTAL) ? cRoot.y + valAxis : cRoot.y + timAxis;
|
||||
|
||||
FormattedData frmtDbData = formatValue(&currValue, *commonData, NO_SIMUDATA);
|
||||
FormattedData frmtDbData = commonData->fmt->formatValue(&currValue, *commonData, NO_SIMUDATA);
|
||||
String sdbValue = frmtDbData.svalue; // value as formatted string
|
||||
String dbUnit = frmtDbData.unit; // Unit of value; limit length to 3 characters
|
||||
|
||||
// box
|
||||
getdisplay().fillRect(xPosVal - 1, yPosVal - 40, 148, 39, bgColor); // Clear area for value
|
||||
getdisplay().drawRect(xPosVal, yPosVal - 39, 146, 37, fgColor); // Draw box for value
|
||||
epd->fillRect(xPosVal - 1, yPosVal - 35, 128, 41, bgColor); // Clear area for TWS value
|
||||
epd->drawRect(xPosVal, yPosVal - 34, 126, 40, fgColor); // Draw box for TWS value
|
||||
epd->setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||
epd->setCursor(xPosVal + 1, yPosVal);
|
||||
epd->print(sdbValue); // value
|
||||
|
||||
// value
|
||||
printBoatValue(sdbValue, xPosVal + 93, yPosVal - 6, RIGHT, 16, smallDecimals);
|
||||
// getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||
// getdisplay().setCursor(xPosVal + 1, yPosVal - 6);
|
||||
// getdisplay().print(sdbValue);
|
||||
epd->setFont(&Ubuntu_Bold10pt8b);
|
||||
epd->setCursor(xPosVal + 76, yPosVal - 17);
|
||||
epd->print(dbName.substring(0, 3)); // Name, limited to 3 characters
|
||||
|
||||
// name
|
||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
||||
getdisplay().setCursor(xPosVal + 97, yPosVal - 23);
|
||||
String name = xdrDelete(dbName);
|
||||
getdisplay().print(name.substring(0, 3)); // Name, limited to 3 characters
|
||||
|
||||
// unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(xPosVal + 98, yPosVal - 8);
|
||||
getdisplay().print(dbUnit);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(xPosVal + 76, yPosVal + 0);
|
||||
epd->print(dbUnit); // Unit
|
||||
}
|
||||
|
||||
// print message for no valid data availabletemplate <typename T>
|
||||
void Chart::prntNoValidData(const ChrtDir chrtDir)
|
||||
void Chart::prntNoValidData(const char direction)
|
||||
{
|
||||
Pos p;
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
||||
epd->setFont(&Ubuntu_Bold10pt8b);
|
||||
|
||||
if (chrtDir == HORIZONTAL) {
|
||||
if (direction == HORIZONTAL) {
|
||||
p.x = cRoot.x + (timAxis / 2);
|
||||
p.y = cRoot.y + (valAxis / 2) - 10;
|
||||
} else {
|
||||
@@ -630,14 +577,14 @@ void Chart::prntNoValidData(const ChrtDir chrtDir)
|
||||
p.y = cRoot.y + (timAxis / 2) - 10;
|
||||
}
|
||||
|
||||
getdisplay().fillRect(p.x - 37, p.y - 10, 78, 24, bgColor); // Clear area for message
|
||||
epd->fillRect(p.x - 37, p.y - 10, 78, 24, bgColor); // Clear area for message
|
||||
drawTextCenter(p.x, p.y, "No data");
|
||||
|
||||
LOG_DEBUG(GwLog::LOG, "Page chart <%s>: No valid data available", dbName);
|
||||
}
|
||||
|
||||
// Get maximum difference of last <amount> of dataBuf ringbuffer values to center chart; for angle data only
|
||||
double Chart::getCircularRng(const double center, size_t amount)
|
||||
double Chart::getAngleRng(const double center, size_t amount)
|
||||
{
|
||||
size_t count = dataBuf.getCurrentSize();
|
||||
|
||||
@@ -677,28 +624,28 @@ void Chart::prntVerticChartThreeValueAxisLabel(const GFXfont* font)
|
||||
double cVal;
|
||||
char sVal[7];
|
||||
|
||||
getdisplay().fillRect(cRoot.x, cRoot.y, valAxis, 2, fgColor); // top chart line
|
||||
getdisplay().setFont(font);
|
||||
epd->fillRect(cRoot.x, cRoot.y, valAxis, 2, fgColor); // top chart line
|
||||
epd->setFont(font);
|
||||
|
||||
cVal = chrtMin;
|
||||
cVal = convertValue(cVal, dbName, dbFormat, *commonData); // value (converted)
|
||||
cVal = commonData->fmt->convertValue(cVal, dbName, dbFormat, *commonData); // value (converted)
|
||||
snprintf(sVal, sizeof(sVal), "%.0f", round(cVal));
|
||||
getdisplay().setCursor(cRoot.x, cRoot.y - 2);
|
||||
getdisplay().printf("%s", sVal); // Range low end
|
||||
epd->setCursor(cRoot.x, cRoot.y - 2);
|
||||
epd->printf("%s", sVal); // Range low end
|
||||
|
||||
cVal = chrtMid;
|
||||
cVal = convertValue(cVal, dbName, dbFormat, *commonData); // value (converted)
|
||||
cVal = commonData->fmt->convertValue(cVal, dbName, dbFormat, *commonData); // value (converted)
|
||||
snprintf(sVal, sizeof(sVal), "%.0f", round(cVal));
|
||||
drawTextCenter(cRoot.x + (valAxis / 2), cRoot.y - 9, sVal); // Range mid end
|
||||
|
||||
cVal = chrtMax;
|
||||
cVal = convertValue(cVal, dbName, dbFormat, *commonData); // value (converted)
|
||||
cVal = commonData->fmt->convertValue(cVal, dbName, dbFormat, *commonData); // value (converted)
|
||||
snprintf(sVal, sizeof(sVal), "%.0f", round(cVal));
|
||||
drawTextRalign(cRoot.x + valAxis - 2, cRoot.y - 2, sVal); // Range high end
|
||||
|
||||
// draw vertical grid lines for each axis label
|
||||
for (int j = 0; j <= valAxis; j += (valAxis / 2)) {
|
||||
getdisplay().drawLine(cRoot.x + j, cRoot.y, cRoot.x + j, cRoot.y + timAxis, fgColor);
|
||||
epd->drawLine(cRoot.x + j, cRoot.y, cRoot.x + j, cRoot.y + timAxis, fgColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -708,114 +655,92 @@ void Chart::prntHorizChartThreeValueAxisLabel(const GFXfont* font)
|
||||
double axLabel;
|
||||
double chrtMin, chrtMid, chrtMax;
|
||||
int xOffset, yOffset; // offset for text position of x axis label for different font sizes
|
||||
char sVal[11]; // data value have max. 6 digits + decimal point + 2 decimals + sign
|
||||
String sVal;
|
||||
|
||||
if (font == &Ubuntu_Bold10pt8b) {
|
||||
xOffset = 32;
|
||||
xOffset = 39;
|
||||
yOffset = 16;
|
||||
} else if (font == &Ubuntu_Bold12pt8b) {
|
||||
xOffset = 42;
|
||||
xOffset = 51;
|
||||
yOffset = 18;
|
||||
}
|
||||
getdisplay().setFont(font);
|
||||
epd->setFont(font);
|
||||
|
||||
// convert & round chart bottom+top label to next range step
|
||||
chrtMin = convertValue(this->chrtMin, dbName, dbFormat, *commonData);
|
||||
chrtMid = convertValue(this->chrtMid, dbName, dbFormat, *commonData);
|
||||
chrtMax = convertValue(this->chrtMax, dbName, dbFormat, *commonData);
|
||||
chrtMin = commonData->fmt->convertValue(this->chrtMin, dbName, dbFormat, *commonData);
|
||||
chrtMid = commonData->fmt->convertValue(this->chrtMid, dbName, dbFormat, *commonData);
|
||||
chrtMax = commonData->fmt->convertValue(this->chrtMax, dbName, dbFormat, *commonData);
|
||||
chrtMin = std::round(chrtMin * 100.0) / 100.0;
|
||||
chrtMid = std::round(chrtMid * 100.0) / 100.0;
|
||||
chrtMax = std::round(chrtMax * 100.0) / 100.0;
|
||||
|
||||
// print top axis label
|
||||
axLabel = (chrtDataFmt == WIND || chrtDataFmt == ROTATION || chrtDataFmt == DEPTH) ? chrtMin : chrtMax;
|
||||
formatLabel(axLabel).toCharArray(sVal, 11);
|
||||
if (chrtDataFmt == PRESSURE) {
|
||||
snprintf(sVal, sizeof(sVal), "%4.0f", axLabel);
|
||||
getdisplay().fillRect(cRoot.x, cRoot.y + 2, xOffset + 12, yOffset, bgColor); // Clear small area to remove potential chart lines
|
||||
drawTextRalign(cRoot.x + xOffset + 11, cRoot.y + yOffset, sVal); // range value
|
||||
} else {
|
||||
if (char* dot = strchr(sVal, '.'))
|
||||
*dot = '\0'; // no decimal for top axis label
|
||||
getdisplay().fillRect(cRoot.x, cRoot.y + 2, xOffset + 3, yOffset, bgColor); // Clear small area to remove potential chart lines
|
||||
axLabel = (chrtDataFmt == SPEED || chrtDataFmt == TEMPERATURE) ? chrtMax : chrtMin;
|
||||
sVal = formatLabel(axLabel);
|
||||
epd->fillRect(cRoot.x, cRoot.y + 2, xOffset + 3, yOffset, bgColor); // Clear small area to remove potential chart lines
|
||||
drawTextRalign(cRoot.x + xOffset, cRoot.y + yOffset, sVal); // range value
|
||||
}
|
||||
|
||||
// print mid axis label
|
||||
axLabel = chrtMid;
|
||||
formatLabel(axLabel).toCharArray(sVal, 11);
|
||||
if (chrtDataFmt == PRESSURE) { // print 4-digit value
|
||||
getdisplay().fillRect(cRoot.x, cRoot.y + (valAxis / 2) - 8, xOffset + 12, yOffset, bgColor); // Clear small area to remove potential chart lines
|
||||
drawTextRalign(cRoot.x + xOffset + 11, cRoot.y + (valAxis / 2) + 6, sVal); // range value
|
||||
getdisplay().drawLine(cRoot.x + xOffset + 14, cRoot.y + (valAxis / 2), cRoot.x + timAxis, cRoot.y + (valAxis / 2), fgColor);
|
||||
} else { // print 3-digit value
|
||||
getdisplay().fillRect(cRoot.x, cRoot.y + (valAxis / 2) - 8, xOffset + 3, yOffset, bgColor); // Clear small area to remove potential chart lines
|
||||
sVal = formatLabel(axLabel);
|
||||
epd->fillRect(cRoot.x, cRoot.y + (valAxis / 2) - 8, xOffset + 3, 16, bgColor); // Clear small area to remove potential chart lines
|
||||
drawTextRalign(cRoot.x + xOffset, cRoot.y + (valAxis / 2) + 6, sVal); // range value
|
||||
getdisplay().drawLine(cRoot.x + xOffset + 3, cRoot.y + (valAxis / 2), cRoot.x + timAxis, cRoot.y + (valAxis / 2), fgColor);
|
||||
}
|
||||
epd->drawLine(cRoot.x + xOffset + 3, cRoot.y + (valAxis / 2), cRoot.x + timAxis, cRoot.y + (valAxis / 2), fgColor);
|
||||
|
||||
// print bottom axis label
|
||||
axLabel = (chrtDataFmt == WIND || chrtDataFmt == ROTATION || chrtDataFmt == DEPTH) ? chrtMax : chrtMin;
|
||||
formatLabel(axLabel).toCharArray(sVal, 11);
|
||||
if (chrtDataFmt == PRESSURE) {
|
||||
getdisplay().fillRect(cRoot.x, cRoot.y + valAxis - 14, xOffset + 12, yOffset, bgColor); // Clear small area to remove potential chart lines
|
||||
drawTextRalign(cRoot.x + xOffset + 11, cRoot.y + valAxis, sVal); // range value
|
||||
getdisplay().drawLine(cRoot.x + xOffset + 14, cRoot.y + valAxis, cRoot.x + timAxis, cRoot.y + valAxis, fgColor);
|
||||
} else {
|
||||
if (char* dot = strchr(sVal, '.'))
|
||||
*dot = '\0'; // no decimal for bottom axis label
|
||||
getdisplay().fillRect(cRoot.x, cRoot.y + valAxis - 14, xOffset + 3, yOffset, bgColor); // Clear small area to remove potential chart lines
|
||||
axLabel = (chrtDataFmt == SPEED || chrtDataFmt == TEMPERATURE) ? chrtMin : chrtMax;
|
||||
sVal = formatLabel(axLabel);
|
||||
epd->fillRect(cRoot.x, cRoot.y + valAxis - 14, xOffset + 3, 15, bgColor); // Clear small area to remove potential chart lines
|
||||
drawTextRalign(cRoot.x + xOffset, cRoot.y + valAxis, sVal); // range value
|
||||
getdisplay().drawLine(cRoot.x + xOffset + 3, cRoot.y + valAxis, cRoot.x + timAxis, cRoot.y + valAxis, fgColor);
|
||||
}
|
||||
epd->drawLine(cRoot.x + xOffset + 3, cRoot.y + valAxis, cRoot.x + timAxis, cRoot.y + valAxis, fgColor);
|
||||
}
|
||||
|
||||
// print value axis label with multiple axis lines for horizontal chart
|
||||
void Chart::prntHorizChartMultiValueAxisLabel(const GFXfont* font)
|
||||
{
|
||||
double chrtMin, chrtMax, chrtRng;
|
||||
double axSlots, axIntv, axLabel;
|
||||
int xOffset; // offset for text position of x axis label for different font sizes
|
||||
char sVal[11]; // data value have max. 6 digits + decimal point + 2 decimals + sign
|
||||
String sVal;
|
||||
|
||||
if (font == &Ubuntu_Bold10pt8b) {
|
||||
xOffset = 32;
|
||||
xOffset = 38;
|
||||
} else if (font == &Ubuntu_Bold12pt8b) {
|
||||
xOffset = 42;
|
||||
xOffset = 50;
|
||||
}
|
||||
getdisplay().setFont(font);
|
||||
epd->setFont(font);
|
||||
|
||||
chrtMin = convertValue(this->chrtMin, dbName, dbFormat, *commonData);
|
||||
chrtMax = convertValue(this->chrtMax, dbName, dbFormat, *commonData);
|
||||
chrtRng = chrtMax - chrtMin;
|
||||
chrtMin = commonData->fmt->convertValue(this->chrtMin, dbName, dbFormat, *commonData);
|
||||
// chrtMin = std::floor(chrtMin / rngStep) * rngStep;
|
||||
chrtMin = std::round(chrtMin * 100.0) / 100.0;
|
||||
chrtMax = commonData->fmt->convertValue(this->chrtMax, dbName, dbFormat, *commonData);
|
||||
// chrtMax = std::ceil(chrtMax / rngStep) * rngStep;
|
||||
chrtMax = std::round(chrtMax * 100.0) / 100.0;
|
||||
chrtRng = std::round((chrtMax - chrtMin) * 100) / 100;
|
||||
|
||||
double axIntv = chrtRng / VALAXIS_SLOTS; // axis label interval
|
||||
double axLabel = chrtMin + axIntv; // current axis label
|
||||
double chrtScale = double(valAxis) / chrtRng; // Chart scale: pixels per value step
|
||||
double valAxisStep = axIntv * chrtScale; // pixel per axis label interval
|
||||
|
||||
// LOG_DEBUG(GwLog::DEBUG, "Chart::printHorizMultiValueAxisLabel: chrtRng: %.2f, th-chrtRng: %.2f, axSlots: %.2f, axIntv: %.2f, axLabel: %.2f, chrtMin: %.2f, chrtMid: %.2f, chrtMax: %.2f", chrtRng, this->chrtRng, VALAXIS_SLOTS, axIntv, axLabel, this->chrtMin, chrtMid, chrtMax);
|
||||
axSlots = valAxis / static_cast<double>(VALAXIS_STEP); // number of axis labels (and we want to have a double calculation, no integer)
|
||||
axIntv = chrtRng / axSlots;
|
||||
axLabel = chrtMin + axIntv;
|
||||
// LOG_DEBUG(GwLog::DEBUG, "Chart::printHorizMultiValueAxisLabel: chrtRng: %.2f, th-chrtRng: %.2f, axSlots: %.2f, axIntv: %.2f, axLabel: %.2f, chrtMin: %.2f, chrtMid: %.2f, chrtMax: %.2f", chrtRng, this->chrtRng, axSlots, axIntv, axLabel, this->chrtMin, chrtMid, chrtMax);
|
||||
|
||||
int loopStrt, loopEnd, loopStp;
|
||||
if (chrtDataFmt == WIND || chrtDataFmt == ROTATION || chrtDataFmt == DEPTH) {
|
||||
// Low value at top
|
||||
loopStrt = valAxisStep;
|
||||
loopEnd = valAxis - (valAxisStep / 2);
|
||||
loopStp = valAxisStep;
|
||||
if (chrtDataFmt == SPEED || chrtDataFmt == TEMPERATURE || chrtDataFmt == OTHER) {
|
||||
// High value at top
|
||||
loopStrt = valAxis - VALAXIS_STEP;
|
||||
loopEnd = VALAXIS_STEP / 2;
|
||||
loopStp = VALAXIS_STEP * -1;
|
||||
} else {
|
||||
// high value at top
|
||||
loopStrt = valAxis - valAxisStep;
|
||||
loopEnd = valAxisStep / 2;
|
||||
loopStp = valAxisStep * -1;
|
||||
// Low value at top
|
||||
loopStrt = VALAXIS_STEP;
|
||||
loopEnd = valAxis - (VALAXIS_STEP / 2);
|
||||
loopStp = VALAXIS_STEP;
|
||||
}
|
||||
|
||||
for (int j = loopStrt; (loopStp > 0) ? (j < loopEnd) : (j > loopEnd); j += loopStp) {
|
||||
formatLabel(axLabel).toCharArray(sVal, 11);
|
||||
if (chrtDataFmt == PRESSURE) { // print 4-digit value
|
||||
getdisplay().fillRect(cRoot.x, cRoot.y + j - 11, xOffset + 12, 21, bgColor); // Clear small area to remove potential chart lines
|
||||
drawTextRalign(cRoot.x + xOffset + 11, cRoot.y + j + 7, sVal); // range value
|
||||
getdisplay().drawLine(cRoot.x + xOffset + 14, cRoot.y + j, cRoot.x + timAxis, cRoot.y + j, fgColor);
|
||||
} else { // print 3-digit value
|
||||
getdisplay().fillRect(cRoot.x, cRoot.y + j - 11, xOffset + 3, 21, bgColor); // Clear small area to remove potential chart lines
|
||||
sVal = formatLabel(axLabel);
|
||||
epd->fillRect(cRoot.x, cRoot.y + j - 11, xOffset + 3, 21, bgColor); // Clear small area to remove potential chart lines
|
||||
drawTextRalign(cRoot.x + xOffset, cRoot.y + j + 7, sVal); // range value
|
||||
getdisplay().drawLine(cRoot.x + xOffset + 3, cRoot.y + j, cRoot.x + timAxis, cRoot.y + j, fgColor);
|
||||
}
|
||||
epd->drawLine(cRoot.x + xOffset + 3, cRoot.y + j, cRoot.x + timAxis, cRoot.y + j, fgColor);
|
||||
|
||||
axLabel += axIntv;
|
||||
}
|
||||
@@ -827,12 +752,12 @@ void Chart::drawBoldLine(const int16_t x1, const int16_t y1, const int16_t x2, c
|
||||
int16_t dx = std::abs(x2 - x1);
|
||||
int16_t dy = std::abs(y2 - y1);
|
||||
|
||||
getdisplay().drawLine(x1, y1, x2, y2, fgColor);
|
||||
epd->drawLine(x1, y1, x2, y2, fgColor);
|
||||
|
||||
if (dx >= dy) { // line has horizontal tendency
|
||||
getdisplay().drawLine(x1, y1 - 1, x2, y2 - 1, fgColor);
|
||||
epd->drawLine(x1, y1 - 1, x2, y2 - 1, fgColor);
|
||||
} else { // line has vertical tendency
|
||||
getdisplay().drawLine(x1 - 1, y1, x2 - 1, y2, fgColor);
|
||||
epd->drawLine(x1 - 1, y1, x2 - 1, y2, fgColor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -845,7 +770,7 @@ String Chart::convNformatLabel(const double& label)
|
||||
tmpBVal.setFormat(dbFormat);
|
||||
tmpBVal.valid = true;
|
||||
tmpBVal.value = label;
|
||||
sVal = formatValue(&tmpBVal, *commonData, NO_SIMUDATA).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
sVal = commonData->fmt->formatValue(&tmpBVal, *commonData, NO_SIMUDATA).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
if (sVal.length() > 0 && sVal[0] == '!') {
|
||||
sVal = sVal.substring(1); // cut leading "!" created at OBPFormatter; doesn't work for other fonts than 7SEG
|
||||
}
|
||||
@@ -858,21 +783,20 @@ String Chart::formatLabel(const double& label)
|
||||
{
|
||||
char sVal[11];
|
||||
|
||||
if (chrtDataFmt == WIND) {
|
||||
snprintf(sVal, sizeof(sVal), "%03.0f", label); // Format 3 numbers with prefix zero
|
||||
if (dbFormat == "formatCourse" || dbFormat == "formatWind") {
|
||||
// Format 3 numbers with prefix zero
|
||||
snprintf(sVal, sizeof(sVal), "%03.0f", label);
|
||||
|
||||
} else if (chrtDataFmt == ROTATION) {
|
||||
if (label > -9.995 && label < 9.995) {
|
||||
} else if (dbFormat == "formatRot") {
|
||||
if (label > -10 && label < 10) {
|
||||
snprintf(sVal, sizeof(sVal), "%3.2f", label);
|
||||
} else {
|
||||
snprintf(sVal, sizeof(sVal), "%3.0f", label);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (chrtDataFmt == PRESSURE) {
|
||||
snprintf(sVal, sizeof(sVal), "%4.0f", label);
|
||||
|
||||
} else {
|
||||
if (label < 9.95) {
|
||||
else {
|
||||
if (label < 10) {
|
||||
snprintf(sVal, sizeof(sVal), "%3.1f", label);
|
||||
} else {
|
||||
snprintf(sVal, sizeof(sVal), "%3.0f", label);
|
||||
|
||||
+31
-55
@@ -2,7 +2,6 @@
|
||||
#pragma once
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "movingAvg.h"
|
||||
|
||||
struct Pos {
|
||||
int x;
|
||||
@@ -19,30 +18,6 @@ class RingBuffer;
|
||||
class GwLog;
|
||||
|
||||
class Chart {
|
||||
public:
|
||||
enum ChrtDir {
|
||||
HORIZONTAL,
|
||||
VERTICAL
|
||||
};
|
||||
|
||||
enum ChrtSize {
|
||||
FULL_SIZE,
|
||||
HALF_SIZE_LEFT_TOP,
|
||||
HALF_SIZE_RIGHT_BOTTOM,
|
||||
TWO_THIRD_TOP
|
||||
};
|
||||
|
||||
static constexpr bool PRNT_NAME = true;
|
||||
static constexpr bool NO_PRNT_NAME = false;
|
||||
static constexpr bool PRNT_VALUE = true;
|
||||
static constexpr bool NO_PRNT_VALUE = false;
|
||||
|
||||
Chart(RingBuffer<uint16_t>& dataBuf, CommonData& common, bool useSimuData); // Chart object of data chart
|
||||
~Chart();
|
||||
bool init(); // initialize chart object parameters
|
||||
bool isValid() { return initValid; }; // Checks if chart object has been fully initialized
|
||||
void showChrt(const ChrtDir chrtDir, const ChrtSize chrtSz, const int8_t chrtIntv, bool prntName, bool showCurrValue, GwApi::BoatValue currValue); // Perform all actions to draw chart
|
||||
|
||||
protected:
|
||||
CommonData* commonData;
|
||||
GwLog* logger;
|
||||
@@ -53,24 +28,28 @@ protected:
|
||||
SPEED,
|
||||
DEPTH,
|
||||
TEMPERATURE,
|
||||
PRESSURE,
|
||||
HUMIDITY,
|
||||
OTHER
|
||||
};
|
||||
|
||||
static constexpr char HORIZONTAL = 'H';
|
||||
static constexpr char VERTICAL = 'V';
|
||||
static constexpr int8_t FULL_SIZE = 0;
|
||||
static constexpr int8_t HALF_SIZE_LEFT = 1;
|
||||
static constexpr int8_t HALF_SIZE_RIGHT = 2;
|
||||
|
||||
static constexpr int8_t MIN_FREE_VALUES = 60; // free 60 values when chart line reaches chart end
|
||||
static constexpr int8_t THRESHOLD_NO_DATA = 3; // max. seconds of invalid values in a row
|
||||
static constexpr int8_t VALAXIS_SLOTS = 5; // no. of value axis labels
|
||||
static constexpr int8_t VALAXIS_STEP = 60; // pixels between two chart value axis labels
|
||||
|
||||
static constexpr bool NO_SIMUDATA = true; // switch off simulation feature of <formatValue> function
|
||||
|
||||
RingBuffer<uint16_t>& dataBuf; // Buffer to display
|
||||
bool initValid = false; // indicates whether object holds valid initialization data or not
|
||||
//char chrtDir; // Chart timeline direction: 'H' = horizontal, 'V' = vertical
|
||||
//int8_t chrtSz; // Chart size: [0] = full size, [1] = half size left/top, [2] half size right/bottom
|
||||
double dfltRng; // Default range of chart, e.g. 30 = [0..30]
|
||||
uint16_t fgColor; // color code for any screen writing
|
||||
uint16_t bgColor; // color code for screen background
|
||||
bool useSimuData; // flag to indicate if simulation data is active
|
||||
bool smoothCharts; // flag to indicate if charts shall be printed with smoothed gradient
|
||||
String tempFormat; // user defined format for temperature
|
||||
double zeroValue; // "0" SI value for temperature
|
||||
|
||||
@@ -87,8 +66,7 @@ protected:
|
||||
double chrtMax; // Range high end value
|
||||
double chrtMid; // Range mid value
|
||||
double rngStep; // Defines the step of adjustment (e.g. 10 m/s) for value axis range
|
||||
bool recalcRngMid; // Flag for re-calculation of mid value of chart for wind data types
|
||||
bool allLeft, allRight; // indicate whether all chart points are left or right of middle value (only for wind data type)
|
||||
bool recalcRngMid = false; // Flag for re-calculation of mid value of chart for wind data types
|
||||
|
||||
String dbName, dbFormat; // Name and format of data buffer
|
||||
ChrtDataFormat chrtDataFmt; // Data format of chart boat data type
|
||||
@@ -99,42 +77,40 @@ protected:
|
||||
int numBufVals; // number of wind values available for current interval selection
|
||||
int bufStart; // 1st data value in buffer to show
|
||||
int numAddedBufVals; // Number of values added to buffer since last display
|
||||
size_t currIdx; // Current index in history buffer
|
||||
size_t lastIdx; // Last index of history buffer
|
||||
size_t lastAddedIdx = 0; // Last index of history buffer when new data was added
|
||||
size_t currIdx; // Current index in TWD history buffer
|
||||
size_t lastIdx; // Last index of TWD history buffer
|
||||
size_t lastAddedIdx = 0; // Last index of TWD history buffer when new data was added
|
||||
int numNoData; // Counter for multiple invalid data values in a row
|
||||
bool bufDataValid = false; // Flag to indicate if buffer data is valid
|
||||
int oldChrtIntv = 0; // remember recent user selection of data interval
|
||||
|
||||
double chrtPrevVal; // Last data value in chart area
|
||||
int x, y; // x and y coordinates for drawing
|
||||
int prevX, prevY; // Last x and y coordinates for drawing
|
||||
|
||||
// Default ranges for various boat data types
|
||||
// Parameters: <1st value> default range, <2nd value> step for range adjustment
|
||||
std::map<String, ChartProps> dfltChrtDta = {
|
||||
{ "formatWind", { 60.0 * DEG_TO_RAD, 10.0 * DEG_TO_RAD } }, // default wind range 60 degrees
|
||||
{ "formatCourse", { 60.0 * DEG_TO_RAD, 10.0 * DEG_TO_RAD } }, // default course range 60 degrees
|
||||
{ "formatKnots", { 2.572, 2.572 } }, // default speed range in m/s
|
||||
{ "formatDepth", { 10.0, 5.0 } }, // default depth range in m
|
||||
{ "kelvinToC", { 20.0, 5.0 } }, // default temp range in °C/K
|
||||
{ "formatXdr:P:P", { 4000.0, 1000.0 } } // default pressure range in Pascal (hPa * 100); XDR <B> (bar) format is represented in gateway in the same way
|
||||
};
|
||||
|
||||
bool setChartDimensions(const ChrtDir direction, const ChrtSize chrtSz); // define dimensions and start points for chart
|
||||
void drawChrt(const ChrtDir chrtDir, const int8_t chrtIntv, GwApi::BoatValue& currValue); // Draw chart line
|
||||
bool setChartDimensions(const char direction, const int8_t size); //define dimensions and start points for chart
|
||||
void drawChrt(const char chrtDir, const int8_t chrtIntv, GwApi::BoatValue& currValue); // Draw chart line
|
||||
void getBufferStartNSize(const int8_t chrtIntv); // Identify buffer size and buffer start position for chart
|
||||
void calcChrtBorders(double& rngMin, double& rngMid, double& rngMax, double& rng); // Calculate chart points for value axis and return range between <min> and <max>
|
||||
void drawChartLines(const ChrtDir direction, const int8_t chrtIntv, const double chrtScale); // Draw chart graph
|
||||
Pos setChartPoint(const int i, const ChrtDir chrtDir, const double chrtVal, const double chrtScale); // Set current chart point to draw
|
||||
void drawChrtTimeAxis(const ChrtDir chrtDir, const ChrtSize chrtSz, const int8_t chrtIntv); // Draw time axis of chart, value and lines
|
||||
void drawChrtValAxis(const ChrtDir chrtDir, const ChrtSize chrtSz, const bool prntLabel); // Draw value axis of chart, value and lines
|
||||
void prntCurrValue(const ChrtDir chrtDir, GwApi::BoatValue& currValue); // Add current boat data value to chart
|
||||
void prntNoValidData(const ChrtDir chrtDir); // print message for no valid data available
|
||||
double getCircularRng(const double center, size_t amount); // Calculate range between chart center and edges
|
||||
void drawChartLines(const char direction, const int8_t chrtIntv, const double chrtScale); // Draw chart graph
|
||||
Pos setCurrentChartPoint(const int i, const char direction, const double chrtVal, const double chrtScale); // Set current chart point to draw
|
||||
void drawChrtTimeAxis(const char chrtDir, const int8_t chrtSz, const int8_t chrtIntv); // Draw time axis of chart, value and lines
|
||||
void drawChrtValAxis(const char chrtDir, const int8_t chrtSz, bool prntLabel); // Draw value axis of chart, value and lines
|
||||
void prntCurrValue(const char chrtDir, GwApi::BoatValue& currValue); // Add current boat data value to chart
|
||||
void prntNoValidData(const char chrtDir); // print message for no valid data available
|
||||
double getAngleRng(const double center, size_t amount); // Calculate range between chart center and edges
|
||||
void prntVerticChartThreeValueAxisLabel(const GFXfont* font); // print value axis label with only three values: top, mid, and bottom for vertical chart
|
||||
void prntHorizChartThreeValueAxisLabel(const GFXfont* font); // print value axis label with only three values: top, mid, and bottom for horizontal chart
|
||||
void prntHorizChartMultiValueAxisLabel(const GFXfont* font); // print value axis label with multiple axis lines for horizontal chart
|
||||
void drawBoldLine(const int16_t x1, const int16_t y1, const int16_t x2, const int16_t y2); // Draw chart line with thickness of 2px
|
||||
String convNformatLabel(const double& label); // Convert and format current axis label to user defined format; helper function for easier handling of OBP60Formatter
|
||||
String formatLabel(const double& label); // Format current axis label for printing w/o data format conversion (has been done earlier)
|
||||
|
||||
public:
|
||||
// Define default chart range and range step for each boat data type
|
||||
static std::map<String, ChartProps> dfltChrtDta;
|
||||
|
||||
Chart(RingBuffer<uint16_t>& dataBuf, double dfltRng, CommonData& common, bool useSimuData); // Chart object of data chart
|
||||
~Chart();
|
||||
void showChrt(char chrtDir, int8_t chrtSz, const int8_t chrtIntv, bool prntName, bool showCurrValue, GwApi::BoatValue currValue); // Perform all actions to draw chart
|
||||
};
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
/*
|
||||
AIS Overview
|
||||
- circle with certain range, e.g. 5nm
|
||||
- AIS-Targets in range with speed and heading
|
||||
- perhaps collision alarm
|
||||
Data: LAT LON SOG HDT
|
||||
|
||||
Feature possibilities
|
||||
- switch between North up / Heading up
|
||||
- filter
|
||||
- zoom
|
||||
- special vessel symbols
|
||||
|
||||
*/
|
||||
|
||||
class PageAIS : public Page
|
||||
{
|
||||
private:
|
||||
|
||||
int scale = 5; // Radius of display circle in nautical miles
|
||||
|
||||
bool alarm = false;
|
||||
bool alarm_enabled = false;
|
||||
int alarm_range = 3;
|
||||
|
||||
char mode = 'N'; // (N)ormal, (C)onfig
|
||||
|
||||
void displayModeNormal(PageData &pageData) {
|
||||
|
||||
// TBD Boatvalues: ...
|
||||
|
||||
logger->logDebug(GwLog::DEBUG,"Drawing at PageAIS");
|
||||
|
||||
Point c = {200, 150}; // center = current boat position
|
||||
uint16_t r = 125;
|
||||
|
||||
const std::vector<Point> pts_boat = { // polygon lines
|
||||
{c.x - 5, c.y},
|
||||
{c.x - 5, c.y - 10},
|
||||
{c.x, c.y - 16},
|
||||
{c.x + 5, c.y - 10},
|
||||
{c.x + 5, c.y}
|
||||
};
|
||||
drawPoly(pts_boat, commonData->fgcolor);
|
||||
|
||||
// Title and corner value headings
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 48);
|
||||
epd->print("AIS");
|
||||
|
||||
// zoom scale
|
||||
epd->drawLine(c.x + 10, c.y, c.x + r - 4, c.y, commonData->fgcolor);
|
||||
// arrow left
|
||||
epd->drawLine(c.x + 10, c.y, c.x + 16, c.y - 4, commonData->fgcolor);
|
||||
epd->drawLine(c.x + 10, c.y, c.x + 16, c.y + 4, commonData->fgcolor);
|
||||
// arrow right
|
||||
epd->drawLine(c.x + r - 4, c.y, c.x + r - 10, c.y - 4, commonData->fgcolor);
|
||||
epd->drawLine(c.x + r - 4, c.y, c.x + r - 10, c.y + 4, commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
drawTextCenter(c.x + r / 2, c.y + 8, String(scale) + "nm");
|
||||
|
||||
}
|
||||
|
||||
void displayModeConfig() {
|
||||
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 48);
|
||||
epd->print("AIS configuration");
|
||||
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
// TODO menu
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
PageAIS(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageAIS");
|
||||
alarm_range = 3;
|
||||
}
|
||||
|
||||
void setupKeys(){
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "MODE";
|
||||
commonData->keydata[1].label = "ALARM";
|
||||
}
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
int handleKey(int key){
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
int handleKey(int key) {
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
#endif
|
||||
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
|
||||
// Logging boat values
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageAIS; Mode=%c", mode);
|
||||
|
||||
// Set display in partial refresh mode
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height());
|
||||
|
||||
if (mode == 'N') {
|
||||
displayModeNormal(pageData);
|
||||
} else if (mode == 'C') {
|
||||
displayModeConfig();
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page *createPage(CommonData &common){
|
||||
return new PageAIS(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 registerPageAIS(
|
||||
"AIS", // Page name
|
||||
createPage, // Action
|
||||
0, // Number of bus values depends on selection in Web configuration
|
||||
{"LAT", "LON", "SOG", "HDT"}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,432 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "ConfigMenu.h"
|
||||
|
||||
/*
|
||||
Anchor overview with additional associated data
|
||||
This page is in experimental stage so be warned!
|
||||
North is up.
|
||||
|
||||
Boatdata used
|
||||
DBS - Water depth
|
||||
HDT - Boat heading
|
||||
AWS - Wind strength; Boat not moving so we assume AWS=TWS and AWD=TWD
|
||||
AWD - Wind direction
|
||||
LAT/LON - Boat position, current
|
||||
HDOP - Position error
|
||||
|
||||
This is the fist page to contain a configuration page with
|
||||
data entry option.
|
||||
Also it will make use of the new alarm function.
|
||||
|
||||
Data
|
||||
Anchor position lat/lon
|
||||
Depth at anchor position
|
||||
Chain length used
|
||||
Boat position current
|
||||
Depth at boat position
|
||||
Boat heading
|
||||
Wind direction
|
||||
Wind strength
|
||||
Alarm j/n
|
||||
Alarm radius
|
||||
GPS position error
|
||||
Timestamp while dropping anchor
|
||||
|
||||
Drop / raise function in device OBP40 has to be done inside
|
||||
config mode because of limited number of buttons.
|
||||
|
||||
Save position in FRAM
|
||||
Alarm: gps fix lost
|
||||
switch unit feet/meter
|
||||
|
||||
*/
|
||||
|
||||
#define anchor_width 16
|
||||
#define anchor_height 16
|
||||
static unsigned char anchor_bits[] = {
|
||||
0x80, 0x01, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0xf0, 0x0f, 0x80, 0x01,
|
||||
0x80, 0x01, 0x88, 0x11, 0x8c, 0x31, 0x8e, 0x71, 0x84, 0x21, 0x86, 0x61,
|
||||
0x86, 0x61, 0xfc, 0x3f, 0xf8, 0x1f, 0x80, 0x01 };
|
||||
|
||||
class PageAnchor : public Page
|
||||
{
|
||||
private:
|
||||
String lengthformat;
|
||||
|
||||
int scale = 50; // Radius of display circle in meter
|
||||
|
||||
bool alarm = false;
|
||||
bool alarm_enabled = false;
|
||||
uint8_t alarm_range;
|
||||
|
||||
uint8_t chain_length;
|
||||
uint8_t chain;
|
||||
|
||||
bool anchor_set = false;
|
||||
double anchor_lat;
|
||||
double anchor_lon;
|
||||
double anchor_depth;
|
||||
int anchor_ts; // time stamp anchor dropped
|
||||
|
||||
char mode = 'N'; // (N)ormal, (C)onfig
|
||||
int8_t editmode = -1; // marker for menu/edit/set function
|
||||
|
||||
ConfigMenu *menu;
|
||||
|
||||
void displayModeNormal(PageData &pageData) {
|
||||
|
||||
// Boatvalues: DBS, HDT, AWS, AWD, LAT, LON, HDOP
|
||||
GwApi::BoatValue *bv_dbs = pageData.values[0]; // DBS
|
||||
String sval_dbs = commonData->fmt->formatValue(bv_dbs, *commonData).svalue;
|
||||
String sunit_dbs = commonData->fmt->formatValue(bv_dbs, *commonData).unit;
|
||||
GwApi::BoatValue *bv_hdt = pageData.values[1]; // HDT
|
||||
String sval_hdt = commonData->fmt->formatValue(bv_hdt, *commonData).svalue;
|
||||
GwApi::BoatValue *bv_aws = pageData.values[2]; // AWS
|
||||
String sval_aws = commonData->fmt->formatValue(bv_aws, *commonData).svalue;
|
||||
String sunit_aws = commonData->fmt->formatValue(bv_aws, *commonData).unit;
|
||||
GwApi::BoatValue *bv_awd = pageData.values[3]; // AWD
|
||||
String sval_awd = commonData->fmt->formatValue(bv_awd, *commonData).svalue;
|
||||
GwApi::BoatValue *bv_lat = pageData.values[4]; // LAT
|
||||
String sval_lat = commonData->fmt->formatValue(bv_lat, *commonData).svalue;
|
||||
GwApi::BoatValue *bv_lon = pageData.values[5]; // LON
|
||||
String sval_lon = commonData->fmt->formatValue(bv_lon, *commonData).svalue;
|
||||
GwApi::BoatValue *bv_hdop = pageData.values[6]; // HDOP
|
||||
String sval_hdop = commonData->fmt->formatValue(bv_hdop, *commonData).svalue;
|
||||
String sunit_hdop = commonData->fmt->formatValue(bv_hdop, *commonData).unit;
|
||||
|
||||
logger->logDebug(GwLog::DEBUG, "Drawing at PageAnchor; DBS=%f, HDT=%f, AWS=%f", bv_dbs->value, bv_hdt->value, bv_aws->value);
|
||||
|
||||
Point c = {200, 150}; // center = anchor position
|
||||
uint16_t r = 125;
|
||||
|
||||
Point b = {200, 180}; // boat position while dropping anchor
|
||||
|
||||
const std::vector<Point> pts_boat = { // polygon lines
|
||||
{b.x - 5, b.y},
|
||||
{b.x - 5, b.y - 10},
|
||||
{b.x, b.y - 16},
|
||||
{b.x + 5, b.y - 10},
|
||||
{b.x + 5, b.y}
|
||||
};
|
||||
//rotatePoints und dann Linien zeichnen
|
||||
// TODO rotate boat according to current heading
|
||||
//drawPoly(rotatePoints(c, pts, RadToDeg(value2)), commonData->fgcolor);
|
||||
drawPoly(pts_boat, commonData->fgcolor);
|
||||
|
||||
// Draw wind arrow
|
||||
const std::vector<Point> pts_wind = {
|
||||
{c.x, c.y - r + 25},
|
||||
{c.x - 12, c.y - r - 4},
|
||||
{c.x, c.y - r + 6},
|
||||
{c.x + 12, c.y - r - 4}
|
||||
};
|
||||
if (bv_awd->valid) {
|
||||
fillPoly4(rotatePoints(c, pts_wind, bv_awd->value), commonData->fgcolor);
|
||||
}
|
||||
|
||||
// Title and corner value headings
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 48);
|
||||
epd->print("Anchor");
|
||||
|
||||
epd->setFont(&Ubuntu_Bold10pt8b);
|
||||
epd->setCursor(8, 200);
|
||||
epd->print("Depth");
|
||||
drawTextRalign(392, 38, "Chain");
|
||||
drawTextRalign(392, 200, "Wind");
|
||||
|
||||
// Units
|
||||
epd->setCursor(8, 272);
|
||||
epd->print(sunit_dbs);
|
||||
drawTextRalign(392, 272, sunit_aws);
|
||||
drawTextRalign(392, 100, lengthformat); // chain unit not implemented
|
||||
|
||||
// Corner values
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(8, 70);
|
||||
epd->print("Alarm: ");
|
||||
epd->print(alarm_enabled ? "On" : "Off");
|
||||
|
||||
epd->setCursor(8, 90);
|
||||
epd->print("HDOP");
|
||||
epd->setCursor(8, 106);
|
||||
if (bv_hdop->valid) {
|
||||
epd->print(round(bv_hdop->value), 0);
|
||||
epd->print(sunit_hdop);
|
||||
} else {
|
||||
epd->print("n/a");
|
||||
}
|
||||
|
||||
// Values
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
// Current chain used
|
||||
epd->setCursor(328, 85);
|
||||
epd->print("27");
|
||||
|
||||
// Depth
|
||||
epd->setCursor(8, 250);
|
||||
epd->print(sval_dbs);
|
||||
// Wind
|
||||
epd->setCursor(328, 250);
|
||||
epd->print(sval_aws);
|
||||
|
||||
epd->drawCircle(c.x, c.y, r, commonData->fgcolor);
|
||||
epd->drawCircle(c.x, c.y, r + 1, commonData->fgcolor);
|
||||
|
||||
// zoom scale
|
||||
epd->drawLine(c.x + 10, c.y, c.x + r - 4, c.y, commonData->fgcolor);
|
||||
// arrow left
|
||||
epd->drawLine(c.x + 10, c.y, c.x + 16, c.y - 4, commonData->fgcolor);
|
||||
epd->drawLine(c.x + 10, c.y, c.x + 16, c.y + 4, commonData->fgcolor);
|
||||
// arrow right
|
||||
epd->drawLine(c.x + r - 4, c.y, c.x + r - 10, c.y - 4, commonData->fgcolor);
|
||||
epd->drawLine(c.x + r - 4, c.y, c.x + r - 10, c.y + 4, commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
drawTextCenter(c.x + r / 2, c.y + 8, String(scale) + "m");
|
||||
|
||||
// alarm range circle
|
||||
if (alarm_enabled) {
|
||||
// alarm range in meter has to be smaller than the scale in meter
|
||||
// r and r_range are pixel values
|
||||
uint16_t r_range = int(alarm_range * r / scale);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageAnchor; Alarm range = %d", r_range);
|
||||
epd->drawCircle(c.x, c.y, r_range, commonData->fgcolor);
|
||||
}
|
||||
|
||||
// draw anchor symbol (as bitmap)
|
||||
epd->drawXBitmap(c.x - anchor_width / 2, c.y - anchor_height / 2,
|
||||
anchor_bits, anchor_width, anchor_height, commonData->fgcolor);
|
||||
|
||||
}
|
||||
|
||||
void displayModeConfig() {
|
||||
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 48);
|
||||
epd->print("Anchor configuration");
|
||||
|
||||
// TODO
|
||||
// show lat/lon for anchor pos
|
||||
// show lat/lon for boat pos
|
||||
// show distance anchor <-> boat
|
||||
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
for (int i = 0 ; i < menu->getItemCount(); i++) {
|
||||
ConfigMenuItem *itm = menu->getItemByIndex(i);
|
||||
if (!itm) {
|
||||
logger->logDebug(GwLog::ERROR, "Menu item not found: %d", i);
|
||||
} else {
|
||||
Rect r = menu->getItemRect(i);
|
||||
bool inverted = (i == menu->getActiveIndex());
|
||||
drawTextBoxed(r, itm->getLabel(), commonData->fgcolor, commonData->bgcolor, inverted, false);
|
||||
if (inverted and editmode > 0) {
|
||||
// triangle as edit marker
|
||||
epd->fillTriangle(r.x + r.w + 20, r.y, r.x + r.w + 30, r.y + r.h / 2, r.x + r.w + 20, r.y + r.h, commonData->fgcolor);
|
||||
}
|
||||
epd->setCursor(r.x + r.w + 40, r.y + r.h - 4);
|
||||
if (itm->getType() == "int") {
|
||||
epd->print(itm->getValue());
|
||||
epd->print(itm->getUnit());
|
||||
} else {
|
||||
epd->print(itm->getValue() == 0 ? "No" : "Yes");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
PageAnchor(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageAnchor");
|
||||
|
||||
// preload configuration data
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
chain_length = config->getInt(config->chainLength);
|
||||
|
||||
chain = 0;
|
||||
anchor_set = false;
|
||||
alarm_range = 30;
|
||||
|
||||
// Initialize config menu
|
||||
menu = new ConfigMenu("Options", 40, 80);
|
||||
menu->setItemDimension(150, 20);
|
||||
|
||||
ConfigMenuItem *newitem;
|
||||
newitem = menu->addItem("chain", "Chain out", "int", 0, "m");
|
||||
if (! newitem) {
|
||||
// Demo: in case of failure exit here, should never be happen
|
||||
logger->logDebug(GwLog::ERROR, "Menu item creation failed");
|
||||
return;
|
||||
}
|
||||
newitem->setRange(0, 200, {1, 5, 10});
|
||||
newitem = menu->addItem("chainmax", "Chain max", "int", chain_length, "m");
|
||||
newitem->setRange(0, 200, {1, 5, 10});
|
||||
newitem = menu->addItem("zoom", "Zoom", "int", 50, "m");
|
||||
newitem->setRange(0, 200, {1, });
|
||||
newitem = menu->addItem("range", "Alarm range", "int", 40, "m");
|
||||
newitem->setRange(0, 200, {1, 5, 10});
|
||||
newitem = menu->addItem("alat", "Adjust anchor lat.", "int", 0, "m");
|
||||
newitem->setRange(0, 200, {1, 5, 10});
|
||||
newitem = menu->addItem("alon", "Adjust anchor lon.", "int", 0, "m");
|
||||
newitem->setRange(0, 200, {1, 5, 10});
|
||||
#ifdef BOARD_OBP40S3
|
||||
// Intodruced here because of missing keys for OBP40
|
||||
newitem = menu->addItem("anchor", "Anchor down", "bool", 0, "");
|
||||
#endif
|
||||
menu->setItemActive("zoom");
|
||||
}
|
||||
|
||||
void setupKeys(){
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "MODE";
|
||||
commonData->keydata[1].label = "ALARM";
|
||||
}
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
int handleKey(int key){
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (mode == 'N') {
|
||||
if (key == 2) { // Toggle alarm
|
||||
alarm_enabled = !alarm_enabled;
|
||||
return 0;
|
||||
}
|
||||
} else { // Config mode
|
||||
if (key == 3) {
|
||||
// menu down
|
||||
menu->goNext();
|
||||
return 0;
|
||||
}
|
||||
if (key == 4) {
|
||||
// menu up
|
||||
menu->goPrev();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
int handleKey(int key){
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
commonData->keydata[1].label = "EDIT";
|
||||
} else {
|
||||
mode = 'N';
|
||||
commonData->keydata[1].label = "ALARM";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (mode == 'N') {
|
||||
if (key == 2) { // Toggle alarm
|
||||
alarm_enabled = !alarm_enabled;
|
||||
return 0;
|
||||
}
|
||||
} else { // Config mode
|
||||
// TODO different code for OBP40 / OBP60
|
||||
if (key == 9) {
|
||||
// menu down
|
||||
if (editmode > 0) {
|
||||
// decrease item value
|
||||
menu->getActiveItem()->decValue();
|
||||
} else {
|
||||
menu->goNext();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 10) {
|
||||
// menu up or value up
|
||||
if (editmode > 0) {
|
||||
// increase item value
|
||||
menu->getActiveItem()->incValue();
|
||||
} else {
|
||||
menu->goPrev();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 2) {
|
||||
// enter / leave edit mode for current menu item
|
||||
if (editmode > 0) {
|
||||
commonData->keydata[1].label = "EDIT";
|
||||
editmode = 0;
|
||||
} else {
|
||||
commonData->keydata[1].label = "SET";
|
||||
editmode = 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
#endif
|
||||
|
||||
void displayNew(PageData &pageData){
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
|
||||
// Logging boat values
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageAnchor; Mode=%c", mode);
|
||||
|
||||
// Set display in partial refresh mode
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
if (mode == 'N') {
|
||||
displayModeNormal(pageData);
|
||||
} else if (mode == 'C') {
|
||||
displayModeConfig();
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page *createPage(CommonData &common){
|
||||
return new PageAnchor(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 registerPageAnchor(
|
||||
"Anchor", // Page name
|
||||
createPage, // Action
|
||||
0, // Number of bus values depends on selection in Web configuration
|
||||
{"DBS", "HDT", "AWS", "AWD", "LAT", "LON", "HDOP"}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
#endif
|
||||
+85
-220
@@ -1,261 +1,126 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
// These constants have to match the declaration below in :
|
||||
// PageDescription registerPageAutopilot(
|
||||
// {"HDM","HDT", "COG", "STW", "SOG", "DBT","XTE", "DTW", "BTW", "RPOS", "ROT"}, // Bus values we need in the page
|
||||
/*
|
||||
Autopilot
|
||||
|
||||
const int HowManyValues = 11;
|
||||
|
||||
const int AverageValues = 4;
|
||||
|
||||
const int ShowHDM = 0;
|
||||
const int ShowHDT = 1;
|
||||
const int ShowCOG = 2;
|
||||
const int ShowSTW = 3;
|
||||
const int ShowSOG = 4;
|
||||
const int ShowDBT = 5;
|
||||
const int ShowXTE = 6;
|
||||
const int ShowDTW = 7;
|
||||
const int ShowBTW = 8;
|
||||
const int ShowRPOS = 9;
|
||||
const int ShowROT = 10;
|
||||
|
||||
const int Compass_X0 = 200; // X center point of compass band
|
||||
const int Compass_Y0 = 90; // Y position of compass lines
|
||||
//const int Compass_LineLength = 22; // Length of compass lines
|
||||
const int Compass_LineLength = 15; // Length of compass lines
|
||||
const float Compass_LineDelta = 8.0;// Compass band: 1deg = 5 Pixels, 10deg = 50 Pixels
|
||||
*/
|
||||
|
||||
class PageAutopilot : public Page
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
private:
|
||||
char mode = 'N'; // (N)ormal, (C)onfig
|
||||
|
||||
int WhichDataCompass = ShowHDM; // Start value
|
||||
int WhichDataDisplay = ShowHDM; // Start value
|
||||
void displayModeNormal(PageData &pageData) {
|
||||
|
||||
// TBD Boatvalues: ...
|
||||
|
||||
logger->logDebug(GwLog::DEBUG, "Drawing at PageAutopilot");
|
||||
|
||||
// Title and corner value headings
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 48);
|
||||
epd->print("Autopilot");
|
||||
|
||||
}
|
||||
|
||||
void displayModeConfig() {
|
||||
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 48);
|
||||
epd->print("Autopilot configuration");
|
||||
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
// TODO menu
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
PageAutopilot(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageAutopilot");
|
||||
PageAutopilot(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageAutopilot");
|
||||
}
|
||||
|
||||
virtual void setupKeys(){
|
||||
void setupKeys() {
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "-10";
|
||||
commonData->keydata[1].label = "-1";
|
||||
commonData->keydata[2].label = "Auto";
|
||||
commonData->keydata[3].label = "+1";
|
||||
commonData->keydata[4].label = "+10";
|
||||
commonData->keydata[0].label = "MODE";
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
// Code for keylock
|
||||
|
||||
if ( key == 1 ) {
|
||||
WhichDataCompass += 1;
|
||||
if ( WhichDataCompass > ShowCOG)
|
||||
WhichDataCompass = ShowHDM;
|
||||
#ifdef BOARD_OBP60S3
|
||||
int handleKey(int key) {
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if ( key == 2 ) {
|
||||
WhichDataDisplay += 1;
|
||||
if ( WhichDataDisplay > ShowDBT)
|
||||
WhichDataDisplay = ShowHDM;
|
||||
}
|
||||
|
||||
if(key == 11){
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0; // Commit the key
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Old values for hold function
|
||||
static String OldDataText[HowManyValues] = {"", "", "", "", "", "","", "", "", "", ""};
|
||||
static String OldDataUnits[HowManyValues] = {"", "", "", "", "", "","", "", "", "", ""};
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
// bool simulation = config->getBool(config->useSimuData);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
GwApi::BoatValue *bvalue;
|
||||
String DataName[HowManyValues];
|
||||
double DataValue[HowManyValues];
|
||||
bool DataValid[HowManyValues];
|
||||
String DataText[HowManyValues];
|
||||
String DataUnits[HowManyValues];
|
||||
String DataFormat[HowManyValues];
|
||||
FormattedData TheFormattedData;
|
||||
|
||||
for (int i = 0; i < HowManyValues; i++){
|
||||
bvalue = pageData.values[i];
|
||||
TheFormattedData = formatValue(bvalue, *commonData);
|
||||
DataName[i] = xdrDelete(bvalue->getName());
|
||||
DataName[i] = DataName[i].substring(0, 6); // String length limit for value name
|
||||
DataUnits[i] = formatValue(bvalue, *commonData).unit;
|
||||
DataText[i] = TheFormattedData.svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
DataValue[i] = TheFormattedData.value; // Value as double in SI unit
|
||||
DataValid[i] = bvalue->valid;
|
||||
DataFormat[i] = bvalue->getFormat(); // Unit of value
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageAutopilot: %d %s %f %s %s", i, DataName[i], DataValue[i], DataFormat[i], DataText[i] );
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
int handleKey(int key){
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
commonData->keydata[1].label = "EDIT";
|
||||
} else {
|
||||
mode = 'N';
|
||||
commonData->keydata[1].label = "ALARM";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
void displayNew(PageData &pageData){
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
//***********************************************************
|
||||
int displayPage(PageData &pageData){
|
||||
|
||||
// Logging boat values
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageAutopilot; Mode=%c", mode);
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
/*
|
||||
// Horizontal line 2 pix top & bottom
|
||||
// Print data on top half
|
||||
getdisplay().fillRect(0, 130, 400, 2, commonData->fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(10, 70);
|
||||
getdisplay().print(DataName[WhichDataDisplay]); // Page name
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(10, 120);
|
||||
getdisplay().print(DataUnits[WhichDataDisplay]);
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height());
|
||||
|
||||
if(holdvalues == false){
|
||||
printBoatValue(DataText[WhichDataDisplay], 190, 120, LEFT, 42, smallDecimals); // Real value as formated string
|
||||
if (mode == 'N') {
|
||||
displayModeNormal(pageData);
|
||||
} else if (mode == 'C') {
|
||||
displayModeConfig();
|
||||
}
|
||||
else{
|
||||
printBoatValue(OldDataText[WhichDataDisplay], 190, 120, LEFT, 42, smallDecimals); // Old value as formated string
|
||||
}
|
||||
if(DataValid[WhichDataDisplay] == true){
|
||||
OldDataText[WhichDataDisplay] = DataText[WhichDataDisplay]; // Save the old value
|
||||
OldDataUnits[WhichDataDisplay] = DataUnits[WhichDataDisplay]; // Save the old unit
|
||||
}
|
||||
*/
|
||||
// Now draw compass band
|
||||
// Get the data
|
||||
double TheAngle = DataValue[WhichDataCompass];
|
||||
static double AvgAngle = 0;
|
||||
AvgAngle = ( AvgAngle * AverageValues + TheAngle ) / (AverageValues + 1 );
|
||||
|
||||
int TheTrend = round( ( TheAngle - AvgAngle) * 180.0 / M_PI );
|
||||
|
||||
static const int bsize = 30;
|
||||
char buffer[bsize+1];
|
||||
buffer[0]=0;
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(10, Compass_Y0-40);
|
||||
getdisplay().print(DataName[WhichDataCompass]); // Page name
|
||||
|
||||
// Draw compass base line and pointer
|
||||
getdisplay().fillRect(0, Compass_Y0, 400, 3, commonData->fgcolor);
|
||||
//getdisplay().fillTriangle(Compass_X0,Compass_Y0-40,Compass_X0-10,Compass_Y0-80,Compass_X0+10,Compass_Y0-80,commonData->fgcolor);
|
||||
getdisplay().fillTriangle(Compass_X0,Compass_Y0-30,Compass_X0-10,Compass_Y0-60,Compass_X0+10,Compass_Y0-60,commonData->fgcolor);
|
||||
// Draw trendlines
|
||||
for ( int i = 1; i < abs(TheTrend) / 2; i++){
|
||||
int x1;
|
||||
if ( TheTrend < 0 )
|
||||
x1 = Compass_X0 + 20 * i;
|
||||
else
|
||||
x1 = Compass_X0 - 20 * ( i + 1 );
|
||||
|
||||
getdisplay().fillRect(x1, Compass_Y0 -55, 10, 6, commonData->fgcolor);
|
||||
}
|
||||
// Central line + satellite lines
|
||||
double NextSector = round(TheAngle / ( M_PI / 9 )) * ( M_PI / 9 ); // Get the next 20degree value
|
||||
double Offset = - ( NextSector - TheAngle); // Offest of the center line compared to TheAngle in Radian
|
||||
|
||||
int Delta_X = int ( Offset * 180.0 / M_PI * Compass_LineDelta );
|
||||
for ( int i = 0; i <=4; i++ ){
|
||||
int x0;
|
||||
x0 = Compass_X0 + Delta_X + 2 * i * 5 * Compass_LineDelta;
|
||||
getdisplay().fillRect(x0-2, Compass_Y0 - 2 * Compass_LineLength, 5, 2 * Compass_LineLength, commonData->fgcolor);
|
||||
x0 = Compass_X0 + Delta_X + ( 2 * i + 1 ) * 5 * Compass_LineDelta;
|
||||
getdisplay().fillRect(x0-1, Compass_Y0 - Compass_LineLength, 3, Compass_LineLength, commonData->fgcolor);
|
||||
|
||||
x0 = Compass_X0 + Delta_X - 2 * i * 5 * Compass_LineDelta;
|
||||
getdisplay().fillRect(x0-2, Compass_Y0 - 2 * Compass_LineLength, 5, 2 * Compass_LineLength, commonData->fgcolor);
|
||||
x0 = Compass_X0 + Delta_X - ( 2 * i + 1 ) * 5 * Compass_LineDelta;
|
||||
getdisplay().fillRect(x0-1, Compass_Y0 - Compass_LineLength, 3, Compass_LineLength, commonData->fgcolor);
|
||||
}
|
||||
|
||||
getdisplay().fillRect(0, Compass_Y0, 400, 3, commonData->fgcolor);
|
||||
// Add the numbers to the compass band
|
||||
int x0;
|
||||
float AngleToDisplay = NextSector * 180.0 / M_PI;
|
||||
|
||||
x0 = Compass_X0 + Delta_X;
|
||||
getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||
|
||||
do {
|
||||
getdisplay().setCursor(x0 - 40, Compass_Y0 + 40);
|
||||
snprintf(buffer,bsize,"%03.0f", AngleToDisplay);
|
||||
getdisplay().print(buffer);
|
||||
AngleToDisplay += 20;
|
||||
if ( AngleToDisplay >= 360.0 )
|
||||
AngleToDisplay -= 360.0;
|
||||
x0 -= 4 * 5 * Compass_LineDelta;
|
||||
} while ( x0 >= 0 - 60 );
|
||||
|
||||
AngleToDisplay = NextSector * 180.0 / M_PI - 20;
|
||||
if ( AngleToDisplay < 0 )
|
||||
AngleToDisplay += 360.0;
|
||||
|
||||
x0 = Compass_X0 + Delta_X + 4 * 5 * Compass_LineDelta;
|
||||
do {
|
||||
getdisplay().setCursor(x0 - 40, Compass_Y0 + 40);
|
||||
snprintf(buffer,bsize,"%03.0f", AngleToDisplay);
|
||||
// Quick and dirty way to prevent wrapping text in next line
|
||||
if ( ( x0 - 40 ) > 380 )
|
||||
buffer[0] = 0;
|
||||
else if ( ( x0 - 40 ) > 355 )
|
||||
buffer[1] = 0;
|
||||
else if ( ( x0 - 40 ) > 325 )
|
||||
buffer[2] = 0;
|
||||
|
||||
getdisplay().print(buffer);
|
||||
|
||||
AngleToDisplay -= 20;
|
||||
if ( AngleToDisplay < 0 )
|
||||
AngleToDisplay += 360.0;
|
||||
x0 += 4 * 5 * Compass_LineDelta;
|
||||
} while (x0 < ( 400 - 20 -40 ) );
|
||||
|
||||
// static int x_test = 320;
|
||||
// x_test += 2;
|
||||
|
||||
// snprintf(buffer,bsize,"%03d", x_test);
|
||||
// getdisplay().setCursor(x_test, Compass_Y0 - 60);
|
||||
// getdisplay().print(buffer);
|
||||
// if ( x_test > 390)
|
||||
// x_test = 320;
|
||||
|
||||
displayRudderPosition(DataValue[ShowSOG], 20, 200, 160, commonData->fgcolor, commonData->bgcolor);
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
static Page *createPage(CommonData &common){
|
||||
return new PageAutopilot(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
|
||||
@@ -266,8 +131,8 @@ PageDescription registerPageAutopilot(
|
||||
"Autopilot", // Page name
|
||||
createPage, // Action
|
||||
0, // Number of bus values depends on selection in Web configuration
|
||||
{"HDM","HDT", "COG", "STW", "SOG", "DBT","XTE", "DTW", "BTW", "RPOS", "ROT"}, // Bus values we need in the page
|
||||
true // Show display header on/off
|
||||
{}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
|
||||
false // Show display header on/off
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -5,17 +6,21 @@
|
||||
|
||||
class PageBME280 : public Page
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
private:
|
||||
String tempformat;
|
||||
String useenvsensor;
|
||||
|
||||
public:
|
||||
PageBME280(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageBME280");
|
||||
PageBME280(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageBME280");
|
||||
|
||||
// Get config data
|
||||
tempformat = config->getString(config->tempFormat);
|
||||
useenvsensor = config->getString(config->useEnvSensor);
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -25,8 +30,6 @@ class PageBME280 : public Page
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
double value1 = 0;
|
||||
double value2 = 0;
|
||||
@@ -35,14 +38,6 @@ class PageBME280 : public Page
|
||||
String svalue2 = "";
|
||||
String svalue3 = "";
|
||||
|
||||
// Get config data
|
||||
String tempformat = config->getString(config->tempFormat);
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
String useenvsensor = config->getString(config->useEnvSensor);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
// Get sensor values #1
|
||||
String name1 = "Temp"; // Value name
|
||||
name1 = name1.substring(0, 6); // String length limit for value name
|
||||
@@ -104,70 +99,82 @@ class PageBME280 : public Page
|
||||
}
|
||||
|
||||
// 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);
|
||||
logger->logDebug(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 display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// ############### Value 1 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 55);
|
||||
getdisplay().print(name1); // Page name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 55);
|
||||
epd->print(name1); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 90);
|
||||
getdisplay().print(unit1); // Unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 90);
|
||||
epd->print(unit1); // Unit
|
||||
|
||||
// Switch font if format for any values
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 90);
|
||||
|
||||
// Show bus data
|
||||
printBoatValue(svalue1, 380, 90, RIGHT, 30, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue1); // Real value as formated string
|
||||
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 105, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 105, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 2 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 145);
|
||||
getdisplay().print(name2); // Page name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 145);
|
||||
epd->print(name2); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 180);
|
||||
getdisplay().print(unit2); // Unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 180);
|
||||
epd->print(unit2); // Unit
|
||||
|
||||
// Switch font if format for any values
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 180);
|
||||
|
||||
// Show bus data
|
||||
printBoatValue(svalue2, 380, 180, RIGHT, 30, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue2); // Real value as formated string
|
||||
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 195, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 195, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 3 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 235);
|
||||
getdisplay().print(name3); // Page name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 235);
|
||||
epd->print(name3); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 270);
|
||||
getdisplay().print(unit3); // Unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 270);
|
||||
epd->print(unit3); // Unit
|
||||
|
||||
// Switch font if format for any values
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(140, 270);
|
||||
|
||||
// Show bus data
|
||||
printBoatValue(svalue3, 380, 270, RIGHT, 30, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue3); // Real value as formated string
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
/*
|
||||
* Barograph WIP
|
||||
* - Zoom feature
|
||||
* - Saves data in FRAM if available
|
||||
*/
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
class PageBarograph : public Page
|
||||
{
|
||||
private:
|
||||
bool keylock = false;
|
||||
bool has_fram = false;
|
||||
String flashLED;
|
||||
String useenvsensor;
|
||||
|
||||
char source = 'I'; // (I)nternal, e(X)ternal
|
||||
const int series[5] = {75, 150, 300, 600, 900};
|
||||
const int zoom[5] = {1, 2, 3, 6, 12};
|
||||
int zoomindex = 4;
|
||||
uint16_t data[336] = {0}; // current data to display
|
||||
|
||||
// y-axis
|
||||
uint16_t vmin;
|
||||
uint16_t vmax;
|
||||
uint16_t scalemin = 1000;
|
||||
uint16_t scalemax = 1020;
|
||||
uint16_t scalestep = 5;
|
||||
int hist1 = 0; // one hour trend
|
||||
int hist3 = 0; // three hours trend
|
||||
|
||||
long refresh = 0; // millis
|
||||
|
||||
void loadData() {
|
||||
// Transfer data from history to page buffer,
|
||||
// set y-axis according to data
|
||||
int i = zoom[zoomindex];
|
||||
|
||||
// get min and max values of measured data
|
||||
vmin = data[0];
|
||||
vmax = data[0];
|
||||
for (int x = 0; x < 336; x++) {
|
||||
if (data[x] != 0) {
|
||||
if (data[x] < vmin) {
|
||||
vmin = data[x];
|
||||
} else if (data[x] > vmax) {
|
||||
vmax = data[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate y-axis scale
|
||||
uint16_t diff = vmax - vmin;
|
||||
if (diff < 20) {
|
||||
scalestep = 5;
|
||||
} else if (diff < 40) {
|
||||
scalestep = 10;
|
||||
} else {
|
||||
scalestep = 15;
|
||||
}
|
||||
scalemin = vmin - (vmin % scalestep);
|
||||
scalemax = vmax + scalestep - (vmax % scalestep);
|
||||
|
||||
// TODO implement history buffer
|
||||
};
|
||||
|
||||
public:
|
||||
PageBarograph(CommonData &common): Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageBarograph");
|
||||
|
||||
// Get config data
|
||||
useenvsensor = config->getString(common.config->useEnvSensor);
|
||||
// possible values for internal sensor
|
||||
static std::vector<String> sensorList = {
|
||||
"BME280", "BMP280", "BMP180", "BMP085", "HTU21", "SHT21"
|
||||
};
|
||||
if (std::find(sensorList.begin(), sensorList.end(), useenvsensor) != sensorList.end()) {
|
||||
source = 'I';
|
||||
} else {
|
||||
// "off" means user external data if available
|
||||
source = 'X';
|
||||
}
|
||||
//common.logger->logDebug(GwLog::LOG,"Source=%s (%s)", source, useenvsensor);
|
||||
loadData(); // initial load
|
||||
}
|
||||
|
||||
int handleKey(int key) {
|
||||
if (key == 1) {
|
||||
// zoom in
|
||||
if (zoomindex > 0) {
|
||||
zoomindex -= 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 2) {
|
||||
// zoom out
|
||||
if (zoomindex < sizeof(zoom)) {
|
||||
zoomindex += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 11) {
|
||||
keylock = !keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
// Logging boat values
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageBarograph");
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
// Frames
|
||||
epd->fillRect(0, 75, 400, 2, commonData->fgcolor); // fillRect: x, y, w, h
|
||||
epd->fillRect(130, 20, 2, 55, commonData->fgcolor);
|
||||
epd->fillRect(270, 20, 2, 55, commonData->fgcolor);
|
||||
epd->fillRect(325, 20, 2, 55, commonData->fgcolor);
|
||||
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
if (source == 'I') {
|
||||
drawTextCenter(360, 40, useenvsensor);
|
||||
} else {
|
||||
drawTextCenter(360, 40, "ext.");
|
||||
}
|
||||
|
||||
// Trend
|
||||
drawTextCenter(295, 62, "0.0");
|
||||
|
||||
// Alarm placeholder
|
||||
drawTextCenter(70, 62, "Alarm Off");
|
||||
|
||||
// Zoom
|
||||
int datastep = series[zoomindex];
|
||||
String fmt;
|
||||
if (datastep > 120) {
|
||||
if (datastep % 60 == 0) {
|
||||
fmt = String(datastep / 60.0, 0) + " min";
|
||||
} else {
|
||||
fmt = String(datastep / 60.0, 1) + " min";
|
||||
}
|
||||
} else {
|
||||
fmt = String(datastep) + " s";
|
||||
}
|
||||
drawTextCenter(360, 62, fmt);
|
||||
|
||||
// Current measurement
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
drawTextCenter(200, 40, String(commonData->data.airPressure / 100, 1));
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
drawTextCenter(200, 62, "hPa"); // Unit
|
||||
|
||||
// Diagram
|
||||
const int xstep = 48; // x-axis-grid
|
||||
const int x0 = 350; // origin
|
||||
const int y0 = 270;
|
||||
const int w = 7 * 48;
|
||||
const int h = 180;
|
||||
|
||||
// epd->drawRect(x0 - w, y0 - h, w, h, commonData->fgcolor);
|
||||
|
||||
// x-axis are hours
|
||||
for (int i = 1; i <= 6; i++) {
|
||||
String label = String(-1 * zoom[zoomindex] * i);
|
||||
epd->drawLine(x0 - i * xstep, y0, x0 - i * xstep, y0 - h, commonData->fgcolor);
|
||||
drawTextCenter(x0 - i * xstep, y0 - 10, label);
|
||||
}
|
||||
|
||||
// y-axis
|
||||
epd->drawLine(x0 + 5, y0, x0 + 5, y0 - h, commonData->fgcolor); // drawLine: x1, y1, x2, y2
|
||||
epd->drawLine(x0 - w, y0, x0 - w, y0 - h, commonData->fgcolor);
|
||||
epd->drawLine(x0 - w - 5, y0, x0 - w - 5, y0 - h, commonData->fgcolor);
|
||||
epd->drawLine(x0, y0, x0, y0 - h, commonData->fgcolor);
|
||||
|
||||
int16_t dy = 9; // px for one hPa
|
||||
int16_t y = y0;
|
||||
int16_t ys = scalemin;
|
||||
while (y >= y0 - h) {
|
||||
if (y % scalestep == 0) {
|
||||
// big step, show label and long line
|
||||
epd->setCursor(x0 + 10, y + 5);
|
||||
epd->print(String(ys));
|
||||
epd->drawLine(x0 + 5, y, x0 - w - 5, y, commonData->fgcolor);
|
||||
} else {
|
||||
// small step, only short lines left and right
|
||||
epd->drawLine(x0 + 5, y, x0, y, commonData->fgcolor);
|
||||
epd->drawLine(x0 - w - 5, y, x0 - w, y, commonData->fgcolor);
|
||||
}
|
||||
y -= dy;
|
||||
ys += 1;
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page* createPage(CommonData &common){
|
||||
return new PageBarograph(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 registerPageBarograph(
|
||||
"Barograph", // Page name
|
||||
createPage, // Action
|
||||
0, // No bus values needed
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
#endif
|
||||
+102
-95
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -5,24 +6,25 @@
|
||||
|
||||
class PageBattery : public Page
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
|
||||
private:
|
||||
String powsensor1;
|
||||
int average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s
|
||||
|
||||
public:
|
||||
PageBattery(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageBattery");
|
||||
PageBattery(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageBattery");
|
||||
|
||||
// Get config data
|
||||
String powsensor1 = config->getString(config->usePowSensor1);
|
||||
}
|
||||
|
||||
virtual void setupKeys(){
|
||||
void setupKeys(){
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "AVG";
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key){
|
||||
// Change average
|
||||
if(key == 1){
|
||||
average ++;
|
||||
@@ -38,9 +40,17 @@ class PageBattery : public Page
|
||||
return key;
|
||||
}
|
||||
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Old values for hold function
|
||||
double value1 = 0;
|
||||
@@ -53,15 +63,6 @@ class PageBattery : public Page
|
||||
static String svalue3old = "";
|
||||
static String unit3old = "";
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
// bool simulation = config->getBool(config->useSimuData);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
String powsensor1 = config->getString(config->usePowSensor1);
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
// Get voltage value
|
||||
String name1 = "VBat"; // Value name
|
||||
if(String(powsensor1) == "INA219" || String(powsensor1) == "INA226"){
|
||||
@@ -150,136 +151,142 @@ class PageBattery : public Page
|
||||
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);
|
||||
logger->logDebug(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 display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
// Show average settings
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
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");
|
||||
epd->setCursor(60, 90);
|
||||
epd->print("Avg: 1s");
|
||||
epd->setCursor(60, 180);
|
||||
epd->print("Avg: 1s");
|
||||
epd->setCursor(60, 270);
|
||||
epd->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");
|
||||
epd->setCursor(60, 90);
|
||||
epd->print("Avg: 10s");
|
||||
epd->setCursor(60, 180);
|
||||
epd->print("Avg: 10s");
|
||||
epd->setCursor(60, 270);
|
||||
epd->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");
|
||||
epd->setCursor(60, 90);
|
||||
epd->print("Avg: 60s");
|
||||
epd->setCursor(60, 180);
|
||||
epd->print("Avg: 60s");
|
||||
epd->setCursor(60, 270);
|
||||
epd->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");
|
||||
epd->setCursor(60, 90);
|
||||
epd->print("Avg: 300s");
|
||||
epd->setCursor(60, 180);
|
||||
epd->print("Avg: 300s");
|
||||
epd->setCursor(60, 270);
|
||||
epd->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");
|
||||
epd->setCursor(60, 90);
|
||||
epd->print("Avg: 1s");
|
||||
epd->setCursor(60, 180);
|
||||
epd->print("Avg: 1s");
|
||||
epd->setCursor(60, 270);
|
||||
epd->print("Avg: 1s");
|
||||
break;
|
||||
}
|
||||
|
||||
// ############### Value 1 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 55);
|
||||
getdisplay().print(name1); // Value name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 55);
|
||||
epd->print(name1); // Value name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 90);
|
||||
getdisplay().print(unit1); // Unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 90);
|
||||
epd->print(unit1); // Unit
|
||||
|
||||
// Show bus value
|
||||
// Show value
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 90);
|
||||
|
||||
// Show bus data
|
||||
if(String(powsensor1) != "off"){
|
||||
svalue1 = formatValue(value1, String("formatXdr:U:V"), *commonData);
|
||||
} else{
|
||||
svalue1 = "---";
|
||||
epd->print(value1,2); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
epd->print(commonData->fmt->placeholder); // No sensor data (sensor is off)
|
||||
}
|
||||
printBoatValue(svalue1, 380, 90, RIGHT, 30, smallDecimals); // Real value as formated string
|
||||
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 105, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 105, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 2 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 145);
|
||||
getdisplay().print(name2); // Value name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 145);
|
||||
epd->print(name2); // Value name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 180);
|
||||
getdisplay().print(unit2); // Unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 180);
|
||||
epd->print(unit2); // Unit
|
||||
|
||||
// Show bus value
|
||||
// Show value
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 180);
|
||||
|
||||
// Show bus data
|
||||
if(String(powsensor1) != "off"){
|
||||
svalue2 = formatValue(value2, String("formatXdr:U:V"), *commonData);
|
||||
} else{
|
||||
svalue2 = "---";
|
||||
epd->print(value2,1); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
epd->print(commonData->fmt->placeholder); // No sensor data (sensor is off)
|
||||
}
|
||||
printBoatValue(svalue2, 380, 180, RIGHT, 30, smallDecimals); // Real value as formated string
|
||||
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 195, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 195, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 3 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 235);
|
||||
getdisplay().print(name3); // Value name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 235);
|
||||
epd->print(name3); // Value name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 270);
|
||||
getdisplay().print(unit3); // Unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 270);
|
||||
epd->print(unit3); // Unit
|
||||
|
||||
// Show bus value
|
||||
// Show value
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 270);
|
||||
|
||||
// Show bus data
|
||||
if(String(powsensor1) != "off"){
|
||||
svalue3 = formatValue(value3, String("formatXdr:U:V"), *commonData);
|
||||
} else{
|
||||
svalue3 = "---";
|
||||
epd->print(value3,1); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
epd->print(commonData->fmt->placeholder); // No sensor data (sensor is off)
|
||||
}
|
||||
printBoatValue(svalue3, 380, 270, RIGHT, 30, smallDecimals); // Real value as formated string
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
|
||||
+124
-121
@@ -1,31 +1,40 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "movingAvg.h" // Lib for moving average building
|
||||
|
||||
class PageBattery2 : public Page
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
|
||||
private:
|
||||
String batVoltage;
|
||||
int batCapacity;
|
||||
String batType;
|
||||
String powerSensor;
|
||||
bool init = false; // Marker for init done
|
||||
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){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageBattery2");
|
||||
PageBattery2(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageBattery2");
|
||||
|
||||
// Get config data
|
||||
batVoltage = config->getString(config->batteryVoltage);
|
||||
batCapacity = config->getInt(config->batteryCapacity);
|
||||
batType = config->getString(config->batteryType);
|
||||
powerSensor = config->getString(config->usePowSensor1);
|
||||
}
|
||||
|
||||
virtual void setupKeys(){
|
||||
void setupKeys(){
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "AVG";
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key) {
|
||||
// Change average
|
||||
if(key == 1){
|
||||
average ++;
|
||||
@@ -47,11 +56,7 @@ public:
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData)
|
||||
{
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
// 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
|
||||
@@ -60,17 +65,6 @@ public:
|
||||
int batPercentage = 0; // Battery level
|
||||
float batRange = 0; // Range in hours
|
||||
|
||||
// Get config data
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
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);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
double value1 = 0; // Battery voltage
|
||||
double value2 = 0; // Battery current
|
||||
double value3 = 0; // Battery power consumption
|
||||
@@ -146,176 +140,185 @@ public:
|
||||
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)){
|
||||
if (flashLED == "Limit Violation") {
|
||||
bool violation = false;
|
||||
if (batType == "Pb") {
|
||||
violation = (raw < 11.8 || raw > 14.8);
|
||||
} else if (batType == "Gel") {
|
||||
violation = (raw < 11.8 || raw > 14.4);
|
||||
} else if (batType == "AGM") {
|
||||
violation = (raw < 11.8 || raw > 14.7);
|
||||
} else if (batType == "LiFePo4") {
|
||||
violation = (raw < 12.0 || raw > 14.6);
|
||||
}
|
||||
if (violation) {
|
||||
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)){
|
||||
} else {
|
||||
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);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageBattery2, Type:%s %s:=%f", batType.c_str(), name1.c_str(), raw);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(10, 65);
|
||||
getdisplay().print("Bat.");
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(10, 65);
|
||||
epd->print("Bat.");
|
||||
|
||||
// Show battery type
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(90, 65);
|
||||
getdisplay().print(batType);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(90, 65);
|
||||
epd->print(batType);
|
||||
|
||||
// Show voltage type
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 140);
|
||||
int bvoltage = 0;
|
||||
if(String(batVoltage) == "12V") bvoltage = 12;
|
||||
else bvoltage = 24;
|
||||
printBoatValue(String(bvoltage), 10, 140, LEFT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("V");
|
||||
epd->print(bvoltage);
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("V");
|
||||
|
||||
// Show battery capacity
|
||||
String svalueCapacity = (batCapacity <= 999) ? String(batCapacity) : String(float(batCapacity/1000.0), 1);
|
||||
printBoatValue(svalueCapacity, 10, 200, LEFT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
if(batCapacity <= 999) getdisplay().print("Ah");
|
||||
if(batCapacity > 999) getdisplay().print("kAh");
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 200);
|
||||
if(batCapacity <= 999) epd->print(batCapacity, 0);
|
||||
if(batCapacity > 999) epd->print(float(batCapacity/1000.0), 1);
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
if(batCapacity <= 999) epd->print("Ah");
|
||||
if(batCapacity > 999) epd->print("kAh");
|
||||
|
||||
// Show info
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 235);
|
||||
getdisplay().print("Installed");
|
||||
getdisplay().setCursor(10, 255);
|
||||
getdisplay().print("Battery Type");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 235);
|
||||
epd->print("Installed");
|
||||
epd->setCursor(10, 255);
|
||||
epd->print("Battery Type");
|
||||
|
||||
// Show battery with fill level
|
||||
batteryGraphic(150, 45, batPercentage, commonData->fgcolor, commonData->bgcolor);
|
||||
|
||||
// Show average settings
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(150, 145);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(150, 145);
|
||||
switch (average) {
|
||||
case 0:
|
||||
getdisplay().print("Avg: 1s");
|
||||
epd->print("Avg: 1s");
|
||||
break;
|
||||
case 1:
|
||||
getdisplay().print("Avg: 10s");
|
||||
epd->print("Avg: 10s");
|
||||
break;
|
||||
case 2:
|
||||
getdisplay().print("Avg: 60s");
|
||||
epd->print("Avg: 60s");
|
||||
break;
|
||||
case 3:
|
||||
getdisplay().print("Avg: 300s");
|
||||
epd->print("Avg: 300s");
|
||||
break;
|
||||
default:
|
||||
getdisplay().print("Avg: 1s");
|
||||
epd->print("Avg: 1s");
|
||||
break;
|
||||
}
|
||||
|
||||
// Show fill level in percent
|
||||
printBoatValue(String(batPercentage), 150, 200, LEFT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("%");
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(150, 200);
|
||||
epd->print(batPercentage);
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("%");
|
||||
|
||||
// Show time to full discharge
|
||||
String svalueRange;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(150, 260);
|
||||
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
|
||||
svalueRange = (batRange < 9.9) ? String(batRange, 1) : String(batRange, 0);
|
||||
if(batRange < 9.9) epd->print(batRange, 1);
|
||||
else epd->print(batRange, 0);
|
||||
}
|
||||
else{
|
||||
svalueRange = "--";
|
||||
}
|
||||
printBoatValue(svalueRange, 150, 260, LEFT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("h");
|
||||
else epd->print("--");
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("h");
|
||||
|
||||
// Show sensor type info
|
||||
String i2cAddr = "";
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(270, 60);
|
||||
if(powerSensor == "off") getdisplay().print("Internal");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(270, 60);
|
||||
if(powerSensor == "off") epd->print("Internal");
|
||||
if(powerSensor == "INA219"){
|
||||
getdisplay().print("INA219");
|
||||
epd->print("INA219");
|
||||
}
|
||||
if(powerSensor == "INA226"){
|
||||
getdisplay().print("INA226");
|
||||
epd->print("INA226");
|
||||
i2cAddr = " (0x" + String(INA226_I2C_ADDR1, HEX) + ")";
|
||||
}
|
||||
getdisplay().print(i2cAddr);
|
||||
getdisplay().setCursor(270, 80);
|
||||
getdisplay().print("Sensor Modul");
|
||||
epd->print(i2cAddr);
|
||||
epd->setCursor(270, 80);
|
||||
epd->print("Sensor Modul");
|
||||
|
||||
// Reading bus data or using simulation data
|
||||
String svalue1;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->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
|
||||
epd->print(value1,1);
|
||||
}
|
||||
else{
|
||||
// Check for valid real data, display also if hold values activated
|
||||
if(valid1 == true || holdvalues == true){
|
||||
svalue1 = formatValue(value1, String("formatXdr:U:V"), *commonData);
|
||||
} else {
|
||||
svalue1 = "---"; // Missing bus data
|
||||
// Resolution switching
|
||||
if(value1 <= 9.9) epd->print(value1, 2);
|
||||
if(value1 > 9.9 && value1 <= 99.9)epd->print(value1, 1);
|
||||
if(value1 > 99.9) epd->print(value1, 0);
|
||||
}
|
||||
printBoatValue(svalue1, 355, 140, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("V");
|
||||
else{
|
||||
epd->print(commonData->fmt->placeholder); // Missing bus data
|
||||
}
|
||||
}
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("V");
|
||||
|
||||
// Show actual current in A
|
||||
String svalue2;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(260, 200);
|
||||
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
|
||||
svalue2 = formatValue(value2, String("formatXdr:I:A"), *commonData);
|
||||
if(value2 <= 9.9) epd->print(value2, 2);
|
||||
if(value2 > 9.9 && value2 <= 99.9)epd->print(value2, 1);
|
||||
if(value2 > 99.9) epd->print(value2, 0);
|
||||
}
|
||||
else {
|
||||
svalue2 = "---";
|
||||
epd->print(commonData->fmt->placeholder);
|
||||
}
|
||||
printBoatValue(svalue2, 355, 200, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("A");
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("A");
|
||||
|
||||
// Show actual consumption in W
|
||||
String svalue3;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(260, 260);
|
||||
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
|
||||
svalue3 = formatValue(value3, String("formatXdr:G:"), *commonData);
|
||||
if(value3 <= 9.9) epd->print(value3, 2);
|
||||
if(value3 > 9.9 && value3 <= 99.9)epd->print(value3, 1);
|
||||
if(value3 > 99.9) epd->print(value3, 0);
|
||||
}
|
||||
else {
|
||||
svalue3 = "---";
|
||||
epd->print(commonData->fmt->placeholder);
|
||||
}
|
||||
printBoatValue(svalue3, 355, 260, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("W");
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("W");
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
|
||||
+197
-560
@@ -1,301 +1,113 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
/*
|
||||
* PageClock: Clock page with
|
||||
* - Analog mode (mode == 'A')
|
||||
* - Digital mode (mode == 'D')
|
||||
* - Countdown timer mode (mode == 'T')
|
||||
* - Keys in mode analog and digital clock:
|
||||
* K1: MODE (A/D/T)
|
||||
* K2: POS (select field: HH / MM / SS)
|
||||
* K3:
|
||||
* K4:
|
||||
* K5: TZ (Local/UTC)
|
||||
* TODO mode: race timer: keys
|
||||
* - prepare: set countdown to 5min
|
||||
* reset: abort current countdown and start over with 5min preparation
|
||||
* - 5min: key press
|
||||
* - 4min: key press to sync
|
||||
* - 1min: buzzer signal
|
||||
* - start: buzzer signal for start
|
||||
*
|
||||
* Regatta timer mode:
|
||||
* - Format HH:MM:SS (24h, leading zeros)
|
||||
* - Keys in timer mode:
|
||||
* K1: MODE (A/D/T)
|
||||
* K2: POS (select field: HH / MM / SS)
|
||||
* K3: + (increment selected field)
|
||||
* K4: - (decrement selected field)
|
||||
* K5: RUN (start/stop countdown)
|
||||
* - Selection marker: line under active field (width 2px, not wider than digits)
|
||||
* - Editing only possible when timer is not running
|
||||
* - When page is left, running timer continues in background using RTC time
|
||||
* (on re-entry, remaining time is recalculated from RTC)
|
||||
*/
|
||||
|
||||
class PageClock : public Page
|
||||
{
|
||||
bool simulation = false;
|
||||
private:
|
||||
fmtDate dateformat;
|
||||
int simtime;
|
||||
bool keylock = false;
|
||||
#ifdef BOARD_OBP60S3
|
||||
char source = 'G'; // Time source (R)TC | (G)PS | (N)TP
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
char source = 'R'; // time source (R)TC | (G)PS | (N)TP
|
||||
#endif
|
||||
char mode = 'A'; // Display mode (A)nalog | (D)igital | race (T)imer
|
||||
char tz = 'L'; // Time zone (L)ocal | (U)TC
|
||||
double timezone = 0; // There are timezones with non int offsets, e.g. 5.5 or 5.75
|
||||
char mode = 'A'; // display mode (A)nalog | (D)igital | race (T)imer
|
||||
char tz = 'L'; // time zone (L)ocal | (U)TC
|
||||
double timezone = 0; // there are timezones with non int offsets, e.g. 5.5 or 5.75
|
||||
double homelat;
|
||||
double homelon;
|
||||
bool homevalid = false; // Homelat and homelon are valid
|
||||
|
||||
// Timer state (static so it survives page switches)
|
||||
static bool timerInitialized;
|
||||
static bool timerRunning;
|
||||
static int timerHours;
|
||||
static int timerMinutes;
|
||||
static int timerSeconds;
|
||||
// Preset seconds for sync button (default 4 minutes)
|
||||
static const int timerPresetSeconds = 4 * 60;
|
||||
// Initial timer setting at start (so we can restore it)
|
||||
static int timerStartHours;
|
||||
static int timerStartMinutes;
|
||||
static int timerStartSeconds;
|
||||
static int selectedField; // 0 = hours, 1 = minutes, 2 = seconds
|
||||
static bool showSelectionMarker;
|
||||
static time_t timerEndEpoch; // Absolute end time based on RTC
|
||||
|
||||
void setupTimerDefaults()
|
||||
{
|
||||
if (!timerInitialized) {
|
||||
timerInitialized = true;
|
||||
timerRunning = false;
|
||||
timerHours = 0;
|
||||
timerMinutes = 0;
|
||||
timerSeconds = 0;
|
||||
timerStartHours = 0;
|
||||
timerStartMinutes = 0;
|
||||
timerStartSeconds = 0;
|
||||
selectedField = 0;
|
||||
showSelectionMarker = true;
|
||||
timerEndEpoch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Limiter for overrun settings values
|
||||
static int clamp(int value, int minVal, int maxVal)
|
||||
{
|
||||
if (value < minVal) return maxVal;
|
||||
if (value > maxVal) return minVal;
|
||||
return value;
|
||||
}
|
||||
|
||||
void incrementSelected()
|
||||
{
|
||||
if (selectedField == 0) {
|
||||
timerHours = clamp(timerHours + 1, 0, 23);
|
||||
} else if (selectedField == 1) {
|
||||
timerMinutes = clamp(timerMinutes + 1, 0, 59);
|
||||
} else {
|
||||
timerSeconds = clamp(timerSeconds + 1, 0, 59);
|
||||
}
|
||||
}
|
||||
|
||||
void decrementSelected()
|
||||
{
|
||||
if (selectedField == 0) {
|
||||
timerHours = clamp(timerHours - 1, 0, 23);
|
||||
} else if (selectedField == 1) {
|
||||
timerMinutes = clamp(timerMinutes - 1, 0, 59);
|
||||
} else {
|
||||
timerSeconds = clamp(timerSeconds - 1, 0, 59);
|
||||
}
|
||||
}
|
||||
|
||||
int totalTimerSeconds() const
|
||||
{
|
||||
return timerHours * 3600 + timerMinutes * 60 + timerSeconds;
|
||||
}
|
||||
bool homevalid = false; // homelat and homelon are valid
|
||||
|
||||
public:
|
||||
PageClock(CommonData& common)
|
||||
PageClock(CommonData &common) : Page(common)
|
||||
{
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG, "Instantiate PageClock");
|
||||
simulation = common.config->getBool(common.config->useSimuData);
|
||||
timezone = common.config->getString(common.config->timeZone).toDouble();
|
||||
homelat = common.config->getString(common.config->homeLAT).toDouble();
|
||||
homelon = common.config->getString(common.config->homeLON).toDouble();
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageClock");
|
||||
|
||||
// Get config data
|
||||
dateformat = common.fmt->getDateFormat(config->getString(config->dateFormat));
|
||||
timezone = config->getString(config->timeZone).toDouble();
|
||||
homelat = config->getString(config->homeLAT).toDouble();
|
||||
homelon = config->getString(config->homeLON).toDouble();
|
||||
homevalid = homelat >= -180.0 and homelat <= 180 and homelon >= -90.0 and homelon <= 90.0;
|
||||
simtime = 38160; // time value 11:36
|
||||
setupTimerDefaults();
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
// WIP time source
|
||||
String use_rtc = config->getString(config->useRTC);
|
||||
if (use_rtc == "off") {
|
||||
source = 'G';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void setupKeys()
|
||||
{
|
||||
void setupKeys(){
|
||||
Page::setupKeys();
|
||||
|
||||
if (mode == 'T') {
|
||||
// Timer mode: MODE, POS, +, -, RUN
|
||||
commonData->keydata[0].label = "MODE";
|
||||
commonData->keydata[1].label = "POS";
|
||||
// K3: '+' while editing, 'SYNC' while running to set a preset countdown
|
||||
commonData->keydata[2].label = timerRunning ? "SYNC" : "+";
|
||||
commonData->keydata[3].label = "-";
|
||||
commonData->keydata[4].label = timerRunning ? "RESET" : "START";
|
||||
} else {
|
||||
// Clock modes: like original
|
||||
commonData->keydata[0].label = "MODE";
|
||||
commonData->keydata[1].label = "SRC";
|
||||
commonData->keydata[0].label = "SRC";
|
||||
commonData->keydata[1].label = "MODE";
|
||||
commonData->keydata[4].label = "TZ";
|
||||
}
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key)
|
||||
{
|
||||
setupTimerDefaults();
|
||||
int handleKey(int key){
|
||||
// Time source
|
||||
if (key == 1) {
|
||||
if (source == 'G') {
|
||||
source = 'R';
|
||||
} else {
|
||||
source = 'G';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 2) {
|
||||
if (mode == 'A') {
|
||||
mode = 'D';
|
||||
} else if (mode == 'D') {
|
||||
mode = 'T';
|
||||
} else {
|
||||
mode = 'A';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// Time zone: Local / UTC
|
||||
if (key == 5) {
|
||||
if (tz == 'L') {
|
||||
tz = 'U';
|
||||
} else {
|
||||
tz = 'L';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Keylock function
|
||||
if(key == 11){ // Code for keylock
|
||||
keylock = !keylock; // Toggle keylock
|
||||
return 0; // Commit the key
|
||||
}
|
||||
|
||||
if (mode == 'T') {
|
||||
// Timer mode key handling
|
||||
|
||||
// MODE (K1): cycle display mode A/D/T
|
||||
if (key == 1) {
|
||||
switch (mode) {
|
||||
case 'A': mode = 'D'; break;
|
||||
case 'D': mode = 'T'; break;
|
||||
case 'T': mode = 'A'; break;
|
||||
default: mode = 'A'; break;
|
||||
}
|
||||
setupKeys();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// POS (K2): select field HH / MM / SS (only if timer not running)
|
||||
if (key == 2 && !timerRunning) {
|
||||
selectedField = (selectedField + 1) % 3;
|
||||
showSelectionMarker = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// + (K3): increment selected field (only if timer not running)
|
||||
if (key == 3 && !timerRunning) {
|
||||
incrementSelected();
|
||||
return 0;
|
||||
}
|
||||
if (key == 3 && timerRunning) {
|
||||
// When timer is running, K3 acts as a synchronization button:
|
||||
// set remaining countdown to the preset value (e.g. 4 minutes).
|
||||
if (commonData->data.rtcValid) {
|
||||
int preset = timerPresetSeconds;
|
||||
// update start-setting so STOP will restore this preset
|
||||
timerStartHours = preset / 3600;
|
||||
timerStartMinutes = (preset % 3600) / 60;
|
||||
timerStartSeconds = preset % 60;
|
||||
|
||||
struct tm rtcCopy = commonData->data.rtcTime;
|
||||
time_t nowEpoch = mktime(&rtcCopy);
|
||||
timerEndEpoch = nowEpoch + preset;
|
||||
|
||||
// Update visible timer fields immediately
|
||||
timerHours = timerStartHours;
|
||||
timerMinutes = timerStartMinutes;
|
||||
timerSeconds = timerStartSeconds;
|
||||
// commonData->keydata[4].label = "RESET";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// - (K4): decrement selected field (only if timer not running)
|
||||
if (key == 4 && !timerRunning) {
|
||||
decrementSelected();
|
||||
return 0;
|
||||
}
|
||||
if (key == 4 && timerRunning) { // No action if timer running
|
||||
return 0;
|
||||
}
|
||||
|
||||
// RUN (K5): start/stop timer
|
||||
if (key == 5) {
|
||||
if (!timerRunning) {
|
||||
// Start timer if a non-zero duration is set
|
||||
int total = totalTimerSeconds();
|
||||
if (total > 0 && commonData->data.rtcValid) {
|
||||
// Remember initial timer setting at start
|
||||
timerStartHours = timerHours;
|
||||
timerStartMinutes = timerMinutes;
|
||||
timerStartSeconds = timerSeconds;
|
||||
|
||||
struct tm rtcCopy = commonData->data.rtcTime;
|
||||
time_t nowEpoch = mktime(&rtcCopy);
|
||||
timerEndEpoch = nowEpoch + total;
|
||||
timerRunning = true;
|
||||
showSelectionMarker = false;
|
||||
}
|
||||
} else {
|
||||
// Stop timer: restore initial start setting
|
||||
timerHours = timerStartHours;
|
||||
timerMinutes = timerStartMinutes;
|
||||
timerSeconds = timerStartSeconds;
|
||||
timerRunning = false;
|
||||
showSelectionMarker = true;
|
||||
// marker will become visible again only after POS press
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// In timer mode, other keys are passed through
|
||||
return key;
|
||||
}
|
||||
|
||||
// Clock (A/D) modes key handling – like original PageClock
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
// MODE (K1)
|
||||
if (key == 1) {
|
||||
switch (mode) {
|
||||
case 'A': mode = 'D'; break;
|
||||
case 'D': mode = 'T'; break;
|
||||
case 'T': mode = 'A'; break;
|
||||
default: mode = 'A'; break;
|
||||
}
|
||||
setupKeys();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Time source (K2)
|
||||
if (key == 2) {
|
||||
switch (source) {
|
||||
case 'G': source = 'R'; break;
|
||||
case 'R': source = 'G'; break;
|
||||
default: source = 'G'; break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Time zone: Local / UTC (K5)
|
||||
if (key == 5) {
|
||||
switch (tz) {
|
||||
case 'L': tz = 'U'; break;
|
||||
case 'U': tz = 'L'; break;
|
||||
default: tz = 'L'; break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData& pageData)
|
||||
{
|
||||
GwConfigHandler* config = commonData->config;
|
||||
GwLog* logger = commonData->logger;
|
||||
|
||||
setupTimerDefaults();
|
||||
setupKeys(); // Ensure correct key labels for current mode
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
static String svalue1old = "";
|
||||
static String unit1old = "";
|
||||
@@ -307,60 +119,58 @@ public:
|
||||
static String svalue5old = "";
|
||||
static String svalue6old = "";
|
||||
|
||||
double value1 = 0;
|
||||
double value2 = 0;
|
||||
double value3 = 0;
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
String dateformat = config->getString(config->dateFormat);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
double value1 = 0; // GPS time
|
||||
double value2 = 0; // GPS date FIXME date defined as uint32_t!
|
||||
double value3 = 0; // HDOP
|
||||
bool gpsvalid = false;
|
||||
|
||||
// Get boat values for GPS time
|
||||
GwApi::BoatValue* bvalue1 = pageData.values[0]; // First element in list
|
||||
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 {
|
||||
}
|
||||
else{
|
||||
value1 = simtime++; // Simulation data for time value 11:36 in seconds
|
||||
} // Other simulation data see OBP60Formatter.cpp
|
||||
bool valid1 = bvalue1->valid; // Valid information
|
||||
String svalue1 = formatValue(bvalue1, *commonData).svalue; // Formatted value
|
||||
String unit1 = formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->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]; // Second element in list
|
||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second 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 informationgetdisplay().print("RTC");
|
||||
String svalue2 = formatValue(bvalue2, *commonData).svalue; // Formatted value
|
||||
String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||
bool valid2 = bvalue2->valid; // Valid information
|
||||
String svalue2 = commonData->fmt->formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit2 = commonData->fmt->formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||
if(valid2 == true){
|
||||
svalue2old = svalue2; // Save old value
|
||||
unit2old = unit2; // Save old unit
|
||||
}
|
||||
|
||||
// Get boat values for HDOP
|
||||
GwApi::BoatValue* bvalue3 = pageData.values[2]; // Third element in list
|
||||
// Get boat values for HDOP date
|
||||
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Third element in list (only one value by PageOneValue)
|
||||
String name3 = bvalue3->getName().c_str(); // Value name
|
||||
name3 = name3.substring(0, 6); // String length limit for value name
|
||||
value3 = bvalue3->value; // Value as double in SI unit
|
||||
bool valid3 = bvalue3->valid; // Valid information
|
||||
String svalue3 = formatValue(bvalue3, *commonData).svalue; // Formatted value
|
||||
String unit3 = formatValue(bvalue3, *commonData).unit; // Unit of value
|
||||
String svalue3 = commonData->fmt->formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit3 = commonData->fmt->formatValue(bvalue3, *commonData).unit; // Unit of value
|
||||
if(valid3 == true){
|
||||
svalue3old = svalue3; // Save old value
|
||||
unit3old = unit3; // Save old unit
|
||||
}
|
||||
|
||||
// GPS date and time are valid and can be used
|
||||
gpsvalid = (valid1 && valid2 && valid3);
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
@@ -368,317 +178,159 @@ public:
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK;
|
||||
LOG_DEBUG(GwLog::LOG, "Drawing at PageClock, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageClock, %s:%f, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2, name3.c_str(), value3);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
time_t tv = mktime(&commonData->data.rtcTime) + timezone * 3600;
|
||||
struct tm *local_tm = localtime(&tv);
|
||||
|
||||
if (mode == 'T') {
|
||||
// REGATTA TIMER MODE: countdown timer HH:MM:SS in the center with 7-segment font
|
||||
//*******************************************************************************
|
||||
|
||||
int dispH = timerHours;
|
||||
int dispM = timerMinutes;
|
||||
int dispS = timerSeconds;
|
||||
|
||||
// Update remaining time if timer is running (based on RTC)
|
||||
if (timerRunning && commonData->data.rtcValid) {
|
||||
struct tm rtcCopy = commonData->data.rtcTime;
|
||||
time_t nowEpoch = mktime(&rtcCopy);
|
||||
time_t remaining = timerEndEpoch - nowEpoch;
|
||||
if(remaining <= 5 && remaining != 0){
|
||||
// Short pre buzzer alarm (100% power)
|
||||
setBuzzerPower(100);
|
||||
buzzer(TONE2, 75);
|
||||
setBuzzerPower(config->getInt(config->buzzerPower));
|
||||
}
|
||||
if (remaining <= 0) {
|
||||
remaining = 0;
|
||||
timerRunning = false;
|
||||
commonData->keydata[3].label = "-";
|
||||
commonData->keydata[4].label = "START";
|
||||
showSelectionMarker = true;
|
||||
// Buzzer alarm (100% power)
|
||||
setBuzzerPower(100);
|
||||
buzzer(TONE2, 800);
|
||||
setBuzzerPower(config->getInt(config->buzzerPower));
|
||||
|
||||
// When countdown is finished, restore the initial start time
|
||||
timerHours = timerStartHours;
|
||||
timerMinutes = timerStartMinutes;
|
||||
timerSeconds = timerStartSeconds;
|
||||
}
|
||||
else{
|
||||
commonData->keydata[3].label = "";
|
||||
commonData->keydata[4].label = "RESET";
|
||||
}
|
||||
int rem = static_cast<int>(remaining);
|
||||
dispH = rem / 3600;
|
||||
rem -= dispH * 3600;
|
||||
dispM = rem / 60;
|
||||
dispS = rem % 60;
|
||||
}
|
||||
|
||||
char buf[9]; // "HH:MM:SS"
|
||||
snprintf(buf, sizeof(buf), "%02d:%02d:%02d", dispH, dispM, dispS);
|
||||
String timeStr = String(buf);
|
||||
|
||||
// Clear central area and draw large digital time
|
||||
getdisplay().fillRect(0, 110, getdisplay().width(), 80, commonData->bgcolor);
|
||||
|
||||
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
|
||||
// Determine widths for digits and colon to position selection underline exactly
|
||||
int16_t x0, y0;
|
||||
uint16_t wDigit, hDigit;
|
||||
uint16_t wColon, hColon;
|
||||
|
||||
displayGetTextBounds("00", 0, 0, &x0, &y0, &wDigit, &hDigit);
|
||||
displayGetTextBounds(":", 0, 0, &x0, &y0, &wColon, &hColon);
|
||||
|
||||
uint16_t totalWidth = 3 * wDigit + 2 * wColon;
|
||||
|
||||
int16_t baseX = (static_cast<int16_t>(getdisplay().width()) - static_cast<int16_t>(totalWidth)) / 2;
|
||||
int16_t centerY = 150;
|
||||
|
||||
// Draw time string centered
|
||||
int16_t x1b, y1b;
|
||||
uint16_t wb, hb;
|
||||
displayGetTextBounds(timeStr, 0, 0, &x1b, &y1b, &wb, &hb);
|
||||
int16_t textX = (static_cast<int16_t>(getdisplay().width()) - static_cast<int16_t>(wb)) / 2;
|
||||
int16_t textY = centerY + hb / 2;
|
||||
|
||||
//getdisplay().setCursor(textX, textY); // horzontal jitter
|
||||
getdisplay().setCursor(47, textY); // static X position
|
||||
getdisplay().print(timeStr);
|
||||
|
||||
// Selection marker (only visible when not running and POS pressed)
|
||||
if (!timerRunning && showSelectionMarker) {
|
||||
int16_t selX = baseX - 8; // Hours start
|
||||
if (selectedField == 1) {
|
||||
selX = baseX + wDigit + wColon; // Minutes start
|
||||
} else if (selectedField == 2) {
|
||||
selX = baseX + 2 * wDigit + 2 * wColon + 12; // Seconds start
|
||||
}
|
||||
|
||||
int16_t underlineY = centerY + hb / 2 + 5;
|
||||
//getdisplay().fillRect(selX, underlineY, wDigit, 6, commonData->fgcolor);
|
||||
getdisplay().fillRoundRect(selX, underlineY, wDigit, 6, 2, commonData->fgcolor);
|
||||
}
|
||||
|
||||
// Page label
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(100, 70);
|
||||
getdisplay().print("Regatta Timer");
|
||||
|
||||
} else if (mode == 'D') {
|
||||
// DIGITAL CLOCK MODE: large 7-segment time based on GPS/RTC
|
||||
//**********************************************************
|
||||
|
||||
int hour24 = 0;
|
||||
int minute24 = 0;
|
||||
int second24 = 0;
|
||||
|
||||
if (source == 'R' && commonData->data.rtcValid) {
|
||||
time_t tv2 = mktime(&commonData->data.rtcTime);
|
||||
if (tz == 'L') {
|
||||
tv2 += static_cast<time_t>(timezone * 3600);
|
||||
}
|
||||
struct tm* tm2 = localtime(&tv2);
|
||||
hour24 = tm2->tm_hour;
|
||||
minute24 = tm2->tm_min;
|
||||
second24 = tm2->tm_sec;
|
||||
} else {
|
||||
double t = value1;
|
||||
if (tz == 'L') {
|
||||
t += timezone * 3600;
|
||||
}
|
||||
if (t >= 86400) t -= 86400;
|
||||
if (t < 0) t += 86400;
|
||||
hour24 = static_cast<int>(t / 3600.0);
|
||||
int rest = static_cast<int>(t) - hour24 * 3600;
|
||||
minute24 = rest / 60;
|
||||
second24 = rest % 60;
|
||||
}
|
||||
|
||||
char buf[9]; // "HH:MM:SS"
|
||||
snprintf(buf, sizeof(buf), "%02d:%02d:%02d", hour24, minute24, second24);
|
||||
String timeStr = String(buf);
|
||||
|
||||
getdisplay().fillRect(0, 110, getdisplay().width(), 80, commonData->bgcolor);
|
||||
|
||||
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
|
||||
int16_t x1b, y1b;
|
||||
uint16_t wb, hb;
|
||||
displayGetTextBounds(timeStr, 0, 0, &x1b, &y1b, &wb, &hb);
|
||||
|
||||
int16_t x = (static_cast<int16_t>(getdisplay().width()) - static_cast<int16_t>(wb)) / 2;
|
||||
int16_t y = 150 + hb / 2;
|
||||
|
||||
//getdisplay().setCursor(x, y); // horizontal jitter
|
||||
getdisplay().setCursor(47, y); // static X position
|
||||
getdisplay().print(timeStr); // Display actual time
|
||||
|
||||
// Small indicators: timezone and source
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
|
||||
getdisplay().setCursor(47, 110);
|
||||
if (source == 'G') {
|
||||
getdisplay().print("GPS");
|
||||
} else {
|
||||
getdisplay().print("RTC");
|
||||
}
|
||||
|
||||
getdisplay().setCursor(47 + 40, 110);
|
||||
if (holdvalues == false) {
|
||||
getdisplay().print(tz == 'L' ? "LOT" : "UTC");
|
||||
} else {
|
||||
getdisplay().print(unit2old); // date unit
|
||||
}
|
||||
|
||||
// Page label
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(100, 70);
|
||||
getdisplay().print("Digital Clock");
|
||||
|
||||
} else {
|
||||
// ANALOG CLOCK MODE (mode == 'A')
|
||||
//********************************
|
||||
|
||||
// Show values GPS date
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 65);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 65);
|
||||
if (holdvalues == false) {
|
||||
if (source == 'G') {
|
||||
// GPS value
|
||||
getdisplay().print(svalue2);
|
||||
epd->print(svalue2);
|
||||
} else if (commonData->data.rtcValid) {
|
||||
// RTC value
|
||||
if (tz == 'L') {
|
||||
getdisplay().print(formatDate(dateformat, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday));
|
||||
} else {
|
||||
getdisplay().print(formatDate(dateformat, commonData->data.rtcTime.tm_year + 1900, commonData->data.rtcTime.tm_mon + 1, commonData->data.rtcTime.tm_mday));
|
||||
epd->print(formatDate(dateformat, local_tm->tm_year + 1900, local_tm->tm_mon + 1, local_tm->tm_mday));
|
||||
}
|
||||
else {
|
||||
epd->print(formatDate(dateformat, commonData->data.rtcTime.tm_year + 1900, commonData->data.rtcTime.tm_mon + 1, commonData->data.rtcTime.tm_mday));
|
||||
}
|
||||
} else {
|
||||
getdisplay().print("---");
|
||||
epd->print(commonData->fmt->placeholder);
|
||||
}
|
||||
} else {
|
||||
getdisplay().print(svalue2old);
|
||||
epd->print(svalue2old);
|
||||
}
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(10, 95);
|
||||
getdisplay().print("Date"); // Name
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(10, 95);
|
||||
epd->print("Date"); // Name
|
||||
|
||||
// Horizontal separator left
|
||||
getdisplay().fillRect(0, 149, 60, 3, commonData->fgcolor);
|
||||
// Horizintal separator left
|
||||
epd->fillRect(0, 149, 60, 3, commonData->fgcolor);
|
||||
|
||||
// Show values GPS time (small text bottom left)
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 250);
|
||||
// Show values GPS time
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 250);
|
||||
if (holdvalues == false) {
|
||||
if (source == 'G') {
|
||||
getdisplay().print(svalue1); // Value
|
||||
} else if (commonData->data.rtcValid) {
|
||||
epd->print(svalue1); // Value
|
||||
}
|
||||
else if (commonData->data.rtcValid) {
|
||||
if (tz == 'L') {
|
||||
getdisplay().print(formatTime('s', local_tm->tm_hour, local_tm->tm_min, local_tm->tm_sec));
|
||||
} else {
|
||||
getdisplay().print(formatTime('s', commonData->data.rtcTime.tm_hour, commonData->data.rtcTime.tm_min, commonData->data.rtcTime.tm_sec));
|
||||
epd->print(formatTime(fmtTime::MMHHSS, local_tm->tm_hour, local_tm->tm_min, local_tm->tm_sec));
|
||||
}
|
||||
else {
|
||||
epd->print(formatTime(fmtTime::MMHHSS, commonData->data.rtcTime.tm_hour, commonData->data.rtcTime.tm_min, commonData->data.rtcTime.tm_sec));
|
||||
}
|
||||
} else {
|
||||
getdisplay().print("---");
|
||||
epd->print(commonData->fmt->placeholder);
|
||||
}
|
||||
} else {
|
||||
getdisplay().print(svalue1old);
|
||||
}
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(10, 220);
|
||||
getdisplay().print("Time"); // Name
|
||||
else {
|
||||
epd->print(svalue1old);
|
||||
}
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(10, 220);
|
||||
epd->print("Time"); // Name
|
||||
|
||||
// Show values sunrise
|
||||
String sunrise = "---";
|
||||
if ((valid1 and valid2 and valid3 == true) or (homevalid and commonData->data.rtcValid)) {
|
||||
String sunrise = commonData->fmt->placeholder;
|
||||
if (((source == 'G') and gpsvalid) or (homevalid and commonData->data.rtcValid)) {
|
||||
sunrise = String(commonData->sundata.sunriseHour) + ":" + String(commonData->sundata.sunriseMinute + 100).substring(1);
|
||||
svalue5old = sunrise;
|
||||
} else if (simulation) {
|
||||
sunrise = String("06:42");
|
||||
}
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(335, 65);
|
||||
if (holdvalues == false) getdisplay().print(sunrise); // Value
|
||||
else getdisplay().print(svalue5old);
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(335, 95);
|
||||
getdisplay().print("SunR"); // Name
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(335, 65);
|
||||
if(holdvalues == false) epd->print(sunrise); // Value
|
||||
else epd->print(svalue5old);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(335, 95);
|
||||
epd->print("SunR"); // Name
|
||||
|
||||
// Horizontal separator right
|
||||
getdisplay().fillRect(340, 149, 80, 3, commonData->fgcolor);
|
||||
// Horizintal separator right
|
||||
epd->fillRect(340, 149, 80, 3, commonData->fgcolor);
|
||||
|
||||
// Show values sunset
|
||||
String sunset = "---";
|
||||
if ((valid1 and valid2 and valid3 == true) or (homevalid and commonData->data.rtcValid)) {
|
||||
String sunset = commonData->fmt->placeholder;
|
||||
if (((source == 'G') and gpsvalid) or (homevalid and commonData->data.rtcValid)) {
|
||||
sunset = String(commonData->sundata.sunsetHour) + ":" + String(commonData->sundata.sunsetMinute + 100).substring(1);
|
||||
svalue6old = sunset;
|
||||
} else if (simulation) {
|
||||
sunset = String("21:03");
|
||||
}
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(335, 250);
|
||||
if (holdvalues == false) getdisplay().print(sunset); // Value
|
||||
else getdisplay().print(svalue6old);
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(335, 220);
|
||||
getdisplay().print("SunS"); // Name
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(335, 250);
|
||||
if(holdvalues == false) epd->print(sunset); // Value
|
||||
else epd->print(svalue6old);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(335, 220);
|
||||
epd->print("SunS"); // Name
|
||||
|
||||
//*******************************************************************************************
|
||||
|
||||
// Draw clock
|
||||
int rInstrument = 110; // Radius of clock
|
||||
float pi = 3.141592;
|
||||
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
epd->fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
epd->fillCircle(200, 150, rInstrument + 7, commonData->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 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 x1c, y1c; // Return values of getTextBounds
|
||||
uint16_t wc, hc; // Return values of getTextBounds
|
||||
displayGetTextBounds(ii, int(x), int(y), &x1c, &y1c, &wc, &hc); // Calc width of new string
|
||||
getdisplay().setCursor(x - wc / 2, y + hc / 2);
|
||||
if (i % 90 == 0) {
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().print(ii);
|
||||
int16_t x1, y1; // Return values of getTextBounds
|
||||
uint16_t w, h; // Return values of getTextBounds
|
||||
epd->getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
epd->setCursor(x-w/2, y+h/2);
|
||||
if(i % 30 == 0){
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->print(ii);
|
||||
}
|
||||
|
||||
// Draw sub scale with dots
|
||||
float sinx = 0;
|
||||
float cosx = 0;
|
||||
if(i % 6 == 0){
|
||||
float x1d = 200 + rInstrument * sin(i / 180.0 * pi);
|
||||
float y1d = 150 - rInstrument * cos(i / 180.0 * pi);
|
||||
getdisplay().fillCircle((int)x1d, (int)y1d, 2, commonData->fgcolor);
|
||||
float x1c = 200 + rInstrument*sin(i/180.0*pi);
|
||||
float y1c = 150 - rInstrument*cos(i/180.0*pi);
|
||||
epd->fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor);
|
||||
sinx=sin(i/180.0*pi);
|
||||
cosx=cos(i/180.0*pi);
|
||||
}
|
||||
@@ -690,30 +342,31 @@ displayGetTextBounds(":", 0, 0, &x0, &y0, &wColon, &hColon);
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
getdisplay().fillTriangle(200 + (int)(cosx * xx2 - sinx * yy1), 150 + (int)(sinx * xx2 + cosx * yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
// Print Unit in clock
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(175, 110);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(175, 110);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(tz == 'L' ? "LOT" : "UTC");
|
||||
} else {
|
||||
getdisplay().print(unit2old); // date unit
|
||||
epd->print(tz == 'L' ? "LOT" : "UTC");
|
||||
}
|
||||
else{
|
||||
epd->print(unit2old); // date unit
|
||||
}
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(185, 190);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(185, 190);
|
||||
if (source == 'G') {
|
||||
getdisplay().print("GPS");
|
||||
epd->print("GPS");
|
||||
} else {
|
||||
getdisplay().print("RTC");
|
||||
epd->print("RTC");
|
||||
}
|
||||
|
||||
// Clock values
|
||||
@@ -721,10 +374,10 @@ displayGetTextBounds(":", 0, 0, &x0, &y0, &wColon, &hColon);
|
||||
double minute = 0;
|
||||
if (source == 'R') {
|
||||
if (tz == 'L') {
|
||||
time_t tv2 = mktime(&commonData->data.rtcTime) + timezone * 3600;
|
||||
struct tm* local_tm2 = localtime(&tv2);
|
||||
minute = local_tm2->tm_min;
|
||||
hour = local_tm2->tm_hour;
|
||||
time_t tv = mktime(&commonData->data.rtcTime) + timezone * 3600;
|
||||
struct tm *local_tm = localtime(&tv);
|
||||
minute = local_tm->tm_min;
|
||||
hour = local_tm->tm_hour;
|
||||
} else {
|
||||
minute = commonData->data.rtcTime.tm_min;
|
||||
hour = commonData->data.rtcTime.tm_hour;
|
||||
@@ -743,7 +396,7 @@ displayGetTextBounds(":", 0, 0, &x0, &y0, &wColon, &hColon);
|
||||
if (hour > 12) {
|
||||
hour -= 12.0;
|
||||
}
|
||||
LOG_DEBUG(GwLog::DEBUG, "... PageClock, value1: %f hour: %f minute:%f", value1, hour, minute);
|
||||
logger->logDebug(GwLog::DEBUG, "... PageClock, value1: %f hour: %f minute:%f", value1, hour, minute);
|
||||
|
||||
// Draw hour pointer
|
||||
float startwidth = 8; // Start width of pointer
|
||||
@@ -756,7 +409,7 @@ displayGetTextBounds(":", 0, 0, &x0, &y0, &wColon, &hColon);
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
// Inverted pointer
|
||||
@@ -766,7 +419,7 @@ displayGetTextBounds(":", 0, 0, &x0, &y0, &wColon, &hColon);
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
}
|
||||
@@ -782,7 +435,7 @@ displayGetTextBounds(":", 0, 0, &x0, &y0, &wColon, &hColon);
|
||||
float xx2 = startwidth;
|
||||
float yy1 = -startwidth;
|
||||
float yy2 = -(rInstrument - 15);
|
||||
getdisplay().fillTriangle(200 + (int)(cosx * xx1 - sinx * yy1), 150 + (int)(sinx * xx1 + cosx * yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
// Inverted pointer
|
||||
@@ -792,43 +445,28 @@ displayGetTextBounds(":", 0, 0, &x0, &y0, &wColon, &hColon);
|
||||
float ix2 = -endwidth;
|
||||
float iy1 = -(rInstrument - 15);
|
||||
float iy2 = -endwidth;
|
||||
getdisplay().fillTriangle(200 + (int)(cosx * ix1 - sinx * iy1), 150 + (int)(sinx * ix1 + cosx * iy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
}
|
||||
|
||||
// Center circle
|
||||
getdisplay().fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
||||
getdisplay().fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
||||
}
|
||||
epd->fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
||||
epd->fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
// Static member definitions
|
||||
bool PageClock::timerInitialized = false;
|
||||
bool PageClock::timerRunning = false;
|
||||
int PageClock::timerHours = 0;
|
||||
int PageClock::timerMinutes = 0;
|
||||
int PageClock::timerSeconds = 0;
|
||||
int PageClock::timerStartHours = 0;
|
||||
int PageClock::timerStartMinutes = 0;
|
||||
int PageClock::timerStartSeconds = 0;
|
||||
int PageClock::selectedField = 0;
|
||||
bool PageClock::showSelectionMarker = true;
|
||||
time_t PageClock::timerEndEpoch = 0;
|
||||
|
||||
static Page* createPage(CommonData& common)
|
||||
{
|
||||
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
|
||||
* we provide the number of user parameters we expect (0 here)
|
||||
* and we provide the names of the fixed values we need
|
||||
* 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
|
||||
@@ -839,4 +477,3 @@ PageDescription registerPageClock(
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -17,35 +18,31 @@ const int ShowSTW = 3;
|
||||
const int ShowSOG = 4;
|
||||
const int ShowDBS = 5;
|
||||
|
||||
const int Compass_X0 = 200; // X center point of compass band
|
||||
const int Compass_Y0 = 220; // Y position of compass lines
|
||||
const int Compass_LineLength = 22; // Length of compass lines
|
||||
const float Compass_LineDelta = 8.0;// Compass band: 1deg = 5 Pixels, 10deg = 50 Pixels
|
||||
const int Compass_X0 = 200; // center point of compass band
|
||||
const int Compass_Y0 = 220; // position of compass lines
|
||||
const int Compass_LineLength = 22; // length of compass lines
|
||||
const float Compass_LineDelta = 8.0;// compass band: 1deg = 5 Pixels, 10deg = 50 Pixels
|
||||
|
||||
class PageCompass : public Page
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
|
||||
private:
|
||||
int WhichDataCompass = ShowHDM;
|
||||
int WhichDataDisplay = ShowHDM;
|
||||
|
||||
public:
|
||||
PageCompass(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageCompass");
|
||||
PageCompass(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageCompass");
|
||||
}
|
||||
|
||||
virtual void setupKeys(){
|
||||
void setupKeys(){
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "CMP";
|
||||
commonData->keydata[1].label = "SRC";
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
|
||||
if (key == 1) {
|
||||
WhichDataCompass += 1;
|
||||
if ( WhichDataCompass > ShowCOG)
|
||||
@@ -57,7 +54,6 @@ class PageCompass : public Page
|
||||
if (WhichDataDisplay > ShowDBS)
|
||||
WhichDataDisplay = ShowHDM;
|
||||
}
|
||||
|
||||
if (key == 11) {
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0; // Commit the key
|
||||
@@ -65,22 +61,22 @@ class PageCompass : public Page
|
||||
return key;
|
||||
}
|
||||
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Old values for hold function
|
||||
static String OldDataText[HowManyValues] = {"", "", "","", "", ""};
|
||||
static String OldDataUnits[HowManyValues] = {"", "", "","", "", ""};
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
// bool simulation = config->getBool(config->useSimuData);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
GwApi::BoatValue *bvalue;
|
||||
String DataName[HowManyValues];
|
||||
double DataValue[HowManyValues];
|
||||
@@ -92,21 +88,15 @@ class PageCompass : public Page
|
||||
|
||||
for (int i = 0; i < HowManyValues; i++){
|
||||
bvalue = pageData.values[i];
|
||||
TheFormattedData = formatValue(bvalue, *commonData);
|
||||
TheFormattedData = commonData->fmt->formatValue(bvalue, *commonData);
|
||||
DataName[i] = xdrDelete(bvalue->getName());
|
||||
DataName[i] = DataName[i].substring(0, 6); // String length limit for value name
|
||||
DataUnits[i] = formatValue(bvalue, *commonData).unit;
|
||||
DataUnits[i] = commonData->fmt->formatValue(bvalue, *commonData).unit;
|
||||
DataText[i] = TheFormattedData.svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
DataValue[i] = TheFormattedData.value; // Value as double in SI unit
|
||||
DataValid[i] = bvalue->valid;
|
||||
DataFormat[i] = bvalue->getFormat(); // Unit of value
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageCompass: %d %s %f %s %s", i, DataName[i], DataValue[i], DataFormat[i], DataText[i] );
|
||||
}
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageCompass: %d %s %f %s %s", i, DataName[i], DataValue[i], DataFormat[i], DataText[i] );
|
||||
}
|
||||
|
||||
if (bvalue == NULL) return PAGE_OK; // WTF why this statement?
|
||||
@@ -114,25 +104,27 @@ class PageCompass : public Page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// Horizontal line 2 pix top & bottom
|
||||
// Print data on top half
|
||||
getdisplay().fillRect(0, 130, 400, 2, commonData->fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(10, 70);
|
||||
getdisplay().print(DataName[WhichDataDisplay]); // Page name
|
||||
epd->fillRect(0, 130, 400, 2, commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(10, 70);
|
||||
epd->print(DataName[WhichDataDisplay]); // Page name
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(10, 120);
|
||||
getdisplay().print(DataUnits[WhichDataDisplay]);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(10, 120);
|
||||
epd->print(DataUnits[WhichDataDisplay]);
|
||||
epd->setCursor(190, 120);
|
||||
epd->setFont(&DSEG7Classic_BoldItalic42pt7b);
|
||||
|
||||
if(holdvalues == false){
|
||||
printBoatValue(DataText[WhichDataDisplay], 190, 120, LEFT, 42, smallDecimals); // Real value as formated string
|
||||
epd->print(DataText[WhichDataDisplay]); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(OldDataText[WhichDataDisplay], 190, 120, LEFT, 42, smallDecimals); // Old value as formated string
|
||||
epd->print(OldDataText[WhichDataDisplay]); // Old value as formated string
|
||||
}
|
||||
if(DataValid[WhichDataDisplay] == true){
|
||||
OldDataText[WhichDataDisplay] = DataText[WhichDataDisplay]; // Save the old value
|
||||
@@ -151,14 +143,14 @@ class PageCompass : public Page
|
||||
char buffer[bsize+1];
|
||||
buffer[0]=0;
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(10, Compass_Y0-60);
|
||||
getdisplay().print(DataName[WhichDataCompass]); // Page name
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->setCursor(10, Compass_Y0-60);
|
||||
epd->print(DataName[WhichDataCompass]); // Page name
|
||||
|
||||
|
||||
// Draw compass base line and pointer
|
||||
getdisplay().fillRect(0, Compass_Y0, 400, 3, commonData->fgcolor);
|
||||
getdisplay().fillTriangle(Compass_X0,Compass_Y0-40,Compass_X0-10,Compass_Y0-80,Compass_X0+10,Compass_Y0-80,commonData->fgcolor);
|
||||
epd->fillRect(0, Compass_Y0, 400, 3, commonData->fgcolor);
|
||||
epd->fillTriangle(Compass_X0,Compass_Y0-40,Compass_X0-10,Compass_Y0-80,Compass_X0+10,Compass_Y0-80,commonData->fgcolor);
|
||||
// Draw trendlines
|
||||
for ( int i = 1; i < abs(TheTrend) / 2; i++){
|
||||
int x1;
|
||||
@@ -167,7 +159,7 @@ class PageCompass : public Page
|
||||
else
|
||||
x1 = Compass_X0 - 20 * ( i + 1 );
|
||||
|
||||
getdisplay().fillRect(x1, Compass_Y0 -55, 10, 6, commonData->fgcolor);
|
||||
epd->fillRect(x1, Compass_Y0 -55, 10, 6, commonData->fgcolor);
|
||||
}
|
||||
// Central line + satellite lines
|
||||
double NextSector = round(TheAngle / ( M_PI / 9 )) * ( M_PI / 9 ); // Get the next 20degree value
|
||||
@@ -177,28 +169,28 @@ class PageCompass : public Page
|
||||
for ( int i = 0; i <=4; i++ ){
|
||||
int x0;
|
||||
x0 = Compass_X0 + Delta_X + 2 * i * 5 * Compass_LineDelta;
|
||||
getdisplay().fillRect(x0-2, Compass_Y0 - 2 * Compass_LineLength, 5, 2 * Compass_LineLength, commonData->fgcolor);
|
||||
epd->fillRect(x0-2, Compass_Y0 - 2 * Compass_LineLength, 5, 2 * Compass_LineLength, commonData->fgcolor);
|
||||
x0 = Compass_X0 + Delta_X + ( 2 * i + 1 ) * 5 * Compass_LineDelta;
|
||||
getdisplay().fillRect(x0-1, Compass_Y0 - Compass_LineLength, 3, Compass_LineLength, commonData->fgcolor);
|
||||
epd->fillRect(x0-1, Compass_Y0 - Compass_LineLength, 3, Compass_LineLength, commonData->fgcolor);
|
||||
|
||||
x0 = Compass_X0 + Delta_X - 2 * i * 5 * Compass_LineDelta;
|
||||
getdisplay().fillRect(x0-2, Compass_Y0 - 2 * Compass_LineLength, 5, 2 * Compass_LineLength, commonData->fgcolor);
|
||||
epd->fillRect(x0-2, Compass_Y0 - 2 * Compass_LineLength, 5, 2 * Compass_LineLength, commonData->fgcolor);
|
||||
x0 = Compass_X0 + Delta_X - ( 2 * i + 1 ) * 5 * Compass_LineDelta;
|
||||
getdisplay().fillRect(x0-1, Compass_Y0 - Compass_LineLength, 3, Compass_LineLength, commonData->fgcolor);
|
||||
epd->fillRect(x0-1, Compass_Y0 - Compass_LineLength, 3, Compass_LineLength, commonData->fgcolor);
|
||||
}
|
||||
|
||||
getdisplay().fillRect(0, Compass_Y0, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, Compass_Y0, 400, 3, commonData->fgcolor);
|
||||
// Add the numbers to the compass band
|
||||
int x0;
|
||||
float AngleToDisplay = NextSector * 180.0 / M_PI;
|
||||
|
||||
x0 = Compass_X0 + Delta_X;
|
||||
getdisplay().setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||
epd->setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||
|
||||
do {
|
||||
getdisplay().setCursor(x0 - 40, Compass_Y0 + 40);
|
||||
epd->setCursor(x0 - 40, Compass_Y0 + 40);
|
||||
snprintf(buffer,bsize,"%03.0f", AngleToDisplay);
|
||||
getdisplay().print(buffer);
|
||||
epd->print(buffer);
|
||||
AngleToDisplay += 20;
|
||||
if ( AngleToDisplay >= 360.0 )
|
||||
AngleToDisplay -= 360.0;
|
||||
@@ -211,7 +203,7 @@ class PageCompass : public Page
|
||||
|
||||
x0 = Compass_X0 + Delta_X + 4 * 5 * Compass_LineDelta;
|
||||
do {
|
||||
getdisplay().setCursor(x0 - 40, Compass_Y0 + 40);
|
||||
epd->setCursor(x0 - 40, Compass_Y0 + 40);
|
||||
snprintf(buffer,bsize,"%03.0f", AngleToDisplay);
|
||||
// Quick and dirty way to prevent wrapping text in next line
|
||||
if ( ( x0 - 40 ) > 380 )
|
||||
@@ -221,7 +213,7 @@ class PageCompass : public Page
|
||||
else if ( ( x0 - 40 ) > 325 )
|
||||
buffer[2] = 0;
|
||||
|
||||
getdisplay().print(buffer);
|
||||
epd->print(buffer);
|
||||
|
||||
AngleToDisplay -= 20;
|
||||
if ( AngleToDisplay < 0 )
|
||||
@@ -233,8 +225,8 @@ class PageCompass : public Page
|
||||
// x_test += 2;
|
||||
|
||||
// snprintf(buffer,bsize,"%03d", x_test);
|
||||
// getdisplay().setCursor(x_test, Compass_Y0 - 60);
|
||||
// getdisplay().print(buffer);
|
||||
// epd->setCursor(x_test, Compass_Y0 - 60);
|
||||
// epd->print(buffer);
|
||||
// if ( x_test > 390)
|
||||
// x_test = 320;
|
||||
|
||||
|
||||
@@ -1,519 +0,0 @@
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "OBPDataOperations.h"
|
||||
#include <unordered_map>
|
||||
|
||||
// leeway K coefficient selection options from OBP configuration page
|
||||
static const std::unordered_map<std::string, int> leeKMap = {
|
||||
{ "---", 0 },
|
||||
{ "Racer [2]", 2 },
|
||||
{ "Multihull Draggerboard [4]", 4 },
|
||||
{ "Performance Cruiser [6]", 6 },
|
||||
{ "Family Cruiser [9]", 9 },
|
||||
{ "Heavy Displacement [13]", 13 },
|
||||
{ "Multihull Fixed Keel [16]", 16 }
|
||||
};
|
||||
|
||||
enum bValueIdx {
|
||||
ROLL = 0,
|
||||
SET,
|
||||
DFT,
|
||||
HDT,
|
||||
STW,
|
||||
COG,
|
||||
SOG,
|
||||
HDM,
|
||||
VAR,
|
||||
AWA,
|
||||
NUM_VALS
|
||||
};
|
||||
|
||||
// Screen coordinates for boat value, name, unit
|
||||
struct Points {
|
||||
int16_t x1, y1;
|
||||
int16_t x2, y2;
|
||||
int16_t x3, y3;
|
||||
};
|
||||
|
||||
// Screen coordinates for four boat data values (top-left, bottom-left, top-right, bottom-right)
|
||||
static constexpr Points POS[] = {
|
||||
{ 101, 65, 10, 95, 10, 115 }, // Position top left for value, name, unit
|
||||
{ 101, 270, 10, 220, 10, 190 }, // Position bottom left
|
||||
{ 395, 65, 390, 95, 390, 115 }, // Position top right
|
||||
{ 395, 270, 390, 220, 390, 190 } // Position bottom right
|
||||
};
|
||||
|
||||
// Define wave visual (XBM Format)
|
||||
static constexpr int WAVE_W = 132;
|
||||
static constexpr int WAVE_H = 20;
|
||||
static const uint8_t wave_bitmap[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0xff, 0xf8, 0x00, 0x00, 0xff, 0x80, 0x00,
|
||||
0x7f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf0, 0x03, 0xff, 0xfe, 0x00, 0x01, 0xff, 0xf0,
|
||||
0x01, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xbf, 0xe0, 0x3f, 0xc0, 0xe2, 0x07,
|
||||
0xff, 0x1f, 0xf8, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x80, 0x07, 0xff, 0x80,
|
||||
0x00, 0xff, 0xff, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0xfe, 0x00, 0x00, 0x78,
|
||||
0x0f, 0x80, 0x3f, 0xff, 0x80, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0f, 0xfe, 0x00, 0x01, 0xff, 0x00,
|
||||
0x00, 0x3f, 0xf0, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x00, 0x3f, 0xff, 0x80, 0x07, 0xff,
|
||||
0xe0, 0x00, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x7e, 0x00, 0xff, 0xff, 0xf0, 0x3f,
|
||||
0xe3, 0xf8, 0x01, 0xc0, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe7, 0xfc, 0x0f, 0xff,
|
||||
0xff, 0x00, 0x3f, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x03,
|
||||
0xff, 0xfc, 0x00, 0x03, 0xf0, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xc0,
|
||||
0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
|
||||
0x00, 0x00, 0x07, 0x80, 0xfc, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xe0, 0x00, 0x03, 0xff, 0x80, 0x01, 0xff, 0xf8, 0x00, 0x3f, 0xfc, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1e, 0x00, 0x0f, 0xff, 0xf0, 0x07, 0xff, 0xff, 0x00, 0xfc, 0x0f, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x3e, 0x03, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xe0, 0x01, 0xe0,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x7f, 0xff, 0x00, 0x07, 0xff, 0x80, 0x00,
|
||||
0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0xfe, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
class PageCurrent : public Page {
|
||||
private:
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
|
||||
GwLog* logger;
|
||||
|
||||
int width; // Screen width
|
||||
int height; // Screen height
|
||||
|
||||
bool keylock = false; // Keylock
|
||||
|
||||
bool useSimuData;
|
||||
bool holdValues;
|
||||
String flashLED;
|
||||
String backlightMode;
|
||||
bool smallDecimals;
|
||||
String leeKStd;
|
||||
double leeK;
|
||||
movingAvgAngle<double> SetAvg {8}; // Store average of the last 8 values of SET angle values
|
||||
movingAvg<double> DftAvg {8}; // Store average of the last 8 values of DFT speed value
|
||||
|
||||
// Old values for hold function
|
||||
String sValueOld[NUM_VALS] = { "", "", "", "", "", "", "", "", "", "" };
|
||||
String unitOld[NUM_VALS] = { "", "", "", "", "", "", "", "", "", "" };
|
||||
|
||||
struct Current {
|
||||
double set; // direction TO which current flows (0..2*PI, true dir)
|
||||
double dft; // current drift speed (m/s)
|
||||
};
|
||||
|
||||
double calcLeeway(
|
||||
double leeK, // leeway coefficient
|
||||
double roll, // heel of boat (rad)
|
||||
double stw // speed through water (m/s)
|
||||
)
|
||||
{
|
||||
static constexpr double MINSTW = 0.5; // minimum speed (m/s) for leeway calculation to prevent math explosion
|
||||
static constexpr double MAXLAY = 30.0 * DEG_TO_RAD; // cap leeway at this level of degree;
|
||||
|
||||
if (stw < MINSTW) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double lay = leeK * roll / (stw * stw);
|
||||
return std::min(lay, MAXLAY);
|
||||
}
|
||||
|
||||
double calcCTW(
|
||||
double awa, // apparent wind angle (0..2PI -> representation within OBP60)
|
||||
double hdt, // heading true (rad)
|
||||
double lay // leeway angle (rad)
|
||||
)
|
||||
{
|
||||
double ctw; // course through water (rad true)
|
||||
|
||||
if (awa >= M_PI) { // apparent wind > 180° -> comes from port
|
||||
ctw = WindUtils::to2PI(hdt + lay);
|
||||
} else { // wind comes from starboard
|
||||
ctw = WindUtils::to2PI(hdt - lay);
|
||||
}
|
||||
|
||||
return ctw;
|
||||
}
|
||||
|
||||
Current calcSetAndDrift(
|
||||
double lay, // leeway angle (rad)
|
||||
double sog, // speed over ground (m/s)
|
||||
double cog, // course over ground (rad true)
|
||||
double stw, // speed through water (m/s)
|
||||
double hdt, // heading true (rad)
|
||||
double awa // apparent wind angle (rad)
|
||||
)
|
||||
{
|
||||
Current crnt;
|
||||
double ctw; // course through water (rad true)
|
||||
|
||||
ctw = calcCTW(awa, hdt, lay);
|
||||
|
||||
// Ground velocity vector (east, north)
|
||||
double vg_x = sog * std::sin(cog);
|
||||
double vg_y = sog * std::cos(cog);
|
||||
|
||||
// Water-relative velocity vector (east, north)
|
||||
double vw_x = stw * std::sin(ctw);
|
||||
double vw_y = stw * std::cos(ctw);
|
||||
|
||||
// Current vector = ground - water
|
||||
double vc_x = vg_x - vw_x;
|
||||
double vc_y = vg_y - vw_y;
|
||||
|
||||
crnt.dft = std::sqrt(vc_x * vc_x + vc_y * vc_y);
|
||||
|
||||
crnt.set = std::atan2(vc_x, vc_y); // atan2(x, y) because 0° = North, clockwise positive
|
||||
crnt.set = WindUtils::to2PI(crnt.set); // internal respresentation of wind is [0..2PI]
|
||||
|
||||
// LOG_DEBUG(GwLog::DEBUG, "PageCurrent-setDrift: sog: %.3f, ctw: %.3f, stw: %.3f, vc_x: %.3f, vc_y: %.3f, set: %.3f, drift: %.3f",
|
||||
// sog, ctw, stw, vc_x, vc_y, crnt.set, crnt.dft);
|
||||
|
||||
return crnt;
|
||||
};
|
||||
|
||||
// Draw compass rose with boat direction up; top heading of compass rose in degree [0..2PI]
|
||||
void drawCompassRose(double topHeading)
|
||||
{
|
||||
int radius = 110;
|
||||
String sDegree;
|
||||
int centerX = 200;
|
||||
int centerY = 150;
|
||||
|
||||
getdisplay().fillCircle(centerX, centerY, radius + 10, commonData->fgcolor);
|
||||
getdisplay().fillCircle(centerX, centerY, radius + 7, commonData->bgcolor);
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
|
||||
for (int i = 0; i < 360; i += 10) {
|
||||
|
||||
float topAngle = (float)(i * DEG_TO_RAD - topHeading); // Calculate the relative angle for drawing; subtracting topHeading shifts the entire rose
|
||||
float sinVal = sin(topAngle);
|
||||
float cosVal = cos(topAngle);
|
||||
|
||||
// Coordinates for the labels (positioned slightly inside the rose)
|
||||
float xLabel = centerX + (radius - 27) * sinVal;
|
||||
float yLabel = centerY - (radius - 24) * cosVal;
|
||||
|
||||
if (i % 30 == 0) {
|
||||
// Draw scale markers (triangles)
|
||||
float dx = 1;
|
||||
float xx1 = -dx;
|
||||
float xx2 = +dx;
|
||||
float yy1 = -(radius - 10);
|
||||
float yy2 = -(radius + 10);
|
||||
|
||||
getdisplay().fillTriangle(centerX + (int)(cosVal * xx1 - sinVal * yy1), centerY + (int)(sinVal * xx1 + cosVal * yy1),
|
||||
centerX + (int)(cosVal * xx2 - sinVal * yy1), centerY + (int)(sinVal * xx2 + cosVal * yy1),
|
||||
centerX + (int)(cosVal * xx1 - sinVal * yy2), centerY + (int)(sinVal * xx1 + cosVal * yy2), commonData->fgcolor);
|
||||
getdisplay().fillTriangle(centerX + (int)(cosVal * xx2 - sinVal * yy1), centerY + (int)(sinVal * xx2 + cosVal * yy1),
|
||||
centerX + (int)(cosVal * xx1 - sinVal * yy2), centerY + (int)(sinVal * xx1 + cosVal * yy2),
|
||||
centerX + (int)(cosVal * xx2 - sinVal * yy2), centerY + (int)(sinVal * xx2 + cosVal * yy2), commonData->fgcolor);
|
||||
|
||||
// Print degree labels
|
||||
sDegree = String(i);
|
||||
int16_t x1, y1;
|
||||
uint16_t w, h;
|
||||
displayGetTextBounds(sDegree, (int)xLabel, (int)yLabel, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(xLabel - w / 2, yLabel + h / 2);
|
||||
getdisplay().print(sDegree);
|
||||
|
||||
} else {
|
||||
// Draw dots for intermediate 10 degree steps
|
||||
float xDot = centerX + radius * sinVal;
|
||||
float yDot = centerY - radius * cosVal;
|
||||
getdisplay().fillCircle((int)xDot, (int)yDot, 2, commonData->fgcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawRotatedArrow(
|
||||
float size, // size of the arrow = speed in m/s [0.5..5.2]
|
||||
float direction // angle the arrow is pointing to [0..2PI]
|
||||
)
|
||||
{
|
||||
static constexpr double MINSIZE = 0.05; // minimum current set (size) (m/s) for arrow size
|
||||
|
||||
if (size < MINSIZE) { // no arrow for current set below 0.05 m/s
|
||||
return;
|
||||
}
|
||||
|
||||
// size [0.5 .. 5.2] -> length [60 .. 130]
|
||||
float maxsize = constrain(size, 0.5, 5.2);
|
||||
float length = 60.0 + ((maxsize - 0.5) / (5.2 - 0.5)) * (130.0 - 60.0);
|
||||
int16_t cx = width / 2;
|
||||
int16_t cy = height / 2;
|
||||
|
||||
// geometry (arrow upwards)
|
||||
float h = length / 2.0;
|
||||
float w = length / 4.0;
|
||||
float headW = length / 1.5;
|
||||
float splitY = -h / 3;
|
||||
|
||||
struct Pt {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
// 7 edges of arrow
|
||||
Pt p[7] = {
|
||||
{ -w / 2, h }, { w / 2, h }, { w / 2, splitY }, { headW / 2, splitY },
|
||||
{ 0, -h }, { -headW / 2, splitY }, { -w / 2, splitY }
|
||||
};
|
||||
|
||||
// edges of arrow with reduced size of 1 px for thicker frame
|
||||
float offset = 1.0;
|
||||
Pt p_in[7] = {
|
||||
{ -w / 2 + offset, h - offset }, { w / 2 - offset, h - offset },
|
||||
{ w / 2 - offset, splitY + offset }, { headW / 2 - offset, splitY + offset },
|
||||
{ 0, -h + offset }, { -headW / 2 + offset, splitY + offset },
|
||||
{ -w / 2 + offset, splitY + offset }
|
||||
};
|
||||
|
||||
// calculate rotation
|
||||
float s = sin(direction);
|
||||
float c = cos(direction);
|
||||
int16_t rx[7], ry[7];
|
||||
|
||||
for (int i = 0; i < 7; i++) {
|
||||
// rotate frame
|
||||
rx[i] = cx + (int16_t)(p[i].x * c - p[i].y * s);
|
||||
ry[i] = cy + (int16_t)(p[i].x * s + p[i].y * c);
|
||||
}
|
||||
|
||||
// fill arrow with white area to delete any background data
|
||||
getdisplay().fillTriangle(rx[0], ry[0], rx[1], ry[1], rx[2], ry[2], commonData->bgcolor);
|
||||
getdisplay().fillTriangle(rx[0], ry[0], rx[2], ry[2], rx[6], ry[6], commonData->bgcolor);
|
||||
getdisplay().fillTriangle(rx[5], ry[5], rx[4], ry[4], rx[3], ry[3], commonData->bgcolor);
|
||||
|
||||
// draw arrow frame with "overdraw" for constant thickness
|
||||
for (int i = 0; i < 7; i++) {
|
||||
int next = (i + 1) % 7;
|
||||
int16_t x0 = rx[i], y0 = ry[i];
|
||||
int16_t x1 = rx[next], y1 = ry[next];
|
||||
|
||||
// original line
|
||||
getdisplay().drawLine(x0, y0, x1, y1, commonData->fgcolor);
|
||||
|
||||
// offset by 1 pixel in x or y depending on delta
|
||||
if (abs(x1 - x0) > abs(y1 - y0)) {
|
||||
getdisplay().drawLine(x0, y0 + 1, x1, y1 + 1, commonData->fgcolor);
|
||||
} else {
|
||||
getdisplay().drawLine(x0 + 1, y0, x1 + 1, y1, commonData->fgcolor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
PageCurrent(CommonData& common)
|
||||
{
|
||||
commonData = &common;
|
||||
logger = commonData->logger;
|
||||
LOG_DEBUG(GwLog::LOG, "Instantiate PageCurrent");
|
||||
|
||||
width = getdisplay().width(); // Screen width
|
||||
height = getdisplay().height(); // Screen height
|
||||
|
||||
// Get config data
|
||||
useSimuData = commonData->config->getBool(commonData->config->useSimuData);
|
||||
holdValues = commonData->config->getBool(commonData->config->holdvalues);
|
||||
flashLED = commonData->config->getString(commonData->config->flashLED);
|
||||
backlightMode = commonData->config->getString(commonData->config->backlight);
|
||||
smallDecimals = commonData->config->getBool(commonData->config->smallDecimals);
|
||||
|
||||
leeKStd = commonData->config->getString(commonData->config->leeKStd);
|
||||
auto it = leeKMap.find(leeKStd.c_str());
|
||||
if (it != leeKMap.end()) {
|
||||
leeK = it->second;
|
||||
} else if (leeKStd == "Individual value") {
|
||||
leeK = (commonData->config->getString(commonData->config->leeK)).toDouble();
|
||||
}
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: leeKStd: %s, leeK: %.3f", leeKStd.c_str(), leeK);
|
||||
|
||||
// Initialize average buffer for SET and DFT
|
||||
SetAvg.begin();
|
||||
DftAvg.begin();
|
||||
}
|
||||
|
||||
virtual int handleKey(int key)
|
||||
{
|
||||
// Keylock function
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0; // Commit the key
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
virtual void displayNew(PageData& pageData)
|
||||
{
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int displayPage(PageData& pageData)
|
||||
{
|
||||
double lay;
|
||||
Current current;
|
||||
|
||||
LOG_DEBUG(GwLog::LOG, "Display PageCurrent");
|
||||
|
||||
// Get boat values for page
|
||||
// 0=ROLL, 1=SET, 2=DFT, 3=HDT, 4=STW, 5=COG, 6=SOG, 7=HDM, 8=VAR, 9=AWA
|
||||
std::vector<GwApi::BoatValue*> bValue(pageData.values.begin(), pageData.values.end());
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: printing #1: %s, %.3f, valid: %d, #2: %s, %.3f, valid: %d, #3: %s, %.3f, valid: %d, #4: %s, %.3f, valid: %d, #5: %s, %.3f, valid: %d",
|
||||
bValue[ROLL]->getName().c_str(), bValue[ROLL]->value, bValue[ROLL]->valid, bValue[SET]->getName().c_str(), bValue[SET]->value, bValue[SET]->valid,
|
||||
bValue[DFT]->getName().c_str(), bValue[DFT]->value, bValue[DFT]->valid, bValue[HDT]->getName().c_str(), bValue[HDT]->value, bValue[HDT]->valid,
|
||||
bValue[STW]->getName().c_str(), bValue[STW]->value, bValue[STW]->valid);
|
||||
|
||||
// Calculate current
|
||||
//***********************************************************
|
||||
|
||||
if (!bValue[SET]->valid || !bValue[DFT]->valid) { // If SET or DRIFT not available, try to calculate them
|
||||
if (bValue[SOG]->valid && bValue[COG]->valid && bValue[STW]->valid) {
|
||||
// calculate current only if all required values are available; we accept missing AWA, because this is only required for leeway adjustment
|
||||
|
||||
if (!bValue[HDT]->valid) { // HDT not available
|
||||
if (bValue[HDM]->valid) {
|
||||
if (bValue[VAR]->valid) {
|
||||
bValue[HDT]->value = bValue[HDM]->value + bValue[VAR]->value; // Use corrected HDM if HDT is not available
|
||||
bValue[HDT]->value = WindUtils::to2PI(bValue[HDT]->value);
|
||||
} else {
|
||||
// if HDT cannot be fully substituted by HDM+VAR, continue with HDM only
|
||||
bValue[HDT] = bValue[HDM];
|
||||
}
|
||||
bValue[HDT]->valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bValue[ROLL]->valid || (bValue[ROLL]->getFormat() != "formatXdr:A:D" && bValue[ROLL]->getFormat() != "formatXdr:A:rd" && bValue[ROLL]->getFormat() != "formatCourse")) {
|
||||
bValue[ROLL]->value = 0; // delete last value if roll value is not valid anymore (gateway keeps last value) or wrong type selected by user
|
||||
}
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: Roll: %s, %.3f, valid: %d, format: %s",
|
||||
bValue[ROLL]->getName().c_str(), bValue[ROLL]->value, bValue[ROLL]->valid, bValue[ROLL]->getFormat().c_str());
|
||||
|
||||
lay = calcLeeway(leeK, bValue[ROLL]->value, bValue[STW]->value);
|
||||
|
||||
if (bValue[HDT]->valid) { // That's either HDT or HDM
|
||||
double awaVal = (bValue[AWA]->valid ? bValue[AWA]->value : 0.0); // catch potentially missing AWA
|
||||
current = calcSetAndDrift(lay, bValue[SOG]->value, bValue[COG]->value, bValue[STW]->value, bValue[HDT]->value, awaVal);
|
||||
bValue[SET]->value = current.set;
|
||||
bValue[SET]->setFormat("formatCourse");
|
||||
bValue[SET]->valid = true;
|
||||
bValue[DFT]->value = current.dft;
|
||||
bValue[DFT]->setFormat("formatKnots");
|
||||
bValue[DFT]->valid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// averaging current for smoother output
|
||||
if (bValue[SET]->valid && bValue[DFT]->valid) { // Are SET and DRIFT now available?
|
||||
bValue[SET]->value = SetAvg.reading(bValue[SET]->value);
|
||||
bValue[DFT]->value = DftAvg.reading(bValue[DFT]->value);
|
||||
}
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageCurrent: leeKStd: %s, leeK: %.3f, lay: %.3f, roll: %.3f, stw: %.3f, awa: %.3f, hdt: %.3f, cog: %.3f, sog: %.3f, set: %.3f, dft: %.3f",
|
||||
leeKStd.c_str(), leeK, lay, bValue[ROLL]->value, bValue[STW]->value, bValue[AWA]->value, bValue[HDT]->value, bValue[COG]->value, bValue[SOG]->value,
|
||||
bValue[SET]->value, bValue[DFT]->value);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
displaySetPartialWindow(0, 0, width, height); // Set partial update
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
|
||||
static const int bValType[] = { HDT, STW, SET, DFT }; // Sequence of boat data types to show on page
|
||||
for (int i = 0; i < 4; i++) {
|
||||
String name = xdrDelete(bValue[bValType[i]]->getName()); // Value name
|
||||
name = name.substring(0, 4); // String length limit for value name
|
||||
String sValue = formatValue(bValue[bValType[i]], *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit = formatValue(bValue[bValType[i]], *commonData).unit; // Unit of value
|
||||
unit = unit.substring(0, 6); // String length limit for value unit
|
||||
|
||||
// Show boat data value
|
||||
if (!holdValues || useSimuData) {
|
||||
printBoatValue(sValue, POS[i].x1, POS[i].y1, RIGHT, 20, smallDecimals);
|
||||
} else {
|
||||
printBoatValue(sValueOld[i], POS[i].x1, POS[i].y1, RIGHT, 20, smallDecimals);
|
||||
}
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
if (i < 2) { // left side values
|
||||
getdisplay().setCursor(POS[i].x2, POS[i].y2);
|
||||
getdisplay().print(name);
|
||||
} else { // right side values
|
||||
drawTextRalign(POS[i].x2, POS[i].y2, name);
|
||||
}
|
||||
|
||||
String dUnit; // Unit to show
|
||||
if (holdValues) {
|
||||
dUnit = unitOld[i];
|
||||
} else {
|
||||
dUnit = unit;
|
||||
}
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
if (i < 2) { // left side values
|
||||
getdisplay().setCursor(POS[i].x3, POS[i].y3);
|
||||
getdisplay().print(dUnit);
|
||||
} else { // right side values
|
||||
drawTextRalign(POS[i].x3, POS[i].y3, dUnit);
|
||||
}
|
||||
|
||||
if (bValue[bValType[i]]->valid) {
|
||||
sValueOld[i] = sValue; // Save the old value
|
||||
unitOld[i] = unit; // Save the old unit
|
||||
}
|
||||
}
|
||||
|
||||
// Horizontal separator left
|
||||
getdisplay().fillRect(0, 149, 60, 2, commonData->fgcolor);
|
||||
// Horizontal separator right
|
||||
getdisplay().fillRect(339, 149, 60, 2, commonData->fgcolor);
|
||||
|
||||
if (bValue[HDT]->valid) {
|
||||
drawCompassRose(bValue[HDT]->value);
|
||||
} else {
|
||||
drawCompassRose(0.0);
|
||||
};
|
||||
getdisplay().drawBitmap((width - WAVE_W) / 2, (height - WAVE_H) / 2, wave_bitmap, WAVE_W, WAVE_H, commonData->fgcolor);
|
||||
if (bValue[SET]->valid && bValue[DFT]->valid) {
|
||||
drawRotatedArrow(bValue[DFT]->value, WindUtils::to2PI(bValue[SET]->value - bValue[HDT]->value));
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page* createPage(CommonData& common)
|
||||
{
|
||||
return new PageCurrent(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 registerPageCurrent(
|
||||
"Current", // Page name
|
||||
createPage, // Action
|
||||
1, // Number of bus values depends on selection in Web configuration -> boat value for ROLL
|
||||
{ "SET", "DFT", "HDT", "STW", "COG", "SOG", "HDM", "VAR", "AWA" }, // Bus values we need in the page
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -6,17 +7,18 @@
|
||||
class PageDST810 : public Page
|
||||
{
|
||||
private:
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
String lengthformat;
|
||||
|
||||
public:
|
||||
PageDST810(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageDST810");
|
||||
PageDST810(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageDST810");
|
||||
|
||||
// Get config data
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key) {
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -26,11 +28,6 @@ public:
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
int valueX, valueY;
|
||||
int DsegFontSize;
|
||||
|
||||
// Old values for hold function
|
||||
static String svalue1old = "";
|
||||
@@ -42,22 +39,14 @@ public:
|
||||
static String svalue4old = "";
|
||||
static String unit4old = "";
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
// bool simulation = config->getBool(config->useSimuData);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
// 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
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->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)
|
||||
@@ -65,8 +54,8 @@ public:
|
||||
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
|
||||
String svalue2 = commonData->fmt->formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit2 = commonData->fmt->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)
|
||||
@@ -74,8 +63,8 @@ public:
|
||||
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
|
||||
String svalue3 = commonData->fmt->formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit3 = commonData->fmt->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)
|
||||
@@ -83,8 +72,8 @@ public:
|
||||
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
|
||||
String svalue4 = commonData->fmt->formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit4 = commonData->fmt->formatValue(bvalue4, *commonData).unit; // Unit of value
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
@@ -94,43 +83,43 @@ public:
|
||||
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
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);
|
||||
logger->logDebug(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 display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// ############### Value 1 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 55);
|
||||
// getdisplay().print("Depth"); // Page name
|
||||
getdisplay().print(name1); // Page name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 55);
|
||||
epd->print("Depth"); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 90);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 90);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit1); // Unit
|
||||
epd->print(unit1); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit1old);
|
||||
epd->print(unit1old);
|
||||
}
|
||||
|
||||
// Set font
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 90);
|
||||
|
||||
// Show bus data
|
||||
valueX = 380;
|
||||
valueY = 90;
|
||||
DsegFontSize = 30;
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue1, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue1); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue1old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue1old); // Old value as formated string
|
||||
}
|
||||
if(valid1 == true){
|
||||
svalue1old = svalue1; // Save the old value
|
||||
@@ -140,35 +129,35 @@ public:
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 105, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 105, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 2 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 145);
|
||||
// getdisplay().print("Speed"); // Page name
|
||||
getdisplay().print(name2); // Page name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 145);
|
||||
epd->print("Speed"); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 180);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 180);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit2); // Unit
|
||||
epd->print(unit2); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit2old);
|
||||
epd->print(unit2old);
|
||||
}
|
||||
|
||||
// Setfont
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 180);
|
||||
|
||||
// Show bus data
|
||||
valueX = 380;
|
||||
valueY = 180;
|
||||
DsegFontSize = 30;
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue2, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue2); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue2old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue2old); // Old value as formated string
|
||||
}
|
||||
if(valid2 == true){
|
||||
svalue2old = svalue2; // Save the old value
|
||||
@@ -178,35 +167,35 @@ public:
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 195, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 195, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 3 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 220);
|
||||
// getdisplay().print("Log"); // Page name
|
||||
getdisplay().print(name3); // Page name
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 220);
|
||||
epd->print("Log"); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(20, 240);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(20, 240);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit3); // Unit
|
||||
epd->print(unit3); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit3old);
|
||||
epd->print(unit3old);
|
||||
}
|
||||
|
||||
// Set font
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(80, 270);
|
||||
|
||||
// Show bus data
|
||||
valueX = 190;
|
||||
valueY = 270;
|
||||
DsegFontSize = 20;
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue3, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue3); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue3old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue3old); // Old value as formated string
|
||||
}
|
||||
if(valid3 == true){
|
||||
svalue3old = svalue3; // Save the old value
|
||||
@@ -216,35 +205,35 @@ public:
|
||||
// ############### Vertical Line ################
|
||||
|
||||
// Vertical line 3 pix
|
||||
getdisplay().fillRect(200, 195, 3, 75, commonData->fgcolor);
|
||||
epd->fillRect(200, 195, 3, 75, commonData->fgcolor);
|
||||
|
||||
// ############### Value 4 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(220, 220);
|
||||
// getdisplay().print("Temp"); // Page name
|
||||
getdisplay().print(name4); // Page name
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(220, 220);
|
||||
epd->print("Temp"); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(220, 240);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(220, 240);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit4); // Unit
|
||||
epd->print(unit4); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit4old);
|
||||
epd->print(unit4old);
|
||||
}
|
||||
|
||||
// Set font
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(280, 270);
|
||||
|
||||
// Show bus data
|
||||
valueX = 390;
|
||||
valueY = 270;
|
||||
DsegFontSize = 20;
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue4, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue4); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue4old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue4old); // Old value as formated string
|
||||
}
|
||||
if(valid4 == true){
|
||||
svalue4old = svalue4; // Save the old value
|
||||
|
||||
@@ -1,20 +1,13 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include <PCF8574.h> // PCF8574 modules from Horter
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
#include "images/OBP_400x300.xbm" // OBP Logo
|
||||
#ifdef BOARD_OBP60S3
|
||||
#include "images/OBP60_400x300.xbm" // MFD with logo
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
#include "images/OBP40_400x300.xbm" // MFD with logo
|
||||
#endif
|
||||
|
||||
class PageDigitalOut : public Page
|
||||
{
|
||||
|
||||
private:
|
||||
// Status values
|
||||
bool button1 = false;
|
||||
bool button2 = false;
|
||||
@@ -22,10 +15,25 @@ bool button3 = false;
|
||||
bool button4 = false;
|
||||
bool button5 = false;
|
||||
|
||||
// Button labels
|
||||
String name1;
|
||||
String name2;
|
||||
String name3;
|
||||
String name4;
|
||||
String name5;
|
||||
|
||||
public:
|
||||
PageDigitalOut(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageDigitalOut");
|
||||
PageDigitalOut(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageDigitalOut");
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
name1 = config->getString(config->mod1Out1);
|
||||
name2 = config->getString(config->mod1Out2);
|
||||
name3 = config->getString(config->mod1Out3);
|
||||
name4 = config->getString(config->mod1Out4);
|
||||
name5 = config->getString(config->mod1Out5);
|
||||
}
|
||||
|
||||
// Set botton labels
|
||||
@@ -42,62 +50,52 @@ bool button5 = false;
|
||||
// Code for keylock
|
||||
if (key == 11) {
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0; // Commit the key
|
||||
return 0;
|
||||
}
|
||||
// Code for button 1
|
||||
if (key == 1) {
|
||||
button1 = !button1;
|
||||
setPCF8574PortPinModul1(0, button1 ? 0 : 1); // Attention! Inverse logic for PCF8574
|
||||
return 0; // Commit the key
|
||||
return 0;
|
||||
}
|
||||
// Code for button 2
|
||||
if (key == 2) {
|
||||
button2 = !button2;
|
||||
setPCF8574PortPinModul1(1, button2 ? 0 : 1); // Attention! Inverse logic for PCF8574
|
||||
return 0; // Commit the key
|
||||
return 0;
|
||||
}
|
||||
// Code for button 3
|
||||
if (key == 3) {
|
||||
button3 = !button3;
|
||||
setPCF8574PortPinModul1(2, button3 ? 0 : 1); // Attention! Inverse logic for PCF8574
|
||||
return 0; // Commit the key
|
||||
return 0;
|
||||
}
|
||||
// Code for button 4
|
||||
if (key == 4) {
|
||||
button4 = !button4;
|
||||
setPCF8574PortPinModul1(3, button4 ? 0 : 1); // Attention! Inverse logic for PCF8574
|
||||
return 0; // Commit the key
|
||||
return 0;
|
||||
}
|
||||
// Code for button 5
|
||||
if (key == 5) {
|
||||
button5 = !button5;
|
||||
setPCF8574PortPinModul1(4, button5 ? 0 : 1); // Attention! Inverse logic for PCF8574
|
||||
return 0; // Commit the key
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
String name1 = config->getString(config->mod1Out1);
|
||||
String name2 = config->getString(config->mod1Out2);
|
||||
String name3 = config->getString(config->mod1Out3);
|
||||
String name4 = config->getString(config->mod1Out4);
|
||||
String name5 = config->getString(config->mod1Out5);
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
|
||||
// Logging boat values
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageDigitalOut");
|
||||
@@ -106,20 +104,23 @@ bool button5 = false;
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
// Write text
|
||||
getdisplay().setCursor(100, 50 + 8);
|
||||
getdisplay().print(name1);
|
||||
getdisplay().setCursor(100, 100 + 8);
|
||||
getdisplay().print(name2);
|
||||
getdisplay().setCursor(100, 150 + 8);
|
||||
getdisplay().print(name3);
|
||||
getdisplay().setCursor(100,200 + 8);
|
||||
getdisplay().print(name4);
|
||||
getdisplay().setCursor(100, 250 + 8);
|
||||
getdisplay().print(name5);
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
|
||||
// Draw labels
|
||||
epd->setCursor(100, 50 + 8);
|
||||
epd->print(name1);
|
||||
epd->setCursor(100, 100 + 8);
|
||||
epd->print(name2);
|
||||
epd->setCursor(100, 150 + 8);
|
||||
epd->print(name3);
|
||||
epd->setCursor(100,200 + 8);
|
||||
epd->print(name4);
|
||||
epd->setCursor(100, 250 + 8);
|
||||
epd->print(name5);
|
||||
|
||||
// Draw bottons
|
||||
drawButtonCenter(50, 50, 40, 27, "1", commonData->fgcolor, commonData->bgcolor, button1);
|
||||
drawButtonCenter(50, 100, 40, 27, "2", commonData->fgcolor, commonData->bgcolor, button2);
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
/*
|
||||
Electric propulsion
|
||||
|
||||
- Current, voltage, power
|
||||
- 12, 24, 48 etc. Voltage
|
||||
- rpm
|
||||
- throttle position
|
||||
- controller state
|
||||
- error codes
|
||||
- temperature engine, controller, batteries
|
||||
|
||||
*/
|
||||
|
||||
class PageEPropulsion : public Page
|
||||
{
|
||||
private:
|
||||
char mode = 'N'; // (N)ormal, (C)onfig
|
||||
|
||||
void displayModeNormal(PageData &pageData) {
|
||||
|
||||
// TBD Boatvalues: ...
|
||||
|
||||
logger->logDebug(GwLog::DEBUG, "Drawing at PageEPropulsion");
|
||||
|
||||
// Title and corner value headings
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 48);
|
||||
epd->print("Electric propulsion");
|
||||
|
||||
}
|
||||
|
||||
void displayModeConfig() {
|
||||
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 48);
|
||||
epd->print("EPropulsion configuration");
|
||||
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
// TODO menu
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
PageEPropulsion(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG,"Instantiate PageEPropulsion");
|
||||
}
|
||||
|
||||
void setupKeys(){
|
||||
Page::setupKeys();
|
||||
}
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
int handleKey(int key){
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
int handleKey(int key){
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
commonData->keydata[1].label = "EDIT";
|
||||
} else {
|
||||
mode = 'N';
|
||||
commonData->keydata[1].label = "ALARM";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
#endif
|
||||
|
||||
void displayNew(PageData &pageData){
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
|
||||
// Logging boat values
|
||||
logger->logDebug(GwLog::LOG,"Drawing at PageEPropulsion; Mode=%c", mode);
|
||||
|
||||
// Set display in partial refresh mode
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height());
|
||||
|
||||
if (mode == 'N') {
|
||||
displayModeNormal(pageData);
|
||||
} else if (mode == 'C') {
|
||||
displayModeConfig();
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page *createPage(CommonData &common){
|
||||
return new PageEPropulsion(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 registerPageEPropulsion(
|
||||
"EPropulsion", // 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
|
||||
+42
-49
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -66,25 +67,22 @@ static unsigned char fish_bits[] = {
|
||||
|
||||
class PageFluid : public Page
|
||||
{
|
||||
bool simulation = false;
|
||||
private:
|
||||
double simgoto;
|
||||
double simval;
|
||||
double simstep;
|
||||
bool holdvalues = false;
|
||||
int fluidtype;
|
||||
|
||||
public:
|
||||
PageFluid(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageFluid");
|
||||
simulation = common.config->getBool(common.config->useSimuData);
|
||||
holdvalues = common.config->getBool(common.config->holdvalues);
|
||||
PageFluid(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageFluid");
|
||||
simval = double(random(0, 100));
|
||||
simgoto = double(random(0, 100));
|
||||
simstep = (simgoto - simval) / 20.0;
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key) {
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -93,27 +91,22 @@ class PageFluid : public Page
|
||||
return key;
|
||||
}
|
||||
|
||||
virtual void displayNew(PageData &pageData){
|
||||
fluidtype = commonData->config->getInt("page" + String(pageData.pageNumber) + "fluid", 0);
|
||||
commonData->logger->logDebug(GwLog::LOG,"New PageFluid: fluidtype=%d", fluidtype);
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Old values for hold function
|
||||
static double value1old;
|
||||
|
||||
// Get config data
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
void displayNew(PageData &pageData) {
|
||||
fluidtype = config->getInt("page" + String(pageData.pageNumber) + "fluid", 0);
|
||||
logger->logDebug(GwLog::LOG, "New PageFluid: fluidtype=%d", fluidtype);
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
// Old values for hold function
|
||||
static double value1old;
|
||||
|
||||
GwApi::BoatValue *bvalue1 = pageData.values[0];
|
||||
String name1 = bvalue1->getName();
|
||||
@@ -132,23 +125,23 @@ class PageFluid : public Page
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageFluid: value=%f", bvalue1->value);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageFluid: value=%f", bvalue1->value);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height());
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height());
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// descriptions
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 60);
|
||||
getdisplay().print("Fluid");
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 60);
|
||||
epd->print("Fluid");
|
||||
|
||||
getdisplay().setCursor(300, 60);
|
||||
getdisplay().print(xdrDelete(name1).substring(0, 6));
|
||||
epd->setCursor(300, 60);
|
||||
epd->print(xdrDelete(name1).substring(0, 6));
|
||||
|
||||
// analog instrument
|
||||
// scale from -120 to 120
|
||||
@@ -158,11 +151,11 @@ class PageFluid : public Page
|
||||
uint8_t r = 110;
|
||||
|
||||
// circular frame
|
||||
getdisplay().drawCircle(c.x, c.y, r+5, commonData->fgcolor);
|
||||
getdisplay().fillCircle(c.x, c.y, r+2, commonData->fgcolor);
|
||||
getdisplay().fillCircle(c.x, c.y, r-1, commonData->bgcolor);
|
||||
epd->drawCircle(c.x, c.y, r+5, commonData->fgcolor);
|
||||
epd->fillCircle(c.x, c.y, r+2, commonData->fgcolor);
|
||||
epd->fillCircle(c.x, c.y, r-1, commonData->bgcolor);
|
||||
// center of pointer as dot
|
||||
getdisplay().fillCircle(c.x, c.y, 8, commonData->fgcolor);
|
||||
epd->fillCircle(c.x, c.y, 8, commonData->fgcolor);
|
||||
|
||||
// value down centered
|
||||
char buffer[6];
|
||||
@@ -176,32 +169,32 @@ class PageFluid : public Page
|
||||
// draw symbol (as bitmap)
|
||||
switch (fluidtype) {
|
||||
case 0:
|
||||
getdisplay().drawXBitmap(c.x-8, c.y-50, fuel_bits, fuel_width, fuel_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(c.x-8, c.y-50, fuel_bits, fuel_width, fuel_height, commonData->fgcolor);
|
||||
break;
|
||||
case 1:
|
||||
getdisplay().drawXBitmap(c.x-8, c.y-50, water_bits, water_width, water_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(c.x-8, c.y-50, water_bits, water_width, water_height, commonData->fgcolor);
|
||||
break;
|
||||
case 2: // gray water no symbol yet
|
||||
// getdisplay().drawXBitmap(c.x-8, c.y-50, gray_bits, gray_width, gray_height, commonData->fgcolor);
|
||||
// epd->drawXBitmap(c.x-8, c.y-50, gray_bits, gray_width, gray_height, commonData->fgcolor);
|
||||
break;
|
||||
case 3:
|
||||
getdisplay().drawXBitmap(c.x-8, c.y-50, fish_bits, fish_width, fish_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(c.x-8, c.y-50, fish_bits, fish_width, fish_height, commonData->fgcolor);
|
||||
break;
|
||||
case 4:
|
||||
getdisplay().drawXBitmap(c.x-8, c.y-50, oil_bits, oil_width, oil_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(c.x-8, c.y-50, oil_bits, oil_width, oil_height, commonData->fgcolor);
|
||||
break;
|
||||
case 5:
|
||||
getdisplay().drawXBitmap(c.x-8, c.y-50, waste_bits, waste_width, waste_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(c.x-8, c.y-50, waste_bits, waste_width, waste_height, commonData->fgcolor);
|
||||
break;
|
||||
case 6:
|
||||
getdisplay().drawXBitmap(c.x-8, c.y-50, gasoline_bits, gasoline_width, gasoline_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(c.x-8, c.y-50, gasoline_bits, gasoline_width, gasoline_height, commonData->fgcolor);
|
||||
break;
|
||||
}
|
||||
|
||||
Point p, pr;
|
||||
|
||||
// scale texts
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
p = {c.x, c.y - r + 30};
|
||||
drawTextCenter(p.x, p.y, "1/2");
|
||||
pr = rotatePoint(c, p, -60);
|
||||
@@ -210,7 +203,7 @@ class PageFluid : public Page
|
||||
drawTextCenter(pr.x, pr.y, "3/4");
|
||||
|
||||
// empty and full
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
p = rotatePoint(c, {c.x, c.y - r + 30}, -130);
|
||||
drawTextCenter(p.x, p.y, "E");
|
||||
p = rotatePoint(c, {c.x, c.y - r + 30}, 130);
|
||||
@@ -236,7 +229,7 @@ class PageFluid : public Page
|
||||
continue;
|
||||
}
|
||||
p = rotatePoint(c, {c.x, c.y - r + 10}, angle);
|
||||
getdisplay().fillCircle(p.x, p.y, 3, commonData->fgcolor);
|
||||
epd->fillCircle(p.x, p.y, 3, commonData->fgcolor);
|
||||
}
|
||||
|
||||
// pointer
|
||||
@@ -249,7 +242,7 @@ class PageFluid : public Page
|
||||
};
|
||||
fillPoly4(rotatePoints(c, pts, -120 + fluidlevel * 2.4), commonData->fgcolor);
|
||||
// Pointer axis is white
|
||||
getdisplay().fillCircle(c.x, c.y, 6, commonData->bgcolor);
|
||||
epd->fillCircle(c.x, c.y, 6, commonData->bgcolor);
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
#include "BoatDataCalibration.h"
|
||||
#endif
|
||||
|
||||
class PageFourValues : public Page
|
||||
{
|
||||
private:
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
String lengthformat;
|
||||
|
||||
public:
|
||||
PageFourValues(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageFourValues");
|
||||
PageFourValues(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageFourValues");
|
||||
|
||||
// Get config data
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -25,12 +31,17 @@ class PageFourValues : public Page
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int valueX, valueY;
|
||||
int DsegFontSize;
|
||||
int displayPage(PageData &pageData){
|
||||
|
||||
// Old values for hold function
|
||||
static String svalue1old = "";
|
||||
@@ -42,103 +53,103 @@ class PageFourValues : public Page
|
||||
static String svalue4old = "";
|
||||
static String unit4old = "";
|
||||
|
||||
// Get config data
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
// 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
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values #2
|
||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list
|
||||
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
||||
name2 = name2.substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue2 = commonData->fmt->formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit2 = commonData->fmt->formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values #3
|
||||
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Third element in list
|
||||
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
||||
name3 = name3.substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue3, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue3 = commonData->fmt->formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit3 = commonData->fmt->formatValue(bvalue3, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values #4
|
||||
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Fourth element in list
|
||||
String name4 = xdrDelete(bvalue4->getName()); // Value name
|
||||
name4 = name4.substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue4, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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);
|
||||
}
|
||||
String svalue4 = commonData->fmt->formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit4 = commonData->fmt->formatValue(bvalue4, *commonData).unit; // Unit of value
|
||||
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
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);
|
||||
logger->logDebug(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 display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// ############### Value 1 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(20, 45);
|
||||
getdisplay().print(name1); // Page name
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->setCursor(20, 45);
|
||||
epd->print(name1); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(20, 67);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(20, 65);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit1); // Unit
|
||||
epd->print(unit1); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit1old);
|
||||
epd->print(unit1old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
valueX = 380;
|
||||
if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){
|
||||
valueY = 55;
|
||||
DsegFontSize = 12;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(120, 55);
|
||||
}
|
||||
else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){
|
||||
valueY = 67;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(150, 58);
|
||||
}
|
||||
else{
|
||||
valueY = 67;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(180, 65);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue1, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue1); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue1old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue1old); // Old value as formated string
|
||||
}
|
||||
if(valid1 == true){
|
||||
svalue1old = svalue1; // Save the old value
|
||||
@@ -148,45 +159,45 @@ class PageFourValues : public Page
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 80, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 80, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 2 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(20, 113);
|
||||
getdisplay().print(name2); // Page name
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->setCursor(20, 113);
|
||||
epd->print(name2); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(20, 135);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(20, 133);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit2); // Unit
|
||||
epd->print(unit2); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit2old);
|
||||
epd->print(unit2old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){
|
||||
valueY = 123;
|
||||
DsegFontSize = 12;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(120, 123);
|
||||
}
|
||||
else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){
|
||||
valueY = 135;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(150, 123);
|
||||
}
|
||||
else{
|
||||
valueY = 135;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(180, 133);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue2, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue2); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue2old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue2old); // Old value as formated string
|
||||
}
|
||||
if(valid2 == true){
|
||||
svalue2old = svalue2; // Save the old value
|
||||
@@ -196,45 +207,45 @@ class PageFourValues : public Page
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 146, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 146, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 3 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(20, 181);
|
||||
getdisplay().print(name3); // Page name
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->setCursor(20, 181);
|
||||
epd->print(name3); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(20, 203);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(20, 201);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit3); // Unit
|
||||
epd->print(unit3); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit3old);
|
||||
epd->print(unit3old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
if(bvalue3->getFormat() == "formatLatitude" || bvalue3->getFormat() == "formatLongitude"){
|
||||
valueY = 191;
|
||||
DsegFontSize = 16;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(120, 191);
|
||||
}
|
||||
else if(bvalue3->getFormat() == "formatTime" || bvalue3->getFormat() == "formatDate"){
|
||||
valueY = 203;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(150, 191);
|
||||
}
|
||||
else{
|
||||
valueY = 203;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(180, 201);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue3, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue3); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue3old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue3old); // Old value as formated string
|
||||
}
|
||||
if(valid3 == true){
|
||||
svalue3old = svalue3; // Save the old value
|
||||
@@ -244,45 +255,45 @@ class PageFourValues : public Page
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 214, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 214, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 4 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(20, 249);
|
||||
getdisplay().print(name4); // Page name
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->setCursor(20, 249);
|
||||
epd->print(name4); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(20, 271);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(20, 269);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit4); // Unit
|
||||
epd->print(unit4); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit4old);
|
||||
epd->print(unit4old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
if(bvalue4->getFormat() == "formatLatitude" || bvalue4->getFormat() == "formatLongitude"){
|
||||
valueY = 271;
|
||||
DsegFontSize = 16;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(120, 259);
|
||||
}
|
||||
else if(bvalue4->getFormat() == "formatTime" || bvalue4->getFormat() == "formatDate"){
|
||||
valueY = 271;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(150, 259);
|
||||
}
|
||||
else{
|
||||
valueY = 271;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(180, 269);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue4, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue4); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue4old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue4old); // Old value as formated string
|
||||
}
|
||||
if(valid4 == true){
|
||||
svalue4old = svalue4; // Save the old value
|
||||
@@ -291,6 +302,11 @@ class PageFourValues : public Page
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
|
||||
void leavePage(PageData &pageData) {
|
||||
logger->logDebug(GwLog::LOG, "Leaving PageFourvalues");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static Page *createPage(CommonData &common){
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -6,17 +7,18 @@
|
||||
class PageFourValues2 : public Page
|
||||
{
|
||||
private:
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
String lengthformat;
|
||||
|
||||
public:
|
||||
PageFourValues2(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageFourValues2");
|
||||
PageFourValues2(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageFourValues2");
|
||||
|
||||
// Get config data
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key) {
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock; // Toggle keylock
|
||||
@@ -25,12 +27,17 @@ class PageFourValues2 : public Page
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int valueX, valueY;
|
||||
int DsegFontSize;
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
// Old values for hold function
|
||||
static String svalue1old = "";
|
||||
@@ -42,19 +49,14 @@ class PageFourValues2 : public Page
|
||||
static String svalue4old = "";
|
||||
static String unit4old = "";
|
||||
|
||||
// Get config data
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
// 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
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->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)
|
||||
@@ -62,8 +64,8 @@ class PageFourValues2 : public Page
|
||||
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
|
||||
String svalue2 = commonData->fmt->formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit2 = commonData->fmt->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)
|
||||
@@ -71,8 +73,8 @@ class PageFourValues2 : public Page
|
||||
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
|
||||
String svalue3 = commonData->fmt->formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit3 = commonData->fmt->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)
|
||||
@@ -80,65 +82,58 @@ class PageFourValues2 : public Page
|
||||
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);
|
||||
}
|
||||
String svalue4 = commonData->fmt->formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit4 = commonData->fmt->formatValue(bvalue4, *commonData).unit; // Unit of value
|
||||
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
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);
|
||||
logger->logDebug(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 display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// ############### Value 1 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 55);
|
||||
getdisplay().print(name1); // Page name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 55);
|
||||
epd->print(name1); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 90);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 90);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit1); // Unit
|
||||
epd->print(unit1); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit1old);
|
||||
epd->print(unit1old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
valueX = 380;
|
||||
if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){
|
||||
valueY = 90;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(100, 90);
|
||||
}
|
||||
else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){
|
||||
valueY = 80;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(180, 77);
|
||||
}
|
||||
else{
|
||||
valueY = 90;
|
||||
DsegFontSize = 30;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 90);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue1, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue1); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue1old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue1old); // Old value as formated string
|
||||
}
|
||||
if(valid1 == true){
|
||||
svalue1old = svalue1; // Save the old value
|
||||
@@ -148,45 +143,45 @@ class PageFourValues2 : public Page
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 105, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 105, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 2 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 145);
|
||||
getdisplay().print(name2); // Page name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 145);
|
||||
epd->print(name2); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 180);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 180);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit2); // Unit
|
||||
epd->print(unit2); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit2old);
|
||||
epd->print(unit2old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){
|
||||
valueY = 180;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(100, 180);
|
||||
}
|
||||
else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){
|
||||
valueY = 170;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(180, 158);
|
||||
}
|
||||
else{
|
||||
valueY = 180;
|
||||
DsegFontSize = 30;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 180);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue2, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue2); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue2old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue2old); // Old value as formated string
|
||||
}
|
||||
if(valid2 == true){
|
||||
svalue2old = svalue2; // Save the old value
|
||||
@@ -196,46 +191,45 @@ class PageFourValues2 : public Page
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 195, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 195, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 3 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(20, 223);
|
||||
getdisplay().print(name3); // Page name
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 220);
|
||||
epd->print(name3); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
||||
getdisplay().setCursor(20, 270);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(20, 240);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit3); // Unit
|
||||
epd->print(unit3); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit3old);
|
||||
epd->print(unit3old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
valueX = 190;
|
||||
if(bvalue3->getFormat() == "formatLatitude" || bvalue3->getFormat() == "formatLongitude"){
|
||||
valueY = 250;
|
||||
DsegFontSize = 10;
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(50, 240);
|
||||
}
|
||||
else if(bvalue3->getFormat() == "formatTime" || bvalue3->getFormat() == "formatDate"){
|
||||
valueY = 253;
|
||||
DsegFontSize = 10;
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(100, 240);
|
||||
}
|
||||
else{
|
||||
valueY = 270;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(80, 270);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue3, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue3); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue3old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue3old); // Old value as formated string
|
||||
}
|
||||
if(valid3 == true){
|
||||
svalue3old = svalue3; // Save the old value
|
||||
@@ -245,46 +239,45 @@ class PageFourValues2 : public Page
|
||||
// ############### Vertical Line ################
|
||||
|
||||
// Vertical line 3 pix
|
||||
getdisplay().fillRect(200, 195, 3, 75, commonData->fgcolor);
|
||||
epd->fillRect(200, 195, 3, 75, commonData->fgcolor);
|
||||
|
||||
// ############### Value 4 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(220, 223);
|
||||
getdisplay().print(name4); // Page name
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(220, 220);
|
||||
epd->print(name4); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
||||
getdisplay().setCursor(220, 270);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(220, 240);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit4); // Unit
|
||||
epd->print(unit4); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit4old);
|
||||
epd->print(unit4old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
valueX = 390;
|
||||
if(bvalue4->getFormat() == "formatLatitude" || bvalue4->getFormat() == "formatLongitude"){
|
||||
valueY = 250;
|
||||
DsegFontSize = 10;
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(250, 240);
|
||||
}
|
||||
else if(bvalue4->getFormat() == "formatTime" || bvalue4->getFormat() == "formatDate"){
|
||||
valueY = 253;
|
||||
DsegFontSize = 10;
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(300, 240);
|
||||
}
|
||||
else{
|
||||
valueY = 270;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(280, 270);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue4, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue4); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue4old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue4old); // Old value as formated string
|
||||
}
|
||||
if(valid4 == true){
|
||||
svalue4old = svalue4; // Save the old value
|
||||
|
||||
+118
-91
@@ -1,20 +1,29 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "movingAvg.h" // Lib for moving average building
|
||||
|
||||
class PageGenerator : public Page
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
private:
|
||||
String batVoltage;
|
||||
int genPower;
|
||||
String powerSensor;
|
||||
|
||||
public:
|
||||
PageGenerator(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageGenerator");
|
||||
PageGenerator(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageGenerator");
|
||||
|
||||
// Get config data
|
||||
batVoltage = config->getString(config->batteryVoltage);
|
||||
genPower = config->getInt(config->genPower);
|
||||
powerSensor = config->getString(config->usePowSensor3);
|
||||
}
|
||||
virtual int handleKey(int key){
|
||||
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -23,20 +32,7 @@ public:
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData)
|
||||
{
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Get config data
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
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);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
double value1 = 0; // Solar voltage
|
||||
double value2 = 0; // Solar current
|
||||
@@ -64,125 +60,156 @@ public:
|
||||
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"){
|
||||
if (flashLED == "Limit Violation") {
|
||||
// Over voltage?
|
||||
if (batVoltage == "12V") {
|
||||
setBlinkingLED(value1 > 14.8);
|
||||
} else if (batVoltage == "24V") {
|
||||
setBlinkingLED(value1 > 29.6);
|
||||
} else {
|
||||
setBlinkingLED(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Logging voltage value
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageGenerator, Type:%iW %s:=%f", genPower, name1.c_str(), value1);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageGenerator, Type:%iW %s:=%f", genPower, name1.c_str(), value1);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(10, 65);
|
||||
getdisplay().print("Power");
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(12, 82);
|
||||
getdisplay().print("Generator");
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(10, 65);
|
||||
epd->print("Power");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(12, 82);
|
||||
epd->print("Generator");
|
||||
|
||||
// Show voltage type
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 140);
|
||||
int bvoltage = 0;
|
||||
if(String(batVoltage) == "12V") bvoltage = 12;
|
||||
else bvoltage = 24;
|
||||
printBoatValue(String(bvoltage), 10, 140, LEFT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("V");
|
||||
epd->print(bvoltage);
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("V");
|
||||
|
||||
// Show solar power
|
||||
String svalueGenPower = (genPower <= 999) ? String(genPower) : String(float(genPower/1000.0), 1);
|
||||
printBoatValue(svalueGenPower, 10, 200, LEFT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
if(genPower <= 999) getdisplay().print("W");
|
||||
if(genPower > 999) getdisplay().print("kW");
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 200);
|
||||
if(genPower <= 999) epd->print(genPower, 0);
|
||||
if(genPower > 999) epd->print(float(genPower/1000.0), 1);
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
if(genPower <= 999) epd->print("W");
|
||||
if(genPower > 999) epd->print("kW");
|
||||
|
||||
// Show info
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 235);
|
||||
getdisplay().print("Installed");
|
||||
getdisplay().setCursor(10, 255);
|
||||
getdisplay().print("Power Modul");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 235);
|
||||
epd->print("Installed");
|
||||
epd->setCursor(10, 255);
|
||||
epd->print("Power Modul");
|
||||
|
||||
// Show generator
|
||||
generatorGraphic(200, 95, commonData->fgcolor, commonData->bgcolor);
|
||||
|
||||
// Show load level in percent
|
||||
printBoatValue(String(genPercentage), 150, 200, LEFT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("%");
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(150, 235);
|
||||
getdisplay().print("Load");
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(150, 200);
|
||||
epd->print(genPercentage);
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("%");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(150, 235);
|
||||
epd->print("Load");
|
||||
|
||||
// Show sensor type info
|
||||
String i2cAddr = "";
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(270, 60);
|
||||
if(powerSensor == "off") getdisplay().print("Internal");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(270, 60);
|
||||
if(powerSensor == "off") epd->print("Internal");
|
||||
if(powerSensor == "INA219"){
|
||||
getdisplay().print("INA219");
|
||||
epd->print("INA219");
|
||||
i2cAddr = " (0x" + String(INA219_I2C_ADDR3, HEX) + ")";
|
||||
}
|
||||
if(powerSensor == "INA226"){
|
||||
getdisplay().print("INA226");
|
||||
epd->print("INA226");
|
||||
i2cAddr = " (0x" + String(INA226_I2C_ADDR3, HEX) + ")";
|
||||
}
|
||||
getdisplay().print(i2cAddr);
|
||||
getdisplay().setCursor(270, 80);
|
||||
getdisplay().print("Sensor Modul");
|
||||
epd->print(i2cAddr);
|
||||
epd->setCursor(270, 80);
|
||||
epd->print("Sensor Modul");
|
||||
|
||||
// Reading bus data or using simulation data
|
||||
String svalue1;
|
||||
if(valid1 == true || holdvalues == true){
|
||||
svalue1 = formatValue(value1, String("formatXdr:U:V"), *commonData);
|
||||
} else {
|
||||
svalue1 = "---"; // Missing bus data
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(260, 140);
|
||||
if(simulation == true){
|
||||
if(batVoltage == "12V"){
|
||||
value1 = 12.0;
|
||||
}
|
||||
printBoatValue(svalue1, 355, 140, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("V");
|
||||
if(batVoltage == "24V"){
|
||||
value1 = 24.0;
|
||||
}
|
||||
value1 += float(random(0, 5)) / 10; // Simulation data
|
||||
epd->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) epd->print(value1, 2);
|
||||
if(value1 > 9.9 && value1 <= 99.9)epd->print(value1, 1);
|
||||
if(value1 > 99.9) epd->print(value1, 0);
|
||||
}
|
||||
else{
|
||||
epd->print(commonData->fmt->placeholder); // Missing bus data
|
||||
}
|
||||
}
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("V");
|
||||
|
||||
// Show actual current in A
|
||||
String svalue2;
|
||||
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
|
||||
svalue2 = formatValue(value2, String("formatXdr:I:A"), *commonData);
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(260, 200);
|
||||
if ((powerSensor == "INA219" || powerSensor == "INA226") && (simulation == false)) {
|
||||
// TODO use formatter for this?
|
||||
if (value2 <= 9.9) {
|
||||
epd->print(value2, 2);
|
||||
} else if (value2 <= 99.9) {
|
||||
epd->print(value2, 1);
|
||||
} else {
|
||||
epd->print(value2, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
svalue2 = "---";
|
||||
epd->print(commonData->fmt->placeholder);
|
||||
}
|
||||
printBoatValue(svalue2, 355, 200, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("A");
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("A");
|
||||
|
||||
// Show actual consumption in W
|
||||
String svalue3;
|
||||
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
|
||||
svalue3 = formatValue(value3, String("formatXdr:G:"), *commonData);
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(260, 260);
|
||||
if ((powerSensor == "INA219" || powerSensor == "INA226") && (simulation == false)) {
|
||||
if(value3 <= 9.9) {
|
||||
epd->print(value3, 2);
|
||||
} else if (value3 <= 99.9) {
|
||||
epd->print(value3, 1);
|
||||
} else {
|
||||
epd->print(value3, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
svalue3 = "---";
|
||||
epd->print(commonData->fmt->placeholder);
|
||||
}
|
||||
printBoatValue(svalue3, 355, 260, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("W");
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("W");
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -5,14 +6,24 @@
|
||||
|
||||
class PageKeelPosition : public Page
|
||||
{
|
||||
private:
|
||||
String lengthformat;
|
||||
String rotsensor;
|
||||
String rotfunction;
|
||||
|
||||
public:
|
||||
PageKeelPosition(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageKeelPosition");
|
||||
PageKeelPosition(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageKeelPosition");
|
||||
|
||||
// Get config data
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
rotsensor = config->getString(config->useRotSensor);
|
||||
rotfunction = config->getString(config->rotFunction);
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -21,23 +32,21 @@ public:
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData)
|
||||
{
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
double value1 = 0;
|
||||
double value1old = 0;
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
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"){
|
||||
@@ -55,20 +64,14 @@ public:
|
||||
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);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageKeelPosition, Keel:%f", value1);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
//*******************************************************************************************
|
||||
|
||||
@@ -76,9 +79,9 @@ public:
|
||||
int rInstrument = 110; // Radius of KeelPosition
|
||||
float pi = 3.141592;
|
||||
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
getdisplay().fillRect(0, 30, 400, 122, commonData->bgcolor); // Delete half top circle
|
||||
epd->fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
epd->fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
epd->fillRect(0, 30, 400, 122, commonData->bgcolor); // Delete half top circle
|
||||
|
||||
for(int i=90; i<=270; i=i+10)
|
||||
{
|
||||
@@ -105,17 +108,17 @@ public:
|
||||
// Print text centered on position x, y
|
||||
int16_t x1, y1; // Return values of getTextBounds
|
||||
uint16_t w, h; // Return values of getTextBounds
|
||||
displayGetTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
getdisplay().setCursor(x-w/2, y+h/2);
|
||||
epd->getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
epd->setCursor(x-w/2, y+h/2);
|
||||
if(i % 30 == 0){
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().print(ii);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->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, commonData->fgcolor);
|
||||
epd->fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor);
|
||||
float sinx=sin(i/180.0*pi);
|
||||
float cosx=cos(i/180.0*pi);
|
||||
|
||||
@@ -126,10 +129,10 @@ public:
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
}
|
||||
@@ -163,7 +166,7 @@ public:
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
// Inverted pointer
|
||||
@@ -173,36 +176,36 @@ public:
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
|
||||
// Draw counterweight
|
||||
getdisplay().fillCircle(200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2), 5, commonData->fgcolor);
|
||||
epd->fillCircle(200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2), 5, commonData->fgcolor);
|
||||
}
|
||||
|
||||
// Center circle
|
||||
getdisplay().fillCircle(200, 140, startwidth + 22, commonData->bgcolor);
|
||||
getdisplay().fillCircle(200, 140, startwidth + 20, commonData->fgcolor); // Boat circle
|
||||
getdisplay().fillRect(200 - 30, 140 - 30, 2 * 30, 30, commonData->bgcolor); // Delete half top of boat circle
|
||||
getdisplay().fillRect(150, 150, 100, 4, commonData->fgcolor); // Water line
|
||||
epd->fillCircle(200, 140, startwidth + 22, commonData->bgcolor);
|
||||
epd->fillCircle(200, 140, startwidth + 20, commonData->fgcolor); // Boat circle
|
||||
epd->fillRect(200 - 30, 140 - 30, 2 * 30, 30, commonData->bgcolor); // Delete half top of boat circle
|
||||
epd->fillRect(150, 150, 100, 4, commonData->fgcolor); // Water line
|
||||
|
||||
// Print label
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(100, 70);
|
||||
getdisplay().print("Keel Position"); // Label
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->setCursor(100, 70);
|
||||
epd->print("Keel Position"); // Label
|
||||
|
||||
if((rotsensor == "AS5600" && rotfunction == "Keel" && (valid1 == true || holdvalues == true)) || simulation == true){
|
||||
// Print Unit of keel position
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(175, 110);
|
||||
getdisplay().print(unit1); // Unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(175, 110);
|
||||
epd->print(unit1); // Unit
|
||||
}
|
||||
else{
|
||||
// Print Unit of keel position
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(145, 110);
|
||||
getdisplay().print("No sensor data"); // Info missing sensor
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(145, 110);
|
||||
epd->print("No sensor data"); // Info missing sensor
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
|
||||
+101
-175
@@ -6,69 +6,20 @@
|
||||
#include "ImageDecoder.h" // Image decoder for navigation map
|
||||
#include <mbedtls/base64.h>
|
||||
|
||||
#include "Logo_OBP_400x300_sw.h"
|
||||
|
||||
// Defines for reading of navigation map
|
||||
#define JSON_BUFFER 30000 // Max buffer size for JSON content (30 kB picture + values)
|
||||
NetworkClient net(JSON_BUFFER); // Define network client
|
||||
ImageDecoder decoder; // Define image decoder
|
||||
|
||||
#ifdef TFT_DISPLAY
|
||||
// Set to true to render a generated RGB565 color-bar test image.
|
||||
static constexpr bool kShowRgb565StripeTestImage = false;
|
||||
|
||||
static void drawRgb565Image(int16_t x, int16_t y, const uint16_t *img, int16_t w, int16_t h) {
|
||||
if (img == nullptr || w <= 0 || h <= 0) {
|
||||
return;
|
||||
}
|
||||
for (int16_t yy = 0; yy < h; ++yy) {
|
||||
const uint16_t *row = img + ((size_t)yy * (size_t)w);
|
||||
for (int16_t xx = 0; xx < w; ++xx) {
|
||||
getdisplay().drawPixel(x + xx, y + yy, row[xx]);
|
||||
}
|
||||
if ((yy & 0x0F) == 0) {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void createRgb565StripeImage(uint16_t *img, int16_t w, int16_t h) {
|
||||
if (img == nullptr || w <= 0 || h <= 0) {
|
||||
return;
|
||||
}
|
||||
static const uint16_t stripes[] = {
|
||||
0xF800, // red
|
||||
0xFD20, // orange
|
||||
0xFFE0, // yellow
|
||||
0x07E0, // green
|
||||
0x07FF, // cyan
|
||||
0x001F, // blue
|
||||
0xF81F, // magenta
|
||||
0xFFFF // white
|
||||
};
|
||||
const int stripeCount = (int)(sizeof(stripes) / sizeof(stripes[0]));
|
||||
|
||||
for (int16_t y = 0; y < h; ++y) {
|
||||
uint16_t *row = img + ((size_t)y * (size_t)w);
|
||||
for (int16_t x = 0; x < w; ++x) {
|
||||
int idx = ((int)x * stripeCount) / (int)w;
|
||||
if (idx >= stripeCount) {
|
||||
idx = stripeCount - 1;
|
||||
}
|
||||
row[x] = stripes[idx];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
class PageNavigation : public Page
|
||||
{
|
||||
private:
|
||||
|
||||
// Values for buttons
|
||||
bool firstRun = true; // Detect the first page run
|
||||
int zoom = 15; // Default zoom level
|
||||
bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
|
||||
private:
|
||||
uint8_t* imageBackupData = nullptr;
|
||||
int imageBackupWidth = 0;
|
||||
int imageBackupHeight = 0;
|
||||
@@ -77,26 +28,50 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
bool hasImageBackup = false;
|
||||
bool imageBackupIsRgb565 = false;
|
||||
|
||||
String lengthformat;
|
||||
String mapsource;
|
||||
String ipAddress;
|
||||
int localPort;
|
||||
String mapType;
|
||||
int zoomLevel;
|
||||
bool grid;
|
||||
String orientation;
|
||||
int refreshDistance;
|
||||
bool showValuesMap;
|
||||
bool ownHeading;
|
||||
|
||||
public:
|
||||
PageNavigation(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageNavigation");
|
||||
imageBackupCapacity = (size_t)GxEPD_WIDTH * (size_t)GxEPD_HEIGHT;
|
||||
#ifdef TFT_DISPLAY
|
||||
imageBackupCapacity *= 2U;
|
||||
#endif
|
||||
PageNavigation(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG,"Instantiate PageNavigation");
|
||||
|
||||
imageBackupCapacity = (size_t) epd->width() * (size_t) epd->height();
|
||||
imageBackupData = (uint8_t*)heap_caps_malloc(imageBackupCapacity, MALLOC_CAP_SPIRAM);
|
||||
|
||||
// Get config data
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
mapsource = config->getString(config->mapsource);
|
||||
ipAddress = config->getString(config->ipAddress);
|
||||
localPort = config->getInt(config->localPort);
|
||||
mapType = config->getString(config->maptype);
|
||||
zoomLevel = config->getInt(config->zoomlevel);
|
||||
grid = config->getBool(config->grid);
|
||||
orientation = config->getString(config->orientation);
|
||||
refreshDistance = config->getInt(config->refreshDistance);
|
||||
showValuesMap = config->getBool(config->showvalues);
|
||||
ownHeading = config->getBool(config->ownheading);
|
||||
|
||||
}
|
||||
|
||||
// Set botton labels
|
||||
virtual void setupKeys(){
|
||||
void setupKeys(){
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "ZOOM -";
|
||||
commonData->keydata[1].label = "ZOOM +";
|
||||
commonData->keydata[4].label = "VALUES";
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -125,31 +100,22 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
String mapsource = config->getString(config->mapsource);
|
||||
String ipAddress = config->getString(config->ipAddress);
|
||||
int localPort = config->getInt(config->localPort);
|
||||
String mapType = config->getString(config->maptype);
|
||||
int zoomLevel = config->getInt(config->zoomlevel);
|
||||
bool grid = config->getBool(config->grid);
|
||||
String orientation = config->getString(config->orientation);
|
||||
int refreshDistance = config->getInt(config->refreshDistance);
|
||||
bool showValuesMap = config->getBool(config->showvalues);
|
||||
bool ownHeading = config->getBool(config->ownheading);
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
if (firstRun == true) {
|
||||
zoom = zoomLevel; // Overwrite zoom level with setup value
|
||||
showValues = showValuesMap; // Overwrite showValues with setup value
|
||||
firstRun = false; // Restet variable
|
||||
firstRun = false;
|
||||
}
|
||||
|
||||
// Local variables
|
||||
@@ -161,7 +127,6 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
int symbolRot = 0;
|
||||
int mapGrid = 0;
|
||||
|
||||
|
||||
// Old values for hold function
|
||||
static double value1old = 0;
|
||||
static String svalue1old = "";
|
||||
@@ -200,8 +165,8 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
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
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values #2 Longitude
|
||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list (only one value by PageOneValue)
|
||||
@@ -209,8 +174,8 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
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
|
||||
String svalue2 = commonData->fmt->formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit2 = commonData->fmt->formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values #3 HDT
|
||||
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Second element in list (only one value by PageOneValue)
|
||||
@@ -218,8 +183,8 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
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
|
||||
String svalue3 = commonData->fmt->formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit3 = commonData->fmt->formatValue(bvalue3, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values #4 HDM
|
||||
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Second element in list (only one value by PageOneValue)
|
||||
@@ -227,8 +192,8 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
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
|
||||
String svalue4 = commonData->fmt->formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit4 = commonData->fmt->formatValue(bvalue4, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values #5 SOG
|
||||
GwApi::BoatValue *bvalue5 = pageData.values[4]; // Second element in list (only one value by PageOneValue)
|
||||
@@ -236,8 +201,8 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
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
|
||||
String svalue5 = commonData->fmt->formatValue(bvalue5, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit5 = commonData->fmt->formatValue(bvalue5, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values #6 DBT
|
||||
GwApi::BoatValue *bvalue6 = pageData.values[5]; // Second element in list (only one value by PageOneValue)
|
||||
@@ -245,18 +210,14 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
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
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
String svalue6 = commonData->fmt->formatValue(bvalue6, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit6 = commonData->fmt->formatValue(bvalue6, *commonData).unit; // Unit of value
|
||||
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageNavigation, %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);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageNavigation, %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);
|
||||
|
||||
// Set variables
|
||||
//***********************************************************
|
||||
@@ -415,7 +376,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
// For more details see: https://github.com/norbert-walter/maps-converter
|
||||
String url = String("http://") + server + ":" + port + // OBP Server
|
||||
String("/get_image_json?") + // Service: Output B&W picture as JSON (Base64 + gzip)
|
||||
#ifdef TFT_DISPLAY
|
||||
#ifdef DISPLAY_ST7796
|
||||
"oformat=3" + // Image output format in JSON: 3=RGB565 format
|
||||
#else
|
||||
"oformat=4" + // Image output format in JSON: 4=b/w 1-Bit format
|
||||
@@ -425,7 +386,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
"&lon=" + String(longitude, 6) + // Longitude
|
||||
"&mrot=" + mapRot + // Rotation angle navigation map in degree
|
||||
"&mtype=" + mType + // Default Map: Open Street Map
|
||||
#ifdef TFT_DISPLAY
|
||||
#ifdef DISPLAY_ST7796
|
||||
"&itype=1" + // Image type: 1=Color
|
||||
#else
|
||||
"&itype=4" + // Image type: 4=b/w with dithering
|
||||
@@ -449,8 +410,8 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
// ############### Draw Navigation Map ################
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// NEW: simple exponential backoff for 1 Hz polling (prevents connection-refused storms)
|
||||
static uint32_t nextAllowedMs = 0;
|
||||
@@ -478,20 +439,20 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
requiredBytesRgb565 = (size_t)imgWidth * (size_t)imgHeight * 2U;
|
||||
}
|
||||
if (requiredBytesMono == 0){
|
||||
LOG_DEBUG(GwLog::ERROR,"Error PageNavigation: invalid image geometry w=%d h=%d",imgWidth,imgHeight);
|
||||
logger->logDebug(GwLog::ERROR,"Error PageNavigation: invalid image geometry w=%d h=%d",imgWidth,imgHeight);
|
||||
return PAGE_UPDATE;
|
||||
}
|
||||
|
||||
const char* b64src = net.pictureBase64(); // Read picture as Base64 content
|
||||
if (b64src == nullptr){
|
||||
LOG_DEBUG(GwLog::ERROR,"Error PageNavigation: picture_base64 missing");
|
||||
logger->logDebug(GwLog::ERROR,"Error PageNavigation: picture_base64 missing");
|
||||
return PAGE_UPDATE;
|
||||
}
|
||||
size_t b64len = net.pictureBase64Len(); // Calculate length of Base64 content
|
||||
// Copy Base64 content in PSRAM
|
||||
char* b64 = (char*) heap_caps_malloc(b64len + 1, MALLOC_CAP_SPIRAM); // Allcate PSRAM for Base64 content
|
||||
if (!b64) {
|
||||
LOG_DEBUG(GwLog::ERROR,"Error PageNavigation: PSRAM alloc base64 failed");
|
||||
logger->logDebug(GwLog::ERROR,"Error PageNavigation: PSRAM alloc base64 failed");
|
||||
return PAGE_UPDATE;
|
||||
}
|
||||
memcpy(b64, b64src, b64len + 1); // Copy Base64 content in PSRAM
|
||||
@@ -501,14 +462,9 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
if (imgSize < requiredBytesMono){
|
||||
imgSize = requiredBytesMono;
|
||||
}
|
||||
#ifdef TFT_DISPLAY
|
||||
if (imgSize < requiredBytesRgb565){
|
||||
imgSize = requiredBytesRgb565;
|
||||
}
|
||||
#endif
|
||||
uint8_t* imageData = (uint8_t*) heap_caps_malloc(imgSize, MALLOC_CAP_SPIRAM); // Allocate PSRAM for image
|
||||
if (!imageData) {
|
||||
LOG_DEBUG(GwLog::ERROR,"Error PageNavigation: PSRAM alloc image buffer failed");
|
||||
logger->logDebug(GwLog::ERROR,"Error PageNavigation: PSRAM alloc image buffer failed");
|
||||
free(b64);
|
||||
return PAGE_UPDATE;
|
||||
}
|
||||
@@ -524,7 +480,7 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
(const unsigned char*)b64,
|
||||
b64len
|
||||
);
|
||||
LOG_DEBUG(GwLog::ERROR,
|
||||
logger->logDebug(GwLog::ERROR,
|
||||
"Error PageNavigation: decode failed (ok=%d, decoded=%u, required=%u, b64ret=%d)",
|
||||
decodeOk ? 1 : 0,
|
||||
(unsigned int)decodedSize,
|
||||
@@ -536,19 +492,6 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
return PAGE_UPDATE;
|
||||
}
|
||||
|
||||
bool imageIsRgb565 = false;
|
||||
#ifdef TFT_DISPLAY
|
||||
imageIsRgb565 = (decodedSize >= requiredBytesRgb565);
|
||||
#endif
|
||||
|
||||
#ifdef TFT_DISPLAY
|
||||
if (kShowRgb565StripeTestImage) {
|
||||
createRgb565StripeImage(reinterpret_cast<uint16_t*>(imageData), imgWidth, imgHeight);
|
||||
decodedSize = requiredBytesRgb565;
|
||||
imageIsRgb565 = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Copy actual navigation map to backup map
|
||||
imageBackupWidth = imgWidth;
|
||||
imageBackupHeight = imgHeight;
|
||||
@@ -558,20 +501,11 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
memcpy(imageBackupData, imageData, copySize);
|
||||
imageBackupSize = copySize;
|
||||
}
|
||||
imageBackupIsRgb565 = imageIsRgb565;
|
||||
hasImageBackup = (imageBackupData != nullptr);
|
||||
lostCounter = 0;
|
||||
|
||||
// Show image (navigation map)
|
||||
#ifdef TFT_DISPLAY
|
||||
if (imageIsRgb565) {
|
||||
drawRgb565Image(0, 25, reinterpret_cast<const uint16_t*>(imageData), imgWidth, imgHeight);
|
||||
} else {
|
||||
displayDrawBitmap(0, 25, imageData, imgWidth, imgHeight, commonData->fgcolor);
|
||||
}
|
||||
#else
|
||||
displayDrawBitmap(0, 25, imageData, imgWidth, imgHeight, commonData->fgcolor);
|
||||
#endif
|
||||
epd->drawBitmap(0, 25, imageData, imgWidth, imgHeight, commonData->fgcolor);
|
||||
|
||||
// Clean PSRAM
|
||||
free(b64);
|
||||
@@ -594,67 +528,59 @@ bool showValues = false; // Show values HDT, SOG, DBT in navigation map
|
||||
|
||||
// Show backup image (backup navigation map)
|
||||
if (hasImageBackup) {
|
||||
#ifdef TFT_DISPLAY
|
||||
if (imageBackupIsRgb565) {
|
||||
drawRgb565Image(0, 25, reinterpret_cast<const uint16_t*>(imageBackupData), imageBackupWidth, imageBackupHeight);
|
||||
} else {
|
||||
displayDrawBitmap(0, 25, imageBackupData, imageBackupWidth, imageBackupHeight, commonData->fgcolor);
|
||||
}
|
||||
#else
|
||||
displayDrawBitmap(0, 25, imageBackupData, imageBackupWidth, imageBackupHeight, commonData->fgcolor);
|
||||
#endif
|
||||
epd->drawBitmap(0, 25, imageBackupData, imageBackupWidth, imageBackupHeight, commonData->fgcolor);
|
||||
}
|
||||
|
||||
// Show connection lost info when 5 page refreshes has a connection lost to the map server
|
||||
// Short connection losts are uncritical
|
||||
if(lostCounter >= 5){
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().fillRect(200, 250 , 200, 25, commonData->fgcolor); // Black rect
|
||||
getdisplay().fillRect(202, 252 , 196, 21, commonData->bgcolor); // White rect
|
||||
getdisplay().setCursor(210, 270);
|
||||
getdisplay().print("Map server lost");
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->fillRect(200, 250 , 200, 25, commonData->fgcolor);
|
||||
epd->fillRect(202, 252 , 196, 21, commonData->bgcolor);
|
||||
epd->setCursor(210, 270);
|
||||
epd->print("Map server lost");
|
||||
}
|
||||
|
||||
lostCounter++; // Increment lost counter
|
||||
lostCounter++;
|
||||
}
|
||||
|
||||
// ############### Draw Values ################
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
|
||||
// Show zoom level
|
||||
getdisplay().fillRect(355, 25 , 45, 25, commonData->fgcolor); // Black rect
|
||||
getdisplay().fillRect(357, 27 , 41, 21, commonData->bgcolor); // White rect
|
||||
getdisplay().setCursor(364, 45);
|
||||
getdisplay().print(zoom);
|
||||
epd->fillRect(355, 25 , 45, 25, commonData->fgcolor);
|
||||
epd->fillRect(357, 27 , 41, 21, commonData->bgcolor);
|
||||
epd->setCursor(364, 45);
|
||||
epd->print(zoom);
|
||||
// If true heading available then use HDT oterwise HDM
|
||||
if (showValues == true) {
|
||||
// Frame
|
||||
getdisplay().fillRect(0, 25 , 130, 65, commonData->fgcolor); // Black rect
|
||||
getdisplay().fillRect(2, 27 , 126, 61, commonData->bgcolor); // White rect
|
||||
epd->fillRect(0, 25 , 130, 65, commonData->fgcolor);
|
||||
epd->fillRect(2, 27 , 126, 61, commonData->bgcolor);
|
||||
if(valid3 == true){
|
||||
// HDT
|
||||
getdisplay().setCursor(10, 45);
|
||||
getdisplay().print(name3);
|
||||
getdisplay().setCursor(70, 45);
|
||||
getdisplay().print(svalue3);
|
||||
epd->setCursor(10, 45);
|
||||
epd->print(name3);
|
||||
epd->setCursor(70, 45);
|
||||
epd->print(svalue3);
|
||||
}
|
||||
else{
|
||||
// HDM
|
||||
getdisplay().setCursor(10, 45);
|
||||
getdisplay().print(name4);
|
||||
getdisplay().setCursor(70, 45);
|
||||
getdisplay().print(svalue4);
|
||||
epd->setCursor(10, 45);
|
||||
epd->print(name4);
|
||||
epd->setCursor(70, 45);
|
||||
epd->print(svalue4);
|
||||
}
|
||||
// SOG
|
||||
getdisplay().setCursor(10, 65);
|
||||
getdisplay().print(name5);
|
||||
getdisplay().setCursor(70, 65);
|
||||
getdisplay().print(svalue5);
|
||||
epd->setCursor(10, 65);
|
||||
epd->print(name5);
|
||||
epd->setCursor(70, 65);
|
||||
epd->print(svalue5);
|
||||
// DBT
|
||||
getdisplay().setCursor(10, 85);
|
||||
getdisplay().print(name6);
|
||||
getdisplay().setCursor(70, 85);
|
||||
getdisplay().print(svalue6);
|
||||
epd->setCursor(10, 85);
|
||||
epd->print(name6);
|
||||
epd->setCursor(70, 85);
|
||||
epd->print(svalue6);
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
|
||||
+69
-259
@@ -1,233 +1,37 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "OBPDataOperations.h"
|
||||
#include "OBPcharts.h"
|
||||
|
||||
class PageOneValue : public Page {
|
||||
private:
|
||||
GwLog* logger;
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
#include "BoatDataCalibration.h"
|
||||
#endif
|
||||
|
||||
enum PageMode {
|
||||
VALUE,
|
||||
BOTH,
|
||||
CHART
|
||||
};
|
||||
enum DisplayMode {
|
||||
FULL,
|
||||
HALF
|
||||
};
|
||||
|
||||
int width; // Screen width
|
||||
int height; // Screen height
|
||||
|
||||
bool keylock = false; // Keylock
|
||||
PageMode pageMode = VALUE; // Page display mode
|
||||
int8_t dataIntv = 1; // Update interval for wind history chart:
|
||||
// (1)|(2)|(3)|(4)|(8) x 240 seconds for 4, 8, 12, 16, 32 min. history chart
|
||||
|
||||
// String lengthformat;
|
||||
bool useSimuData;
|
||||
bool holdValues;
|
||||
String flashLED;
|
||||
bool smallDecimals;
|
||||
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
|
||||
// Old values for hold function
|
||||
String sValue1Old = "";
|
||||
String unit1Old = "";
|
||||
|
||||
// Data buffer pointer (owned by HstryBuffers)
|
||||
RingBuffer<uint16_t>* dataHstryBuf = nullptr;
|
||||
std::unique_ptr<Chart> dataChart = nullptr; // Chart object
|
||||
|
||||
// display data value in display <mode> [FULL|HALF]
|
||||
void showData(GwApi::BoatValue* bValue1, DisplayMode mode)
|
||||
class PageOneValue : public Page
|
||||
{
|
||||
int nameXoff, nameYoff, unitX, unitY, unitXoff, unitYoff, valueX, valueY, valueXoff, valueYoff;
|
||||
const GFXfont *nameFnt, *unitFnt;
|
||||
int valueFontSize1, valueFontSize2, valueFontSize3, DsegFontSize;
|
||||
|
||||
if (mode == FULL) { // full size data display
|
||||
nameXoff = 0;
|
||||
nameYoff = 0;
|
||||
nameFnt = &Ubuntu_Bold32pt8b;
|
||||
unitX = 380;
|
||||
unitY = 100;
|
||||
unitXoff = 0;
|
||||
unitYoff = 0;
|
||||
unitFnt = &Ubuntu_Bold20pt8b;
|
||||
valueXoff = 0;
|
||||
valueYoff = 0;
|
||||
valueFontSize1 = 20;
|
||||
valueFontSize2 = 30;
|
||||
valueFontSize3 = 60;
|
||||
} else { // half size data and chart display
|
||||
nameXoff = -10;
|
||||
nameYoff = -34;
|
||||
nameFnt = &Ubuntu_Bold20pt8b;
|
||||
unitX = 10;
|
||||
unitY = 121;
|
||||
unitFnt = &Ubuntu_Bold12pt8b;
|
||||
valueXoff = 0;
|
||||
valueYoff = -119;
|
||||
valueFontSize1 = 12;
|
||||
valueFontSize2 = 20;
|
||||
valueFontSize3 = 42;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// Show name
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
getdisplay().setFont(nameFnt);
|
||||
getdisplay().setCursor(20 + nameXoff, 100 + nameYoff);
|
||||
getdisplay().print(name1); // name
|
||||
|
||||
// Show unit
|
||||
String unitName;
|
||||
getdisplay().setFont(unitFnt);
|
||||
if (holdValues) {
|
||||
unitName = unit1Old;
|
||||
} else {
|
||||
unitName = unit1;
|
||||
}
|
||||
if (mode == FULL) {
|
||||
drawTextRalign(unitX, unitY, unitName);
|
||||
} else {
|
||||
getdisplay().setCursor(unitX, unitY);
|
||||
getdisplay().print(unitName);
|
||||
}
|
||||
|
||||
// Switch font depending on value format and adjust position
|
||||
valueX = 380 + valueXoff;
|
||||
if (bValue1->getFormat() == "formatLatitude" || bValue1->getFormat() == "formatLongitude") {
|
||||
valueY = 180 + valueYoff;
|
||||
DsegFontSize = valueFontSize1;
|
||||
} else if (bValue1->getFormat() == "formatTime" || bValue1->getFormat() == "formatDate") {
|
||||
valueY = 200 + valueYoff;
|
||||
DsegFontSize = valueFontSize2;
|
||||
} else {
|
||||
valueY = 240 + valueYoff;
|
||||
DsegFontSize = valueFontSize3;
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if (!holdValues || useSimuData) {
|
||||
printBoatValue(sValue1, valueX, valueY, RIGHT, DsegFontSize, smallDecimals);
|
||||
} else {
|
||||
printBoatValue(sValue1Old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals);
|
||||
}
|
||||
|
||||
if (valid1 == true) {
|
||||
sValue1Old = sValue1; // Save the old value
|
||||
unit1Old = unit1; // Save the old unit
|
||||
}
|
||||
}
|
||||
private:
|
||||
String lengthformat;
|
||||
|
||||
public:
|
||||
PageOneValue(CommonData& common)
|
||||
PageOneValue(CommonData &common) : Page(common)
|
||||
{
|
||||
commonData = &common;
|
||||
logger = commonData->logger;
|
||||
GwConfigHandler *config = commonData->config;
|
||||
|
||||
LOG_DEBUG(GwLog::LOG, "Instantiate PageOneValue");
|
||||
|
||||
width = getdisplay().width(); // Screen width
|
||||
height = getdisplay().height(); // Screen height
|
||||
getdisplay().setTextWrap(false);
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageOneValue");
|
||||
|
||||
// Get config data
|
||||
useSimuData = config->getBool(config->useSimuData);
|
||||
holdValues = commonData->config->getBool(commonData->config->holdvalues);
|
||||
flashLED = commonData->config->getString(commonData->config->flashLED);
|
||||
smallDecimals = commonData->config->getBool(commonData->config->smallDecimals);
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
}
|
||||
|
||||
virtual void setupKeys()
|
||||
{
|
||||
Page::setupKeys();
|
||||
|
||||
#if defined BOARD_OBP60S3
|
||||
constexpr int ZOOM_KEY = 4;
|
||||
#elif defined BOARD_OBP40S3
|
||||
constexpr int ZOOM_KEY = 1;
|
||||
#endif
|
||||
|
||||
if (dataHstryBuf) { // show "Mode" key only if chart-supported boat data type is available
|
||||
commonData->keydata[0].label = "MODE";
|
||||
if (pageMode != VALUE) { // show "ZOOM" key only if chart is visible
|
||||
commonData->keydata[ZOOM_KEY].label = "ZOOM";
|
||||
} else {
|
||||
commonData->keydata[ZOOM_KEY].label = "";
|
||||
}
|
||||
} else {
|
||||
commonData->keydata[0].label = "";
|
||||
commonData->keydata[ZOOM_KEY].label = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key)
|
||||
{
|
||||
if (dataHstryBuf) { // if boat data type supports charts
|
||||
|
||||
// Set page mode: value | value/half chart | full chart
|
||||
if (key == 1) {
|
||||
switch (pageMode) {
|
||||
case VALUE:
|
||||
pageMode = BOTH;
|
||||
break;
|
||||
case BOTH:
|
||||
pageMode = CHART;
|
||||
break;
|
||||
case CHART:
|
||||
pageMode = VALUE;
|
||||
break;
|
||||
}
|
||||
setupKeys(); // Adjust key definition depending on <pageMode> and chart-supported boat data type
|
||||
return 0; // Commit the key
|
||||
}
|
||||
|
||||
// Set time frame to show for chart
|
||||
#if defined BOARD_OBP60S3
|
||||
if (key == 5 && pageMode != VALUE) {
|
||||
#elif defined BOARD_OBP40S3
|
||||
if (key == 2 && pageMode != VALUE) {
|
||||
#endif
|
||||
if (dataIntv == 1) {
|
||||
dataIntv = 2;
|
||||
} else if (dataIntv == 2) {
|
||||
dataIntv = 3;
|
||||
} else if (dataIntv == 3) {
|
||||
dataIntv = 4;
|
||||
} else {
|
||||
dataIntv = 1;
|
||||
}
|
||||
return 0; // Commit the key
|
||||
}
|
||||
}
|
||||
|
||||
// Keylock function
|
||||
if (key == 11) { // Code for keylock
|
||||
int handleKey(int key) {
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0; // Commit the key
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
virtual void displayNew(PageData& pageData)
|
||||
{
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
@@ -235,78 +39,84 @@ public:
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
// buffer initialization will fail, if page is default page, because <displayNew> is not executed at system start for default page
|
||||
if (!dataChart) { // Create chart objects if they don't exist
|
||||
};
|
||||
|
||||
GwApi::BoatValue* bValue1 = pageData.values[0]; // Page boat data element
|
||||
String bValName1 = bValue1->getName(); // Value name
|
||||
String bValFormat = bValue1->getFormat(); // Value format
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
dataHstryBuf = pageData.hstryBuffers->getBuffer(bValName1);
|
||||
// Old values for hold function
|
||||
static String svalue1old = "";
|
||||
static String unit1old = "";
|
||||
|
||||
if (dataHstryBuf) {
|
||||
dataChart.reset(new Chart(*dataHstryBuf, *commonData, useSimuData));
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageOneValue: Created chart object for %s", bValName1);
|
||||
} else {
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageOneValue: No chart object available for %s", bValName1);
|
||||
}
|
||||
}
|
||||
|
||||
setupKeys(); // Adjust key definition depending on <pageMode> and chart-supported boat data type
|
||||
}
|
||||
|
||||
int displayPage(PageData& pageData)
|
||||
{
|
||||
LOG_DEBUG(GwLog::LOG, "Display PageOneValue");
|
||||
|
||||
// Get boat value for page
|
||||
GwApi::BoatValue* bValue1 = pageData.values[0]; // Page boat data element
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Optical warning by limit violation (unused)
|
||||
if (String(flashLED) == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
// 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
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
if (bValue1 == NULL)
|
||||
return PAGE_OK; // no data, no page to display
|
||||
double value1 = bvalue1->value; // Value as double in SI unit
|
||||
bool valid1 = bvalue1->valid; // Valid information
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageOneValue: printing %s, %.3f", bValue1->getName().c_str(), bValue1->value);
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageOneValue, %s: %f", name1.c_str(), value1);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
displaySetPartialWindow(0, 0, width, height); // Set partial update
|
||||
/// Set display in partial refresh mode
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
if (dataChart) { // Check only if dataChart object exists at all
|
||||
if (!dataChart->isValid()) {
|
||||
dataChart->init(); // try late initialization if chart object could not be properly initialized earlier due to missing boat data
|
||||
// Show name
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold32pt8b);
|
||||
epd->setCursor(20, 100);
|
||||
epd->print(name1); // Page name
|
||||
|
||||
// Show unit
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(270, 100);
|
||||
if(holdvalues == false){
|
||||
epd->print(unit1); // Unit
|
||||
}
|
||||
else{
|
||||
epd->print(unit1old);
|
||||
}
|
||||
|
||||
if (pageMode == VALUE || dataChart == nullptr) {
|
||||
// show only data value; ignore other pageMode options if no chart supported boat data history buffer is available
|
||||
showData(bValue1, FULL);
|
||||
|
||||
} else if (pageMode == CHART) { // show only data chart
|
||||
if (dataChart) {
|
||||
dataChart->showChrt(Chart::HORIZONTAL, Chart::FULL_SIZE, dataIntv, Chart::PRNT_NAME, Chart::PRNT_VALUE, *bValue1);
|
||||
// Switch font if format for any values
|
||||
if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 180);
|
||||
}
|
||||
else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){
|
||||
epd->setFont(&Ubuntu_Bold32pt8b);
|
||||
epd->setCursor(20, 200);
|
||||
}
|
||||
else{
|
||||
epd->setFont(&DSEG7Classic_BoldItalic60pt7b);
|
||||
epd->setCursor(20, 240);
|
||||
}
|
||||
|
||||
} else if (pageMode == BOTH) { // show data value and chart
|
||||
showData(bValue1, HALF);
|
||||
if (dataChart) {
|
||||
dataChart->showChrt(Chart::HORIZONTAL, Chart::HALF_SIZE_RIGHT_BOTTOM, dataIntv, Chart::NO_PRNT_NAME, Chart::NO_PRNT_VALUE, *bValue1);
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
epd->print(svalue1); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
epd->print(svalue1old); // Old value as formated string
|
||||
}
|
||||
if(valid1 == true){
|
||||
svalue1old = svalue1; // Save the old value
|
||||
unit1old = unit1; // Save the old unit
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page* createPage(CommonData& common)
|
||||
{
|
||||
static Page* createPage(CommonData &common){
|
||||
return new PageOneValue(common);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -5,18 +6,30 @@
|
||||
|
||||
class PageRollPitch : public Page
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
private:
|
||||
String lengthformat;
|
||||
int rolllimit;
|
||||
String roffset;
|
||||
double rolloffset;
|
||||
String poffset;
|
||||
double pitchoffset;
|
||||
|
||||
public:
|
||||
PageRollPitch(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageRollPitch");
|
||||
PageRollPitch(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageRollPitch");
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
rolllimit = config->getInt(config->rollLimit);
|
||||
roffset = config->getString(config->rollOffset);
|
||||
rolloffset = roffset.toFloat() / 360 * (2 * M_PI);
|
||||
poffset = config->getString(config->pitchOffset);
|
||||
pitchoffset = poffset.toFloat() / 360 * (2 * M_PI);
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -26,8 +39,6 @@ public:
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
double value1 = 0;
|
||||
double value2 = 0;
|
||||
@@ -36,27 +47,11 @@ public:
|
||||
String svalue2 = "";
|
||||
String svalue2old = "";
|
||||
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
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*M_PI);
|
||||
String poffset = config->getString(config->pitchOffset);
|
||||
double pitchoffset = poffset.toFloat()/360*(2*M_PI);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
// 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, 5); // String length limit for value name
|
||||
name1 = name1.substring(0, 6); // String length limit for value name
|
||||
bool valid1 = bvalue1->valid; // Valid information
|
||||
String unit1 = formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||
unit1 = unit1.substring(0, 4); // String length limit for value unit
|
||||
if(valid1 == true){
|
||||
value1 = bvalue1->value + rolloffset; // Raw value for pitch
|
||||
}
|
||||
@@ -80,10 +75,8 @@ public:
|
||||
// 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, 5); // String length limit for value name
|
||||
name2 = name2.substring(0, 6); // String length limit for value name
|
||||
bool valid2 = bvalue2->valid; // Valid information
|
||||
String unit2 = formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||
unit2 = unit2.substring(0, 4); // String length limit for value unit
|
||||
if(valid2 == true){
|
||||
value2 = bvalue2->value + pitchoffset; // Raw value for pitch
|
||||
}
|
||||
@@ -95,7 +88,7 @@ public:
|
||||
value2 = 0;
|
||||
}
|
||||
}
|
||||
if(value2/(2*M_PI)*360 > -10 && value2/(2*M_PI)*360 < 10){
|
||||
if(value2/(2*PI)*360 > -10 && value2/(2*M_PI)*360 < 10){
|
||||
svalue2 = String(value2/(2*M_PI)*360,1); // Convert raw value to string
|
||||
}
|
||||
else{
|
||||
@@ -106,71 +99,79 @@ public:
|
||||
}
|
||||
|
||||
// Optical warning by limit violation
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
if (flashLED == "Limit Violation") {
|
||||
// Limits for roll
|
||||
if (value1*360/(2*M_PI) >= -1*rolllimit && value1*360/(2*M_PI) <= rolllimit) {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
setBlinkingLED(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageRollPitch, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageRollPitch, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// Show roll limit
|
||||
printBoatValue(String(rolllimit), 10, 65, LEFT, 20, smallDecimals); // Value
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 65);
|
||||
epd->print(rolllimit); // Value
|
||||
//epd->print(svalue1); // Value
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(10, 95);
|
||||
getdisplay().print("Limit"); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 115);
|
||||
getdisplay().print("Deg");
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(10, 95);
|
||||
epd->print("Limit"); // Name
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 115);
|
||||
epd->print("DEG");
|
||||
|
||||
// Horizintal separator left
|
||||
getdisplay().fillRect(0, 149, 60, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 149, 60, 3, commonData->fgcolor);
|
||||
|
||||
// Show roll value
|
||||
if(holdvalues == false) printBoatValue(svalue1, 101, 270, RIGHT, 20, smallDecimals); // Value
|
||||
else printBoatValue(svalue1old, 101, 270, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(10, 220);
|
||||
getdisplay().print(name1); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 190);
|
||||
getdisplay().print(unit1); // Unit
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 270);
|
||||
if(holdvalues == false) epd->print(svalue1); // Value
|
||||
else epd->print(svalue1old);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(10, 220);
|
||||
epd->print(name1); // Name
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 190);
|
||||
epd->print("Deg");
|
||||
|
||||
// Horizintal separator right
|
||||
getdisplay().fillRect(340, 149, 80, 3, commonData->fgcolor);
|
||||
epd->fillRect(340, 149, 80, 3, commonData->fgcolor);
|
||||
|
||||
// Show pitch value
|
||||
if(holdvalues == false) printBoatValue(svalue2, 395, 270, RIGHT, 20, smallDecimals); // Value
|
||||
else printBoatValue(svalue2old, 395, 270, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
drawTextRalign(395, 220, name2); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(335, 190);
|
||||
getdisplay().print(unit2); // Unit
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(295, 270);
|
||||
if(holdvalues == false) epd->print(svalue2); // Value
|
||||
else epd->print(svalue2old);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(335, 220);
|
||||
epd->print(name2); // Name
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(335, 190);
|
||||
epd->print("Deg");
|
||||
|
||||
//*******************************************************************************************
|
||||
|
||||
// Draw instrument
|
||||
int rInstrument = 100; // Radius of instrument
|
||||
float pi = 3.141592;
|
||||
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
epd->fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
epd->fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
|
||||
for(int i=0; i<360; i=i+10)
|
||||
{
|
||||
@@ -194,17 +195,17 @@ public:
|
||||
// Print text centered on position x, y
|
||||
int16_t x1, y1; // Return values of getTextBounds
|
||||
uint16_t w, h; // Return values of getTextBounds
|
||||
displayGetTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
getdisplay().setCursor(x-w/2, y+h/2);
|
||||
epd->getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
epd->setCursor(x-w/2, y+h/2);
|
||||
if(i % 20 == 0){
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().print(ii);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->print(ii);
|
||||
}
|
||||
|
||||
// Draw sub scale with dots
|
||||
float x1c = 200 + rInstrument*sin(i/180.0*M_PI);
|
||||
float y1c = 150 - rInstrument*cos(i/180.0*M_PI);
|
||||
getdisplay().fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor);
|
||||
epd->fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor);
|
||||
float sinx=sin(i/180.0*M_PI);
|
||||
float cosx=cos(i/180.0*M_PI);
|
||||
|
||||
@@ -215,10 +216,10 @@ public:
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
}
|
||||
@@ -239,7 +240,7 @@ public:
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
// Inverted pointer
|
||||
@@ -249,28 +250,28 @@ public:
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
|
||||
// Draw counterweight
|
||||
getdisplay().fillCircle(200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2), 5, commonData->fgcolor);
|
||||
epd->fillCircle(200+(int)(cosx*0-sinx*yy2),150+(int)(sinx*0+cosx*yy2), 5, commonData->fgcolor);
|
||||
}
|
||||
|
||||
// Center circle
|
||||
getdisplay().fillCircle(200, 150, startwidth + 22, commonData->bgcolor);
|
||||
getdisplay().fillCircle(200, 150, startwidth + 20, commonData->fgcolor); // Boat circle
|
||||
epd->fillCircle(200, 150, startwidth + 22, commonData->bgcolor);
|
||||
epd->fillCircle(200, 150, startwidth + 20, commonData->fgcolor); // 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 - M_PI/2);
|
||||
int y2 = y0 + 50*sin(value1 - M_PI/2);
|
||||
getdisplay().fillTriangle(x0, y0, x1, y1, x2, y2, commonData->bgcolor); // Clear half top side of boat circle (right triangle)
|
||||
x1 = x0 + 50*cos(value1 + M_PI);
|
||||
y1 = y0 + 50*sin(value1 + M_PI);
|
||||
getdisplay().fillTriangle(x0, y0, x1, y1, x2, y2, commonData->bgcolor); // Clear half top side of boat circle (left triangle)
|
||||
getdisplay().fillRect(150, 160, 100, 4, commonData->fgcolor); // Water line
|
||||
int x2 = x0 + 50*cos(value1 - pi/2);
|
||||
int y2 = y0 + 50*sin(value1 - pi/2);
|
||||
epd->fillTriangle(x0, y0, x1, y1, x2, y2, commonData->bgcolor); // Clear half top side of boat circle (right triangle)
|
||||
x1 = x0 + 50*cos(value1 + pi);
|
||||
y1 = y0 + 50*sin(value1 + pi);
|
||||
epd->fillTriangle(x0, y0, x1, y1, x2, y2, commonData->bgcolor); // Clear half top side of boat circle (left triangle)
|
||||
epd->fillRect(150, 160, 100, 4, commonData->fgcolor); // Water line
|
||||
|
||||
// Draw roll pointer
|
||||
startwidth = 4; // Start width of pointer
|
||||
@@ -283,7 +284,7 @@ public:
|
||||
float xx2 = startwidth;
|
||||
float yy1 = -startwidth;
|
||||
float yy2 = -(rInstrument - 15);
|
||||
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
// Inverted pointer
|
||||
@@ -293,15 +294,15 @@ public:
|
||||
float ix2 = -endwidth;
|
||||
float iy1 = -(rInstrument - 15);
|
||||
float iy2 = -endwidth;
|
||||
getdisplay().fillTriangle(200+(int)(cosx*ix1-sinx*iy1),150+(int)(sinx*ix1+cosx*iy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
}
|
||||
else{
|
||||
// Print sensor info
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(145, 200);
|
||||
getdisplay().print("No sensor data"); // Info missing sensor
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(145, 200);
|
||||
epd->print("No sensor data"); // Info missing sensor
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
#include "BoatDataCalibration.h"
|
||||
#endif
|
||||
|
||||
class PageRudderPosition : public Page
|
||||
{
|
||||
private:
|
||||
String lengthformat;
|
||||
|
||||
public:
|
||||
PageRudderPosition(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Show PageRudderPosition");
|
||||
PageRudderPosition(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageRudderPosition");
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key) {
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -21,68 +32,64 @@ public:
|
||||
return key;
|
||||
}
|
||||
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(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);
|
||||
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
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||
|
||||
if (valid1 == true) {
|
||||
value1old = value1; // Save old value
|
||||
unit1old = unit1; // Save old unit
|
||||
} else {
|
||||
if (simulation == true) {
|
||||
value1 = (3 + float(random(0, 50)) / 10.0)/360*2*PI;
|
||||
value1 = (3 + float(random(0, 50)) / 10.0) / 360 * 2 * M_PI;
|
||||
unit1 = "Deg";
|
||||
}
|
||||
else{
|
||||
} 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 PAGE_OK; // WTF why this statement?
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageRudderPosition, %s:%f", name1.c_str(), value1);
|
||||
// Log boat values
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageRudderPosition, %s:%f", name1.c_str(), value1);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
//*******************************************************************************************
|
||||
|
||||
// Draw RudderPosition
|
||||
int rInstrument = 110; // Radius of RudderPosition
|
||||
float pi = 3.141592;
|
||||
const float pi = 3.141592;
|
||||
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
getdisplay().fillRect(0, 30, 400, 122, commonData->bgcolor); // Delete half top circle
|
||||
epd->fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
epd->fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
epd->fillRect(0, 30, 400, 122, commonData->bgcolor); // Delete half top circle
|
||||
|
||||
for(int i=90; i<=270; i=i+10)
|
||||
{
|
||||
@@ -90,8 +97,7 @@ public:
|
||||
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)
|
||||
{
|
||||
switch (i) {
|
||||
case 0: ii=" "; break; // Use a blank for a empty scale value
|
||||
case 30 : ii=" "; break;
|
||||
case 60 : ii=" "; break;
|
||||
@@ -110,17 +116,17 @@ public:
|
||||
// Print text centered on position x, y
|
||||
int16_t x1, y1; // Return values of getTextBounds
|
||||
uint16_t w, h; // Return values of getTextBounds
|
||||
displayGetTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
getdisplay().setCursor(x-w/2, y+h/2);
|
||||
epd->getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
epd->setCursor(x-w/2, y+h/2);
|
||||
if(i % 30 == 0){
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().print(ii);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->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, commonData->fgcolor);
|
||||
epd->fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor);
|
||||
float sinx=sin(i/180.0*pi);
|
||||
float cosx=cos(i/180.0*pi);
|
||||
|
||||
@@ -131,10 +137,10 @@ public:
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
}
|
||||
@@ -142,28 +148,28 @@ public:
|
||||
}
|
||||
|
||||
// Print label
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(80, 70);
|
||||
getdisplay().print("Rudder Position"); // Label
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->setCursor(80, 70);
|
||||
epd->print("Rudder Position"); // Label
|
||||
|
||||
// Print Unit in RudderPosition
|
||||
if(valid1 == true || simulation == true){
|
||||
if(holdvalues == false){
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(175, 110);
|
||||
getdisplay().print(unit1); // Unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(175, 110);
|
||||
epd->print(unit1); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(175, 110);
|
||||
getdisplay().print(unit1old); // Unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(175, 110);
|
||||
epd->print(unit1old); // Unit
|
||||
}
|
||||
}
|
||||
else{
|
||||
// Print Unit of keel position
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(145, 110);
|
||||
getdisplay().print("No sensor data"); // Info missing sensor
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(145, 110);
|
||||
epd->print("No sensor data"); // Info missing sensor
|
||||
}
|
||||
|
||||
// Calculate rudder position
|
||||
@@ -186,7 +192,7 @@ public:
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
// Inverted pointer
|
||||
@@ -196,14 +202,14 @@ public:
|
||||
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),
|
||||
epd->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),commonData->fgcolor);
|
||||
}
|
||||
|
||||
// Center circle
|
||||
getdisplay().fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
||||
getdisplay().fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
||||
epd->fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
||||
epd->fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
|
||||
@@ -1,49 +1,30 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
class PageSixValues : public Page {
|
||||
private:
|
||||
GwLog* logger;
|
||||
GwConfigHandler* config;
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
#include "BoatDataCalibration.h"
|
||||
#endif
|
||||
|
||||
bool holdValues;
|
||||
String flashLED;
|
||||
String backlightMode;
|
||||
bool smallDecimals;
|
||||
const int SixValues_x1 = 5;
|
||||
const int SixValues_DeltaX = 200;
|
||||
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
const int SixValues_y1 = 23;
|
||||
const int SixValues_DeltaY = 83;
|
||||
|
||||
static constexpr int SixValues_x1 = 5;
|
||||
static constexpr int SixValues_DeltaX = 200;
|
||||
static constexpr int SixValues_y1 = 22;
|
||||
static constexpr int SixValues_DeltaY = 83;
|
||||
const int HowManyValues = 6;
|
||||
|
||||
static constexpr int HowManyValues = 6;
|
||||
// Old values for hold function
|
||||
String OldDataText[HowManyValues] = { "", "", "", "", "", "" };
|
||||
String OldDataUnit[HowManyValues] = { "", "", "", "", "", "" };
|
||||
|
||||
public:
|
||||
PageSixValues(CommonData& common)
|
||||
class PageSixValues : public Page
|
||||
{
|
||||
commonData = &common;
|
||||
config = commonData->config;
|
||||
logger = commonData->logger;
|
||||
LOG_DEBUG(GwLog::LOG, "Instantiate PageSixValues");
|
||||
|
||||
// Get config data
|
||||
holdValues = config->getBool(config->holdvalues);
|
||||
flashLED = config->getString(config->flashLED);
|
||||
backlightMode = config->getString(config->backlight);
|
||||
smallDecimals = config->getBool(config->smallDecimals);
|
||||
public:
|
||||
PageSixValues(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageSixValues");
|
||||
}
|
||||
|
||||
virtual int handleKey(int key)
|
||||
{
|
||||
int handleKey(int key) {
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -52,106 +33,134 @@ public:
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData& pageData)
|
||||
{
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
// Old values for hold function
|
||||
static String OldDataText[HowManyValues] = {"", "", "", "", "", ""};
|
||||
static String OldDataUnits[HowManyValues] = {"", "", "", "", "", ""};
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
// bool simulation = config->getBool(config->useSimuData);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
|
||||
GwApi::BoatValue *bvalue;
|
||||
String DataName[HowManyValues];
|
||||
double DataValue[HowManyValues];
|
||||
bool DataValid[HowManyValues];
|
||||
String DataText[HowManyValues];
|
||||
String DataUnit[HowManyValues];
|
||||
String DataUnits[HowManyValues];
|
||||
String DataFormat[HowManyValues];
|
||||
int8_t DsegFontSize = 0;
|
||||
|
||||
for (int i = 0; i < HowManyValues; i++){
|
||||
bvalue = pageData.values[i];
|
||||
DataName[i] = xdrDelete(bvalue->getName());
|
||||
DataName[i] = DataName[i].substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
DataValue[i] = bvalue->value; // Value as double in SI unit
|
||||
DataValid[i] = bvalue->valid;
|
||||
DataText[i] = formatValue(bvalue, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
DataUnit[i] = formatValue(bvalue, *commonData).unit;
|
||||
DataText[i] = commonData->fmt->formatValue(bvalue, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
DataUnits[i] = commonData->fmt->formatValue(bvalue, *commonData).unit;
|
||||
DataFormat[i] = bvalue->getFormat(); // Unit of value
|
||||
}
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Optical warning by limit violation (unused)
|
||||
if (String(flashLED) == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
if (bvalue == NULL)
|
||||
return PAGE_OK;
|
||||
if (bvalue == NULL) return PAGE_OK; // WTF why this statement?
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().setTextWrap(false);
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
for (int i = 0; i < ( HowManyValues / 2 ); i++) {
|
||||
if (i < (HowManyValues / 2) - 1) { // Don't draw horizontal line after last line of values
|
||||
// Horizontal line 3 px
|
||||
getdisplay().fillRect(0, SixValues_y1 + (i + 1) * SixValues_DeltaY, 400, 3, commonData->fgcolor);
|
||||
if (i < (HowManyValues / 2) - 1) { // Don't draw horizontal line after last line of values -> standard design
|
||||
// Horizontal line 3 pix
|
||||
epd->fillRect(0, SixValues_y1+(i+1)*SixValues_DeltaY, 400, 3, commonData->fgcolor);
|
||||
}
|
||||
|
||||
for (int j = 0; j < 2; j++) {
|
||||
int ValueIndex = i * 2 + j;
|
||||
int x0 = SixValues_x1 + j * SixValues_DeltaX;
|
||||
int y0 = SixValues_y1 + i * SixValues_DeltaY;
|
||||
//LOG_DEBUG(GwLog::DEBUG, "Drawing at PageSixValue: %d %s %f %s %s", ValueIndex, DataName[ValueIndex],
|
||||
// DataValue[ValueIndex], DataUnit[ValueIndex], DataFormat[ValueIndex]);
|
||||
LOG_DEBUG(GwLog::LOG, "Drawing at PageSixValue: %d %s %f %s", ValueIndex, DataName[ValueIndex], DataValue[ValueIndex], DataFormat[ValueIndex]);
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(x0, y0 + 25);
|
||||
getdisplay().print(DataName[ValueIndex]); // Page name
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(x0, y0+25);
|
||||
epd->print(DataName[ValueIndex]); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
if (holdValues == false) {
|
||||
drawTextRalign(x0 + 187, y0 + 19, DataUnit[ValueIndex]); // Unit
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(x0, y0+72);
|
||||
if (holdvalues == false) {
|
||||
epd->print(DataUnits[ValueIndex]); // Unit
|
||||
} else {
|
||||
drawTextRalign(x0 + 187, y0 + 19, OldDataUnit[ValueIndex]);
|
||||
epd->print(OldDataUnits[ValueIndex]);
|
||||
}
|
||||
|
||||
// Set font size depending on data type
|
||||
// Switch font if format for any values
|
||||
if (DataFormat[ValueIndex] == "formatLatitude" || DataFormat[ValueIndex] == "formatLongitude") {
|
||||
DsegFontSize = 12;
|
||||
} else if (DataFormat[ValueIndex] == "formatTime" || DataFormat[ValueIndex] == "formatDate") {
|
||||
DsegFontSize = 16;
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(x0+10, y0+60);
|
||||
}
|
||||
else if (DataFormat[ValueIndex] == "formatXdr:T:R") { // RPM
|
||||
DsegFontSize = 20;
|
||||
else if (DataFormat[ValueIndex] == "formatTime" || DataFormat[ValueIndex] == "formatDate") {
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->setCursor(x0+20,y0+55);
|
||||
}
|
||||
// pressure in hPa
|
||||
else if (DataFormat[ValueIndex] == "formatXdr:P:P") {
|
||||
epd->setFont(&DSEG7Classic_BoldItalic26pt7b);
|
||||
epd->setCursor(x0+5, y0+70);
|
||||
}
|
||||
// RPM
|
||||
else if (DataFormat[ValueIndex] == "formatXdr:T:R") {
|
||||
epd->setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||
epd->setCursor(x0+25, y0+70);
|
||||
}
|
||||
else {
|
||||
DsegFontSize = 26;
|
||||
}
|
||||
|
||||
// Show bus data value
|
||||
if (holdValues == false) {
|
||||
printBoatValue(DataText[ValueIndex], x0 + 187, y0 + 79, RIGHT, DsegFontSize, smallDecimals);
|
||||
epd->setFont(&DSEG7Classic_BoldItalic26pt7b);
|
||||
if (DataText[ValueIndex][0] == '-' ) {
|
||||
epd->setCursor(x0+25, y0+70);
|
||||
} else {
|
||||
printBoatValue(OldDataText[ValueIndex], x0 + 187, y0 + 79, RIGHT, DsegFontSize, smallDecimals);
|
||||
epd->setCursor(x0+65, y0+70);
|
||||
}
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if (holdvalues == false) {
|
||||
epd->print(DataText[ValueIndex]); // Real value as formated string
|
||||
} else{
|
||||
epd->print(OldDataText[ValueIndex]); // Old value as formated string
|
||||
}
|
||||
if (DataValid[ValueIndex] == true) {
|
||||
OldDataText[ValueIndex] = DataText[ValueIndex]; // Save the old value
|
||||
OldDataUnit[ValueIndex] = DataUnit[ValueIndex]; // Save the old unit
|
||||
}
|
||||
}
|
||||
// Vertical line 3 px
|
||||
getdisplay().fillRect(SixValues_x1 + SixValues_DeltaX - 8, SixValues_y1 + i * SixValues_DeltaY, 3, SixValues_DeltaY, commonData->fgcolor);
|
||||
OldDataUnits[ValueIndex] = DataUnits[ValueIndex]; // Save the old unit
|
||||
}
|
||||
} // for j
|
||||
// Vertical line 3 pix
|
||||
epd->fillRect(SixValues_x1+SixValues_DeltaX-8, SixValues_y1+i*SixValues_DeltaY, 3, SixValues_DeltaY, commonData->fgcolor);
|
||||
} // for i
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
|
||||
};
|
||||
static Page* createPage(CommonData& common)
|
||||
{
|
||||
|
||||
static Page *createPage(CommonData &common){
|
||||
return new PageSixValues(common);
|
||||
}/**
|
||||
* with the code below we make this page known to the PageTask
|
||||
|
||||
@@ -14,20 +14,15 @@
|
||||
class PageSkyView : public Page
|
||||
{
|
||||
private:
|
||||
String flashLED;
|
||||
GwBoatData *bd;
|
||||
|
||||
public:
|
||||
PageSkyView(CommonData &common)
|
||||
PageSkyView(CommonData &common) : Page(common)
|
||||
{
|
||||
commonData = &common;
|
||||
|
||||
// task name access is for example purpose only
|
||||
TaskHandle_t currentTaskHandle = xTaskGetCurrentTaskHandle();
|
||||
const char* taskName = pcTaskGetName(currentTaskHandle);
|
||||
common.logger->logDebug(GwLog::LOG, "Instantiate PageSkyView in task '%s'", taskName);
|
||||
|
||||
flashLED = common.config->getString(common.config->flashLED);
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageSkyView in task '%s'", taskName);
|
||||
}
|
||||
|
||||
int handleKey(int key) {
|
||||
@@ -57,7 +52,6 @@ public:
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
std::vector<GwSatInfo> sats;
|
||||
int nSat = bd->SatInfo->getNumSats();
|
||||
@@ -73,111 +67,109 @@ public:
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
// current position
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
|
||||
|
||||
GwApi::BoatValue *bv_lat = pageData.values[0];
|
||||
String sv_lat = commonData->fmt->formatValue(bv_lat, *commonData).svalue;
|
||||
//epd->setCursor(300, 40);
|
||||
//epd->print(sv_lat);
|
||||
|
||||
GwApi::BoatValue *bv_lon = pageData.values[1];
|
||||
String sv_lon = commonData->fmt->formatValue(bv_lon, *commonData).svalue;
|
||||
//epd->setCursor(300, 60);
|
||||
//epd->print(sv_lon);
|
||||
|
||||
GwApi::BoatValue *bv_hdop = pageData.values[2];
|
||||
String sv_hdop = commonData->fmt->formatValue(bv_hdop, *commonData).svalue;
|
||||
//epd->setCursor(300, 80);
|
||||
//epd->print(sv_hdop);
|
||||
|
||||
// sky view
|
||||
Point c = {130, 148};
|
||||
uint16_t r = 120;
|
||||
uint16_t r = 125;
|
||||
uint16_t r1 = r / 2;
|
||||
|
||||
getdisplay().fillCircle(c.x, c.y, r + 2, commonData->fgcolor);
|
||||
getdisplay().fillCircle(c.x, c.y, r - 1, commonData->bgcolor);
|
||||
getdisplay().drawCircle(c.x, c.y, r1, commonData->fgcolor);
|
||||
epd->fillCircle(c.x, c.y, r, commonData->bgcolor);
|
||||
epd->drawCircle(c.x, c.y, r + 1, commonData->fgcolor);
|
||||
epd->drawCircle(c.x, c.y, r + 2, commonData->fgcolor);
|
||||
epd->drawCircle(c.x, c.y, r1, commonData->fgcolor);
|
||||
|
||||
// separation lines
|
||||
getdisplay().drawLine(c.x - r, c.y, c.x + r, c.y, commonData->fgcolor);
|
||||
getdisplay().drawLine(c.x, c.y - r, c.x, c.y + r, commonData->fgcolor);
|
||||
epd->drawLine(c.x - r, c.y, c.x + r, c.y, commonData->fgcolor);
|
||||
epd->drawLine(c.x, c.y - r, c.x, c.y + r, commonData->fgcolor);
|
||||
Point p = {c.x, c.y - r};
|
||||
Point p1, p2;
|
||||
p1 = rotatePoint(c, p, 45);
|
||||
p2 = rotatePoint(c, p, 45 + 180);
|
||||
getdisplay().drawLine(p1.x, p1.y, p2.x, p2.y, commonData->fgcolor);
|
||||
epd->drawLine(p1.x, p1.y, p2.x, p2.y, commonData->fgcolor);
|
||||
p1 = rotatePoint(c, p, -45);
|
||||
p2 = rotatePoint(c, p, -45 + 180);
|
||||
getdisplay().drawLine(p1.x, p1.y, p2.x, p2.y, commonData->fgcolor);
|
||||
epd->drawLine(p1.x, p1.y, p2.x, p2.y, commonData->fgcolor);
|
||||
|
||||
// directions
|
||||
|
||||
int16_t x1, y1;
|
||||
uint16_t w, h;
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
|
||||
displayGetTextBounds("N", 0, 150, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(c.x - w / 2, c.y - r + h + 3);
|
||||
getdisplay().print("N");
|
||||
epd->getTextBounds("N", 0, 150, &x1, &y1, &w, &h);
|
||||
epd->setCursor(c.x - w / 2, c.y - r + h + 2);
|
||||
epd->print("N");
|
||||
|
||||
displayGetTextBounds("S", 0, 150, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(c.x - w / 2, c.y + r - 3);
|
||||
getdisplay().print("S");
|
||||
epd->getTextBounds("S", 0, 150, &x1, &y1, &w, &h);
|
||||
epd->setCursor(c.x - w / 2, c.y + r - 2);
|
||||
epd->print("S");
|
||||
|
||||
displayGetTextBounds("E", 0, 150, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(c.x + r - w - 3, c.y + h / 2);
|
||||
getdisplay().print("E");
|
||||
epd->getTextBounds("E", 0, 150, &x1, &y1, &w, &h);
|
||||
epd->setCursor(c.x + r - w - 2, c.y + h / 2);
|
||||
epd->print("E");
|
||||
|
||||
displayGetTextBounds("W", 0, 150, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(c.x - r + 3 , c.y + h / 2);
|
||||
getdisplay().print("W");
|
||||
epd->getTextBounds("W", 0, 150, &x1, &y1, &w, &h);
|
||||
epd->setCursor(c.x - r + 2 , c.y + h / 2);
|
||||
epd->print("W");
|
||||
|
||||
// show satellites in "map"
|
||||
getdisplay().setFont(&IBM8x8px);
|
||||
epd->setFont(&Atari6px);
|
||||
for (int i = 0; i < nSat; i++) {
|
||||
float arad = (sats[i].Azimut * M_PI / 180.0) + M_PI;
|
||||
float arad = sats[i].Azimut * M_PI / 180.0;
|
||||
float erad = sats[i].Elevation * M_PI / 180.0;
|
||||
uint16_t x = c.x + sin(arad) * erad * r1;
|
||||
uint16_t y = c.y + cos(arad) * erad * r1;
|
||||
getdisplay().fillRect(x-4, y-4, 8, 8, commonData->fgcolor);
|
||||
getdisplay().setCursor(x-7, y+12);
|
||||
getdisplay().printf("%02d", static_cast<int>(sats[i].PRN));
|
||||
uint16_t x = c.x + sin(arad) * erad * r;
|
||||
uint16_t y = c.y + cos(arad) * erad * r;
|
||||
epd->drawRect(x-4, y-4, 8, 8, commonData->fgcolor);
|
||||
// Add Sat number
|
||||
epd->setCursor(x+5, y);
|
||||
char buffer[3];
|
||||
snprintf(buffer, 3, "%02d", static_cast<int>(sats[i].PRN));
|
||||
epd->print(String(buffer));
|
||||
}
|
||||
|
||||
// Signal / Noise bars
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(325, 34);
|
||||
getdisplay().print("SNR");
|
||||
// getdisplay().drawRect(270, 20, 125, 257, commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(325, 34);
|
||||
epd->print("SNR");
|
||||
epd->drawRect(270, 20, 125, 257, commonData->fgcolor);
|
||||
int maxsat = std::min(nSat, 12);
|
||||
for (int i = 0; i < maxsat; i++) {
|
||||
uint16_t y = 29 + (i + 1) * 20;
|
||||
getdisplay().setCursor(276, y);
|
||||
epd->setCursor(276, y);
|
||||
char buffer[3];
|
||||
snprintf(buffer, 3, "%02d", static_cast<int>(sats[i].PRN));
|
||||
getdisplay().print(String(buffer));
|
||||
getdisplay().drawRect(305, y-12, 85, 14, commonData->fgcolor);
|
||||
getdisplay().setCursor(315, y);
|
||||
epd->print(String(buffer));
|
||||
epd->drawRect(305, y-12, 85, 14, commonData->fgcolor);
|
||||
epd->setCursor(315, y);
|
||||
// TODO SNR as number or as bar via mode key?
|
||||
if (sats[i].SNR <= 100) {
|
||||
// getdisplay().print(sats[i].SNR);
|
||||
getdisplay().fillRect(307, y-10, int(81 * sats[i].SNR / 100.0), 10, commonData->fgcolor);
|
||||
// epd->print(sats[i].SNR);
|
||||
epd->fillRect(307, y-10, int(81 * sats[i].SNR / 100.0), 10, commonData->fgcolor);
|
||||
} else {
|
||||
getdisplay().print("n/a");
|
||||
epd->print("n/a");
|
||||
}
|
||||
}
|
||||
|
||||
// Show SatInfo and HDOP
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
|
||||
getdisplay().setCursor(220, 34);
|
||||
getdisplay().print("Sat:");
|
||||
|
||||
GwApi::BoatValue *bv_satinfo = pageData.values[0]; // SatInfo
|
||||
String sval_satinfo = formatValue(bv_satinfo, *commonData).svalue;
|
||||
getdisplay().setCursor(220, 49);
|
||||
getdisplay().print(sval_satinfo);
|
||||
|
||||
getdisplay().setCursor(220, 254);
|
||||
getdisplay().print("HDOP:");
|
||||
|
||||
GwApi::BoatValue *bv_hdop = pageData.values[1]; // HDOP
|
||||
double hdop = formatValue(bv_hdop, *commonData).value * 4; // 4 is factor for UERE (translation in meter)
|
||||
char sval_hdop[20];
|
||||
dtostrf(hdop, 0, 1, sval_hdop); // Only one prefix
|
||||
strcat(sval_hdop, "m");
|
||||
getdisplay().setCursor(220, 269);
|
||||
getdisplay().print(sval_hdop);
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
@@ -197,7 +189,7 @@ PageDescription registerPageSkyView(
|
||||
"SkyView", // Page name
|
||||
createPage, // Action
|
||||
0, // Number of bus values depends on selection in Web configuration
|
||||
{"SatInfo", "HDOP"}, // Bus values we need in the page
|
||||
{"LAT", "LON", "HDOP"}, // Bus values we need in the page
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
|
||||
+117
-86
@@ -1,20 +1,29 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "movingAvg.h" // Lib for moving average building
|
||||
|
||||
class PageSolar : public Page
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
private:
|
||||
String batVoltage;
|
||||
int solPower;
|
||||
String powerSensor;
|
||||
|
||||
public:
|
||||
PageSolar(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageSolar");
|
||||
PageSolar(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageSolar");
|
||||
|
||||
// Get config data
|
||||
String batVoltage = config->getString(config->batteryVoltage);
|
||||
int solPower = config->getInt(config->solarPower);
|
||||
String powerSensor = config->getString(config->usePowSensor2);
|
||||
}
|
||||
virtual int handleKey(int key){
|
||||
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -24,18 +33,6 @@ public:
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Get config data
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
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);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
double value1 = 0; // Solar voltage
|
||||
double value2 = 0; // Solar current
|
||||
@@ -63,122 +60,156 @@ public:
|
||||
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"){
|
||||
if (flashLED == "Limit Violation") {
|
||||
// Over voltage?
|
||||
if (batVoltage == "12V") {
|
||||
setBlinkingLED(value1 > 14.8);
|
||||
} else if (batVoltage == "24V") {
|
||||
setBlinkingLED(value1 > 29.6);
|
||||
} else {
|
||||
setBlinkingLED(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Logging voltage value
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageSolar, Type:%iW %s:=%f", solPower, name1.c_str(), value1);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageSolar, Type:%iW %s:=%f", solPower, name1.c_str(), value1);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(10, 65);
|
||||
getdisplay().print("Solar");
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(10, 65);
|
||||
epd->print("Solar");
|
||||
|
||||
// Show voltage type
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 140);
|
||||
int bvoltage = 0;
|
||||
if(String(batVoltage) == "12V") bvoltage = 12;
|
||||
else bvoltage = 24;
|
||||
printBoatValue(String(bvoltage), 10, 140, LEFT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("V");
|
||||
epd->print(bvoltage);
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("V");
|
||||
|
||||
// Show solar power
|
||||
String svalueSolPower = (solPower <= 999) ? String(solPower) : String(float(solPower/1000.0), 1);
|
||||
printBoatValue(svalueSolPower, 10, 200, LEFT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
if(solPower <= 999) getdisplay().print("W");
|
||||
if(solPower > 999) getdisplay().print("kW");
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 200);
|
||||
if(solPower <= 999) epd->print(solPower, 0);
|
||||
if(solPower > 999) epd->print(float(solPower/1000.0), 1);
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
if(solPower <= 999) epd->print("W");
|
||||
if(solPower > 999) epd->print("kW");
|
||||
|
||||
// Show info
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 235);
|
||||
getdisplay().print("Installed");
|
||||
getdisplay().setCursor(10, 255);
|
||||
getdisplay().print("Solar Modul");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 235);
|
||||
epd->print("Installed");
|
||||
epd->setCursor(10, 255);
|
||||
epd->print("Solar Modul");
|
||||
|
||||
// Show solar panel
|
||||
solarGraphic(150, 45, commonData->fgcolor, commonData->bgcolor);
|
||||
|
||||
// Show load level in percent
|
||||
printBoatValue(String(solPercentage), 150, 200, LEFT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("%");
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(150, 235);
|
||||
getdisplay().print("Load");
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(150, 200);
|
||||
epd->print(solPercentage);
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("%");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(150, 235);
|
||||
epd->print("Load");
|
||||
|
||||
// Show sensor type info
|
||||
String i2cAddr = "";
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(270, 60);
|
||||
if(powerSensor == "off") getdisplay().print("Internal");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(270, 60);
|
||||
if(powerSensor == "off") epd->print("Internal");
|
||||
if(powerSensor == "INA219"){
|
||||
getdisplay().print("INA219");
|
||||
epd->print("INA219");
|
||||
i2cAddr = " (0x" + String(INA219_I2C_ADDR2, HEX) + ")";
|
||||
}
|
||||
if(powerSensor == "INA226"){
|
||||
getdisplay().print("INA226");
|
||||
epd->print("INA226");
|
||||
i2cAddr = " (0x" + String(INA226_I2C_ADDR2, HEX) + ")";
|
||||
}
|
||||
getdisplay().print(i2cAddr);
|
||||
getdisplay().setCursor(270, 80);
|
||||
getdisplay().print("Sensor Modul");
|
||||
epd->print(i2cAddr);
|
||||
epd->setCursor(270, 80);
|
||||
epd->print("Sensor Modul");
|
||||
|
||||
// Reading bus data or using simulation data
|
||||
String svalue1;
|
||||
if(valid1 == true || holdvalues == true){
|
||||
svalue1 = formatValue(value1, String("formatXdr:U:V"), *commonData);
|
||||
} else {
|
||||
svalue1 = "---"; // Missing bus data
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(260, 140);
|
||||
if(simulation == true){
|
||||
if(batVoltage == "12V"){
|
||||
value1 = 12.0;
|
||||
}
|
||||
printBoatValue(svalue1, 355, 140, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("V");
|
||||
if(batVoltage == "24V"){
|
||||
value1 = 24.0;
|
||||
}
|
||||
value1 += float(random(0, 5)) / 10; // Simulation data
|
||||
epd->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) {
|
||||
epd->print(value1, 2);
|
||||
} else if (value1 <= 99.9) {
|
||||
epd->print(value1, 1);
|
||||
} else {
|
||||
epd->print(value1, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
epd->print(commonData->fmt->placeholder); // Missing bus data
|
||||
}
|
||||
}
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("V");
|
||||
|
||||
// Show actual current in A
|
||||
String svalue2;
|
||||
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
|
||||
svalue2 = formatValue(value2, String("formatXdr:I:A"), *commonData);
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(260, 200);
|
||||
if ((powerSensor == "INA219" || powerSensor == "INA226") && (simulation == false)) {
|
||||
if (value2 <= 9.9) {
|
||||
epd->print(value2, 2);
|
||||
} else if (value2 <= 99.9) {
|
||||
epd->print(value2, 1);
|
||||
} else {
|
||||
epd->print(value2, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
svalue2 = "---";
|
||||
epd->print(commonData->fmt->placeholder);
|
||||
}
|
||||
printBoatValue(svalue2, 355, 200, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("A");
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("A");
|
||||
|
||||
// Show actual consumption in W
|
||||
String svalue3;
|
||||
if((powerSensor == "INA219" || powerSensor == "INA226") && simulation == false){
|
||||
svalue3 = formatValue(value3, String("formatXdr:G:"), *commonData);
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(260, 260);
|
||||
if ((powerSensor == "INA219" || powerSensor == "INA226") && (simulation == false)) {
|
||||
if (value3 <= 9.9) {
|
||||
epd->print(value3, 2);
|
||||
} else if (value3 <= 99.9) {
|
||||
epd->print(value3, 1);
|
||||
} else {
|
||||
epd->print(value3, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
svalue3 = "---";
|
||||
epd->print(commonData->fmt->placeholder);
|
||||
}
|
||||
printBoatValue(svalue3, 355, 260, RIGHT, 20, smallDecimals);
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().print("W");
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->print("W");
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
|
||||
+394
-382
File diff suppressed because it is too large
Load Diff
@@ -1,22 +1,28 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
#include "BoatDataCalibration.h"
|
||||
#endif
|
||||
|
||||
class PageThreeValues : public Page
|
||||
{
|
||||
private:
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
String lengthformat;
|
||||
|
||||
public:
|
||||
PageThreeValues(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageThreeValue");
|
||||
PageThreeValues(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageThreeValue");
|
||||
|
||||
// Get config data
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -25,12 +31,17 @@ class PageThreeValues : public Page
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int valueX, valueY;
|
||||
int DsegFontSize;
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
// Old values for hold function
|
||||
static String svalue1old = "";
|
||||
@@ -40,94 +51,92 @@ class PageThreeValues : public Page
|
||||
static String svalue3old = "";
|
||||
static String unit3old = "";
|
||||
|
||||
// Get config data
|
||||
// bool simulation = config->getBool(config->useSimuData);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
// 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
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values #2
|
||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list
|
||||
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
||||
name2 = name2.substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue2 = commonData->fmt->formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit2 = commonData->fmt->formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values #3
|
||||
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Third element in list
|
||||
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
||||
name3 = name3.substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue3, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue3 = commonData->fmt->formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit3 = commonData->fmt->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 PAGE_OK; // WTF why this statement?
|
||||
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);
|
||||
// Log boat values
|
||||
logger->logDebug(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 display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
// ############### Value 1 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 55);
|
||||
getdisplay().print(name1); // Page name
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 55);
|
||||
epd->print(name1); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 90);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 90);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit1); // Unit
|
||||
epd->print(unit1); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit1old);
|
||||
epd->print(unit1old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
valueX = 380;
|
||||
if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){
|
||||
valueY = 90;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(50, 90);
|
||||
}
|
||||
else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){
|
||||
valueY = 80;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(170, 68);
|
||||
}
|
||||
else{
|
||||
valueY = 90;
|
||||
DsegFontSize = 30;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 90);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue1, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue1); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue1old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
epd->print(svalue1old); // Old value as formated string
|
||||
}
|
||||
if(valid1 == true){
|
||||
svalue1old = svalue1; // Save the old value
|
||||
@@ -137,51 +146,45 @@ class PageThreeValues : public Page
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 105, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 105, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 2 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 145);
|
||||
getdisplay().print(name2); // Page name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 145);
|
||||
epd->print(name2); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 180);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 180);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit2); // Unit
|
||||
epd->print(unit2); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit2old);
|
||||
epd->print(unit2old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){
|
||||
valueY = 180;
|
||||
DsegFontSize = 20;
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(50, 180);
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(50, 180);
|
||||
}
|
||||
else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){
|
||||
valueY = 170;
|
||||
DsegFontSize = 20;
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(170, 158);
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(170, 158);
|
||||
}
|
||||
else{
|
||||
valueY = 180;
|
||||
DsegFontSize = 30;
|
||||
getdisplay().setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
getdisplay().setCursor(180, 180);
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 180);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue2, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue2); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue2old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue2old); // Old value as formated string
|
||||
}
|
||||
if(valid2 == true){
|
||||
svalue2old = svalue2; // Save the old value
|
||||
@@ -191,45 +194,45 @@ class PageThreeValues : public Page
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
getdisplay().fillRect(0, 195, 400, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 195, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 3 ################
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 235);
|
||||
getdisplay().print(name3); // Page name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 235);
|
||||
epd->print(name3); // Page name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 270);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 270);
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit3); // Unit
|
||||
epd->print(unit3); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit3old);
|
||||
epd->print(unit3old);
|
||||
}
|
||||
|
||||
// Switch font if format for any values
|
||||
if(bvalue3->getFormat() == "formatLatitude" || bvalue3->getFormat() == "formatLongitude"){
|
||||
valueY = 270;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(50, 270);
|
||||
}
|
||||
else if(bvalue3->getFormat() == "formatTime" || bvalue3->getFormat() == "formatDate"){
|
||||
valueY = 260;
|
||||
DsegFontSize = 20;
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(170, 248);
|
||||
}
|
||||
else{
|
||||
valueY = 270;
|
||||
DsegFontSize = 30;
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
epd->setCursor(180, 270);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
printBoatValue(svalue3, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue3); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
printBoatValue(svalue3old, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
epd->print(svalue3old); // Old value as formated string
|
||||
}
|
||||
if(valid3 == true){
|
||||
svalue3old = svalue3; // Save the old value
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
/*
|
||||
Tracker
|
||||
- standalone with SD card backend
|
||||
- standalone with server backend
|
||||
- Regatta Hero integration
|
||||
*/
|
||||
|
||||
class PageTracker : public Page
|
||||
{
|
||||
private:
|
||||
|
||||
char mode = 'N'; // (N)ormal, (C)onfig
|
||||
|
||||
void displayModeNormal(PageData &pageData) {
|
||||
|
||||
// TBD Boatvalues: ...
|
||||
|
||||
logger->logDebug(GwLog::DEBUG,"Drawing at PageTracker");
|
||||
|
||||
// Title
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 48);
|
||||
epd->print("Tracker");
|
||||
|
||||
}
|
||||
|
||||
void displayModeConfig() {
|
||||
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 48);
|
||||
epd->print("Tracker configuration");
|
||||
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
// TODO
|
||||
|
||||
}
|
||||
|
||||
public:
|
||||
PageTracker(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageTracker");
|
||||
}
|
||||
|
||||
void setupKeys(){
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "START";
|
||||
commonData->keydata[1].label = "STOP";
|
||||
}
|
||||
|
||||
int handleKey(int key){
|
||||
if (key == 1) { // Switch between normal and config mode
|
||||
if (mode == 'N') {
|
||||
mode = 'C';
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 11) {
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
|
||||
// Logging boat values
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageTracker; Mode=%c", mode);
|
||||
|
||||
// Set display in partial refresh mode
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height());
|
||||
|
||||
if (mode == 'N') {
|
||||
displayModeNormal(pageData);
|
||||
} else if (mode == 'C') {
|
||||
displayModeConfig();
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page *createPage(CommonData &common){
|
||||
return new PageTracker(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 registerPageTracker(
|
||||
"Tracker", // Page name
|
||||
createPage, // Action
|
||||
0, // Number of bus values depends on selection in Web configuration
|
||||
{"LAT", "LON"}, // Names of bus values undepends on selection in Web configuration (refer GwBoatData.h)
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
#endif
|
||||
+128
-273
@@ -1,227 +1,37 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "OBPDataOperations.h"
|
||||
#include "OBPcharts.h"
|
||||
|
||||
class PageTwoValues : public Page {
|
||||
private:
|
||||
GwLog* logger;
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
#include "BoatDataCalibration.h"
|
||||
#endif
|
||||
|
||||
enum PageMode {
|
||||
VALUES,
|
||||
VAL1_CHART,
|
||||
VAL2_CHART,
|
||||
CHARTS
|
||||
};
|
||||
enum DisplayMode {
|
||||
FULL,
|
||||
HALF
|
||||
};
|
||||
|
||||
static constexpr int YOFFSET = 130; // y offset for display of 2nd boat value
|
||||
|
||||
int width; // Screen width
|
||||
int height; // Screen height
|
||||
|
||||
bool keylock = false; // Keylock
|
||||
PageMode pageMode = VALUES; // Page display mode
|
||||
int8_t dataIntv = 1; // Update interval for wind history chart:
|
||||
// (1)|(2)|(3)|(4)|(8) x 240 seconds for 4, 8, 12, 16, 32 min. history chart
|
||||
|
||||
// String lengthformat;
|
||||
bool useSimuData;
|
||||
bool holdValues;
|
||||
String flashLED;
|
||||
bool smallDecimals;
|
||||
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
|
||||
// Data buffer pointer (owned by HstryBuffers)
|
||||
static constexpr int NUMVALUES = 2; // two data values in this page
|
||||
RingBuffer<uint16_t>* dataHstryBuf[NUMVALUES] = { nullptr };
|
||||
std::unique_ptr<Chart> dataChart[NUMVALUES]; // Chart object
|
||||
|
||||
// Old values for hold function
|
||||
String sValueOld[NUMVALUES] = { "", "" };
|
||||
String unitOld[NUMVALUES] = { "", "" };
|
||||
|
||||
// display data values in display <mode> [FULL|HALF]
|
||||
void showData(const std::vector<GwApi::BoatValue*>& bValue, DisplayMode mode)
|
||||
class PageTwoValues : public Page
|
||||
{
|
||||
int valueX, valueY;
|
||||
int DsegFontSize;
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
int numValues = bValue.size(); // do we have to handle 1 or 2 values?
|
||||
|
||||
for (int i = 0; i < numValues; i++) {
|
||||
int yOffset = YOFFSET * i;
|
||||
String name = xdrDelete(bValue[i]->getName()); // Value name
|
||||
name = name.substring(0, 6); // String length limit for value name
|
||||
double value = bValue[i]->value; // Value as double in SI unit
|
||||
bool valid = bValue[i]->valid; // Valid information
|
||||
String sValue = formatValue(bValue[i], *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit = formatValue(bValue[i], *commonData).unit; // Unit of value
|
||||
|
||||
// Show name
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 75 + yOffset);
|
||||
getdisplay().print(name); // name
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(20, 125 + yOffset);
|
||||
|
||||
if (holdValues) {
|
||||
getdisplay().print(unitOld[i]); // name
|
||||
} else {
|
||||
getdisplay().print(unit); // name
|
||||
}
|
||||
|
||||
// Switch font depending on value format and adjust position
|
||||
valueX = 380;
|
||||
if (bValue[i]->getFormat() == "formatLatitude" || bValue[i]->getFormat() == "formatLongitude") {
|
||||
valueY = 125 + yOffset;
|
||||
DsegFontSize = 20;
|
||||
} else if (bValue[i]->getFormat() == "formatTime" || bValue[i]->getFormat() == "formatDate") {
|
||||
valueY = 105 + yOffset;
|
||||
DsegFontSize = 20;
|
||||
} else { // Default font for other formats
|
||||
valueY = 125 + yOffset;
|
||||
DsegFontSize = 42;
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if (!holdValues || useSimuData) {
|
||||
printBoatValue(sValue, valueX, valueY, RIGHT, DsegFontSize, smallDecimals);
|
||||
} else {
|
||||
printBoatValue(sValueOld[i], valueX, valueY, RIGHT, DsegFontSize, smallDecimals);
|
||||
}
|
||||
|
||||
if (valid == true) {
|
||||
sValueOld[i] = sValue; // Save the old value
|
||||
unitOld[i] = unit; // Save the old unit
|
||||
}
|
||||
}
|
||||
|
||||
if (numValues == 2 && mode == FULL) { // print line only, if we want to show 2 data values
|
||||
getdisplay().fillRect(0, 145, width, 3, commonData->fgcolor); // Horizontal line 3 pix
|
||||
}
|
||||
}
|
||||
private:
|
||||
String lengthformat;
|
||||
|
||||
public:
|
||||
PageTwoValues(CommonData& common)
|
||||
PageTwoValues(CommonData &common) : Page(common)
|
||||
{
|
||||
commonData = &common;
|
||||
logger = commonData->logger;
|
||||
LOG_DEBUG(GwLog::LOG, "Instantiate PageTwoValues");
|
||||
|
||||
width = getdisplay().width(); // Screen width
|
||||
height = getdisplay().height(); // Screen height
|
||||
getdisplay().setTextWrap(false);
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageTwoValue");
|
||||
|
||||
// Get config data
|
||||
useSimuData = commonData->config->getBool(commonData->config->useSimuData);
|
||||
holdValues = commonData->config->getBool(commonData->config->holdvalues);
|
||||
flashLED = commonData->config->getString(commonData->config->flashLED);
|
||||
smallDecimals = commonData->config->getBool(commonData->config->smallDecimals);
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
}
|
||||
|
||||
virtual void setupKeys()
|
||||
{
|
||||
Page::setupKeys();
|
||||
|
||||
#if defined BOARD_OBP60S3
|
||||
constexpr int ZOOM_KEY = 4;
|
||||
#elif defined BOARD_OBP40S3
|
||||
constexpr int ZOOM_KEY = 1;
|
||||
#endif
|
||||
|
||||
if (dataHstryBuf[0] || dataHstryBuf[1]) { // show "Mode" key only if at least 1 chart supported boat data type is available
|
||||
commonData->keydata[0].label = "MODE";
|
||||
if (pageMode != VALUES) { // show "ZOOM" key only if chart is visible
|
||||
commonData->keydata[ZOOM_KEY].label = "ZOOM";
|
||||
} else {
|
||||
commonData->keydata[ZOOM_KEY].label = "";
|
||||
}
|
||||
} else {
|
||||
commonData->keydata[0].label = "";
|
||||
commonData->keydata[ZOOM_KEY].label = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key)
|
||||
{
|
||||
if (dataHstryBuf[0] || dataHstryBuf[1]) { // if at least 1 boat data type supports charts
|
||||
|
||||
// Set page mode: value | value/half chart | full charts
|
||||
if (key == 1) {
|
||||
switch (pageMode) {
|
||||
|
||||
case VALUES:
|
||||
|
||||
if (dataHstryBuf[0]) {
|
||||
pageMode = VAL1_CHART;
|
||||
} else if (dataHstryBuf[1]) {
|
||||
pageMode = VAL2_CHART;
|
||||
}
|
||||
break;
|
||||
|
||||
case VAL1_CHART:
|
||||
|
||||
if (dataHstryBuf[1]) {
|
||||
pageMode = VAL2_CHART;
|
||||
} else {
|
||||
pageMode = CHARTS;
|
||||
}
|
||||
break;
|
||||
|
||||
case VAL2_CHART:
|
||||
pageMode = CHARTS;
|
||||
break;
|
||||
|
||||
case CHARTS:
|
||||
pageMode = VALUES;
|
||||
break;
|
||||
}
|
||||
setupKeys(); // Adjust key definition depending on <pageMode> and chart-supported boat data type
|
||||
return 0; // Commit the key
|
||||
}
|
||||
|
||||
// Set time frame to show for chart
|
||||
#if defined BOARD_OBP60S3
|
||||
if (key == 5 && pageMode != VALUES) {
|
||||
#elif defined BOARD_OBP40S3
|
||||
if (key == 2 && pageMode != VALUES) {
|
||||
#endif
|
||||
if (dataIntv == 1) {
|
||||
dataIntv = 2;
|
||||
} else if (dataIntv == 2) {
|
||||
dataIntv = 3;
|
||||
} else if (dataIntv == 3) {
|
||||
dataIntv = 4;
|
||||
} else {
|
||||
dataIntv = 1;
|
||||
}
|
||||
return 0; // Commit the key
|
||||
}
|
||||
}
|
||||
|
||||
// Keylock function
|
||||
if (key == 11) { // Code for keylock
|
||||
int handleKey(int key){
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0; // Commit the key
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
virtual void displayNew(PageData& pageData)
|
||||
{
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
@@ -229,105 +39,150 @@ public:
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
// buffer initialization will fail, if page is default page, because <displayNew> is not executed at system start for default page
|
||||
for (int i = 0; i < NUMVALUES; i++) {
|
||||
if (!dataChart[i]) { // Create chart objects if they don't exist
|
||||
};
|
||||
|
||||
GwApi::BoatValue* bValue = pageData.values[i]; // Page boat data element
|
||||
String bValName = bValue->getName(); // Value name
|
||||
String bValFormat = bValue->getFormat(); // Value format
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
dataHstryBuf[i] = pageData.hstryBuffers->getBuffer(bValName);
|
||||
// Old values for hold function
|
||||
static String svalue1old = "";
|
||||
static String unit1old = "";
|
||||
static String svalue2old = "";
|
||||
static String unit2old = "";
|
||||
|
||||
if (dataHstryBuf[i]) {
|
||||
dataChart[i].reset(new Chart(*dataHstryBuf[i], *commonData, useSimuData));
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageTwoValues: Created chart object %d for %s", i, bValName.c_str());
|
||||
} else {
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageTwoValues: No chart object available for %s", bValName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setupKeys(); // Adjust key definition depending on <pageMode> and chart-supported boat data type
|
||||
}
|
||||
|
||||
int displayPage(PageData& pageData)
|
||||
{
|
||||
LOG_DEBUG(GwLog::LOG, "Display PageTwoValues");
|
||||
|
||||
// Get boat values for page
|
||||
std::vector<GwApi::BoatValue*> bValue;
|
||||
bValue.push_back(pageData.values[0]); // Page boat data element 1
|
||||
bValue.push_back(pageData.values[1]); // Page boat data element 2
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Optical warning by limit violation (unused)
|
||||
if (String(flashLED) == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
// 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
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
if (bValue[0] == NULL && bValue[1] == NULL)
|
||||
return PAGE_OK; // no data, no page to display
|
||||
double value1 = bvalue1->value; // Value as double in SI unit
|
||||
bool valid1 = bvalue1->valid; // Valid information
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageTwoValues: printing #1: %s, %.3f, #2: %s, %.3f",
|
||||
bValue[0]->getName().c_str(), bValue[0]->value, bValue[1]->getName().c_str(), bValue[1]->value);
|
||||
// Get boat values #2
|
||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list
|
||||
String name2 = xdrDelete(bvalue2->getName()); // Value name
|
||||
name2 = name2.substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
double value2 = bvalue2->value; // Value as double in SI unit
|
||||
bool valid2 = bvalue2->valid; // Valid information
|
||||
String svalue2 = commonData->fmt->formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit2 = commonData->fmt->formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageTwoValues, %s: %f, %s: %f", name1.c_str(), value1, name2.c_str(), value2);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
displaySetPartialWindow(0, 0, width, height); // Set partial update
|
||||
// Set display in partial refresh mode
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
for (int i = 0; i < NUMVALUES; i++) {
|
||||
if (dataChart[i]) { // Check only if dataChart object exists at all
|
||||
if (!dataChart[i]->isValid()) {
|
||||
dataChart[i]->init(); // try late initialization if chart object could not be properly initialized earlier due to missing boat data
|
||||
}
|
||||
// ############### Value 1 ################
|
||||
|
||||
// Show name
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 80);
|
||||
epd->print(name1); // Page name
|
||||
|
||||
// Show unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 130);
|
||||
if(holdvalues == false){
|
||||
epd->print(unit1); // Unit
|
||||
}
|
||||
else{
|
||||
epd->print(unit1old);
|
||||
}
|
||||
|
||||
if (pageMode == VALUES || (dataChart[0] == nullptr && dataChart[1] == nullptr)) {
|
||||
// show only data value; ignore other pageMode options if no chart supported boat data history buffer is available
|
||||
showData(bValue, FULL);
|
||||
|
||||
} else if (pageMode == VAL1_CHART) { // show data value 1 and chart
|
||||
showData({ bValue[0] }, HALF);
|
||||
if (dataChart[0]) {
|
||||
dataChart[0]->showChrt(Chart::HORIZONTAL, Chart::HALF_SIZE_RIGHT_BOTTOM, dataIntv, Chart::NO_PRNT_NAME, Chart::NO_PRNT_VALUE, *bValue[0]);
|
||||
// Switch font if format for any values
|
||||
if(bvalue1->getFormat() == "formatLatitude" || bvalue1->getFormat() == "formatLongitude"){
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(50, 130);
|
||||
}
|
||||
else if(bvalue1->getFormat() == "formatTime" || bvalue1->getFormat() == "formatDate"){
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(170, 105);
|
||||
}
|
||||
else{
|
||||
epd->setFont(&DSEG7Classic_BoldItalic42pt7b);
|
||||
epd->setCursor(180, 130);
|
||||
}
|
||||
|
||||
} else if (pageMode == VAL2_CHART) { // show data value 2 and chart
|
||||
showData({ bValue[1] }, HALF);
|
||||
if (dataChart[1]) {
|
||||
dataChart[1]->showChrt(Chart::HORIZONTAL, Chart::HALF_SIZE_RIGHT_BOTTOM, dataIntv, Chart::NO_PRNT_NAME, Chart::NO_PRNT_VALUE, *bValue[1]);
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
epd->print(svalue1); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
epd->print(svalue1old); // Old value as formated string
|
||||
}
|
||||
if(valid1 == true){
|
||||
svalue1old = svalue1; // Save the old value
|
||||
unit1old = unit1; // Save the old unit
|
||||
}
|
||||
|
||||
} else if (pageMode == CHARTS) { // show both data charts
|
||||
if (dataChart[0]) {
|
||||
if (dataChart[1]) {
|
||||
dataChart[0]->showChrt(Chart::HORIZONTAL, Chart::HALF_SIZE_LEFT_TOP, dataIntv, Chart::PRNT_NAME, Chart::PRNT_VALUE, *bValue[0]);
|
||||
} else {
|
||||
dataChart[0]->showChrt(Chart::HORIZONTAL, Chart::FULL_SIZE, dataIntv, Chart::PRNT_NAME, Chart::PRNT_VALUE, *bValue[0]);
|
||||
// ############### Horizontal Line ################
|
||||
|
||||
// Horizontal line 3 pix
|
||||
epd->fillRect(0, 145, 400, 3, commonData->fgcolor);
|
||||
|
||||
// ############### Value 2 ################
|
||||
|
||||
// Show name
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 190);
|
||||
epd->print(name2); // Page name
|
||||
|
||||
// Show unit
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(20, 240);
|
||||
if(holdvalues == false){
|
||||
epd->print(unit2); // Unit
|
||||
}
|
||||
else{
|
||||
epd->print(unit2old);
|
||||
}
|
||||
if (dataChart[1]) {
|
||||
if (dataChart[0]) {
|
||||
dataChart[1]->showChrt(Chart::HORIZONTAL, Chart::HALF_SIZE_RIGHT_BOTTOM, dataIntv, Chart::PRNT_NAME, Chart::PRNT_VALUE, *bValue[1]);
|
||||
} else {
|
||||
dataChart[1]->showChrt(Chart::HORIZONTAL, Chart::FULL_SIZE, dataIntv, Chart::PRNT_NAME, Chart::PRNT_VALUE, *bValue[1]);
|
||||
|
||||
// Switch font if format for any values
|
||||
if(bvalue2->getFormat() == "formatLatitude" || bvalue2->getFormat() == "formatLongitude"){
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(50, 240);
|
||||
}
|
||||
else if(bvalue2->getFormat() == "formatTime" || bvalue2->getFormat() == "formatDate"){
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(170, 215);
|
||||
}
|
||||
else{
|
||||
epd->setFont(&DSEG7Classic_BoldItalic42pt7b);
|
||||
epd->setCursor(180, 240);
|
||||
}
|
||||
|
||||
// Show bus data
|
||||
if(holdvalues == false){
|
||||
epd->print(svalue2); // Real value as formated string
|
||||
}
|
||||
else{
|
||||
epd->print(svalue2old); // Old value as formated string
|
||||
}
|
||||
if(valid2 == true){
|
||||
svalue2old = svalue2; // Save the old value
|
||||
unit2old = unit2; // Save the old unit
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page* createPage(CommonData& common)
|
||||
{
|
||||
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
|
||||
|
||||
+113
-107
@@ -1,24 +1,30 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "movingAvg.h" // Lib for moving average building
|
||||
|
||||
class PageVoltage : public Page
|
||||
{
|
||||
private:
|
||||
String batVoltage;
|
||||
String batType;
|
||||
bool init = false; // Marker for init done
|
||||
uint8_t 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;
|
||||
char mode = 'D'; // display mode (A)nalog | (D)igital
|
||||
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
|
||||
public:
|
||||
PageVoltage(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageVoltage");
|
||||
PageVoltage(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageVoltage");
|
||||
|
||||
// Get config data
|
||||
batVoltage = config->getString(config->batteryVoltage);
|
||||
batType = config->getString(config->batteryType);
|
||||
|
||||
if (hasFRAM) {
|
||||
average = fram.read(FRAM_VOLTAGE_AVG);
|
||||
trend = fram.read(FRAM_VOLTAGE_TREND);
|
||||
@@ -26,14 +32,18 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setupKeys(){
|
||||
~PageVoltage(){
|
||||
logger->logDebug(GwLog::LOG, "Destroy PageVoltage");
|
||||
}
|
||||
|
||||
void setupKeys() {
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "AVG";
|
||||
commonData->keydata[1].label = "MODE";
|
||||
commonData->keydata[4].label = "TRD";
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key) {
|
||||
// Change average
|
||||
if(key == 1){
|
||||
average ++;
|
||||
@@ -69,55 +79,43 @@ public:
|
||||
}
|
||||
|
||||
void printAvg(int avg, uint16_t x, uint16_t y, bool prefix) {
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(x, y);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(x, y);
|
||||
if (prefix) {
|
||||
getdisplay().print("Avg: ");
|
||||
epd->print("Avg: ");
|
||||
}
|
||||
switch (average) {
|
||||
case 0:
|
||||
getdisplay().print("1s");
|
||||
epd->print("1s");
|
||||
break;
|
||||
case 1:
|
||||
getdisplay().print("10s");
|
||||
epd->print("10s");
|
||||
break;
|
||||
case 2:
|
||||
getdisplay().print("60s");
|
||||
epd->print("60s");
|
||||
break;
|
||||
case 3:
|
||||
getdisplay().print("300s");
|
||||
epd->print("300s");
|
||||
break;
|
||||
default:
|
||||
getdisplay().print("1s");
|
||||
epd->print("1s");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void printVoltageSymbol(uint16_t x, uint16_t y, uint16_t color) {
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt8b);
|
||||
getdisplay().setCursor(x, y);
|
||||
getdisplay().print("V");
|
||||
getdisplay().fillRect(x, y + 6, 22, 3, color);
|
||||
getdisplay().fillRect(x, y + 11, 6, 3, color);
|
||||
getdisplay().fillRect(x + 8, y + 11, 6, 3, color);
|
||||
getdisplay().fillRect(x + 16, y + 11, 6, 3, color);
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
epd->setCursor(x, y);
|
||||
epd->print("V");
|
||||
epd->fillRect(x, y + 6, 22, 3, color);
|
||||
epd->fillRect(x, y + 11, 6, 3, color);
|
||||
epd->fillRect(x + 8, y + 11, 6, 3, color);
|
||||
epd->fillRect(x + 16, y + 11, 6, 3, color);
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Get config data
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
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);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
double value1 = 0;
|
||||
String svalue = "---";
|
||||
double valueTrend = 0; // Average over 10 values
|
||||
|
||||
// Get voltage value
|
||||
@@ -156,100 +154,108 @@ public:
|
||||
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)){
|
||||
if (flashLED == "Limit Violation") {
|
||||
bool violation = false;
|
||||
if (batType == "Pb") {
|
||||
violation = (raw < 11.8 || raw > 14.8);
|
||||
} else if (batType == "Gel") {
|
||||
violation = (raw < 11.8 || raw > 14.4);
|
||||
} else if (batType == "AGM") {
|
||||
violation = (raw < 11.8 || raw > 14.7);
|
||||
} else if (batType == "LiFePo4") {
|
||||
violation = (raw < 12.0 || raw > 14.6);
|
||||
}
|
||||
if (violation) {
|
||||
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)){
|
||||
} else {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Logging voltage value
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageVoltage, Type:%s %s:=%f", batType, name1.c_str(), raw);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageVoltage, Type:%s %s:=%f", batType, name1.c_str(), raw);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
if (mode == 'D') {
|
||||
// Display mode digital
|
||||
|
||||
// Show name
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold32pt8b);
|
||||
getdisplay().setCursor(20, 100);
|
||||
getdisplay().print(name1); // Value name
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold32pt8b);
|
||||
epd->setCursor(20, 100);
|
||||
epd->print(name1); // Value name
|
||||
|
||||
#if defined BOARD_OBP40S3 && defined LIPO_ACCU_1200 && defined VOLTAGE_SENSOR
|
||||
// Show charge status
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(185, 100);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(185, 100);
|
||||
if(commonData->data.BatteryChargeStatus == true){
|
||||
getdisplay().print("Charge");
|
||||
epd->print("Charge");
|
||||
}
|
||||
else{
|
||||
getdisplay().print("Discharge");
|
||||
epd->print("Discharge");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(270, 100);
|
||||
getdisplay().print("V");
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(270, 100);
|
||||
epd->print("V");
|
||||
|
||||
// Show battery type
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(295, 100);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(295, 100);
|
||||
#ifdef BOARD_OBP60S3
|
||||
getdisplay().print(batType);
|
||||
epd->print(batType);
|
||||
#endif
|
||||
#if defined BOARD_OBP40S3 && defined LIPO_ACCU_1200 && defined VOLTAGE_SENSOR
|
||||
getdisplay().print("LiPo");
|
||||
epd->print("LiPo");
|
||||
#endif
|
||||
|
||||
// Show average settings
|
||||
printAvg(average, 320, 84, true);
|
||||
|
||||
// Reading bus data or using simulation data
|
||||
if(valid1 == true || holdvalues == true){
|
||||
svalue = formatValue(value1, String("formatXdr:U:V"), *commonData);
|
||||
} else {
|
||||
svalue = "---"; // Missing bus data
|
||||
epd->setFont(&DSEG7Classic_BoldItalic60pt7b);
|
||||
epd->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
|
||||
epd->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){
|
||||
epd->print(value1,2);
|
||||
}
|
||||
if(value1 >= 10 && value1 < 100){
|
||||
epd->print(value1,1);
|
||||
}
|
||||
if(value1 >= 100){
|
||||
epd->print(value1,0);
|
||||
}
|
||||
}
|
||||
else{
|
||||
epd->print(commonData->fmt->placeholder); // Missing bus data
|
||||
}
|
||||
}
|
||||
printBoatValue(svalue, 300, 240, RIGHT, 60, smallDecimals);
|
||||
|
||||
// Show trend indicator
|
||||
if(trend == true){
|
||||
getdisplay().fillRect(315, 183, 35, 4, commonData->fgcolor); // Draw separator
|
||||
epd->fillRect(315, 183, 35, 4, commonData->fgcolor); // Draw separator
|
||||
if(int(raw * 10) > int(valueTrend * 10)){
|
||||
displayTrendHigh(320, 174, 11, commonData->fgcolor); // Show high indicator
|
||||
}
|
||||
@@ -270,9 +276,9 @@ public:
|
||||
std::vector<Point> pts;
|
||||
|
||||
// Instrument
|
||||
getdisplay().drawCircleHelper(c.x, c.y, r + 2, 0x01, commonData->fgcolor);
|
||||
getdisplay().drawCircleHelper(c.x, c.y, r + 1, 0x01, commonData->fgcolor);
|
||||
getdisplay().drawCircleHelper(c.x, c.y, r , 0x01, commonData->fgcolor);
|
||||
epd->drawCircleHelper(c.x, c.y, r + 2, 0x01, commonData->fgcolor);
|
||||
epd->drawCircleHelper(c.x, c.y, r + 1, 0x01, commonData->fgcolor);
|
||||
epd->drawCircleHelper(c.x, c.y, r , 0x01, commonData->fgcolor);
|
||||
|
||||
// Scale
|
||||
// angle to voltage scale mapping
|
||||
@@ -285,7 +291,7 @@ public:
|
||||
{c.x - r + 12, c.y + 1},
|
||||
{c.x - r, c.y + 1}
|
||||
};
|
||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
||||
epd->setFont(&Ubuntu_Bold10pt8b);
|
||||
for (int angle = 3; angle < 90; angle += 3) {
|
||||
if (angle % 15 == 0) {
|
||||
fillPoly4(rotatePoints(c, pts, angle), commonData->fgcolor);
|
||||
@@ -295,7 +301,7 @@ public:
|
||||
else {
|
||||
p1 = rotatePoint(c, {c.x - r, c.y}, angle);
|
||||
p2 = rotatePoint(c, {c.x - r + 6, c.y}, angle);
|
||||
getdisplay().drawLine(p1.x, p1.y, p2.x, p2.y, commonData->fgcolor);
|
||||
epd->drawLine(p1.x, p1.y, p2.x, p2.y, commonData->fgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,31 +341,31 @@ public:
|
||||
fillPoly4(rotatePoints(c, pts, angle), commonData->fgcolor);
|
||||
|
||||
// base
|
||||
getdisplay().fillCircle(c.x, c.y, 7, commonData->fgcolor);
|
||||
getdisplay().fillCircle(c.x, c.y, 4, commonData->bgcolor);
|
||||
epd->fillCircle(c.x, c.y, 7, commonData->fgcolor);
|
||||
epd->fillCircle(c.x, c.y, 4, commonData->bgcolor);
|
||||
|
||||
// Symbol
|
||||
printVoltageSymbol(40, 60, commonData->fgcolor);
|
||||
|
||||
// Additional information at right side
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(300, 60);
|
||||
getdisplay().print("Source:");
|
||||
getdisplay().setCursor(300, 80);
|
||||
getdisplay().print(name1);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(300, 60);
|
||||
epd->print("Source:");
|
||||
epd->setCursor(300, 80);
|
||||
epd->print(name1);
|
||||
|
||||
getdisplay().setCursor(300, 110);
|
||||
getdisplay().print("Type:");
|
||||
getdisplay().setCursor(300, 130);
|
||||
getdisplay().print(batType);
|
||||
epd->setCursor(300, 110);
|
||||
epd->print("Type:");
|
||||
epd->setCursor(300, 130);
|
||||
epd->print(batType);
|
||||
|
||||
getdisplay().setCursor(300, 160);
|
||||
getdisplay().print("Avg:");
|
||||
epd->setCursor(300, 160);
|
||||
epd->print("Avg:");
|
||||
printAvg(average, 300, 180, false);
|
||||
|
||||
// FRAM indicator
|
||||
if (hasFRAM) {
|
||||
getdisplay().drawXBitmap(300, 240, fram_bits, icon_width, icon_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(300, 240, fram_bits, icon_width, icon_height, commonData->fgcolor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,280 +0,0 @@
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "OBPDataOperations.h"
|
||||
#include "OBPcharts.h"
|
||||
|
||||
class PageWeather : public Page {
|
||||
private:
|
||||
GwLog* logger;
|
||||
|
||||
enum PageMode {
|
||||
VAL_CHART,
|
||||
CHART
|
||||
};
|
||||
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
|
||||
static constexpr int XOFFSET = 133; // x offset for display of boat values
|
||||
|
||||
int width; // Screen width
|
||||
int height; // Screen height
|
||||
|
||||
bool keylock = false; // Keylock
|
||||
PageMode pageMode = VAL_CHART; // Page display mode
|
||||
int8_t dataIntv = 1; // Update interval for barograph history chart:
|
||||
// (1)|(3)|(6)|(12)|(24) x 60 min. for 1, 3, 6, 12, 24 hours history chart
|
||||
|
||||
// String lengthformat;
|
||||
bool useSimuData;
|
||||
bool holdValues;
|
||||
String flashLED;
|
||||
bool smallDecimals;
|
||||
|
||||
static constexpr int NUMVALUES = 4; // number of boat values used on this page
|
||||
static constexpr int NUMCHARTS = 1; // one data buffer used on this page
|
||||
|
||||
// Data buffer pointer (owned by HstryBuffers)
|
||||
RingBuffer<uint16_t>* dataHstryBuf[NUMCHARTS] = { nullptr };
|
||||
std::unique_ptr<Chart> dataChart[NUMCHARTS]; // Chart object
|
||||
|
||||
// Old values for hold function
|
||||
String sValueOld[NUMVALUES] = { "", "", "", "" };
|
||||
String unitOld[NUMVALUES] = { "", "", "", "" };
|
||||
|
||||
// display data values in display mode <HALF>
|
||||
void showData(const std::vector<GwApi::BoatValue*>& bValue)
|
||||
{
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
|
||||
int numValues = bValue.size(); // How many values do we have to handle? We will ignore value no. 1
|
||||
|
||||
for (int i = 1; i < numValues; i++) {
|
||||
String name = xdrDelete(bValue[i]->getName()); // Value name
|
||||
name = name.substring(0, 7); // String length limit for value name
|
||||
double value = bValue[i]->value; // Value as double in SI unit
|
||||
bool valid = bValue[i]->valid; // Valid information
|
||||
String sValue = formatValue(bValue[i], *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit = formatValue(bValue[i], *commonData).unit; // Unit of value
|
||||
|
||||
int xOffset = XOFFSET * (i - 1);
|
||||
|
||||
// Print name
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(5 + xOffset, 213);
|
||||
getdisplay().print(name); // name
|
||||
|
||||
// Print unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(5 + xOffset, 229);
|
||||
if (holdValues) {
|
||||
getdisplay().print(unitOld[i]); // name
|
||||
} else {
|
||||
getdisplay().print(unit); // name
|
||||
}
|
||||
|
||||
// Print value
|
||||
int valueX = XOFFSET * i - 5;
|
||||
int valueY = 275;
|
||||
int DsegFontSize = 20;
|
||||
if (!holdValues || useSimuData) {
|
||||
printBoatValue(sValue, valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Real value as formated string
|
||||
} else {
|
||||
printBoatValue(sValueOld[i], valueX, valueY, RIGHT, DsegFontSize, smallDecimals); // Old value as formated string
|
||||
}
|
||||
|
||||
if (valid) { // Save value for hold function
|
||||
sValueOld[i] = sValue;
|
||||
unitOld[i] = unit;
|
||||
}
|
||||
}
|
||||
|
||||
// print lines for data separation of bottom data values
|
||||
getdisplay().fillRect(0, 191, 400, 2, commonData->fgcolor); // horizontal line
|
||||
getdisplay().fillRect(133, 192, 2, 84, commonData->fgcolor); // vertical lines
|
||||
getdisplay().fillRect(266, 192, 2, 84, commonData->fgcolor);
|
||||
}
|
||||
|
||||
public:
|
||||
PageWeather(CommonData& common)
|
||||
{
|
||||
commonData = &common;
|
||||
logger = commonData->logger;
|
||||
LOG_DEBUG(GwLog::LOG, "Instantiate PageWeather");
|
||||
|
||||
width = getdisplay().width(); // Screen width
|
||||
height = getdisplay().height(); // Screen height
|
||||
|
||||
// Get config data
|
||||
useSimuData = commonData->config->getBool(commonData->config->useSimuData);
|
||||
holdValues = commonData->config->getBool(commonData->config->holdvalues);
|
||||
flashLED = commonData->config->getString(commonData->config->flashLED);
|
||||
smallDecimals = commonData->config->getBool(commonData->config->smallDecimals);
|
||||
}
|
||||
|
||||
virtual void setupKeys()
|
||||
{
|
||||
Page::setupKeys();
|
||||
|
||||
#if defined BOARD_OBP60S3
|
||||
constexpr int ZOOM_KEY = 4;
|
||||
#elif defined BOARD_OBP40S3
|
||||
constexpr int ZOOM_KEY = 1;
|
||||
#endif
|
||||
|
||||
if (dataHstryBuf) { // show "Mode" key only if chart-supported boat data type is available
|
||||
commonData->keydata[0].label = "MODE";
|
||||
commonData->keydata[ZOOM_KEY].label = "ZOOM";
|
||||
} else {
|
||||
commonData->keydata[0].label = "";
|
||||
commonData->keydata[ZOOM_KEY].label = "";
|
||||
}
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key)
|
||||
{
|
||||
if (dataHstryBuf) { // if boat data type supports charts
|
||||
|
||||
// Set page mode: value/half chart | full chart
|
||||
if (key == 1) {
|
||||
switch (pageMode) {
|
||||
case VAL_CHART:
|
||||
pageMode = CHART;
|
||||
break;
|
||||
case CHART:
|
||||
pageMode = VAL_CHART;
|
||||
break;
|
||||
}
|
||||
setupKeys(); // Adjust key definition depending on <pageMode> and chart-supported boat data type
|
||||
return 0; // Commit the key
|
||||
}
|
||||
|
||||
// Set time frame to show for chart
|
||||
#if defined BOARD_OBP60S3
|
||||
if (key == 5) {
|
||||
#elif defined BOARD_OBP40S3
|
||||
if (key == 2) {
|
||||
#endif
|
||||
if (dataIntv == 1) {
|
||||
dataIntv = 2;
|
||||
} else if (dataIntv == 2) {
|
||||
dataIntv = 4;
|
||||
} else if (dataIntv == 4) {
|
||||
dataIntv = 8;
|
||||
} else if (dataIntv == 8) {
|
||||
dataIntv = 12;
|
||||
} else {
|
||||
dataIntv = 1;
|
||||
}
|
||||
return 0; // Commit the key
|
||||
}
|
||||
}
|
||||
|
||||
// Keylock function
|
||||
if (key == 11) { // Code for keylock
|
||||
commonData->keylock = !commonData->keylock;
|
||||
return 0; // Commit the key
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
virtual void displayNew(PageData& pageData)
|
||||
{
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < NUMCHARTS; i++) {
|
||||
if (!dataChart[i]) { // Create chart objects if they don't exist
|
||||
|
||||
GwApi::BoatValue* bValue = pageData.values[i]; // Page boat data element
|
||||
String bValName = bValue->getName(); // Value name
|
||||
String bValFormat = bValue->getFormat(); // Value format
|
||||
|
||||
dataHstryBuf[i] = pageData.hstryBuffers->getBuffer(bValName);
|
||||
|
||||
if (dataHstryBuf[i]) {
|
||||
dataChart[i].reset(new Chart(*dataHstryBuf[i], *commonData, useSimuData));
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageWeather: Created chart object %d for %s, format: %s", i, bValName.c_str(), dataHstryBuf[i]->getFormat().c_str());
|
||||
} else {
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageWeather: No chart object available for %s", bValName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int displayPage(PageData& pageData)
|
||||
{
|
||||
|
||||
LOG_DEBUG(GwLog::LOG, "Display PageWeather");
|
||||
|
||||
// Get latest boat values for page
|
||||
std::vector<GwApi::BoatValue*> bValue;
|
||||
for (int i = 0; i < NUMVALUES; i++) {
|
||||
bValue.push_back(pageData.values[i]);
|
||||
}
|
||||
|
||||
if (bValue[0] == NULL && bValue[1] == NULL && bValue[2] == NULL && bValue[3] == NULL) {
|
||||
return PAGE_OK; // no data, no page to display
|
||||
}
|
||||
if (dataHstryBuf == nullptr) { // no buffer for main boat data item, no page display
|
||||
return PAGE_OK;
|
||||
}
|
||||
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageWeather: printing #1: %s, %.3f, %s, #2: %s, %.3f, %s, #3: %s, %.3f, %s, #4: %s, %.3f, %s",
|
||||
bValue[0]->getName().c_str(), bValue[0]->value, bValue[0]->getFormat().c_str(), bValue[1]->getName().c_str(), bValue[1]->value, bValue[1]->getFormat().c_str(),
|
||||
bValue[2]->getName().c_str(), bValue[2]->value, bValue[2]->getFormat().c_str(), bValue[3]->getName().c_str(), bValue[3]->value, bValue[3]->getFormat().c_str());
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
displaySetPartialWindow(0, 0, width, height); // Set partial update
|
||||
|
||||
if (dataChart[0]) { // Check only if dataChart object exists at all
|
||||
if (!dataChart[0]->isValid()) {
|
||||
dataChart[0]->init(); // try late initialization if chart object could not be properly initialized earlier due to missing boat data
|
||||
}
|
||||
}
|
||||
|
||||
if (pageMode == VAL_CHART) {
|
||||
if (dataChart[0]) {
|
||||
dataChart[0]->showChrt(Chart::HORIZONTAL, Chart::TWO_THIRD_TOP, dataIntv, Chart::PRNT_NAME, Chart::PRNT_VALUE, *bValue[0]);
|
||||
}
|
||||
showData(bValue);
|
||||
|
||||
} else if (pageMode == CHART && dataChart[0]) { // show only data chart, but that has to exist
|
||||
dataChart[0]->showChrt(Chart::HORIZONTAL, Chart::FULL_SIZE, dataIntv, Chart::PRNT_NAME, Chart::PRNT_VALUE, *bValue[0]);
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page* createPage(CommonData& common)
|
||||
{
|
||||
return new PageWeather(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 registerPageWeather(
|
||||
"Weather", // Page name
|
||||
createPage, // Action
|
||||
4, // Number of bus values depends on selection in Web configuration (air baro pressure, air temperature, humidity, true wind speed)
|
||||
{ }, // Bus values we need in the page
|
||||
true // Show display header on/off
|
||||
);
|
||||
#endif
|
||||
+20
-19
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -13,16 +14,17 @@
|
||||
|
||||
class PageWhite : public Page
|
||||
{
|
||||
private:
|
||||
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");
|
||||
PageWhite(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageWhite");
|
||||
refreshtime = 15000;
|
||||
}
|
||||
|
||||
virtual int handleKey(int key) {
|
||||
int handleKey(int key) {
|
||||
// Change display mode
|
||||
if (key == 1) {
|
||||
if (mode == 'W') {
|
||||
@@ -37,21 +39,20 @@ public:
|
||||
return key;
|
||||
}
|
||||
|
||||
int 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"){
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
// Logging boat values
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageWhite");
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageWhite");
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
@@ -61,19 +62,19 @@ public:
|
||||
|
||||
// Set display in partial refresh mode
|
||||
if (mode == 'W') {
|
||||
getdisplay().setFullWindow();
|
||||
epd->setFullWindow();
|
||||
} else {
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
}
|
||||
|
||||
if (mode == 'L') {
|
||||
getdisplay().drawXBitmap(0, 0, OBP_400x300_bits, OBP_400x300_width, OBP_400x300_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(0, 0, OBP_400x300_bits, OBP_400x300_width, OBP_400x300_height, commonData->fgcolor);
|
||||
} else if (mode == 'M') {
|
||||
#ifdef BOARD_OBP60S3
|
||||
getdisplay().drawXBitmap(0, 0, OBP60_400x300_bits, OBP60_400x300_width, OBP60_400x300_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(0, 0, OBP60_400x300_bits, OBP60_400x300_width, OBP60_400x300_height, commonData->fgcolor);
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
getdisplay().drawXBitmap(0, 0, OBP40_400x300_bits, OBP40_400x300_width, OBP40_400x300_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(0, 0, OBP40_400x300_bits, OBP40_400x300_width, OBP40_400x300_height, commonData->fgcolor);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+99
-85
@@ -1,9 +1,14 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
#include "N2kMessages.h"
|
||||
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
#include "BoatDataCalibration.h"
|
||||
#endif
|
||||
|
||||
#define front_width 120
|
||||
#define front_height 162
|
||||
static unsigned char front_bits[] PROGMEM = {
|
||||
@@ -213,19 +218,21 @@ static unsigned char front_bits[] PROGMEM = {
|
||||
|
||||
class PageWind : public Page
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
|
||||
private:
|
||||
String lengthformat;
|
||||
bool keylock = false; // Keylock
|
||||
int8_t lp = 80; // Pointer length
|
||||
char mode = 'N'; // page mode (N)ormal | (L)ens | e(X)ample
|
||||
char source = 'A'; // data source (A)pparent | (T)rue
|
||||
|
||||
public:
|
||||
PageWind(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageWind");
|
||||
PageWind(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageWind");
|
||||
|
||||
// Get config data
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
|
||||
if (hasFRAM) {
|
||||
lp = fram.read(FRAM_WIND_SIZE);
|
||||
source = fram.read(FRAM_WIND_SRC);
|
||||
@@ -233,7 +240,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setupKeys(){
|
||||
void setupKeys() {
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "MODE";
|
||||
if (mode == 'X') {
|
||||
@@ -245,13 +252,13 @@ public:
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key) {
|
||||
|
||||
if(key == 1){ // Mode switch
|
||||
if(mode == 'N'){
|
||||
mode = 'L';
|
||||
// } else if (mode == 'L') {
|
||||
// mode = 'X';
|
||||
} else if (mode == 'L') {
|
||||
mode = 'X';
|
||||
} else {
|
||||
mode = 'N';
|
||||
}
|
||||
@@ -299,22 +306,23 @@ public:
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData)
|
||||
{
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
static String svalue1old = "";
|
||||
static String unit1old = "";
|
||||
static String svalue2old = "";
|
||||
static String unit2old = "";
|
||||
|
||||
// Get config data
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
GwApi::BoatValue *bvalue1; // Value 1 for speed on top
|
||||
GwApi::BoatValue *bvalue2; // Value 2 for angle on bottom
|
||||
|
||||
@@ -326,10 +334,13 @@ public:
|
||||
}
|
||||
String name1 = bvalue1->getName().c_str(); // Value name
|
||||
name1 = name1.substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||
|
||||
// Get boat values for angle (AWD/TWD)
|
||||
if (source == 'A') {
|
||||
@@ -339,73 +350,70 @@ public:
|
||||
}
|
||||
String name2 = bvalue2->getName().c_str(); // Value name
|
||||
name2 = name2.substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
double value2 = bvalue2->value; // Value as double in SI unit
|
||||
// bool valid2 = bvalue2->valid; // Valid information
|
||||
if (simulation) {
|
||||
value2 = 0.62731; // some random value
|
||||
}
|
||||
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);
|
||||
}
|
||||
String svalue2 = commonData->fmt->formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit2 = commonData->fmt->formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageWind, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageWind, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
|
||||
if (mode == 'X') {
|
||||
// Original example code with scaling circle
|
||||
|
||||
// Show values AWS/TWS
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 50);
|
||||
getdisplay().print(name1); // Value name
|
||||
getdisplay().print(": ");
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 50);
|
||||
epd->print(name1); // Value name
|
||||
epd->print(": ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(svalue1); // Value
|
||||
getdisplay().print(" ");
|
||||
getdisplay().print(unit1); // Unit
|
||||
epd->print(svalue1); // Value
|
||||
epd->print(" ");
|
||||
epd->print(unit1); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(svalue1old); // Value old
|
||||
getdisplay().print(" ");
|
||||
getdisplay().print(unit1old); // Unit old
|
||||
epd->print(svalue1old); // Value old
|
||||
epd->print(" ");
|
||||
epd->print(unit1old); // Unit old
|
||||
}
|
||||
|
||||
// Show values AWD/TWD
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(20, 260);
|
||||
getdisplay().print(name2); // Value name
|
||||
getdisplay().print(": ");
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(20, 260);
|
||||
epd->print(name2); // Value name
|
||||
epd->print(": ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(svalue2); // Value
|
||||
getdisplay().print(" ");
|
||||
getdisplay().print(unit2); // Unit
|
||||
epd->print(svalue2); // Value
|
||||
epd->print(" ");
|
||||
epd->print(unit2); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(svalue2old); // Value old
|
||||
getdisplay().print(" ");
|
||||
getdisplay().print(unit2old); // Unit old
|
||||
epd->print(svalue2old); // Value old
|
||||
epd->print(" ");
|
||||
epd->print(unit2old); // Unit old
|
||||
}
|
||||
|
||||
Point c = {200, 145};
|
||||
|
||||
// Draw instrument
|
||||
getdisplay().fillCircle(c.x, c.y, lp + 5, commonData->fgcolor);
|
||||
getdisplay().fillCircle(c.x, c.y, lp + 1, commonData->bgcolor);
|
||||
epd->fillCircle(c.x, c.y, lp + 5, commonData->fgcolor);
|
||||
epd->fillCircle(c.x, c.y, lp + 1, commonData->bgcolor);
|
||||
|
||||
// Wind pointer
|
||||
if (bvalue2->valid or simulation) {
|
||||
@@ -420,7 +428,7 @@ public:
|
||||
};
|
||||
fillPoly4(rotatePoints(c, pts, RadToDeg(value2)), commonData->fgcolor);
|
||||
} else {
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
drawTextCenter(c.x, c.y, "no data");
|
||||
}
|
||||
|
||||
@@ -438,7 +446,7 @@ public:
|
||||
};
|
||||
int angle;
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
|
||||
// starbord
|
||||
// text with line
|
||||
@@ -453,7 +461,7 @@ public:
|
||||
for (int i = 30; i < 138; i += 6) {
|
||||
if (i % 15 != 0) {
|
||||
p = rotatePoint(c, {c.x, c.y - r + 5}, i);
|
||||
getdisplay().fillCircle(p.x, p.y, 2, commonData->fgcolor);
|
||||
epd->fillCircle(p.x, p.y, 2, commonData->fgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -470,17 +478,17 @@ public:
|
||||
for (int i = 228; i < 330; i += 6) {
|
||||
if (i % 15 != 0) {
|
||||
p = rotatePoint(c, {c.x, c.y - r + 5}, i);
|
||||
getdisplay().fillCircle(p.x, p.y, 2, commonData->fgcolor);
|
||||
epd->fillCircle(p.x, p.y, 2, commonData->fgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
// data source
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 50);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 50);
|
||||
if (source == 'A') {
|
||||
getdisplay().print("APP");
|
||||
epd->print("APP");
|
||||
} else {
|
||||
getdisplay().print("TRUE");
|
||||
epd->print("TRUE");
|
||||
}
|
||||
|
||||
// Wind pointer (angle)
|
||||
@@ -500,7 +508,7 @@ public:
|
||||
alpha *= -1;
|
||||
}
|
||||
|
||||
getdisplay().fillCircle(c.x, c.y, 8, commonData->fgcolor);
|
||||
epd->fillCircle(c.x, c.y, 8, commonData->fgcolor);
|
||||
pts = {
|
||||
{c.x - 1, c.y - (r - 20)},
|
||||
{c.x + 1, c.y - (r - 20)},
|
||||
@@ -508,36 +516,39 @@ public:
|
||||
{c.x - 6, c.y + 15}
|
||||
};
|
||||
fillPoly4(rotatePoints(c, pts, alpha), commonData->fgcolor);
|
||||
getdisplay().fillCircle(c.x, c.y, 6, commonData->bgcolor);
|
||||
epd->fillCircle(c.x, c.y, 6, commonData->bgcolor);
|
||||
} else {
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
drawTextCenter(c.x, c.y, "no data");
|
||||
}
|
||||
|
||||
// Wind speed as decimal number
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(150, 250);
|
||||
if (holdvalues == false) {
|
||||
printBoatValue(svalue1, 260, 250, RIGHT, 26, smallDecimals);
|
||||
epd->print(svalue1);
|
||||
} else {
|
||||
printBoatValue(svalue1old, 260, 250, RIGHT, 26, smallDecimals);
|
||||
epd->print(svalue1old);
|
||||
}
|
||||
// unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
drawTextRalign(260, 265, unit1);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(220, 265);
|
||||
epd->print("kts");
|
||||
}
|
||||
else {
|
||||
// Normal mode
|
||||
|
||||
// data source
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(8, 50);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(8, 50);
|
||||
if (source == 'A') {
|
||||
getdisplay().print("APP");
|
||||
epd->print("APP");
|
||||
} else {
|
||||
getdisplay().print("TRUE");
|
||||
epd->print("TRUE");
|
||||
}
|
||||
|
||||
// draw ship front symbol (as bitmap)
|
||||
getdisplay().drawXBitmap(140, 30, front_bits, front_width, front_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(140, 30, front_bits, front_width, front_height, commonData->fgcolor);
|
||||
|
||||
Point c = {200, 155};
|
||||
uint16_t r = 150;
|
||||
@@ -562,7 +573,7 @@ public:
|
||||
for (int i = 30; i < 150; i += 10) {
|
||||
if (i % 30 != 0) {
|
||||
p = rotatePoint(c, {c.x, c.y - r + 5}, i);
|
||||
getdisplay().fillCircle(p.x, p.y, 3, commonData->fgcolor);
|
||||
epd->fillCircle(p.x, p.y, 3, commonData->fgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -579,24 +590,27 @@ public:
|
||||
for (int i = 210; i < 340; i += 10) {
|
||||
if (i % 30 != 0) {
|
||||
p = rotatePoint(c, {c.x, c.y - r + 5}, i);
|
||||
getdisplay().fillCircle(p.x, p.y, 3, commonData->fgcolor);
|
||||
epd->fillCircle(p.x, p.y, 3, commonData->fgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
// Wind speed as decimal number
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(150, 250);
|
||||
if (holdvalues == false) {
|
||||
printBoatValue(svalue1, 260, 250, RIGHT, 26, smallDecimals);
|
||||
epd->print(svalue1);
|
||||
} else {
|
||||
printBoatValue(svalue1old, 260, 250, RIGHT, 26, smallDecimals);
|
||||
epd->print(svalue1old);
|
||||
}
|
||||
// unit
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
drawTextRalign(260, 265, unit1);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(220, 265);
|
||||
epd->print("kts");
|
||||
|
||||
// Wind pointer (angle)
|
||||
if (bvalue2->valid or simulation) {
|
||||
float alpha = RadToDeg(value2);
|
||||
getdisplay().fillCircle(c.x, c.y, 8, commonData->fgcolor);
|
||||
epd->fillCircle(c.x, c.y, 8, commonData->fgcolor);
|
||||
pts = {
|
||||
{c.x - 1, c.y - (r - 20)},
|
||||
{c.x + 1, c.y - (r - 20)},
|
||||
@@ -604,9 +618,9 @@ public:
|
||||
{c.x - 6, c.y + 15}
|
||||
};
|
||||
fillPoly4(rotatePoints(c, pts, alpha), commonData->fgcolor);
|
||||
getdisplay().fillCircle(c.x, c.y, 6, commonData->bgcolor);
|
||||
epd->fillCircle(c.x, c.y, 6, commonData->bgcolor);
|
||||
} else {
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
drawTextCenter(c.x, c.y, "no data");
|
||||
}
|
||||
|
||||
|
||||
@@ -6,27 +6,39 @@
|
||||
#include "OBPcharts.h"
|
||||
|
||||
// ****************************************************************
|
||||
class PageWindPlot : public Page {
|
||||
class PageWindPlot : public Page
|
||||
{
|
||||
|
||||
private:
|
||||
GwLog* logger;
|
||||
|
||||
enum PageMode {
|
||||
enum ChartMode {
|
||||
DIRECTION,
|
||||
SPEED,
|
||||
BOTH
|
||||
};
|
||||
|
||||
int width; // Screen width
|
||||
int height; // Screen height
|
||||
static constexpr char HORIZONTAL = 'H';
|
||||
static constexpr char VERTICAL = 'V';
|
||||
static constexpr int8_t FULL_SIZE = 0;
|
||||
static constexpr int8_t HALF_SIZE_LEFT = 1;
|
||||
static constexpr int8_t HALF_SIZE_RIGHT = 2;
|
||||
|
||||
static constexpr bool PRNT_NAME = true;
|
||||
static constexpr bool NO_PRNT_NAME = false;
|
||||
static constexpr bool PRNT_VALUE = true;
|
||||
static constexpr bool NO_PRNT_VALUE = false;
|
||||
|
||||
// int width; // Screen width
|
||||
// int height; // Screen height
|
||||
|
||||
bool keylock = false; // Keylock
|
||||
PageMode chrtMode = DIRECTION;
|
||||
ChartMode chrtMode = DIRECTION;
|
||||
bool showTruW = true; // Show true wind or apparent wind in chart area
|
||||
bool oldShowTruW = false; // remember recent user selection of wind data type
|
||||
|
||||
int8_t dataIntv = 1; // Update interval for wind history chart:
|
||||
// (1)|(2)|(3)|(4)|(8) seconds for up to 32 min. history chart
|
||||
// (1)|(2)|(3)|(4)|(8) x 240 seconds for 4, 8, 12, 16, 32 min. history chart
|
||||
bool useSimuData;
|
||||
// bool holdValues;
|
||||
String flashLED;
|
||||
@@ -53,25 +65,18 @@ private:
|
||||
GwApi::BoatValue* wsBVal = nullptr;
|
||||
|
||||
public:
|
||||
PageWindPlot(CommonData& common)
|
||||
PageWindPlot(CommonData& common) : Page(common)
|
||||
{
|
||||
commonData = &common;
|
||||
logger = commonData->logger;
|
||||
LOG_DEBUG(GwLog::LOG, "Instantiate PageWindPlot");
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageWindPlot");
|
||||
|
||||
width = getdisplay().width(); // Screen width
|
||||
height = getdisplay().height(); // Screen height
|
||||
//width = epd->width(); // Screen width
|
||||
//height = epd->height(); // Screen height
|
||||
|
||||
// Get config data
|
||||
useSimuData = common.config->getBool(common.config->useSimuData);
|
||||
// holdValues = common.config->getBool(common.config->holdvalues);
|
||||
flashLED = common.config->getString(common.config->flashLED);
|
||||
backlightMode = common.config->getString(common.config->backlight);
|
||||
|
||||
oldShowTruW = !showTruW; // makes wind source being initialized at initial page call
|
||||
}
|
||||
|
||||
virtual void setupKeys()
|
||||
void setupKeys()
|
||||
{
|
||||
Page::setupKeys();
|
||||
commonData->keydata[0].label = "MODE";
|
||||
@@ -84,7 +89,7 @@ public:
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key)
|
||||
int handleKey(int key)
|
||||
{
|
||||
// Set chart mode
|
||||
if (key == 1) {
|
||||
@@ -95,14 +100,14 @@ public:
|
||||
} else {
|
||||
chrtMode = DIRECTION;
|
||||
}
|
||||
return 0; // Commit the key
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined BOARD_OBP60S3
|
||||
// Set data source TRUE | APP
|
||||
if (key == 2) {
|
||||
showTruW = !showTruW;
|
||||
return 0; // Commit the key
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set interval for wind history chart update time (interval)
|
||||
@@ -121,7 +126,7 @@ public:
|
||||
} else {
|
||||
dataIntv = 1;
|
||||
}
|
||||
return 0; // Commit the key
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Keylock function
|
||||
@@ -157,10 +162,10 @@ public:
|
||||
twsHstry = pageData.hstryBuffers->getBuffer("TWS");
|
||||
|
||||
if (twdHstry) {
|
||||
twdChart.reset(new Chart(*twdHstry, *commonData, useSimuData));
|
||||
twdChart.reset(new Chart(*twdHstry, Chart::dfltChrtDta["formatCourse"].range, *commonData, useSimuData));
|
||||
}
|
||||
if (twsHstry) {
|
||||
twsChart.reset(new Chart(*twsHstry, *commonData, useSimuData));
|
||||
twsChart.reset(new Chart(*twsHstry, Chart::dfltChrtDta["formatKnots"].range, *commonData, useSimuData));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,10 +174,10 @@ public:
|
||||
awsHstry = pageData.hstryBuffers->getBuffer("AWS");
|
||||
|
||||
if (awdHstry) {
|
||||
awdChart.reset(new Chart(*awdHstry, *commonData, useSimuData));
|
||||
awdChart.reset(new Chart(*awdHstry, Chart::dfltChrtDta["formatCourse"].range, *commonData, useSimuData));
|
||||
}
|
||||
if (awsHstry) {
|
||||
awsChart.reset(new Chart(*awsHstry, *commonData, useSimuData));
|
||||
awsChart.reset(new Chart(*awsHstry, Chart::dfltChrtDta["formatKnots"].range, *commonData, useSimuData));
|
||||
}
|
||||
if (twdHstry && twsHstry && awdHstry && awsHstry) {
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot: Created wind charts");
|
||||
@@ -184,7 +189,7 @@ public:
|
||||
|
||||
int displayPage(PageData& pageData)
|
||||
{
|
||||
LOG_DEBUG(GwLog::LOG, "Display PageWindPlot");
|
||||
logger->logDebug(GwLog::LOG, "Display PageWindPlot");
|
||||
// ulong pageTime = millis();
|
||||
|
||||
if (showTruW != oldShowTruW) {
|
||||
@@ -204,38 +209,35 @@ public:
|
||||
|
||||
oldShowTruW = showTruW;
|
||||
}
|
||||
LOG_DEBUG(GwLog::DEBUG, "PageWindPlot: draw with data %s: %.2f, %s: %.2f", wdBVal->getName().c_str(), wdBVal->value, wsBVal->getName().c_str(), wsBVal->value);
|
||||
logger->logDebug(GwLog::DEBUG, "PageWindPlot: draw with data %s: %.2f, %s: %.2f", wdBVal->getName().c_str(), wdBVal->value, wsBVal->getName().c_str(), wsBVal->value);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, width, height); // Set partial update
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height());
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
if (chrtMode == DIRECTION) {
|
||||
if (wdChart) {
|
||||
wdChart->showChrt(Chart::VERTICAL, Chart::FULL_SIZE, dataIntv, Chart::PRNT_NAME, Chart::PRNT_VALUE, *wdBVal);
|
||||
wdChart->showChrt(VERTICAL, FULL_SIZE, dataIntv, PRNT_NAME, PRNT_VALUE, *wdBVal);
|
||||
}
|
||||
|
||||
} else if (chrtMode == SPEED) {
|
||||
if (wsChart) {
|
||||
if (dataIntv == 8) {
|
||||
dataIntv = 1; // horizontal charts show max. 4 x 7 min. only; no factor 8 multiplier
|
||||
}
|
||||
wsChart->showChrt(Chart::HORIZONTAL, Chart::FULL_SIZE, dataIntv, Chart::PRNT_NAME, Chart::PRNT_VALUE, *wsBVal);
|
||||
wsChart->showChrt(HORIZONTAL, FULL_SIZE, dataIntv, PRNT_NAME, PRNT_VALUE, *wsBVal);
|
||||
}
|
||||
|
||||
} else if (chrtMode == BOTH) {
|
||||
if (wdChart) {
|
||||
wdChart->showChrt(Chart::VERTICAL, Chart::HALF_SIZE_LEFT_TOP, dataIntv, Chart::NO_PRNT_NAME, Chart::PRNT_VALUE, *wdBVal);
|
||||
wdChart->showChrt(VERTICAL, HALF_SIZE_LEFT, dataIntv, PRNT_NAME, PRNT_VALUE, *wdBVal);
|
||||
}
|
||||
if (wsChart) {
|
||||
wsChart->showChrt(Chart::VERTICAL, Chart::HALF_SIZE_RIGHT_BOTTOM, dataIntv, Chart::NO_PRNT_NAME, Chart::PRNT_VALUE, *wsBVal);
|
||||
wsChart->showChrt(VERTICAL, HALF_SIZE_RIGHT, dataIntv, PRNT_NAME, PRNT_VALUE, *wsBVal);
|
||||
}
|
||||
}
|
||||
|
||||
// LOG_DEBUG(GwLog::DEBUG, "PageWindPlot: page time %ldms", millis() - pageTime);
|
||||
// logger->logDebug(GwLog::DEBUG, "PageWindPlot: page time %ldms", millis() - pageTime);
|
||||
return PAGE_UPDATE;
|
||||
}
|
||||
};
|
||||
|
||||
+215
-226
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -6,18 +7,20 @@
|
||||
class PageWindRose : public Page
|
||||
{
|
||||
private:
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
String lengthformat;
|
||||
int16_t lp = 80; // Pointer length
|
||||
|
||||
public:
|
||||
PageWindRose(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageWindRose");
|
||||
PageWindRose(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageWindRose");
|
||||
|
||||
// Get config data
|
||||
String lengthformat = config->getString(config->lengthFormat);
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key) {
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -26,255 +29,242 @@ public:
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
int valueX, valueY;
|
||||
int DsegFontSize;
|
||||
|
||||
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
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
// Get boat value 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
|
||||
value1 = formatValue(bvalue1, *commonData).value;// Format only nesaccery for simulation data for pointer
|
||||
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 value for AWS
|
||||
GwApi::BoatValue *bvalue2 = pageData.values[1]; // Second element in list
|
||||
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 value for TWD
|
||||
GwApi::BoatValue *bvalue3 = pageData.values[2]; // Third element in list
|
||||
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 value for TWS
|
||||
GwApi::BoatValue *bvalue4 = pageData.values[3]; // Fourth element in list
|
||||
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 value for DBT
|
||||
GwApi::BoatValue *bvalue5 = pageData.values[4]; // Fifth element in list
|
||||
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 value for STW
|
||||
GwApi::BoatValue *bvalue6 = pageData.values[5]; // Sixth element in list
|
||||
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"){
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
// Logging boat values
|
||||
if (bvalue1 == NULL) return PAGE_OK; // WTF why this statement?
|
||||
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);
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
// storage for hold values
|
||||
static FormattedData bvf_awa_old;
|
||||
static FormattedData bvf_aws_old;
|
||||
static FormattedData bvf_twd_old;
|
||||
static FormattedData bvf_tws_old;
|
||||
static FormattedData bvf_dbt_old;
|
||||
static FormattedData bvf_stw_old;
|
||||
// units? why?
|
||||
|
||||
// Get boat value for AWA
|
||||
GwApi::BoatValue *bv_awa = pageData.values[0]; // First element in list
|
||||
String name_awa = xdrDelete(bv_awa->getName(), 6); // get name without prefix and limit length
|
||||
FormattedData bvf_awa = commonData->fmt->formatValue(bv_awa, *commonData);
|
||||
if (bv_awa->valid) { // Save formatted data for hold feature
|
||||
bvf_awa_old = bvf_awa;
|
||||
}
|
||||
|
||||
// Get boat value for AWS
|
||||
GwApi::BoatValue *bv_aws = pageData.values[1]; // Second element in list
|
||||
String name_aws = xdrDelete(bv_aws->getName(), 6); // get name without prefix and limit length
|
||||
FormattedData bvf_aws = commonData->fmt->formatValue(bv_aws, *commonData);
|
||||
if (bv_aws->valid) { // Save formatted data for hold feature
|
||||
bvf_aws_old = bvf_aws;
|
||||
}
|
||||
|
||||
// Get boat value for TWD
|
||||
GwApi::BoatValue *bv_twd = pageData.values[2]; // Third element in list
|
||||
String name_twd = xdrDelete(bv_twd->getName(), 6); // get name without prefix and limit length
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bv_twd, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
FormattedData bvf_twd = commonData->fmt->formatValue(bv_twd, *commonData);
|
||||
if (bv_twd->valid) { // Save formatted data for hold feature
|
||||
bvf_twd_old = bvf_twd;
|
||||
}
|
||||
|
||||
// Get boat value for TWS
|
||||
GwApi::BoatValue *bv_tws = pageData.values[3]; // Fourth element in list
|
||||
String name_tws = xdrDelete(bv_tws->getName(), 6); // get name without prefix and limit length
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bv_tws, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
FormattedData bvf_tws = commonData->fmt->formatValue(bv_tws, *commonData);
|
||||
if (bv_tws->valid) { // Save formatted data for hold feature
|
||||
bvf_tws_old = bvf_tws;
|
||||
}
|
||||
|
||||
// Get boat value for DBT
|
||||
GwApi::BoatValue *bv_dbt = pageData.values[4]; // Fifth element in list
|
||||
String name_dbt = xdrDelete(bv_dbt->getName(), 6); // get name without prefix and limit length
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bv_dbt, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
FormattedData bvf_dbt = commonData->fmt->formatValue(bv_dbt, *commonData);
|
||||
if (bv_dbt->valid) { // Save formatted data for hold feature
|
||||
bvf_dbt_old = bvf_dbt;
|
||||
}
|
||||
|
||||
// Get boat value for STW
|
||||
GwApi::BoatValue *bv_stw = pageData.values[5]; // Sixth element in list
|
||||
String name_stw = xdrDelete(bv_stw->getName(), 6); // get name without prefix and limit length
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bv_stw, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
FormattedData bvf_stw = commonData->fmt->formatValue(bv_stw, *commonData);
|
||||
if (bv_stw->valid) { // Save formatted data for hold feature
|
||||
bvf_stw_old = bvf_stw;
|
||||
}
|
||||
|
||||
// Log boat values
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageWindRose, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f, %s:%f",
|
||||
name_awa.c_str(), bv_awa->value,
|
||||
name_aws.c_str(), bv_aws->value,
|
||||
name_twd.c_str(), bv_twd->value,
|
||||
name_tws.c_str(), bv_tws->value,
|
||||
name_dbt.c_str(), bv_dbt->value,
|
||||
name_stw.c_str(), bv_stw->value);
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
// *********************************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height());
|
||||
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// Show values AWA
|
||||
printBoatValue(svalue1, 101, 65, RIGHT, 20, smallDecimals); // value
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(10, 95);
|
||||
getdisplay().print(name1); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 115);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit1); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit1old); // Unit
|
||||
}
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 65);
|
||||
epd->print(holdvalues ? bvf_awa_old.value : bvf_awa.value);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(10, 95);
|
||||
epd->print(name_awa);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 115);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? bvf_awa_old.unit : bvf_awa.unit);
|
||||
|
||||
// Horizontal separator left
|
||||
getdisplay().fillRect(0, 149, 60, 3, commonData->fgcolor);
|
||||
// Horizintal separator left
|
||||
epd->fillRect(0, 149, 60, 3, commonData->fgcolor);
|
||||
|
||||
// Show values AWS
|
||||
printBoatValue(svalue2, 101, 270, RIGHT, 20, smallDecimals); // value
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(10, 220);
|
||||
getdisplay().print(name2); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 190);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit2); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit2old); // Unit
|
||||
}
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 270);
|
||||
epd->print(holdvalues ? bvf_aws_old.value : bvf_aws.value);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(10, 220);
|
||||
epd->print(name_aws);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 190);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? bvf_aws_old.unit : bvf_aws.unit);
|
||||
|
||||
// Show values TWD
|
||||
printBoatValue(svalue3, 391, 65, RIGHT, 20, smallDecimals); // value
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(335, 95);
|
||||
getdisplay().print(name3); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(335, 115);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit3); // Unit
|
||||
// Show value TWD
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(295, 65);
|
||||
// TODO WTF? Der Formatter sollte das korrekt machen
|
||||
if (bv_twd->valid) {
|
||||
epd->print(abs(bv_twd->value * 180 / PI), 0); // Value
|
||||
}
|
||||
else {
|
||||
getdisplay().print(unit3old); // Unit
|
||||
epd->print(commonData->fmt->placeholder);
|
||||
}
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(335, 95);
|
||||
epd->print(name_twd); // Name
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(335, 115);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? bvf_twd_old.unit : bvf_twd.unit);
|
||||
|
||||
// Horizintal separator right
|
||||
getdisplay().fillRect(340, 149, 80, 3, commonData->fgcolor);
|
||||
epd->fillRect(340, 149, 80, 3, commonData->fgcolor);
|
||||
|
||||
// Show values TWS
|
||||
printBoatValue(svalue4, 391, 270, RIGHT, 20, smallDecimals); // value
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(335, 220);
|
||||
getdisplay().print(name4); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(335, 190);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit4); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit4old); // Unit
|
||||
}
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(295, 270);
|
||||
epd->print(name_tws);
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(335, 220);
|
||||
epd->print(holdvalues ? bvf_tws_old.value : bvf_tws.value);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(335, 190);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? bvf_tws_old.unit : bvf_tws.unit);
|
||||
|
||||
//*******************************************************************************************
|
||||
// *********************************************************************
|
||||
|
||||
// Draw wind rose
|
||||
int rInstrument = 110; // Radius of grafic instrument
|
||||
String sDegree;
|
||||
float pi = 3.141592;
|
||||
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
getdisplay().fillCircle(200, 150, rInstrument - 10, commonData->fgcolor); // Inner circle
|
||||
getdisplay().fillCircle(200, 150, rInstrument - 13, commonData->bgcolor); // Inner circle
|
||||
epd->fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
epd->fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
epd->fillCircle(200, 150, rInstrument - 10, commonData->fgcolor); // Inner circle
|
||||
epd->fillCircle(200, 150, rInstrument - 13, commonData->bgcolor); // Inner circle
|
||||
|
||||
for(int i=0; i<360; i=i+10)
|
||||
{
|
||||
// Scaling values
|
||||
float x = 200 + (rInstrument-30)*sin(i/180.0*M_PI); // x-coordinate dots
|
||||
float y = 150 - (rInstrument-30)*cos(i/180.0*M_PI); // y-coordinate cots
|
||||
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;
|
||||
}
|
||||
|
||||
if(i % 30 == 0){
|
||||
// Print text centered on position x, y
|
||||
int16_t x1, y1; // Return values of getTextBounds
|
||||
uint16_t w, h; // Return values of getTextBounds
|
||||
sDegree = String(i);
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
displayGetTextBounds(sDegree, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
getdisplay().setCursor(x-w/2, y+h/2);
|
||||
getdisplay().print(sDegree);
|
||||
epd->getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
epd->setCursor(x-w/2, y+h/2);
|
||||
if (i % 30 == 0) {
|
||||
epd->setFont(&Ubuntu_Bold8pt8b); // TODO move out of loop
|
||||
epd->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);
|
||||
epd->fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor);
|
||||
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);
|
||||
float sinx = sin(i/180.0*M_PI);
|
||||
float cosx = cos(i/180.0*M_PI);
|
||||
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
} else {
|
||||
// Draw sub scale with dots
|
||||
float x1c = 200 + rInstrument*sin(i/180.0*M_PI);
|
||||
float y1c = 150 - rInstrument*cos(i/180.0*M_PI);
|
||||
getdisplay().fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (bv_aws->valid || holdvalues || simulation) {
|
||||
float sinx = sin(bv_awa->value); // Wind direction
|
||||
float cosx = cos(bv_awa->value);
|
||||
// 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),
|
||||
epd->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),commonData->fgcolor);
|
||||
// Inverted pointer
|
||||
@@ -284,43 +274,42 @@ public:
|
||||
float ix2 = -endwidth;
|
||||
float iy1 = -(rInstrument-15);
|
||||
float iy2 = -endwidth;
|
||||
getdisplay().fillTriangle(200+(int)(cosx*ix1-sinx*iy1),150+(int)(sinx*ix1+cosx*iy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
}
|
||||
|
||||
// Center circle
|
||||
getdisplay().fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
||||
getdisplay().fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
||||
epd->fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
||||
epd->fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
||||
|
||||
//*******************************************************************************************
|
||||
// *********************************************************************
|
||||
|
||||
// Show values DBT
|
||||
printBoatValue(svalue5, 200, 200, CENTER, 16, smallDecimals); // value
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(190, 215);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit5); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit5old); // Unit
|
||||
}
|
||||
// Show value DBT
|
||||
epd->setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||
epd->setCursor(160, 200);
|
||||
epd->print(holdvalues ? bvf_dbt_old.value : bvf_dbt.value);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(190, 215);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? bvf_dbt_old.unit : bvf_dbt.unit);
|
||||
|
||||
// Show values STW
|
||||
printBoatValue(svalue6, 200, 130, CENTER, 16, smallDecimals); // value
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(190, 90);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit6); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit6old); // Unit
|
||||
}
|
||||
// Show value STW
|
||||
epd->setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||
epd->setCursor(160, 130);
|
||||
epd->print(holdvalues ? bvf_stw_old.value : bvf_stw.value);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(190, 90);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? bvf_stw_old.unit : bvf_stw.unit);
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
|
||||
void leavePage(PageData &pageData) {
|
||||
logger->logDebug(GwLog::LOG, "Leaving PageWindRose");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static Page *createPage(CommonData &common){
|
||||
|
||||
+178
-189
@@ -1,38 +1,37 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
#include "BoatDataCalibration.h"
|
||||
#endif
|
||||
|
||||
class PageWindRoseFlex : public Page
|
||||
{
|
||||
private:
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
String lengthformat;
|
||||
int16_t lp = 80; // Pointer length
|
||||
char source = 'A'; // data source (A)pparent | (T)rue
|
||||
String ssource="App."; // String for Data Source
|
||||
|
||||
public:
|
||||
PageWindRoseFlex(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageWindRoseFlex");
|
||||
PageWindRoseFlex(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageWindRoseFlex");
|
||||
|
||||
// Get config data
|
||||
lengthformat = config->getString(config->lengthFormat);
|
||||
}
|
||||
virtual void setupKeys(){
|
||||
|
||||
void setupKeys() {
|
||||
Page::setupKeys();
|
||||
commonData->keydata[1].label = "SRC";
|
||||
}
|
||||
|
||||
// Key functions
|
||||
virtual int handleKey(int key){
|
||||
if(key == 2){
|
||||
// Code for set source
|
||||
if(source == 'A'){
|
||||
source = 'T';
|
||||
} else {
|
||||
source = 'A';
|
||||
}
|
||||
}
|
||||
return key; // Commit the key
|
||||
|
||||
int handleKey(int key) {
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -41,12 +40,17 @@ public:
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int valueX, valueY;
|
||||
int DsegFontSize;
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
static String svalue1old = "";
|
||||
static String unit1old = "";
|
||||
@@ -60,17 +64,6 @@ public:
|
||||
static String unit5old = "";
|
||||
static String svalue6old = "";
|
||||
static String unit6old = "";
|
||||
static GFXfont name3font;
|
||||
static GFXfont name4font;
|
||||
static GFXfont name5font;
|
||||
static GFXfont name6font;
|
||||
|
||||
|
||||
// Get config data
|
||||
bool simulation = config->getBool(config->useSimuData);
|
||||
bool holdvalues = config->getBool(config->holdvalues);
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
bool smallDecimals = config->getBool(config->smallDecimals);
|
||||
|
||||
GwApi::BoatValue *bvalue1; // Value 1 for angle
|
||||
GwApi::BoatValue *bvalue2; // Value 2 for speed
|
||||
@@ -83,11 +76,13 @@ public:
|
||||
}
|
||||
String name1 = bvalue1->getName().c_str(); // Value name
|
||||
name1 = name1.substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue1, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
double value1 = bvalue1->value; // Value as double in SI unit
|
||||
value1 = formatValue(bvalue1, *commonData).value;// Format only nesaccery for simulation data for pointer
|
||||
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
|
||||
String svalue1 = commonData->fmt->formatValue(bvalue1, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit1 = commonData->fmt->formatValue(bvalue1, *commonData).unit; // Unit of value
|
||||
if (valid1 == true) {
|
||||
svalue1old = svalue1; // Save old value
|
||||
unit1old = unit1; // Save old unit
|
||||
@@ -101,31 +96,32 @@ public:
|
||||
}
|
||||
String name2 = bvalue2->getName().c_str(); // Value name
|
||||
name2 = name2.substring(0, 6); // String length limit for value name
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue2, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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 (simulation) {
|
||||
value2 = 0.62731; // some random value
|
||||
}
|
||||
String svalue2 = commonData->fmt->formatValue(bvalue2, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit2 = commonData->fmt->formatValue(bvalue2, *commonData).unit; // Unit of value
|
||||
if (valid2 == true) {
|
||||
svalue2old = svalue2; // Save old value
|
||||
unit2old = unit2; // Save old unit
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Get boat value for bottom left corner
|
||||
GwApi::BoatValue *bvalue3 = pageData.values[0];
|
||||
String name3 = xdrDelete(bvalue3->getName()); // Value name
|
||||
name3 = name3.substring(0, 6); // String length limit for value name
|
||||
if (name3.length()>3){
|
||||
name3font=Ubuntu_Bold8pt8b;
|
||||
}
|
||||
else{
|
||||
name3font=Ubuntu_Bold12pt8b;
|
||||
}
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue3, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue3 = commonData->fmt->formatValue(bvalue3, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit3 = commonData->fmt->formatValue(bvalue3, *commonData).unit; // Unit of value
|
||||
if(valid3 == true){
|
||||
svalue3old = svalue3; // Save old value
|
||||
unit3old = unit3; // Save old unit
|
||||
@@ -135,189 +131,185 @@ public:
|
||||
GwApi::BoatValue *bvalue4 = pageData.values[1];
|
||||
String name4 = xdrDelete(bvalue4->getName()); // Value name
|
||||
name4 = name4.substring(0, 6); // String length limit for value name
|
||||
if (name4.length()>3){
|
||||
name4font=Ubuntu_Bold8pt8b;
|
||||
}
|
||||
else{
|
||||
name4font=Ubuntu_Bold12pt8b;
|
||||
}
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue4, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue4 = commonData->fmt->formatValue(bvalue4, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit4 = commonData->fmt->formatValue(bvalue4, *commonData).unit; // Unit of value
|
||||
if(valid4 == true){
|
||||
svalue4old = svalue4; // Save old value
|
||||
unit4old = unit4; // Save old unit
|
||||
}
|
||||
|
||||
// Get boat value bottom right corner
|
||||
// Get boat value for bottom right corner
|
||||
GwApi::BoatValue *bvalue5 = pageData.values[2];
|
||||
String name5 = xdrDelete(bvalue5->getName()); // Value name
|
||||
name5 = name5.substring(0, 6); // String length limit for value name
|
||||
if (name5.length()>3){
|
||||
name5font=Ubuntu_Bold8pt8b;
|
||||
}
|
||||
else{
|
||||
name5font=Ubuntu_Bold12pt8b;
|
||||
}
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue5, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue5 = commonData->fmt->formatValue(bvalue5, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit5 = commonData->fmt->formatValue(bvalue5, *commonData).unit; // Unit of value
|
||||
if(valid5 == true){
|
||||
svalue5old = svalue5; // Save old value
|
||||
unit5old = unit5; // Save old unit
|
||||
}
|
||||
|
||||
// Get boat value for center (name is not displayed)
|
||||
// Get boat value for center
|
||||
GwApi::BoatValue *bvalue6 = pageData.values[3];
|
||||
String name6 = xdrDelete(bvalue6->getName()); // Value name
|
||||
name6 = name6.substring(0, 6); // String length limit for value name
|
||||
if (name6.length()>3){
|
||||
name6font=Ubuntu_Bold8pt8b;
|
||||
}
|
||||
else{
|
||||
name6font=Ubuntu_Bold8pt8b;
|
||||
}
|
||||
#ifdef ENABLE_CALIBRATION
|
||||
calibrationData.calibrateInstance(bvalue6, logger); // Check if boat data value is to be calibrated
|
||||
#endif
|
||||
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
|
||||
String svalue6 = commonData->fmt->formatValue(bvalue6, *commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||
String unit6 = commonData->fmt->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 PAGE_OK; // WTF why this statement?
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageWindRoseFlex, %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);
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageWindRoseFlex, %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 display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// Show AWS or TWS top left
|
||||
printBoatValue(svalue2, 101, 65, RIGHT, 20, smallDecimals); // value
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt8b);
|
||||
getdisplay().setCursor(10, 95);
|
||||
getdisplay().print(name2); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 115);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit2); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit2old); // Unit
|
||||
}
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 65);
|
||||
epd->print(svalue2); // Value
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(10, 95);
|
||||
epd->print(name2); // Name
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 115);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? unit2old : unit2);
|
||||
|
||||
// Horizintal separator left
|
||||
getdisplay().fillRect(0, 149, 60, 3, commonData->fgcolor);
|
||||
epd->fillRect(0, 149, 60, 3, commonData->fgcolor);
|
||||
|
||||
// Show value 3 (=first user-configured parameter) at bottom left
|
||||
printBoatValue(svalue3, 101, 270, RIGHT, 20, smallDecimals); // value
|
||||
getdisplay().setFont(&name3font);
|
||||
getdisplay().setCursor(10, 220);
|
||||
getdisplay().print(name3); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(10, 190);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit3); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit3old); // Unit
|
||||
}
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(10, 270);
|
||||
epd->print(svalue3); // Value
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(10, 220);
|
||||
epd->print(name3); // Name
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(10, 190);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? unit3old : unit3);
|
||||
|
||||
|
||||
// Show value 4 (=second user-configured parameter) at top right
|
||||
printBoatValue(svalue4, 395, 65, RIGHT, 20, smallDecimals); // value
|
||||
getdisplay().setFont(&name4font);
|
||||
getdisplay().setCursor(325, 95);
|
||||
getdisplay().print(name4); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(325, 115);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit4); // Unit
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(295, 65);
|
||||
if(valid3 == true){
|
||||
epd->print(svalue4); // Value
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit4old); // Unit
|
||||
epd->print(commonData->fmt->placeholder);
|
||||
}
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(335, 95);
|
||||
epd->print(name4); // Name
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(335, 115);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? unit4old : unit4);
|
||||
|
||||
// Horizontal separator right
|
||||
getdisplay().fillRect(340, 149, 80, 3, commonData->fgcolor);
|
||||
|
||||
// Horizintal separator right
|
||||
epd->fillRect(340, 149, 80, 3, commonData->fgcolor);
|
||||
|
||||
// Show value 5 (=third user-configured parameter) at bottom right
|
||||
printBoatValue(svalue5, 395, 270, RIGHT, 20, smallDecimals); // value
|
||||
getdisplay().setFont(&name5font);
|
||||
getdisplay().setCursor(325, 220);
|
||||
getdisplay().print(name5); // Name
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(325, 190);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit5); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit5old); // Unit
|
||||
}
|
||||
|
||||
epd->setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||
epd->setCursor(295, 270);
|
||||
epd->print(svalue5); // Value
|
||||
epd->setFont(&Ubuntu_Bold12pt8b);
|
||||
epd->setCursor(335, 220);
|
||||
epd->print(name5); // Name
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(335, 190);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? unit5old : unit5);
|
||||
|
||||
//*******************************************************************************************
|
||||
|
||||
// Draw wind rose
|
||||
int rInstrument = 110; // Radius of grafic instrument
|
||||
String sDegree;
|
||||
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
getdisplay().fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
getdisplay().fillCircle(200, 150, rInstrument - 10, commonData->fgcolor); // Inner circle
|
||||
getdisplay().fillCircle(200, 150, rInstrument - 13, commonData->bgcolor); // Inner circle
|
||||
epd->fillCircle(200, 150, rInstrument + 10, commonData->fgcolor); // Outer circle
|
||||
epd->fillCircle(200, 150, rInstrument + 7, commonData->bgcolor); // Outer circle
|
||||
epd->fillCircle(200, 150, rInstrument - 10, commonData->fgcolor); // Inner circle
|
||||
epd->fillCircle(200, 150, rInstrument - 13, commonData->bgcolor); // Inner circle
|
||||
|
||||
for(int i=0; i<360; i=i+10)
|
||||
{
|
||||
// Scaling values
|
||||
float x = 200 + (rInstrument-30)*sin(i/180.0*M_PI); // x-coordinate dots
|
||||
float y = 150 - (rInstrument-30)*cos(i/180.0*M_PI); // y-coordinate dots
|
||||
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;
|
||||
}
|
||||
|
||||
if(i % 30 == 0){
|
||||
// Print text centered on position x, y
|
||||
int16_t x1, y1; // Return values of getTextBounds
|
||||
uint16_t w, h; // Return values of getTextBounds
|
||||
sDegree = String(i);
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
displayGetTextBounds(sDegree, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
getdisplay().setCursor(x-w/2, y+h/2);
|
||||
getdisplay().print(sDegree);
|
||||
epd->getTextBounds(ii, int(x), int(y), &x1, &y1, &w, &h); // Calc width of new string
|
||||
epd->setCursor(x-w/2, y+h/2);
|
||||
if(i % 30 == 0){
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->print(ii);
|
||||
}
|
||||
|
||||
// Draw sub scale with dots
|
||||
float x1c = 200 + rInstrument*sin(i/180.0*M_PI);
|
||||
float y1c = 150 - rInstrument*cos(i/180.0*M_PI);
|
||||
epd->fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor);
|
||||
float sinx=sin(i/180.0*M_PI);
|
||||
float cosx=cos(i/180.0*M_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);
|
||||
float sinx = sin(i/180.0*M_PI);
|
||||
float cosx = cos(i/180.0*M_PI);
|
||||
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
getdisplay().fillTriangle(200+(int)(cosx*xx2-sinx*yy1),150+(int)(sinx*xx2+cosx*yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
} else {
|
||||
// Draw sub scale with dots
|
||||
float x1c = 200 + rInstrument*sin(i/180.0*M_PI);
|
||||
float y1c = 150 - rInstrument*cos(i/180.0*M_PI);
|
||||
getdisplay().fillCircle((int)x1c, (int)y1c, 2, commonData->fgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,7 +324,7 @@ public:
|
||||
float xx2 = startwidth;
|
||||
float yy1 = -startwidth;
|
||||
float yy2 = -(rInstrument-15);
|
||||
getdisplay().fillTriangle(200+(int)(cosx*xx1-sinx*yy1),150+(int)(sinx*xx1+cosx*yy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
// Inverted pointer
|
||||
@@ -342,52 +334,49 @@ public:
|
||||
float ix2 = -endwidth;
|
||||
float iy1 = -(rInstrument-15);
|
||||
float iy2 = -endwidth;
|
||||
getdisplay().fillTriangle(200+(int)(cosx*ix1-sinx*iy1),150+(int)(sinx*ix1+cosx*iy1),
|
||||
epd->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),commonData->fgcolor);
|
||||
}
|
||||
|
||||
// Center circle
|
||||
getdisplay().fillCircle(200, 150, startwidth + 8, commonData->bgcolor);
|
||||
getdisplay().fillCircle(200, 150, startwidth + 6, commonData->fgcolor);
|
||||
getdisplay().fillCircle(200, 150, startwidth + 4, commonData->bgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
||||
if (source=='A'){
|
||||
getdisplay().setCursor(193, 155);
|
||||
}
|
||||
else {
|
||||
getdisplay().setCursor(195, 156);
|
||||
}
|
||||
getdisplay().print({source});
|
||||
epd->fillCircle(200, 150, startwidth + 6, commonData->bgcolor);
|
||||
epd->fillCircle(200, 150, startwidth + 4, commonData->fgcolor);
|
||||
|
||||
//*******************************************************************************************
|
||||
|
||||
// Show value6 (=fourth user-configured parameter)
|
||||
// Show value6 (=fourth user-configured parameter) and ssource, so that they do not collide with the wind pointer
|
||||
if (cos(value1) > 0) {
|
||||
// pointer points upwards
|
||||
printBoatValue(svalue6, 200, 200, CENTER, 16, smallDecimals); // value
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(190, 215);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit6); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit6old); // Unit
|
||||
epd->setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||
epd->setCursor(160, 200);
|
||||
epd->print(svalue6); // Value
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(190, 215);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? unit6old : unit6);
|
||||
if (sin(value1) > 0) {
|
||||
epd->setCursor(160, 130);
|
||||
} else {
|
||||
epd->setCursor(220, 130);
|
||||
}
|
||||
epd->print(ssource); // true or app.
|
||||
}
|
||||
else {
|
||||
// pointer points downwards
|
||||
printBoatValue(svalue6, 200, 130, CENTER, 16, smallDecimals); // value
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(190, 90);
|
||||
getdisplay().print(" ");
|
||||
if(holdvalues == false){
|
||||
getdisplay().print(unit6); // Unit
|
||||
}
|
||||
else{
|
||||
getdisplay().print(unit6old); // Unit
|
||||
epd->setFont(&DSEG7Classic_BoldItalic16pt7b);
|
||||
epd->setCursor(160, 130);
|
||||
epd->print(svalue6);
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(190, 90);
|
||||
epd->print(" ");
|
||||
epd->print(holdvalues ? unit6old : unit6);
|
||||
if (sin(value1) > 0) {
|
||||
epd->setCursor(160, 200);
|
||||
} else {
|
||||
epd->setCursor(220, 200);
|
||||
}
|
||||
epd->print(ssource); //true or app.
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
#include "Pagedata.h"
|
||||
@@ -28,21 +29,18 @@ static unsigned char ship_bits[] PROGMEM = {
|
||||
|
||||
class PageXTETrack : public Page
|
||||
{
|
||||
static constexpr int8_t LEFT = 0;
|
||||
static constexpr int8_t CENTER = 1;
|
||||
static constexpr int8_t RIGHT = 2;
|
||||
|
||||
bool simulation = false;
|
||||
bool holdvalues = false;
|
||||
bool smallDecimals = false;
|
||||
private:
|
||||
String trackStep;
|
||||
double seg_step;
|
||||
|
||||
public:
|
||||
PageXTETrack(CommonData &common){
|
||||
commonData = &common;
|
||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageXTETrack");
|
||||
simulation = common.config->getBool(common.config->useSimuData);
|
||||
holdvalues = common.config->getBool(common.config->holdvalues);
|
||||
smallDecimals = common.config->getBool(common.config->smallDecimals);
|
||||
PageXTETrack(CommonData &common) : Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageXTETrack");
|
||||
|
||||
// Get config data
|
||||
String trackStep = config->getString(config->trackStep);
|
||||
seg_step = trackStep.toDouble() * M_PI / 180;
|
||||
}
|
||||
|
||||
void drawSegment(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,
|
||||
@@ -51,18 +49,18 @@ class PageXTETrack : public Page
|
||||
if (fill == true) {
|
||||
// no primitive for quadrangular object
|
||||
// we create it from 2 triangles
|
||||
getdisplay().fillTriangle(x0, y0, x1, y1, x3, y3, color);
|
||||
getdisplay().fillTriangle(x1, y1, x2, y2, x3, y3, color);
|
||||
epd->fillTriangle(x0, y0, x1, y1, x3, y3, color);
|
||||
epd->fillTriangle(x1, y1, x2, y2, x3, y3, color);
|
||||
} else {
|
||||
// draw outline
|
||||
getdisplay().drawLine(x0, y0, x1, y1, color);
|
||||
getdisplay().drawLine(x1, y1, x2, y2, color);
|
||||
getdisplay().drawLine(x2, y2, x3, y3, color);
|
||||
getdisplay().drawLine(x3, y3, x0, y0, color);
|
||||
epd->drawLine(x0, y0, x1, y1, color);
|
||||
epd->drawLine(x1, y1, x2, y2, color);
|
||||
epd->drawLine(x2, y2, x3, y3, color);
|
||||
epd->drawLine(x3, y3, x0, y0, color);
|
||||
}
|
||||
}
|
||||
|
||||
virtual int handleKey(int key){
|
||||
int handleKey(int key) {
|
||||
// Code for keylock
|
||||
if(key == 11){
|
||||
commonData->keylock = !commonData->keylock;
|
||||
@@ -71,88 +69,93 @@ class PageXTETrack : public Page
|
||||
return key;
|
||||
}
|
||||
|
||||
int displayPage(PageData &pageData){
|
||||
GwConfigHandler *config = commonData->config;
|
||||
GwLog *logger = commonData->logger;
|
||||
|
||||
// Get config data
|
||||
String flashLED = config->getString(config->flashLED);
|
||||
String backlightMode = config->getString(config->backlight);
|
||||
|
||||
String trackStep = config->getString(config->trackStep);
|
||||
double seg_step = trackStep.toFloat() * PI / 180;
|
||||
|
||||
// Optical warning by limit violation (unused)
|
||||
if(String(flashLED) == "Limit Violation"){
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
// Logging boat values
|
||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageXTETrack");
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageXTETrack");
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
getdisplay().setTextColor(commonData->fgcolor);
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
// descriptions
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(30, 188);
|
||||
getdisplay().print("Cross-track error");
|
||||
getdisplay().setCursor(270, 188);
|
||||
getdisplay().print("Track");
|
||||
getdisplay().setCursor(25, 275);
|
||||
getdisplay().print("Distance to waypoint");
|
||||
getdisplay().setCursor(280, 275);
|
||||
getdisplay().print("Bearing");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(50, 188);
|
||||
epd->print("Cross-track error");
|
||||
epd->setCursor(270, 188);
|
||||
epd->print("Track");
|
||||
epd->setCursor(45, 275);
|
||||
epd->print("Distance to waypoint");
|
||||
epd->setCursor(260, 275);
|
||||
epd->print("Bearing");
|
||||
|
||||
// values
|
||||
epd->setFont(&DSEG7Classic_BoldItalic30pt7b);
|
||||
|
||||
int16_t x, y;
|
||||
uint16_t w, h;
|
||||
|
||||
GwApi::BoatValue *bv_xte = pageData.values[0]; // XTE
|
||||
String sval_xte = formatValue(bv_xte, *commonData).svalue;
|
||||
// printBoatValue(sval_xte, 160, 170, RIGHT, 30, smallDecimals);
|
||||
printBoatValue(sval_xte, 180, 170, RIGHT, 30, smallDecimals);
|
||||
String sval_xte = commonData->fmt->formatValue(bv_xte, *commonData).svalue;
|
||||
epd->getTextBounds(sval_xte, 0, 0, &x, &y, &w, &h);
|
||||
epd->setCursor(160-w, 170);
|
||||
epd->print(sval_xte);
|
||||
|
||||
GwApi::BoatValue *bv_cog = pageData.values[1]; // COG
|
||||
String sval_cog = formatValue(bv_cog, *commonData).svalue;
|
||||
printBoatValue(sval_cog, 360, 170, RIGHT, 30, smallDecimals);
|
||||
String sval_cog = commonData->fmt->formatValue(bv_cog, *commonData).svalue;
|
||||
epd->getTextBounds(sval_cog, 0, 0, &x, &y, &w, &h);
|
||||
epd->setCursor(360-w, 170);
|
||||
epd->print(sval_cog);
|
||||
|
||||
GwApi::BoatValue *bv_dtw = pageData.values[2]; // DTW
|
||||
String sval_dtw = formatValue(bv_dtw, *commonData).svalue;
|
||||
// printBoatValue(sval_dtw, 160, 257, RIGHT, 30, smallDecimals);
|
||||
printBoatValue(sval_dtw, 160, 257, RIGHT, 30, smallDecimals);
|
||||
String sval_dtw = commonData->fmt->formatValue(bv_dtw, *commonData).svalue;
|
||||
epd->getTextBounds(sval_dtw, 0, 0, &x, &y, &w, &h);
|
||||
epd->setCursor(160-w, 257);
|
||||
epd->print(sval_dtw);
|
||||
|
||||
GwApi::BoatValue *bv_btw = pageData.values[3]; // BTW
|
||||
String sval_btw = formatValue(bv_btw, *commonData).svalue;
|
||||
printBoatValue(sval_btw, 368, 257, RIGHT, 30, smallDecimals);
|
||||
String sval_btw = commonData->fmt->formatValue(bv_btw, *commonData).svalue;
|
||||
epd->getTextBounds(sval_btw, 0, 0, &x, &y, &w, &h);
|
||||
epd->setCursor(360-w, 257);
|
||||
epd->print(sval_btw);
|
||||
|
||||
GwApi::BoatValue *bv_wpname = pageData.values[4]; // WPName
|
||||
|
||||
bool valid = bv_cog->valid && bv_btw->valid;
|
||||
|
||||
// XTETrack view
|
||||
|
||||
// draw ship symbol (as bitmap)
|
||||
getdisplay().drawXBitmap(184, 68, ship_bits, ship_width, ship_height, commonData->fgcolor);
|
||||
epd->drawXBitmap(184, 68, ship_bits, ship_width, ship_height, commonData->fgcolor);
|
||||
|
||||
// draw next waypoint name
|
||||
String sval_wpname = "no data";
|
||||
|
||||
if (valid) {
|
||||
sval_wpname = "Tonne 122";
|
||||
sval_wpname = bv_wpname->svalue;
|
||||
}
|
||||
|
||||
int16_t x, y;
|
||||
uint16_t w, h;
|
||||
|
||||
getdisplay().setFont(&Ubuntu_Bold10pt8b);
|
||||
displayGetTextBounds(sval_wpname, 0, 150, &x, &y, &w, &h);
|
||||
epd->setFont(&Ubuntu_Bold10pt8b);
|
||||
epd->getTextBounds(sval_wpname, 0, 150, &x, &y, &w, &h);
|
||||
// TODO if text don't fix use smaller font size.
|
||||
// if smallest size does not fit use 2 lines
|
||||
// last resort: clip with ellipsis
|
||||
getdisplay().setCursor(200 - w / 2, 60);
|
||||
getdisplay().print(sval_wpname);
|
||||
epd->setCursor(200 - w / 2, 60);
|
||||
epd->print(sval_wpname);
|
||||
|
||||
// draw course segments
|
||||
|
||||
@@ -224,7 +227,7 @@ PageDescription registerPageXTETrack(
|
||||
"XTETrack", // Page name
|
||||
createPage, // Action
|
||||
0, // Number of bus values depends on selection in Web configuration
|
||||
{"XTE", "COG", "DTW", "BTW"}, // Bus values we need in the page
|
||||
{"XTE", "COG", "DTW", "BTW", "WPName"}, // Bus values we need in the page
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
|
||||
+29
-26
@@ -1,9 +1,12 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <Arduino.h>
|
||||
#include "GwApi.h"
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include "LedSpiTask.h"
|
||||
// #include "OBPDataOperations.h"
|
||||
|
||||
#define MAX_PAGE_NUMBER 10 // Max number of pages for show data
|
||||
|
||||
@@ -51,7 +54,7 @@ typedef struct{
|
||||
double rotationAngle = 0; // Rotation angle in radiant
|
||||
bool validRotAngle = false; // Valid flag magnet present for rotation sensor
|
||||
struct tm rtcTime; // UTC time from internal RTC
|
||||
bool rtcValid = false; // Internal RTC chip
|
||||
bool rtcValid = false;
|
||||
int sunsetHour = 0;
|
||||
int sunsetMinute = 0;
|
||||
int sunriseHour = 0;
|
||||
@@ -99,15 +102,22 @@ typedef struct{
|
||||
uint8_t length_sec; // seconds until alarm disappeares without user interaction
|
||||
} AlarmData;
|
||||
|
||||
typedef struct{
|
||||
int voltage = 0;
|
||||
} AvgData;
|
||||
|
||||
class Formatter; // forward declaration
|
||||
typedef struct{
|
||||
GwApi::Status status;
|
||||
GwLog *logger = nullptr;
|
||||
GwConfigHandler *config = nullptr;
|
||||
Formatter *fmt = nullptr;
|
||||
SensorData data;
|
||||
SunData sundata;
|
||||
TouchKeyData keydata[6];
|
||||
BacklightData backlight;
|
||||
AlarmData alarm;
|
||||
AvgData avgdata;
|
||||
GwApi::BoatValue *time = nullptr;
|
||||
GwApi::BoatValue *date = nullptr;
|
||||
uint16_t fgcolor;
|
||||
@@ -119,14 +129,31 @@ typedef struct{
|
||||
//a base class that all pages must inherit from
|
||||
class Page{
|
||||
protected:
|
||||
// TODO Future: GwApi *api;
|
||||
CommonData *commonData;
|
||||
GwConfigHandler *config;
|
||||
GwLog *logger;
|
||||
bool simulation = false;
|
||||
bool holdvalues = false;
|
||||
String flashLED;
|
||||
String backlightMode;
|
||||
public:
|
||||
Page(CommonData &common) {
|
||||
commonData = &common;
|
||||
config = commonData->config;
|
||||
logger = commonData->logger;
|
||||
// preload generic configuration data
|
||||
simulation = config->getBool(config->useSimuData);
|
||||
holdvalues = config->getBool(config->holdvalues);
|
||||
flashLED = config->getString(config->flashLED);
|
||||
backlightMode = config->getString(config->backlight);
|
||||
}
|
||||
int refreshtime = 1000;
|
||||
virtual int displayPage(PageData &pageData)=0;
|
||||
virtual void displayNew(PageData &pageData){}
|
||||
virtual void leavePage(PageData &pageData){}
|
||||
virtual void setupKeys() {
|
||||
#ifdef BOARD_OBP60S3
|
||||
#ifdef HARDWARE_V21
|
||||
commonData->keydata[0].label = "";
|
||||
commonData->keydata[1].label = "";
|
||||
commonData->keydata[2].label = "#LEFT";
|
||||
@@ -187,27 +214,3 @@ class PageStruct{
|
||||
PageData parameters;
|
||||
PageDescription *description = nullptr;
|
||||
};
|
||||
|
||||
// Standard format functions without overhead
|
||||
String formatDate(String fmttype, uint16_t year, uint8_t month, uint8_t day);
|
||||
String formatTime(char fmttype, uint8_t hour, uint8_t minute, uint8_t second);
|
||||
String formatLatitude(double lat);
|
||||
String formatLongitude(double lon);
|
||||
|
||||
// Structure for formatted boat values
|
||||
typedef struct{
|
||||
double value; // SI value of boat data value
|
||||
double cvalue; // value converted to target unit
|
||||
String svalue; // value converted to target unit and formatted
|
||||
String unit; // target value unit
|
||||
} FormattedData;
|
||||
|
||||
// Formatter for boat values
|
||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata);
|
||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, bool ignoreSimuDataSetting);
|
||||
FormattedData formatValue(GwApi::BoatValue *value, CommonData &commondata, String setPrecision);
|
||||
String formatValue(const double &value, const String &vFormat, CommonData &commondata);
|
||||
|
||||
// Helper method for conversion of any data value from SI to user defined format (defined in OBP60Formatter)
|
||||
double convertValue(const double &value, const String &format, CommonData &commondata);
|
||||
double convertValue(const double &value, const String &name, const String &format, CommonData &commondata);
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
Development information
|
||||
=======================
|
||||
|
||||
This file contains some hints concerning building the firmware as well as
|
||||
developing and debugging it.
|
||||
|
||||
Coding style
|
||||
------------
|
||||
WIP
|
||||
Please format your new code the same as already existing code.
|
||||
|
||||
Some rules:
|
||||
- Preprocessor directives go to column zero
|
||||
- Identation is 4 spaces
|
||||
|
||||
Git commands
|
||||
------------
|
||||
Some useful commands are
|
||||
|
||||
git status
|
||||
git fetch upstream
|
||||
git diff --name-status upstream/master
|
||||
git checkout upstream/master platformio.ini
|
||||
|
||||
# how to reset my Repo to match norbert's status
|
||||
|
||||
git remote add upstream https://github.com/norbert-walter/esp32-nmea2000-obp60
|
||||
git fetch upstream
|
||||
git checkout master
|
||||
git reset --hard upstream/master
|
||||
git push origin master --force
|
||||
|
||||
|
||||
New pages
|
||||
---------
|
||||
To create a new page for OBP60 the following steps are necessary:
|
||||
|
||||
1. Create a page under /lib/obp60task/PageXXXX.cpp. You can use a simple
|
||||
page e.g. PageOneValue.cpp as template
|
||||
2. Set page name in PageXXXX.cpp on file name
|
||||
3. Register new page in /lib/obp60task/obp60task.cpp in function
|
||||
'registerAllPages'
|
||||
4. Add new page in /lib/obp60task/config.json for each page type
|
||||
or use gen_set.py to auto-generate the relevant section of
|
||||
config.json. For further information on that read the comments
|
||||
in gen_set.py.
|
||||
5. Copy the changes in config.json to config_obp40.json and rename
|
||||
strings accordingly. E.g. obp60 to obp40.
|
||||
|
||||
Using Gitpod
|
||||
------------
|
||||
|
||||
Warning: You have to register with gitpod!
|
||||
|
||||
Open web page:
|
||||
https://gitpod.io/#https://github.com/norbert-walter/esp32-nmea2000-obp60/tree/master/lib/obp60task
|
||||
|
||||
Input in terminal:
|
||||
cd /workspace/esp32-nmea2000-obp60
|
||||
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 for OBP60:
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/bootloader.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/firmware.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/partitions.bin
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev<yyyymmdd>-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/obp60_s3-dev<yyyymmdd>-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-dev<yyyymmdd>-all.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-dev<yyyymmdd>-update.bin
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin, ready to flash to offset 0x0000
|
||||
|
||||
Compilation issues
|
||||
------------------
|
||||
? Error while linking: "undefined reference to `registerPageXXX'"
|
||||
: Check if the required page is enabled for current board/environment: #if defined ...
|
||||
|
||||
Debugging tool
|
||||
--------------
|
||||
|
||||
log.txt = text file with error messages from terminal console
|
||||
|
||||
tools/decoder.py -p ESP32S3 -t ~/.platformio/packages/toolchain-xtensa-esp32s3/ -e .pio/build/obp60_s3/firmware.elf log.txt
|
||||
@@ -0,0 +1,19 @@
|
||||
- fix unstable accesspoint availability
|
||||
|
||||
- page refresh after page change and not connected to key codes
|
||||
|
||||
- config: getFloat, getDouble
|
||||
|
||||
- dseg7 font to new version
|
||||
|
||||
- new pages: ais, autopilot, epropulsion
|
||||
|
||||
- automate config.json generation with extra_task.py
|
||||
|
||||
- extend boatdata: ais, waypoints, alarms
|
||||
|
||||
- page clock: sunrise / sunset in local time or UTC
|
||||
|
||||
- implement alerts
|
||||
|
||||
- implement formatter as class
|
||||
@@ -1,38 +0,0 @@
|
||||
Using Gitpod
|
||||
############
|
||||
|
||||
Open web page:
|
||||
https://gitpod.io/#https://github.com/norbert-walter/esp32-nmea2000-obp60/tree/master/lib/obp60task
|
||||
|
||||
Input in terminal:
|
||||
cd /workspace/esp32-nmea2000-obp60
|
||||
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 for OBP60
|
||||
########################
|
||||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/bootloader.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/firmware.bin
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp60_s3/partitions.bin
|
||||
|
||||
/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
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
param(
|
||||
[string]$dir = "."
|
||||
)
|
||||
|
||||
$total = 0
|
||||
|
||||
Get-ChildItem -Path $dir -Recurse -File | Where-Object {
|
||||
$_.Extension -in ".c", ".cpp", ".h"
|
||||
} | ForEach-Object {
|
||||
$lines = [System.Linq.Enumerable]::Count([System.IO.File]::ReadLines($_.FullName))
|
||||
Write-Output "$($_.FullName) : $lines"
|
||||
$total += $lines
|
||||
}
|
||||
|
||||
Write-Output "-----------------------------"
|
||||
Write-Output "Over all files: $total"
|
||||
+493
-518
File diff suppressed because it is too large
Load Diff
+470
-509
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,9 +0,0 @@
|
||||
Debugging tool
|
||||
##############
|
||||
|
||||
log.txt = text file with error messages from terminal console
|
||||
|
||||
cd /home/norbert/esp32-nmea2000-obp60
|
||||
tools/decoder.py -p ESP32S3 -t ~/.platformio/packages/toolchain-xtensa-esp32s3/ -e .pio/build/obp60_s3/firmware.elf log.txt
|
||||
|
||||
tools/decoder.py -p ESP32S3 -t ~/.platformio/packages/toolchain-xtensa-esp32s3/ -e .pio/build/obp70_s3/firmware.elf /home/norbert/Dokumente/Multifunktionsdisplay_OBP60/Crashes/20260313/log.txt
|
||||
@@ -45,6 +45,7 @@ except:
|
||||
env["CPPDEFINES"].extend([("BOARD", env["BOARD"]), ("EPDTYPE", epdtype), ("PCBVERS", pcbvers), ("GXEPD2VERS", gxepd2vers)])
|
||||
|
||||
print("added hardware info to CPPDEFINES")
|
||||
print("friendly board name is '{}'".format(env.GetProjectOption("board_name")))
|
||||
|
||||
if patching:
|
||||
# apply patches to gateway code
|
||||
|
||||
@@ -0,0 +1,273 @@
|
||||
const uint8_t Atari6pxBitmaps[] PROGMEM = {
|
||||
0x00, 0xF0, 0x30, 0xCF, 0x38, 0x80, 0x53, 0xF5, 0x14, 0xFD, 0x40, 0x7E,
|
||||
0x47, 0x85, 0x13, 0xE1, 0x00, 0xC7, 0x21, 0x00, 0x4E, 0x30, 0x63, 0x26,
|
||||
0x39, 0xC3, 0x26, 0x40, 0x6F, 0x00, 0x7B, 0x24, 0xC0, 0xCD, 0xA5, 0x80,
|
||||
0x8B, 0x3E, 0x00, 0x44, 0x10, 0x4F, 0xC4, 0x10, 0x40, 0x6F, 0x00, 0xF8,
|
||||
0xF0, 0x0C, 0x66, 0x18, 0x82, 0x00, 0x7A, 0x39, 0x58, 0x61, 0xE0, 0x75,
|
||||
0x50, 0xF8, 0x17, 0xA0, 0x83, 0xF0, 0xF8, 0x17, 0x80, 0x07, 0xE0, 0x39,
|
||||
0x28, 0xA2, 0xFC, 0x20, 0xFE, 0x0F, 0x80, 0x07, 0xE0, 0x7A, 0x0F, 0xC0,
|
||||
0x01, 0xE0, 0xF8, 0x44, 0x02, 0x10, 0x7A, 0x17, 0x80, 0x85, 0xE0, 0x7A,
|
||||
0x17, 0xC0, 0x01, 0xE0, 0xF0, 0xF0, 0xF3, 0x58, 0x1B, 0x30, 0x42, 0x0C,
|
||||
0xF8, 0x3E, 0xC3, 0x06, 0xC4, 0x60, 0x7A, 0x31, 0x86, 0x00, 0x01, 0x80,
|
||||
0x7A, 0x19, 0xE6, 0x82, 0x07, 0xC0, 0x7A, 0x1F, 0xE1, 0x86, 0x10, 0xFA,
|
||||
0x1F, 0xA0, 0x87, 0xE0, 0x7E, 0x08, 0x00, 0x01, 0xF0, 0xFA, 0x18, 0x60,
|
||||
0x83, 0xE0, 0xFE, 0x0F, 0xA0, 0x83, 0xF0, 0xFE, 0x0F, 0xA0, 0x82, 0x00,
|
||||
0x7E, 0x08, 0xC1, 0x05, 0xF0, 0x86, 0x1F, 0xE1, 0x86, 0x10, 0xF4, 0x44,
|
||||
0x4F, 0x04, 0x10, 0x41, 0x85, 0xE0, 0x8C, 0xB9, 0x09, 0x44, 0x84, 0x21,
|
||||
0x08, 0x7C, 0x83, 0xDE, 0x4C, 0x18, 0x30, 0x40, 0x83, 0xC6, 0x4C, 0x18,
|
||||
0xF0, 0x40, 0x7A, 0x18, 0x40, 0x01, 0xE0, 0xFA, 0x1F, 0xA0, 0x82, 0x00,
|
||||
0x7A, 0x18, 0x40, 0x01, 0xE0, 0xC0, 0xFA, 0x1F, 0xA4, 0x92, 0x30, 0x7E,
|
||||
0x07, 0x80, 0x07, 0xE0, 0xFC, 0x41, 0x04, 0x10, 0x40, 0x86, 0x18, 0x61,
|
||||
0x85, 0xE0, 0x86, 0x10, 0x00, 0x48, 0x40, 0x83, 0x06, 0x4C, 0x1E, 0xF0,
|
||||
0x40, 0x85, 0x21, 0x00, 0x4A, 0x10, 0x86, 0x14, 0x80, 0x10, 0x40, 0xFC,
|
||||
0x21, 0x10, 0x43, 0xF0, 0xFC, 0xCC, 0xCF, 0xC1, 0x81, 0x86, 0x04, 0x10,
|
||||
0xF3, 0x33, 0x3F, 0x11, 0xEC, 0xC0, 0xFC, 0xD9, 0x80, 0x78, 0x10, 0x7F,
|
||||
0x7C, 0x83, 0xE8, 0x61, 0x83, 0xE0, 0x7E, 0x08, 0x00, 0x7C, 0x05, 0xF8,
|
||||
0x61, 0x05, 0xF0, 0x7B, 0xF8, 0x00, 0x78, 0x1A, 0x3E, 0x84, 0x20, 0x7E,
|
||||
0x17, 0xC1, 0x07, 0xE0, 0x81, 0x33, 0x8C, 0x18, 0x30, 0x40, 0xC4, 0x44,
|
||||
0xF0, 0x08, 0x42, 0x10, 0x87, 0xC0, 0x82, 0x2F, 0x20, 0x8A, 0x10, 0xC4,
|
||||
0x44, 0x4F, 0x4B, 0xF9, 0x61, 0x84, 0xFA, 0x18, 0x61, 0x84, 0x7A, 0x18,
|
||||
0x40, 0x78, 0xFA, 0x18, 0x60, 0xFA, 0x00, 0x7E, 0x18, 0x41, 0x7C, 0x10,
|
||||
0xF4, 0x61, 0x08, 0x00, 0x7E, 0x00, 0x3F, 0x00, 0x4F, 0x44, 0x41, 0x86,
|
||||
0x10, 0x41, 0x7C, 0x86, 0x10, 0x12, 0x10, 0x83, 0x26, 0x4C, 0x1E, 0xE0,
|
||||
0x8B, 0x18, 0x08, 0x80, 0x86, 0x17, 0xC1, 0x07, 0xE0, 0xF8, 0x94, 0x8F,
|
||||
0x80, 0x76, 0xC6, 0x67, 0xFF, 0xFC, 0xE6, 0x36, 0x6E, 0x41, 0x0B, 0x6F,
|
||||
0x08, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD,
|
||||
0xFC, 0x11, 0xEC, 0x71, 0xFC, 0x11, 0xEC, 0xC4, 0x10, 0x41, 0x00, 0x10,
|
||||
0x40, 0x33, 0x49, 0xE1, 0x00, 0x08, 0x1B, 0xD8, 0x40, 0x81, 0x00, 0x10,
|
||||
0xE3, 0x39, 0x01, 0x02, 0x00, 0x7A, 0x5E, 0xC4, 0x11, 0xE0, 0xFF, 0xEF,
|
||||
0x3C, 0xC6, 0x30, 0xEE, 0x57, 0xA1, 0x87, 0xB0, 0x06, 0x1A, 0x64, 0x86,
|
||||
0x08, 0x00, 0x7D, 0x06, 0x4C, 0xD8, 0x30, 0x5F, 0x00, 0x18, 0xF9, 0xF7,
|
||||
0xF0, 0x00, 0x06, 0x00, 0x08, 0x30, 0x9E, 0x7B, 0xE6, 0x00, 0xF1, 0x03,
|
||||
0xBC, 0x48, 0x81, 0x82, 0x00, 0xF1, 0x02, 0x77, 0xA1, 0x43, 0x85, 0x80,
|
||||
0x12, 0x24, 0x48, 0x97, 0x3E, 0x70, 0x80, 0x92, 0x4D, 0xD8, 0xFF, 0x1C,
|
||||
0x73, 0xCF, 0x3F, 0xC0, 0xC4, 0x4F, 0xFF, 0xF0, 0x7C, 0x1F, 0xF0, 0xC3,
|
||||
0x0F, 0xC0, 0xF8, 0x2F, 0xC3, 0x0C, 0x3F, 0xC0, 0xC3, 0x0C, 0xFF, 0x0C,
|
||||
0x30, 0xC0, 0xFB, 0x0F, 0xC3, 0x0C, 0x3F, 0xC0, 0xC3, 0x0F, 0xE3, 0xCF,
|
||||
0x3F, 0xC0, 0xFC, 0x13, 0xCC, 0x30, 0xC3, 0x00, 0x71, 0x47, 0x37, 0xDF,
|
||||
0x7F, 0xC0, 0xFF, 0x3C, 0x7F, 0x0C, 0x30, 0xC0, 0x78, 0x00, 0x7F, 0x78,
|
||||
0xF0, 0x80, 0xEF, 0x88, 0x88, 0xF8, 0x0F, 0x1E, 0xFF, 0x84, 0x08, 0x1E,
|
||||
0x26, 0x00, 0xF3, 0x20, 0xC1, 0x05, 0xF1, 0x40, 0x42, 0x2C, 0x50, 0x40,
|
||||
0x1E, 0xF0, 0x00, 0x07, 0x24, 0x80, 0x93, 0x80, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC, 0xFC, 0x7F, 0xDD, 0xFC,
|
||||
0xFC, 0x7F, 0xDD, 0xFC };
|
||||
|
||||
const GFXglyph Atari6pxGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 7, 0, 0 }, // 0x20 ' ' U+0020
|
||||
{ 1, 2, 6, 6, 2, -5 }, // 0x21 '!' U+0021
|
||||
{ 3, 6, 3, 7, 0, -5 }, // 0x22 '"' U+0022
|
||||
{ 6, 6, 6, 7, 0, -5 }, // 0x23 '#' U+0023
|
||||
{ 11, 6, 7, 7, 0, -5 }, // 0x24 '$' U+0024
|
||||
{ 17, 6, 6, 7, 0, -5 }, // 0x25 '%' U+0025
|
||||
{ 22, 6, 7, 7, 0, -6 }, // 0x26 '&' U+0026
|
||||
{ 28, 3, 3, 6, 1, -5 }, // 0x27 ''' U+0027
|
||||
{ 30, 3, 6, 6, 1, -5 }, // 0x28 '(' U+0028
|
||||
{ 33, 3, 6, 6, 1, -5 }, // 0x29 ')' U+0029
|
||||
{ 36, 5, 6, 7, 1, -5 }, // 0x2a '*' U+002A
|
||||
{ 40, 6, 6, 7, 0, -5 }, // 0x2b '+' U+002B
|
||||
{ 45, 3, 3, 6, 1, -1 }, // 0x2c ',' U+002C
|
||||
{ 47, 5, 1, 7, 1, -3 }, // 0x2d '-' U+002D
|
||||
{ 48, 2, 2, 6, 2, -1 }, // 0x2e '.' U+002E
|
||||
{ 49, 6, 6, 7, 0, -5 }, // 0x2f '/' U+002F
|
||||
{ 54, 6, 6, 7, 0, -5 }, // 0x30 '0' U+0030
|
||||
{ 59, 2, 6, 7, 3, -5 }, // 0x31 '1' U+0031
|
||||
{ 61, 6, 6, 7, 0, -5 }, // 0x32 '2' U+0032
|
||||
{ 66, 6, 6, 7, 0, -5 }, // 0x33 '3' U+0033
|
||||
{ 71, 6, 6, 7, 0, -5 }, // 0x34 '4' U+0034
|
||||
{ 76, 6, 6, 7, 0, -5 }, // 0x35 '5' U+0035
|
||||
{ 81, 6, 6, 7, 0, -5 }, // 0x36 '6' U+0036
|
||||
{ 86, 5, 6, 7, 0, -5 }, // 0x37 '7' U+0037
|
||||
{ 90, 6, 6, 7, 0, -5 }, // 0x38 '8' U+0038
|
||||
{ 95, 6, 6, 7, 0, -5 }, // 0x39 '9' U+0039
|
||||
{ 100, 2, 6, 6, 2, -5 }, // 0x3a ':' U+003A
|
||||
{ 102, 2, 7, 6, 2, -5 }, // 0x3b ';' U+003B
|
||||
{ 104, 5, 6, 7, 1, -5 }, // 0x3c '<' U+003C
|
||||
{ 108, 5, 3, 7, 1, -4 }, // 0x3d '=' U+003D
|
||||
{ 110, 5, 6, 7, 1, -5 }, // 0x3e '>' U+003E
|
||||
{ 114, 6, 7, 7, 0, -5 }, // 0x3f '?' U+003F
|
||||
{ 120, 6, 7, 7, 0, -5 }, // 0x40 '@' U+0040
|
||||
{ 126, 6, 6, 7, 0, -5 }, // 0x41 'A' U+0041
|
||||
{ 131, 6, 6, 7, 0, -5 }, // 0x42 'B' U+0042
|
||||
{ 136, 6, 6, 7, 0, -5 }, // 0x43 'C' U+0043
|
||||
{ 141, 6, 6, 7, 0, -5 }, // 0x44 'D' U+0044
|
||||
{ 146, 6, 6, 7, 0, -5 }, // 0x45 'E' U+0045
|
||||
{ 151, 6, 6, 7, 0, -5 }, // 0x46 'F' U+0046
|
||||
{ 156, 6, 6, 7, 0, -5 }, // 0x47 'G' U+0047
|
||||
{ 161, 6, 6, 7, 0, -5 }, // 0x48 'H' U+0048
|
||||
{ 166, 4, 6, 7, 1, -5 }, // 0x49 'I' U+0049
|
||||
{ 169, 6, 6, 7, 0, -5 }, // 0x4a 'J' U+004A
|
||||
{ 174, 5, 6, 7, 1, -5 }, // 0x4b 'K' U+004B
|
||||
{ 178, 5, 6, 7, 1, -5 }, // 0x4c 'L' U+004C
|
||||
{ 182, 7, 6, 8, 0, -5 }, // 0x4d 'M' U+004D
|
||||
{ 188, 7, 6, 8, 0, -5 }, // 0x4e 'N' U+004E
|
||||
{ 194, 6, 6, 7, 0, -5 }, // 0x4f 'O' U+004F
|
||||
{ 199, 6, 6, 7, 0, -5 }, // 0x50 'P' U+0050
|
||||
{ 204, 6, 7, 7, 0, -5 }, // 0x51 'Q' U+0051
|
||||
{ 210, 6, 6, 7, 0, -5 }, // 0x52 'R' U+0052
|
||||
{ 215, 6, 6, 7, 0, -5 }, // 0x53 'S' U+0053
|
||||
{ 220, 6, 6, 7, 0, -5 }, // 0x54 'T' U+0054
|
||||
{ 225, 6, 6, 7, 0, -5 }, // 0x55 'U' U+0055
|
||||
{ 230, 6, 6, 7, 0, -5 }, // 0x56 'V' U+0056
|
||||
{ 235, 7, 6, 8, 0, -5 }, // 0x57 'W' U+0057
|
||||
{ 241, 6, 6, 7, 0, -5 }, // 0x58 'X' U+0058
|
||||
{ 246, 6, 6, 7, 0, -5 }, // 0x59 'Y' U+0059
|
||||
{ 251, 6, 6, 7, 0, -5 }, // 0x5a 'Z' U+005A
|
||||
{ 256, 4, 6, 7, 1, -5 }, // 0x5b '[' U+005B
|
||||
{ 259, 6, 6, 7, 0, -5 }, // 0x5c '\' U+005C
|
||||
{ 264, 4, 6, 7, 2, -5 }, // 0x5d ']' U+005D
|
||||
{ 267, 6, 3, 7, 0, -5 }, // 0x5e '^' U+005E
|
||||
{ 270, 6, 1, 7, 0, 0 }, // 0x5f '_' U+005F
|
||||
{ 271, 3, 3, 6, 1, -5 }, // 0x60 '`' U+0060
|
||||
{ 273, 6, 5, 7, 0, -4 }, // 0x61 'a' U+0061
|
||||
{ 277, 6, 6, 7, 0, -5 }, // 0x62 'b' U+0062
|
||||
{ 282, 6, 5, 7, 0, -4 }, // 0x63 'c' U+0063
|
||||
{ 286, 6, 6, 7, 0, -5 }, // 0x64 'd' U+0064
|
||||
{ 291, 6, 5, 7, 0, -4 }, // 0x65 'e' U+0065
|
||||
{ 295, 5, 6, 7, 1, -5 }, // 0x66 'f' U+0066
|
||||
{ 299, 6, 6, 7, 0, -4 }, // 0x67 'g' U+0067
|
||||
{ 304, 7, 6, 8, 0, -5 }, // 0x68 'h' U+0068
|
||||
{ 310, 4, 5, 7, 1, -4 }, // 0x69 'i' U+0069
|
||||
{ 313, 5, 7, 7, 0, -5 }, // 0x6a 'j' U+006A
|
||||
{ 318, 6, 6, 7, 0, -5 }, // 0x6b 'k' U+006B
|
||||
{ 323, 4, 6, 7, 1, -5 }, // 0x6c 'l' U+006C
|
||||
{ 326, 6, 5, 7, 0, -4 }, // 0x6d 'm' U+006D
|
||||
{ 330, 6, 5, 7, 0, -4 }, // 0x6e 'n' U+006E
|
||||
{ 334, 6, 5, 7, 0, -4 }, // 0x6f 'o' U+006F
|
||||
{ 338, 6, 6, 7, 0, -4 }, // 0x70 'p' U+0070
|
||||
{ 343, 6, 6, 7, 0, -4 }, // 0x71 'q' U+0071
|
||||
{ 348, 5, 5, 7, 1, -4 }, // 0x72 'r' U+0072
|
||||
{ 352, 5, 5, 7, 1, -4 }, // 0x73 's' U+0073
|
||||
{ 356, 4, 6, 7, 1, -5 }, // 0x74 't' U+0074
|
||||
{ 359, 6, 5, 7, 0, -4 }, // 0x75 'u' U+0075
|
||||
{ 363, 6, 5, 7, 0, -4 }, // 0x76 'v' U+0076
|
||||
{ 367, 7, 5, 8, 0, -4 }, // 0x77 'w' U+0077
|
||||
{ 372, 5, 5, 7, 0, -4 }, // 0x78 'x' U+0078
|
||||
{ 376, 6, 6, 7, 0, -4 }, // 0x79 'y' U+0079
|
||||
{ 381, 5, 5, 7, 1, -4 }, // 0x7a 'z' U+007A
|
||||
{ 385, 4, 6, 6, 1, -5 }, // 0x7b '{' U+007B
|
||||
{ 388, 2, 7, 7, 4, -5 }, // 0x7c '|' U+007C
|
||||
{ 390, 4, 6, 6, 1, -5 }, // 0x7d '}' U+007D
|
||||
{ 393, 6, 5, 7, 0, -5 }, // 0x7e '~' U+007E
|
||||
{ 397, 5, 6, 6, 0, -5 }, // 0x7f 'REPLACEMENT CHARACTER *' U+2370
|
||||
{ 401, 5, 6, 6, 0, -5 }, // 0x80 'NO-BREAK SPACE' U+00A0
|
||||
{ 405, 5, 6, 6, 0, -5 }, // 0x81 'INVERTED EXCLAMATION MARK' U+00A1
|
||||
{ 409, 5, 6, 6, 0, -5 }, // 0x82 'CENT SIGN' U+00A2
|
||||
{ 413, 5, 6, 6, 0, -5 }, // 0x83 'POUND SIGN' U+00A3
|
||||
{ 417, 5, 6, 6, 0, -5 }, // 0x84 'CURRENCY SIGN' U+00A4
|
||||
{ 421, 5, 6, 6, 0, -5 }, // 0x85 'YEN SIGN' U+00A5
|
||||
{ 425, 5, 6, 6, 0, -5 }, // 0x86 'BROKEN BAR' U+00A6
|
||||
{ 429, 5, 6, 6, 0, -5 }, // 0x87 'SECTION SIGN' U+00A7
|
||||
{ 433, 5, 6, 6, 0, -5 }, // 0x88 'DIAERESIS' U+00A8
|
||||
{ 437, 5, 6, 6, 0, -5 }, // 0x89 'COPYRIGHT SIGN' U+00A9
|
||||
{ 441, 5, 6, 6, 0, -5 }, // 0x8a 'FEMININE ORDINAL INDICATOR' U+00AA
|
||||
{ 445, 5, 6, 6, 0, -5 }, // 0x8b 'LEFT-POINTING DOUBLE ANGLE QUOTATION MARK' U+00AB
|
||||
{ 449, 5, 6, 6, 0, -5 }, // 0x8c 'NOT SIGN' U+00AC
|
||||
{ 453, 5, 6, 6, 0, -5 }, // 0x8d 'SOFT HYPHEN' U+00AD
|
||||
{ 457, 5, 6, 6, 0, -5 }, // 0x8e 'REGISTERED SIGN' U+00AE
|
||||
{ 461, 5, 6, 6, 0, -5 }, // 0x8f 'MACRON' U+00AF
|
||||
{ 465, 5, 6, 6, 0, -5 }, // 0x90 'DEGREE SIGN' U+00B0
|
||||
{ 469, 5, 6, 6, 0, -5 }, // 0x91 'PLUS-MINUS SIGN' U+00B1
|
||||
{ 473, 5, 6, 6, 0, -5 }, // 0x92 'SUPERSCRIPT TWO' U+00B2
|
||||
{ 477, 5, 6, 6, 0, -5 }, // 0x93 'SUPERSCRIPT THREE' U+00B3
|
||||
{ 481, 5, 6, 6, 0, -5 }, // 0x94 'ACUTE ACCENT' U+00B4
|
||||
{ 485, 5, 6, 6, 0, -5 }, // 0x95 'MICRO SIGN' U+00B5
|
||||
{ 489, 5, 6, 6, 0, -5 }, // 0x96 'PILCROW SIGN' U+00B6
|
||||
{ 493, 5, 6, 6, 0, -5 }, // 0x97 'MIDDLE DOT' U+00B7
|
||||
{ 497, 5, 6, 6, 0, -5 }, // 0x98 'CEDILLA' U+00B8
|
||||
{ 501, 5, 6, 6, 0, -5 }, // 0x99 'SUPERSCRIPT ONE' U+00B9
|
||||
{ 505, 5, 6, 6, 0, -5 }, // 0x9a 'MASCULINE ORDINAL INDICATOR' U+00BA
|
||||
{ 509, 5, 6, 6, 0, -5 }, // 0x9b 'RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK' U+00BB
|
||||
{ 513, 5, 6, 6, 0, -5 }, // 0x9c 'VULGAR FRACTION ONE QUARTER' U+00BC
|
||||
{ 517, 5, 6, 6, 0, -5 }, // 0x9d 'VULGAR FRACTION ONE HALF' U+00BD
|
||||
{ 521, 5, 6, 6, 0, -5 }, // 0x9e 'VULGAR FRACTION THREE QUARTERS' U+00BE
|
||||
{ 525, 5, 6, 6, 0, -5 }, // 0x9f 'INVERTED QUESTION MARK' U+00BF
|
||||
{ 529, 6, 5, 7, 0, -4 }, // 0xa0 'LATIN CAPITAL LETTER A WITH GRAVE' U+00C0
|
||||
{ 533, 6, 7, 7, 0, -5 }, // 0xa1 'LATIN CAPITAL LETTER A WITH ACUTE' U+00C1
|
||||
{ 539, 6, 7, 7, 0, -5 }, // 0xa2 'LATIN CAPITAL LETTER A WITH CIRCUMFLEX' U+00C2
|
||||
{ 545, 7, 6, 7, 0, -5 }, // 0xa3 'LATIN CAPITAL LETTER A WITH TILDE' U+00C3
|
||||
{ 551, 7, 6, 7, 0, -5 }, // 0xa4 'LATIN CAPITAL LETTER A WITH DIAERESIS' U+00C4
|
||||
{ 557, 6, 6, 7, 0, -5 }, // 0xa5 'LATIN CAPITAL LETTER A WITH RING ABOVE' U+00C5
|
||||
{ 562, 6, 6, 7, 0, -5 }, // 0xa6 'LATIN CAPITAL LETTER AE' U+00C6
|
||||
{ 567, 6, 6, 7, 0, -5 }, // 0xa7 'LATIN CAPITAL LETTER C WITH CEDILLA' U+00C7
|
||||
{ 572, 7, 6, 7, 0, -5 }, // 0xa8 'LATIN CAPITAL LETTER E WITH GRAVE' U+00C8
|
||||
{ 578, 7, 7, 7, 0, -5 }, // 0xa9 'LATIN CAPITAL LETTER E WITH ACUTE' U+00C9
|
||||
{ 585, 7, 7, 7, 0, -5 }, // 0xaa 'LATIN CAPITAL LETTER E WITH CIRCUMFLEX' U+00CA
|
||||
{ 592, 6, 7, 7, 0, -5 }, // 0xab 'LATIN CAPITAL LETTER E WITH DIAERESIS' U+00CB
|
||||
{ 598, 7, 7, 7, 0, -5 }, // 0xac 'LATIN CAPITAL LETTER I WITH GRAVE' U+00CC
|
||||
{ 605, 7, 7, 7, 0, -5 }, // 0xad 'LATIN CAPITAL LETTER I WITH ACUTE' U+00CD
|
||||
{ 612, 7, 7, 8, 1, -5 }, // 0xae 'LATIN CAPITAL LETTER I WITH CIRCUMFLEX' U+00CE
|
||||
{ 619, 3, 7, 6, 1, -5 }, // 0xaf 'LATIN CAPITAL LETTER I WITH DIAERESIS' U+00CF
|
||||
{ 622, 6, 7, 7, 0, -5 }, // 0xb0 'LATIN CAPITAL LETTER ETH' U+00D0
|
||||
{ 628, 4, 7, 7, 1, -5 }, // 0xb1 'LATIN CAPITAL LETTER N WITH TILDE' U+00D1
|
||||
{ 632, 6, 7, 7, 0, -5 }, // 0xb2 'LATIN CAPITAL LETTER O WITH GRAVE' U+00D2
|
||||
{ 638, 6, 7, 7, 0, -5 }, // 0xb3 'LATIN CAPITAL LETTER O WITH ACUTE' U+00D3
|
||||
{ 644, 6, 7, 7, 0, -5 }, // 0xb4 'LATIN CAPITAL LETTER O WITH CIRCUMFLEX' U+00D4
|
||||
{ 650, 6, 7, 7, 0, -5 }, // 0xb5 'LATIN CAPITAL LETTER O WITH TILDE' U+00D5
|
||||
{ 656, 6, 7, 7, 0, -5 }, // 0xb6 'LATIN CAPITAL LETTER O WITH DIAERESIS' U+00D6
|
||||
{ 662, 6, 7, 7, 0, -5 }, // 0xb7 'MULTIPLICATION SIGN' U+00D7
|
||||
{ 668, 6, 7, 7, 0, -5 }, // 0xb8 'LATIN CAPITAL LETTER O WITH STROKE' U+00D8
|
||||
{ 674, 6, 7, 7, 0, -5 }, // 0xb9 'LATIN CAPITAL LETTER U WITH GRAVE' U+00D9
|
||||
{ 680, 6, 5, 7, 0, -4 }, // 0xba 'LATIN CAPITAL LETTER U WITH ACUTE' U+00DA
|
||||
{ 684, 8, 7, 8, 0, -5 }, // 0xbb 'LATIN CAPITAL LETTER U WITH CIRCUMFLEX' U+00DB
|
||||
{ 691, 7, 7, 8, 1, -5 }, // 0xbc 'LATIN CAPITAL LETTER U WITH DIAERESIS' U+00DC
|
||||
{ 698, 6, 7, 7, 0, -5 }, // 0xbd 'LATIN CAPITAL LETTER Y WITH ACUTE' U+00DD
|
||||
{ 704, 7, 7, 7, 0, -5 }, // 0xbe 'LATIN CAPITAL LETTER THORN' U+00DE
|
||||
{ 711, 6, 6, 7, 0, -5 }, // 0xbf 'LATIN SMALL LETTER SHARP S' U+00DF
|
||||
{ 716, 5, 6, 6, 0, -5 }, // 0xc0 'LATIN SMALL LETTER A WITH GRAVE' U+00E0
|
||||
{ 720, 5, 6, 6, 0, -5 }, // 0xc1 'LATIN SMALL LETTER A WITH ACUTE' U+00E1
|
||||
{ 724, 5, 6, 6, 0, -5 }, // 0xc2 'LATIN SMALL LETTER A WITH CIRCUMFLEX' U+00E2
|
||||
{ 728, 5, 6, 6, 0, -5 }, // 0xc3 'LATIN SMALL LETTER A WITH TILDE' U+00E3
|
||||
{ 732, 5, 6, 6, 0, -5 }, // 0xc4 'LATIN SMALL LETTER A WITH DIAERESIS' U+00E4
|
||||
{ 736, 5, 6, 6, 0, -5 }, // 0xc5 'LATIN SMALL LETTER A WITH RING ABOVE' U+00E5
|
||||
{ 740, 5, 6, 6, 0, -5 }, // 0xc6 'LATIN SMALL LETTER AE' U+00E6
|
||||
{ 744, 5, 6, 6, 0, -5 }, // 0xc7 'LATIN SMALL LETTER C WITH CEDILLA' U+00E7
|
||||
{ 748, 5, 6, 6, 0, -5 }, // 0xc8 'LATIN SMALL LETTER E WITH GRAVE' U+00E8
|
||||
{ 752, 5, 6, 6, 0, -5 }, // 0xc9 'LATIN SMALL LETTER E WITH ACUTE' U+00E9
|
||||
{ 756, 5, 6, 6, 0, -5 }, // 0xca 'LATIN SMALL LETTER E WITH CIRCUMFLEX' U+00EA
|
||||
{ 760, 5, 6, 6, 0, -5 }, // 0xcb 'LATIN SMALL LETTER E WITH DIAERESIS' U+00EB
|
||||
{ 764, 5, 6, 6, 0, -5 }, // 0xcc 'LATIN SMALL LETTER I WITH GRAVE' U+00EC
|
||||
{ 768, 5, 6, 6, 0, -5 }, // 0xcd 'LATIN SMALL LETTER I WITH ACUTE' U+00ED
|
||||
{ 772, 5, 6, 6, 0, -5 }, // 0xce 'LATIN SMALL LETTER I WITH CIRCUMFLEX' U+00EE
|
||||
{ 776, 5, 6, 6, 0, -5 }, // 0xcf 'LATIN SMALL LETTER I WITH DIAERESIS' U+00EF
|
||||
{ 780, 5, 6, 6, 0, -5 }, // 0xd0 'LATIN SMALL LETTER ETH' U+00F0
|
||||
{ 784, 5, 6, 6, 0, -5 }, // 0xd1 'LATIN SMALL LETTER N WITH TILDE' U+00F1
|
||||
{ 788, 5, 6, 6, 0, -5 }, // 0xd2 'LATIN SMALL LETTER O WITH GRAVE' U+00F2
|
||||
{ 792, 5, 6, 6, 0, -5 }, // 0xd3 'LATIN SMALL LETTER O WITH ACUTE' U+00F3
|
||||
{ 796, 5, 6, 6, 0, -5 }, // 0xd4 'LATIN SMALL LETTER O WITH CIRCUMFLEX' U+00F4
|
||||
{ 800, 5, 6, 6, 0, -5 }, // 0xd5 'LATIN SMALL LETTER O WITH TILDE' U+00F5
|
||||
{ 804, 5, 6, 6, 0, -5 }, // 0xd6 'LATIN SMALL LETTER O WITH DIAERESIS' U+00F6
|
||||
{ 808, 5, 6, 6, 0, -5 }, // 0xd7 'DIVISION SIGN' U+00F7
|
||||
{ 812, 5, 6, 6, 0, -5 }, // 0xd8 'LATIN SMALL LETTER O WITH STROKE' U+00F8
|
||||
{ 816, 5, 6, 6, 0, -5 }, // 0xd9 'LATIN SMALL LETTER U WITH GRAVE' U+00F9
|
||||
{ 820, 5, 6, 6, 0, -5 }, // 0xda 'LATIN SMALL LETTER U WITH ACUTE' U+00FA
|
||||
{ 824, 5, 6, 6, 0, -5 }, // 0xdb 'LATIN SMALL LETTER U WITH CIRCUMFLEX' U+00FB
|
||||
{ 828, 5, 6, 6, 0, -5 }, // 0xdc 'LATIN SMALL LETTER U WITH DIAERESIS' U+00FC
|
||||
{ 832, 5, 6, 6, 0, -5 }, // 0xdd 'LATIN SMALL LETTER Y WITH ACUTE' U+00FD
|
||||
{ 836, 5, 6, 6, 0, -5 }, // 0xde 'LATIN SMALL LETTER THORN' U+00FE
|
||||
{ 840, 5, 6, 6, 0, -5 } }; // 0xdf 'LATIN SMALL LETTER Y WITH DIAERESIS' U+000FF
|
||||
|
||||
const GFXfont Atari6px PROGMEM = {
|
||||
(uint8_t *)Atari6pxBitmaps,
|
||||
(GFXglyph *)Atari6pxGlyphs,
|
||||
0x20, 0xDF, 9 };
|
||||
|
||||
// Approx. 2195 bytes
|
||||
@@ -1,278 +0,0 @@
|
||||
const uint8_t DSEG7Classic_BoldItalic10pt7bBitmaps[] PROGMEM = {
|
||||
0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE,
|
||||
0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18,
|
||||
0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61,
|
||||
0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86,
|
||||
0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18,
|
||||
0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86,
|
||||
0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18,
|
||||
0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87,
|
||||
0xF0, 0xFF, 0x7F, 0x80, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86,
|
||||
0x18, 0x61, 0x87, 0xF0, 0x1F, 0xF8, 0xBF, 0xD3, 0x00, 0xCC, 0x07, 0x70,
|
||||
0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07, 0x70, 0x19, 0x00, 0x24, 0x00, 0x98,
|
||||
0x06, 0x60, 0x19, 0x80, 0x66, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEB,
|
||||
0xFF, 0x9F, 0xF8, 0x13, 0x77, 0x77, 0x76, 0x22, 0x66, 0x6E, 0xEE, 0xE6,
|
||||
0x1F, 0xF8, 0x3F, 0xD0, 0x00, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01,
|
||||
0xC0, 0x07, 0x00, 0x18, 0x7F, 0xA5, 0xFE, 0x18, 0x00, 0x60, 0x01, 0x80,
|
||||
0x06, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0B, 0xFE, 0x1F, 0xF8, 0x3F,
|
||||
0xF0, 0xFF, 0x40, 0x06, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07,
|
||||
0x00, 0x31, 0xFE, 0x8F, 0xF4, 0x00, 0x60, 0x03, 0x00, 0x18, 0x01, 0xC0,
|
||||
0x0E, 0x00, 0x70, 0x03, 0x9F, 0xFD, 0xFF, 0x80, 0x40, 0x0B, 0x00, 0xD8,
|
||||
0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x06, 0xBF, 0xD1, 0xFE,
|
||||
0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70,
|
||||
0x01, 0x80, 0x3F, 0xF5, 0xFE, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0,
|
||||
0x0E, 0x00, 0xE0, 0x0B, 0xFC, 0x3F, 0xD0, 0x03, 0x00, 0x30, 0x03, 0x00,
|
||||
0x70, 0x07, 0x00, 0x70, 0x07, 0x7F, 0xFF, 0xFC, 0x1F, 0xF9, 0x7F, 0x8C,
|
||||
0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x02, 0xFF,
|
||||
0x17, 0xFA, 0xC0, 0x36, 0x01, 0xB0, 0x0D, 0x80, 0xFC, 0x07, 0xE0, 0x3F,
|
||||
0x01, 0xEF, 0xFE, 0xFF, 0xC0, 0x3F, 0xF2, 0xFF, 0x58, 0x06, 0xC0, 0x7E,
|
||||
0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x34, 0x00, 0x80, 0x04, 0x00,
|
||||
0x60, 0x03, 0x00, 0x18, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x0C,
|
||||
0x1F, 0xF8, 0xBF, 0xD3, 0x00, 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01,
|
||||
0xDC, 0x07, 0x70, 0x19, 0x7F, 0xA5, 0xFE, 0x98, 0x06, 0x60, 0x19, 0x80,
|
||||
0x66, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xEB, 0xFF, 0x9F, 0xF8, 0x3F,
|
||||
0xF2, 0xFF, 0x58, 0x06, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07,
|
||||
0xE0, 0x35, 0xFE, 0x8F, 0xF4, 0x00, 0x60, 0x03, 0x00, 0x18, 0x01, 0xC0,
|
||||
0x0E, 0x00, 0x70, 0x03, 0x9F, 0xFD, 0xFF, 0x80, 0x67, 0x00, 0x00, 0x00,
|
||||
0x4E, 0x40, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87,
|
||||
0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0,
|
||||
0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE,
|
||||
0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18,
|
||||
0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61,
|
||||
0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0x1F, 0xF8, 0xBF, 0xD3,
|
||||
0x00, 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07, 0x70, 0x19,
|
||||
0x7F, 0xA5, 0xFE, 0x98, 0x06, 0x60, 0x19, 0x80, 0x66, 0x03, 0xB8, 0x0E,
|
||||
0xE0, 0x3B, 0x80, 0xE8, 0x01, 0x80, 0x20, 0x01, 0x80, 0x0C, 0x00, 0xE0,
|
||||
0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x5F, 0xE2, 0xFF, 0x58, 0x06,
|
||||
0xC0, 0x36, 0x01, 0xB0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3D, 0xFF, 0xDF,
|
||||
0xF8, 0x1F, 0xE5, 0xFE, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E,
|
||||
0x00, 0xE0, 0x0B, 0xFE, 0x7F, 0xE0, 0x00, 0x04, 0x00, 0x30, 0x01, 0xC0,
|
||||
0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x06, 0x1F, 0xE9, 0x7F, 0xA6,
|
||||
0x01, 0x98, 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A,
|
||||
0xFF, 0xE7, 0xFE, 0x00, 0x1F, 0xF9, 0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00,
|
||||
0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x02, 0xFF, 0x17, 0xF8, 0xC0, 0x06,
|
||||
0x00, 0x30, 0x01, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x2F, 0xF8, 0xFF,
|
||||
0xC0, 0x1F, 0xF9, 0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0,
|
||||
0x0E, 0x00, 0x70, 0x02, 0xFF, 0x17, 0xF8, 0xC0, 0x06, 0x00, 0x30, 0x01,
|
||||
0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x20, 0x00, 0x1F, 0xF9, 0x7F, 0x8C,
|
||||
0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x02, 0x00,
|
||||
0x10, 0x02, 0xC0, 0x36, 0x01, 0xB0, 0x0D, 0x80, 0xFC, 0x07, 0xE0, 0x3F,
|
||||
0x01, 0xEF, 0xFE, 0xFF, 0xC0, 0x20, 0x01, 0x80, 0x0C, 0x00, 0xE0, 0x07,
|
||||
0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x5F, 0xE2, 0xFF, 0x58, 0x06, 0xC0,
|
||||
0x36, 0x01, 0xB0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3C, 0x00, 0xC0, 0x2D,
|
||||
0xBF, 0xFF, 0x60, 0x00, 0x04, 0x00, 0x30, 0x01, 0xC0, 0x07, 0x00, 0x1C,
|
||||
0x00, 0x70, 0x01, 0xC0, 0x06, 0x00, 0x09, 0x00, 0x26, 0x01, 0x98, 0x06,
|
||||
0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0xFF, 0xE7, 0xFE,
|
||||
0x00, 0x1F, 0xF9, 0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0,
|
||||
0x0E, 0x00, 0x70, 0x02, 0xFF, 0x17, 0xFA, 0xC0, 0x36, 0x01, 0xB0, 0x0D,
|
||||
0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xE0, 0x06, 0x20, 0x03, 0x00, 0x30,
|
||||
0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x40, 0x04, 0x00, 0x60,
|
||||
0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0B, 0xFE, 0x7F,
|
||||
0xE0, 0x1F, 0xF8, 0xBF, 0xD3, 0x00, 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77,
|
||||
0x01, 0xDC, 0x07, 0x70, 0x19, 0x00, 0x24, 0x00, 0x98, 0x06, 0x60, 0x19,
|
||||
0x80, 0x66, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xE8, 0x01, 0x80, 0x1F,
|
||||
0xE2, 0xFF, 0x58, 0x06, 0xC0, 0x36, 0x01, 0xB0, 0x1F, 0x80, 0xFC, 0x07,
|
||||
0xE0, 0x3C, 0x00, 0xC0, 0x1F, 0xE2, 0xFF, 0x58, 0x06, 0xC0, 0x36, 0x01,
|
||||
0xB0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3D, 0xFF, 0xDF, 0xF8, 0x1F, 0xF8,
|
||||
0xBF, 0xD3, 0x00, 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07,
|
||||
0x70, 0x19, 0x7F, 0xA5, 0xFE, 0x18, 0x00, 0x60, 0x01, 0x80, 0x06, 0x00,
|
||||
0x38, 0x00, 0xE0, 0x03, 0x80, 0x08, 0x00, 0x00, 0x3F, 0xF2, 0xFF, 0x58,
|
||||
0x06, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x35, 0xFE,
|
||||
0x8F, 0xF4, 0x00, 0x60, 0x03, 0x00, 0x18, 0x01, 0xC0, 0x0E, 0x00, 0x70,
|
||||
0x03, 0x80, 0x0C, 0x1F, 0xE5, 0xFE, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00,
|
||||
0xE0, 0x0E, 0x00, 0xE0, 0x08, 0x00, 0x40, 0x06, 0x00, 0x60, 0x0E, 0x00,
|
||||
0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xBF, 0xC3, 0xFD, 0x00, 0x30, 0x03,
|
||||
0x00, 0x30, 0x07, 0x00, 0x70, 0x07, 0x00, 0x77, 0xFF, 0xFF, 0xC0, 0x20,
|
||||
0x03, 0x00, 0x30, 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x5F,
|
||||
0xE5, 0xFE, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0,
|
||||
0x0B, 0xFE, 0x7F, 0xE0, 0x40, 0x0B, 0x00, 0xD8, 0x06, 0xC0, 0x36, 0x03,
|
||||
0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xBF, 0xFB, 0xFF, 0x00, 0x20, 0x04, 0xC0,
|
||||
0x33, 0x01, 0xDC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x06, 0x40,
|
||||
0x09, 0x00, 0x26, 0x01, 0x98, 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8,
|
||||
0x0E, 0xE0, 0x3A, 0xFF, 0xE7, 0xFE, 0x00, 0x20, 0x04, 0xC0, 0x33, 0x01,
|
||||
0xDC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x06, 0x5F, 0xE9, 0x7F,
|
||||
0xA6, 0x01, 0x98, 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0,
|
||||
0x3A, 0xFF, 0xE7, 0xFE, 0x00, 0x20, 0x04, 0xC0, 0x33, 0x01, 0xDC, 0x07,
|
||||
0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x06, 0x5F, 0xE9, 0x7F, 0xA6, 0x01,
|
||||
0x98, 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0x00,
|
||||
0x60, 0x40, 0x0B, 0x00, 0xD8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80,
|
||||
0xFC, 0x06, 0xBF, 0xD1, 0xFE, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x38,
|
||||
0x01, 0xC0, 0x0E, 0x00, 0x73, 0xFF, 0xBF, 0xF0, 0x1F, 0xF8, 0x3F, 0xD0,
|
||||
0x00, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x18,
|
||||
0x00, 0x24, 0x00, 0x18, 0x00, 0x60, 0x01, 0x80, 0x06, 0x00, 0x38, 0x00,
|
||||
0xE0, 0x03, 0x80, 0x0B, 0xFE, 0x1F, 0xF8, 0xFE, 0x18, 0x61, 0x86, 0x18,
|
||||
0x61, 0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x86, 0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86,
|
||||
0x18, 0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18,
|
||||
0x61, 0x87, 0xF0, 0x7F, 0xDF, 0xF8, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x86, 0x18, 0x61, 0x87, 0xF0, 0x1F, 0xF8, 0xBF, 0xD3, 0x00, 0xCC, 0x07,
|
||||
0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07, 0x70, 0x19, 0x7F, 0xA5, 0xFE,
|
||||
0x98, 0x06, 0x60, 0x19, 0x80, 0x66, 0x03, 0xB8, 0x0E, 0xE0, 0x3B, 0x80,
|
||||
0xE8, 0x01, 0x80, 0x20, 0x01, 0x80, 0x0C, 0x00, 0xE0, 0x07, 0x00, 0x38,
|
||||
0x01, 0xC0, 0x0E, 0x00, 0x5F, 0xE2, 0xFF, 0x58, 0x06, 0xC0, 0x36, 0x01,
|
||||
0xB0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3D, 0xFF, 0xDF, 0xF8, 0x1F, 0xE5,
|
||||
0xFE, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0B,
|
||||
0xFE, 0x7F, 0xE0, 0x00, 0x04, 0x00, 0x30, 0x01, 0xC0, 0x07, 0x00, 0x1C,
|
||||
0x00, 0x70, 0x01, 0xC0, 0x06, 0x1F, 0xE9, 0x7F, 0xA6, 0x01, 0x98, 0x06,
|
||||
0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0xFF, 0xE7, 0xFE,
|
||||
0x00, 0x1F, 0xF9, 0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0,
|
||||
0x0E, 0x00, 0x70, 0x02, 0xFF, 0x17, 0xF8, 0xC0, 0x06, 0x00, 0x30, 0x01,
|
||||
0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x2F, 0xF8, 0xFF, 0xC0, 0x1F, 0xF9,
|
||||
0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70,
|
||||
0x02, 0xFF, 0x17, 0xF8, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80, 0x1C, 0x00,
|
||||
0xE0, 0x07, 0x00, 0x20, 0x00, 0x1F, 0xF9, 0x7F, 0x8C, 0x00, 0x60, 0x07,
|
||||
0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x02, 0x00, 0x10, 0x02, 0xC0,
|
||||
0x36, 0x01, 0xB0, 0x0D, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xEF, 0xFE,
|
||||
0xFF, 0xC0, 0x20, 0x01, 0x80, 0x0C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01,
|
||||
0xC0, 0x0E, 0x00, 0x5F, 0xE2, 0xFF, 0x58, 0x06, 0xC0, 0x36, 0x01, 0xB0,
|
||||
0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3C, 0x00, 0xC0, 0x2D, 0xBF, 0xFF, 0x60,
|
||||
0x00, 0x04, 0x00, 0x30, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01,
|
||||
0xC0, 0x06, 0x00, 0x09, 0x00, 0x26, 0x01, 0x98, 0x06, 0x60, 0x19, 0x80,
|
||||
0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0xFF, 0xE7, 0xFE, 0x00, 0x1F, 0xF9,
|
||||
0x7F, 0x8C, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70,
|
||||
0x02, 0xFF, 0x17, 0xFA, 0xC0, 0x36, 0x01, 0xB0, 0x0D, 0x80, 0xFC, 0x07,
|
||||
0xE0, 0x3F, 0x01, 0xE0, 0x06, 0x20, 0x03, 0x00, 0x30, 0x07, 0x00, 0x70,
|
||||
0x07, 0x00, 0x70, 0x07, 0x00, 0x40, 0x04, 0x00, 0x60, 0x06, 0x00, 0x60,
|
||||
0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0B, 0xFE, 0x7F, 0xE0, 0x1F, 0xF8,
|
||||
0xBF, 0xD3, 0x00, 0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07,
|
||||
0x70, 0x19, 0x00, 0x24, 0x00, 0x98, 0x06, 0x60, 0x19, 0x80, 0x66, 0x03,
|
||||
0xB8, 0x0E, 0xE0, 0x3B, 0x80, 0xE8, 0x01, 0x80, 0x1F, 0xE2, 0xFF, 0x58,
|
||||
0x06, 0xC0, 0x36, 0x01, 0xB0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3C, 0x00,
|
||||
0xC0, 0x1F, 0xE2, 0xFF, 0x58, 0x06, 0xC0, 0x36, 0x01, 0xB0, 0x1F, 0x80,
|
||||
0xFC, 0x07, 0xE0, 0x3D, 0xFF, 0xDF, 0xF8, 0x1F, 0xF8, 0xBF, 0xD3, 0x00,
|
||||
0xCC, 0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x07, 0x70, 0x19, 0x7F,
|
||||
0xA5, 0xFE, 0x18, 0x00, 0x60, 0x01, 0x80, 0x06, 0x00, 0x38, 0x00, 0xE0,
|
||||
0x03, 0x80, 0x08, 0x00, 0x00, 0x3F, 0xF2, 0xFF, 0x58, 0x06, 0xC0, 0x7E,
|
||||
0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x35, 0xFE, 0x8F, 0xF4, 0x00,
|
||||
0x60, 0x03, 0x00, 0x18, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x0C,
|
||||
0x1F, 0xE5, 0xFE, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00,
|
||||
0xE0, 0x08, 0x00, 0x40, 0x06, 0x00, 0x60, 0x0E, 0x00, 0xE0, 0x0E, 0x00,
|
||||
0xE0, 0x0E, 0x00, 0xBF, 0xC3, 0xFD, 0x00, 0x30, 0x03, 0x00, 0x30, 0x07,
|
||||
0x00, 0x70, 0x07, 0x00, 0x77, 0xFF, 0xFF, 0xC0, 0x20, 0x03, 0x00, 0x30,
|
||||
0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x5F, 0xE5, 0xFE, 0x60,
|
||||
0x06, 0x00, 0x60, 0x06, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0B, 0xFE, 0x7F,
|
||||
0xE0, 0x40, 0x0B, 0x00, 0xD8, 0x06, 0xC0, 0x36, 0x03, 0xF0, 0x1F, 0x80,
|
||||
0xFC, 0x07, 0xBF, 0xFB, 0xFF, 0x00, 0x20, 0x04, 0xC0, 0x33, 0x01, 0xDC,
|
||||
0x07, 0x70, 0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x06, 0x40, 0x09, 0x00, 0x26,
|
||||
0x01, 0x98, 0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A,
|
||||
0xFF, 0xE7, 0xFE, 0x00, 0x20, 0x04, 0xC0, 0x33, 0x01, 0xDC, 0x07, 0x70,
|
||||
0x1D, 0xC0, 0x77, 0x01, 0xDC, 0x06, 0x5F, 0xE9, 0x7F, 0xA6, 0x01, 0x98,
|
||||
0x06, 0x60, 0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0xFF, 0xE7,
|
||||
0xFE, 0x00, 0x20, 0x04, 0xC0, 0x33, 0x01, 0xDC, 0x07, 0x70, 0x1D, 0xC0,
|
||||
0x77, 0x01, 0xDC, 0x06, 0x5F, 0xE9, 0x7F, 0xA6, 0x01, 0x98, 0x06, 0x60,
|
||||
0x19, 0x80, 0xEE, 0x03, 0xB8, 0x0E, 0xE0, 0x3A, 0x00, 0x60, 0x40, 0x0B,
|
||||
0x00, 0xD8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x06, 0xBF,
|
||||
0xD1, 0xFE, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x38, 0x01, 0xC0, 0x0E,
|
||||
0x00, 0x73, 0xFF, 0xBF, 0xF0, 0x1F, 0xF8, 0x3F, 0xD0, 0x00, 0xC0, 0x07,
|
||||
0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x18, 0x00, 0x24, 0x00,
|
||||
0x18, 0x00, 0x60, 0x01, 0x80, 0x06, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80,
|
||||
0x0B, 0xFE, 0x1F, 0xF8, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18,
|
||||
0x61, 0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61,
|
||||
0x87, 0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87,
|
||||
0xF0, 0xFE, 0x18, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x61, 0x87, 0xF0 };
|
||||
|
||||
const GFXglyph DSEG7Classic_BoldItalic10pt7bGlyphs[] PROGMEM = {
|
||||
{ 0, 0, 0, 4, 0, 1 }, // 0x20 ' '
|
||||
{ 0, 0, 0, 16, 0, 1 }, // 0x21 '!'
|
||||
{ 0, 6, 14, 7, 1, -13 }, // 0x22 '"'
|
||||
{ 11, 6, 14, 7, 1, -13 }, // 0x23 '#'
|
||||
{ 22, 6, 14, 7, 1, -13 }, // 0x24 '$'
|
||||
{ 33, 6, 14, 7, 1, -13 }, // 0x25 '%'
|
||||
{ 44, 6, 14, 7, 1, -13 }, // 0x26 '&'
|
||||
{ 55, 6, 14, 7, 1, -13 }, // 0x27 '''
|
||||
{ 66, 6, 14, 7, 1, -13 }, // 0x28 '('
|
||||
{ 77, 6, 14, 7, 1, -13 }, // 0x29 ')'
|
||||
{ 88, 6, 14, 7, 1, -13 }, // 0x2A '*'
|
||||
{ 99, 6, 14, 7, 1, -13 }, // 0x2B '+'
|
||||
{ 110, 6, 14, 7, 1, -13 }, // 0x2C ','
|
||||
{ 121, 9, 2, 16, 4, -10 }, // 0x2D '-'
|
||||
{ 124, 2, 2, 0, -2, -1 }, // 0x2E '.'
|
||||
{ 125, 6, 14, 7, 1, -13 }, // 0x2F '/'
|
||||
{ 136, 14, 20, 16, 1, -19 }, // 0x30 '0'
|
||||
{ 171, 4, 18, 16, 11, -18 }, // 0x31 '1'
|
||||
{ 180, 14, 20, 16, 1, -19 }, // 0x32 '2'
|
||||
{ 215, 13, 20, 16, 2, -19 }, // 0x33 '3'
|
||||
{ 248, 13, 18, 16, 2, -18 }, // 0x34 '4'
|
||||
{ 278, 12, 20, 16, 2, -19 }, // 0x35 '5'
|
||||
{ 308, 13, 20, 16, 1, -19 }, // 0x36 '6'
|
||||
{ 341, 13, 19, 16, 2, -19 }, // 0x37 '7'
|
||||
{ 372, 14, 20, 16, 1, -19 }, // 0x38 '8'
|
||||
{ 407, 13, 20, 16, 2, -19 }, // 0x39 '9'
|
||||
{ 440, 4, 11, 4, 0, -14 }, // 0x3A ':'
|
||||
{ 446, 6, 14, 7, 1, -13 }, // 0x3B ';'
|
||||
{ 457, 6, 14, 7, 1, -13 }, // 0x3C '<'
|
||||
{ 468, 6, 14, 7, 1, -13 }, // 0x3D '='
|
||||
{ 479, 6, 14, 7, 1, -13 }, // 0x3E '>'
|
||||
{ 490, 6, 14, 7, 1, -13 }, // 0x3F '?'
|
||||
{ 501, 6, 14, 7, 1, -13 }, // 0x40 '@'
|
||||
{ 512, 14, 19, 16, 1, -19 }, // 0x41 'A'
|
||||
{ 546, 13, 19, 16, 1, -18 }, // 0x42 'B'
|
||||
{ 577, 12, 11, 16, 1, -10 }, // 0x43 'C'
|
||||
{ 594, 14, 19, 16, 1, -18 }, // 0x44 'D'
|
||||
{ 628, 13, 20, 16, 1, -19 }, // 0x45 'E'
|
||||
{ 661, 13, 19, 16, 1, -19 }, // 0x46 'F'
|
||||
{ 692, 13, 20, 16, 1, -19 }, // 0x47 'G'
|
||||
{ 725, 13, 18, 16, 1, -18 }, // 0x48 'H'
|
||||
{ 755, 3, 9, 16, 11, -9 }, // 0x49 'I'
|
||||
{ 759, 14, 19, 16, 1, -18 }, // 0x4A 'J'
|
||||
{ 793, 13, 19, 16, 1, -19 }, // 0x4B 'K'
|
||||
{ 824, 12, 19, 16, 1, -18 }, // 0x4C 'L'
|
||||
{ 853, 14, 19, 16, 1, -19 }, // 0x4D 'M'
|
||||
{ 887, 13, 10, 16, 1, -10 }, // 0x4E 'N'
|
||||
{ 904, 13, 11, 16, 1, -10 }, // 0x4F 'O'
|
||||
{ 922, 14, 19, 16, 1, -19 }, // 0x50 'P'
|
||||
{ 956, 13, 19, 16, 2, -19 }, // 0x51 'Q'
|
||||
{ 987, 12, 10, 16, 1, -10 }, // 0x52 'R'
|
||||
{ 1002, 12, 19, 16, 2, -18 }, // 0x53 'S'
|
||||
{ 1031, 12, 19, 16, 1, -18 }, // 0x54 'T'
|
||||
{ 1060, 13, 10, 16, 1, -9 }, // 0x55 'U'
|
||||
{ 1077, 14, 19, 16, 1, -18 }, // 0x56 'V'
|
||||
{ 1111, 14, 19, 16, 1, -18 }, // 0x57 'W'
|
||||
{ 1145, 14, 18, 16, 1, -18 }, // 0x58 'X'
|
||||
{ 1177, 13, 19, 16, 2, -18 }, // 0x59 'Y'
|
||||
{ 1208, 14, 20, 16, 1, -19 }, // 0x5A 'Z'
|
||||
{ 1243, 6, 14, 7, 1, -13 }, // 0x5B '['
|
||||
{ 1254, 6, 14, 7, 1, -13 }, // 0x5C '\'
|
||||
{ 1265, 6, 14, 7, 1, -13 }, // 0x5D ']'
|
||||
{ 1276, 6, 14, 7, 1, -13 }, // 0x5E '^'
|
||||
{ 1287, 11, 2, 16, 2, -1 }, // 0x5F '_'
|
||||
{ 1290, 6, 14, 7, 1, -13 }, // 0x60 '`'
|
||||
{ 1301, 14, 19, 16, 1, -19 }, // 0x61 'a'
|
||||
{ 1335, 13, 19, 16, 1, -18 }, // 0x62 'b'
|
||||
{ 1366, 12, 11, 16, 1, -10 }, // 0x63 'c'
|
||||
{ 1383, 14, 19, 16, 1, -18 }, // 0x64 'd'
|
||||
{ 1417, 13, 20, 16, 1, -19 }, // 0x65 'e'
|
||||
{ 1450, 13, 19, 16, 1, -19 }, // 0x66 'f'
|
||||
{ 1481, 13, 20, 16, 1, -19 }, // 0x67 'g'
|
||||
{ 1514, 13, 18, 16, 1, -18 }, // 0x68 'h'
|
||||
{ 1544, 3, 9, 16, 11, -9 }, // 0x69 'i'
|
||||
{ 1548, 14, 19, 16, 1, -18 }, // 0x6A 'j'
|
||||
{ 1582, 13, 19, 16, 1, -19 }, // 0x6B 'k'
|
||||
{ 1613, 12, 19, 16, 1, -18 }, // 0x6C 'l'
|
||||
{ 1642, 14, 19, 16, 1, -19 }, // 0x6D 'm'
|
||||
{ 1676, 13, 10, 16, 1, -10 }, // 0x6E 'n'
|
||||
{ 1693, 13, 11, 16, 1, -10 }, // 0x6F 'o'
|
||||
{ 1711, 14, 19, 16, 1, -19 }, // 0x70 'p'
|
||||
{ 1745, 13, 19, 16, 2, -19 }, // 0x71 'q'
|
||||
{ 1776, 12, 10, 16, 1, -10 }, // 0x72 'r'
|
||||
{ 1791, 12, 19, 16, 2, -18 }, // 0x73 's'
|
||||
{ 1820, 12, 19, 16, 1, -18 }, // 0x74 't'
|
||||
{ 1849, 13, 10, 16, 1, -9 }, // 0x75 'u'
|
||||
{ 1866, 14, 19, 16, 1, -18 }, // 0x76 'v'
|
||||
{ 1900, 14, 19, 16, 1, -18 }, // 0x77 'w'
|
||||
{ 1934, 14, 18, 16, 1, -18 }, // 0x78 'x'
|
||||
{ 1966, 13, 19, 16, 2, -18 }, // 0x79 'y'
|
||||
{ 1997, 14, 20, 16, 1, -19 }, // 0x7A 'z'
|
||||
{ 2032, 6, 14, 7, 1, -13 }, // 0x7B '{'
|
||||
{ 2043, 6, 14, 7, 1, -13 }, // 0x7C '|'
|
||||
{ 2054, 6, 14, 7, 1, -13 }, // 0x7D '}'
|
||||
{ 2065, 6, 14, 7, 1, -13 } }; // 0x7E '~'
|
||||
|
||||
const GFXfont DSEG7Classic_BoldItalic10pt7b PROGMEM = {
|
||||
(uint8_t *)DSEG7Classic_BoldItalic10pt7bBitmaps,
|
||||
(GFXglyph *)DSEG7Classic_BoldItalic10pt7bGlyphs,
|
||||
0x20, 0x7E, 22 };
|
||||
|
||||
// Approx. 2748 bytes
|
||||
@@ -1,352 +0,0 @@
|
||||
const uint8_t DSEG7Classic_BoldItalic12pt7bBitmaps[] PROGMEM = {
|
||||
0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30,
|
||||
0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||
0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83,
|
||||
0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60,
|
||||
0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18,
|
||||
0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06,
|
||||
0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF,
|
||||
0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30,
|
||||
0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||
0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83,
|
||||
0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60,
|
||||
0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18,
|
||||
0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0x7F, 0xEF,
|
||||
0xFC, 0x7D, 0x80, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06,
|
||||
0x0C, 0x18, 0x30, 0x60, 0xFF, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67,
|
||||
0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03,
|
||||
0x9C, 0x03, 0x9C, 0x00, 0xCC, 0x00, 0x26, 0x00, 0x13, 0x80, 0x39, 0xC0,
|
||||
0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x00, 0xE7,
|
||||
0x00, 0xE3, 0xFF, 0xF1, 0xFF, 0xE8, 0x7F, 0xF8, 0x08, 0xCE, 0x73, 0x9C,
|
||||
0xE7, 0x71, 0x84, 0x27, 0x39, 0xCE, 0x73, 0x9D, 0xC6, 0x10, 0x0F, 0xFF,
|
||||
0x07, 0xFF, 0x41, 0xFF, 0x60, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00,
|
||||
0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0xC1, 0xFF, 0xA6,
|
||||
0xFF, 0xC3, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00,
|
||||
0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0xFF, 0xC1, 0xFF, 0xE0, 0x7F,
|
||||
0xF8, 0x1F, 0xFE, 0x1F, 0xFD, 0x0F, 0xFB, 0x00, 0x07, 0x00, 0x07, 0x00,
|
||||
0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x06, 0x1F,
|
||||
0xFA, 0x1F, 0xFA, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00,
|
||||
0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x3F, 0xFC, 0x7F, 0xF4, 0x7F,
|
||||
0xF8, 0x00, 0x01, 0x60, 0x03, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0xE0, 0x06, 0xDF, 0xFA, 0x1F,
|
||||
0xFA, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00,
|
||||
0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x04, 0x1F, 0xFE, 0x3F,
|
||||
0xF9, 0xBF, 0xE3, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00,
|
||||
0x70, 0x00, 0xE0, 0x03, 0x80, 0x06, 0xFF, 0xC1, 0xFF, 0xA0, 0x01, 0xC0,
|
||||
0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x01,
|
||||
0xC7, 0xFF, 0x9F, 0xFD, 0x3F, 0xFC, 0x0F, 0xFF, 0x0F, 0xFE, 0x37, 0xFC,
|
||||
0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
|
||||
0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07,
|
||||
0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E,
|
||||
0x7F, 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x1F, 0xFE, 0x1F, 0xFD, 0x6F, 0xFB,
|
||||
0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07,
|
||||
0x70, 0x0E, 0xE0, 0x06, 0xC0, 0x02, 0x00, 0x02, 0x00, 0x0E, 0x00, 0x0E,
|
||||
0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C,
|
||||
0x00, 0x0C, 0x00, 0x04, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67, 0x00,
|
||||
0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C,
|
||||
0x03, 0x9C, 0x00, 0xCD, 0xFF, 0xA6, 0xFF, 0xD3, 0x80, 0x39, 0xC0, 0x1C,
|
||||
0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x00, 0xE7, 0x00,
|
||||
0xE3, 0xFF, 0xF1, 0xFF, 0xE8, 0x7F, 0xF8, 0x1F, 0xFE, 0x1F, 0xFD, 0x6F,
|
||||
0xFB, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x0E, 0xE0, 0x06, 0xDF, 0xFA, 0x1F, 0xFA, 0x00, 0x0E, 0x00,
|
||||
0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00,
|
||||
0x1C, 0x3F, 0xFC, 0x7F, 0xF4, 0x7F, 0xF8, 0x37, 0x30, 0x00, 0x00, 0x00,
|
||||
0x6E, 0x60, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C,
|
||||
0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83,
|
||||
0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60,
|
||||
0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18,
|
||||
0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06,
|
||||
0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF,
|
||||
0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30,
|
||||
0x60, 0xFF, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67, 0x00, 0x73, 0x80,
|
||||
0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x03, 0x9C,
|
||||
0x00, 0xCD, 0xFF, 0xA6, 0xFF, 0xD3, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E,
|
||||
0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x00, 0xE7, 0x00, 0xE3, 0x00,
|
||||
0x31, 0x00, 0x08, 0x00, 0x00, 0x30, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F,
|
||||
0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F,
|
||||
0xFC, 0x0F, 0xFD, 0xBF, 0xF7, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07,
|
||||
0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0xFF, 0x9F, 0xFE, 0x3F, 0xFC,
|
||||
0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00,
|
||||
0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x07, 0x00, 0x01, 0x83, 0xFF, 0x4D,
|
||||
0xFF, 0xA7, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07,
|
||||
0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, 0xD0, 0xFF,
|
||||
0xF0, 0x0F, 0xFF, 0x0F, 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F,
|
||||
0xFC, 0x6F, 0xFC, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70,
|
||||
0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x7F, 0xF8, 0x7F, 0xF8, 0x3F,
|
||||
0xFC, 0x0F, 0xFF, 0x0F, 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F,
|
||||
0xFC, 0x6F, 0xFC, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70,
|
||||
0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x60, 0x00, 0x40, 0x00, 0x0F,
|
||||
0xFF, 0x0F, 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x60, 0x00, 0x60,
|
||||
0x01, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x00,
|
||||
0x00, 0x30, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFD, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x0E, 0x60, 0x06, 0x40, 0x02, 0x17, 0x77, 0x77, 0x77, 0xE6,
|
||||
0x20, 0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38,
|
||||
0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x07, 0x00, 0x01, 0x80, 0x00,
|
||||
0x4C, 0x00, 0x27, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70,
|
||||
0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, 0xD0,
|
||||
0xFF, 0xF0, 0x0F, 0xFF, 0x0F, 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00,
|
||||
0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00,
|
||||
0x6F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07,
|
||||
0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x60, 0x06, 0x40, 0x02,
|
||||
0x00, 0x00, 0xC0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80,
|
||||
0x0E, 0x00, 0x38, 0x01, 0xC0, 0x06, 0x00, 0x18, 0x00, 0x70, 0x01, 0xC0,
|
||||
0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x7F,
|
||||
0xF9, 0xFF, 0xE3, 0xFF, 0xC0, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67,
|
||||
0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03,
|
||||
0x9C, 0x03, 0x9C, 0x00, 0xCC, 0x00, 0x26, 0x00, 0x13, 0x80, 0x39, 0xC0,
|
||||
0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x00, 0xE7,
|
||||
0x00, 0xE3, 0x00, 0x31, 0x00, 0x08, 0x0F, 0xFC, 0x6F, 0xFD, 0x70, 0x07,
|
||||
0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07,
|
||||
0x70, 0x0E, 0x60, 0x06, 0x40, 0x02, 0x0F, 0xFC, 0x6F, 0xFD, 0x70, 0x07,
|
||||
0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07,
|
||||
0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x0F, 0xFF, 0x07, 0xFF,
|
||||
0x4D, 0xFF, 0x67, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70,
|
||||
0x07, 0x38, 0x03, 0x9C, 0x03, 0x9C, 0x00, 0xCD, 0xFF, 0xA6, 0xFF, 0xC3,
|
||||
0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00,
|
||||
0x0E, 0x00, 0x07, 0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x1F, 0xFE, 0x1F,
|
||||
0xFD, 0x6F, 0xFB, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x0E, 0xE0, 0x06, 0xDF, 0xFA, 0x1F, 0xFA, 0x00,
|
||||
0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00,
|
||||
0x0E, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x04, 0x0F, 0xFD, 0xBF, 0xF7, 0x00,
|
||||
0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0,
|
||||
0x06, 0x00, 0x10, 0x00, 0x00, 0x00, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x07,
|
||||
0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x01, 0xC0, 0x03, 0x7F,
|
||||
0xE0, 0xFF, 0xD0, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E,
|
||||
0x00, 0x1C, 0x00, 0x38, 0x00, 0xE3, 0xFF, 0xCF, 0xFE, 0x9F, 0xFE, 0x00,
|
||||
0x00, 0x00, 0xC0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80,
|
||||
0x0E, 0x00, 0x38, 0x01, 0xC0, 0x06, 0xFF, 0xDB, 0xFF, 0x70, 0x01, 0xC0,
|
||||
0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x7F,
|
||||
0xF9, 0xFF, 0xE3, 0xFF, 0xC0, 0x60, 0x01, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x7F,
|
||||
0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x00, 0x00, 0x98, 0x00, 0xCE, 0x00, 0xE7,
|
||||
0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x07,
|
||||
0x38, 0x01, 0x98, 0x00, 0x4C, 0x00, 0x27, 0x00, 0x73, 0x80, 0x39, 0xC0,
|
||||
0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC7,
|
||||
0xFF, 0xE3, 0xFF, 0xD0, 0xFF, 0xF0, 0x00, 0x00, 0x98, 0x00, 0xCE, 0x00,
|
||||
0xE7, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38,
|
||||
0x07, 0x38, 0x01, 0x9B, 0xFF, 0x4D, 0xFF, 0xA7, 0x00, 0x73, 0x80, 0x39,
|
||||
0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01,
|
||||
0xC7, 0xFF, 0xE3, 0xFF, 0xD0, 0xFF, 0xF0, 0x00, 0x00, 0x98, 0x00, 0xCE,
|
||||
0x00, 0xE7, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07,
|
||||
0x38, 0x07, 0x38, 0x01, 0x9B, 0xFF, 0x4D, 0xFF, 0xA7, 0x00, 0x73, 0x80,
|
||||
0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE,
|
||||
0x01, 0xC6, 0x00, 0x62, 0x00, 0x10, 0x00, 0x01, 0x60, 0x03, 0x70, 0x07,
|
||||
0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E,
|
||||
0xE0, 0x06, 0xDF, 0xFA, 0x1F, 0xFA, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E,
|
||||
0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x3F, 0xFC,
|
||||
0x7F, 0xF4, 0x7F, 0xF8, 0x0F, 0xFF, 0x07, 0xFF, 0x41, 0xFF, 0x60, 0x00,
|
||||
0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80,
|
||||
0x03, 0x80, 0x00, 0xC0, 0x00, 0x26, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00,
|
||||
0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00,
|
||||
0x03, 0xFF, 0xC1, 0xFF, 0xE0, 0x7F, 0xF8, 0xFF, 0x06, 0x0C, 0x18, 0x30,
|
||||
0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C,
|
||||
0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF,
|
||||
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60,
|
||||
0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18,
|
||||
0x30, 0x60, 0xFF, 0x3F, 0xF3, 0xFF, 0x9F, 0xFE, 0xFF, 0x06, 0x0C, 0x18,
|
||||
0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0x0F, 0xFF,
|
||||
0x07, 0xFF, 0x4D, 0xFF, 0x67, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0,
|
||||
0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x03, 0x9C, 0x00, 0xCD, 0xFF, 0xA6,
|
||||
0xFF, 0xD3, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03,
|
||||
0x9C, 0x01, 0xCE, 0x00, 0xE7, 0x00, 0xE3, 0x00, 0x31, 0x00, 0x08, 0x00,
|
||||
0x00, 0x30, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFD, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x0F, 0xFD, 0xBF,
|
||||
0xF7, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70,
|
||||
0x01, 0xC0, 0x07, 0xFF, 0x9F, 0xFE, 0x3F, 0xFC, 0x00, 0x00, 0x80, 0x00,
|
||||
0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00,
|
||||
0x07, 0x00, 0x07, 0x00, 0x01, 0x83, 0xFF, 0x4D, 0xFF, 0xA7, 0x00, 0x73,
|
||||
0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01,
|
||||
0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, 0xD0, 0xFF, 0xF0, 0x0F, 0xFF, 0x0F,
|
||||
0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFC, 0x70,
|
||||
0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70,
|
||||
0x00, 0x70, 0x00, 0x7F, 0xF8, 0x7F, 0xF8, 0x3F, 0xFC, 0x0F, 0xFF, 0x0F,
|
||||
0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFC, 0x70,
|
||||
0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70,
|
||||
0x00, 0x70, 0x00, 0x60, 0x00, 0x40, 0x00, 0x0F, 0xFF, 0x0F, 0xFE, 0x37,
|
||||
0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x70, 0x00, 0x60, 0x00, 0x60, 0x01, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F, 0xFC, 0x00, 0x00, 0x30, 0x00, 0x38,
|
||||
0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38,
|
||||
0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x60,
|
||||
0x06, 0x40, 0x02, 0x17, 0x77, 0x77, 0x77, 0xE6, 0x20, 0x00, 0x00, 0x80,
|
||||
0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E,
|
||||
0x00, 0x07, 0x00, 0x07, 0x00, 0x01, 0x80, 0x00, 0x4C, 0x00, 0x27, 0x00,
|
||||
0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C,
|
||||
0x01, 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, 0xD0, 0xFF, 0xF0, 0x0F, 0xFF,
|
||||
0x0F, 0xFE, 0x37, 0xFC, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00,
|
||||
0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0x70, 0x00, 0x6F, 0xFC, 0x6F, 0xFD,
|
||||
0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07,
|
||||
0x70, 0x07, 0x70, 0x0E, 0x60, 0x06, 0x40, 0x02, 0x00, 0x00, 0xC0, 0x03,
|
||||
0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x01,
|
||||
0xC0, 0x06, 0x00, 0x18, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00,
|
||||
0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x7F, 0xF9, 0xFF, 0xE3, 0xFF,
|
||||
0xC0, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67, 0x00, 0x73, 0x80, 0x39,
|
||||
0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x03, 0x9C, 0x00,
|
||||
0xCC, 0x00, 0x26, 0x00, 0x13, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70,
|
||||
0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x00, 0xE7, 0x00, 0xE3, 0x00, 0x31,
|
||||
0x00, 0x08, 0x0F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07,
|
||||
0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x60, 0x06,
|
||||
0x40, 0x02, 0x0F, 0xFC, 0x6F, 0xFD, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07,
|
||||
0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x7F, 0xFE,
|
||||
0x7F, 0xFA, 0x3F, 0xFC, 0x0F, 0xFF, 0x07, 0xFF, 0x4D, 0xFF, 0x67, 0x00,
|
||||
0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C,
|
||||
0x03, 0x9C, 0x00, 0xCD, 0xFF, 0xA6, 0xFF, 0xC3, 0x80, 0x01, 0xC0, 0x00,
|
||||
0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00,
|
||||
0x03, 0x00, 0x01, 0x00, 0x00, 0x1F, 0xFE, 0x1F, 0xFD, 0x6F, 0xFB, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x0E, 0xE0, 0x06, 0xDF, 0xFA, 0x1F, 0xFA, 0x00, 0x0E, 0x00, 0x0E, 0x00,
|
||||
0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x00,
|
||||
0x0C, 0x00, 0x04, 0x0F, 0xFD, 0xBF, 0xF7, 0x00, 0x1C, 0x00, 0x70, 0x01,
|
||||
0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x06, 0x00, 0x10, 0x00,
|
||||
0x00, 0x00, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C,
|
||||
0x00, 0x38, 0x00, 0x70, 0x01, 0xC0, 0x03, 0x7F, 0xE0, 0xFF, 0xD0, 0x00,
|
||||
0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38,
|
||||
0x00, 0xE3, 0xFF, 0xCF, 0xFE, 0x9F, 0xFE, 0x00, 0x00, 0x00, 0xC0, 0x03,
|
||||
0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x01,
|
||||
0xC0, 0x06, 0xFF, 0xDB, 0xFF, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00,
|
||||
0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x7F, 0xF9, 0xFF, 0xE3, 0xFF,
|
||||
0xC0, 0x60, 0x01, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
|
||||
0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0x7F, 0xFE, 0x7F, 0xFA, 0x3F,
|
||||
0xFC, 0x00, 0x00, 0x98, 0x00, 0xCE, 0x00, 0xE7, 0x00, 0x73, 0x80, 0x39,
|
||||
0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x07, 0x38, 0x01, 0x98, 0x00,
|
||||
0x4C, 0x00, 0x27, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70,
|
||||
0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF, 0xD0,
|
||||
0xFF, 0xF0, 0x00, 0x00, 0x98, 0x00, 0xCE, 0x00, 0xE7, 0x00, 0x73, 0x80,
|
||||
0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x07, 0x38, 0x01, 0x9B,
|
||||
0xFF, 0x4D, 0xFF, 0xA7, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E,
|
||||
0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC7, 0xFF, 0xE3, 0xFF,
|
||||
0xD0, 0xFF, 0xF0, 0x00, 0x00, 0x98, 0x00, 0xCE, 0x00, 0xE7, 0x00, 0x73,
|
||||
0x80, 0x39, 0xC0, 0x1C, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x07, 0x38, 0x01,
|
||||
0x9B, 0xFF, 0x4D, 0xFF, 0xA7, 0x00, 0x73, 0x80, 0x39, 0xC0, 0x1C, 0xE0,
|
||||
0x0E, 0x70, 0x07, 0x38, 0x03, 0x9C, 0x01, 0xCE, 0x01, 0xC6, 0x00, 0x62,
|
||||
0x00, 0x10, 0x00, 0x01, 0x60, 0x03, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07,
|
||||
0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x0E, 0xE0, 0x06, 0xDF, 0xFA,
|
||||
0x1F, 0xFA, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E,
|
||||
0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x3F, 0xFC, 0x7F, 0xF4, 0x7F, 0xF8,
|
||||
0x0F, 0xFF, 0x07, 0xFF, 0x41, 0xFF, 0x60, 0x00, 0x70, 0x00, 0x38, 0x00,
|
||||
0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0xC0,
|
||||
0x00, 0x26, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00,
|
||||
0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0xFF, 0xC1, 0xFF,
|
||||
0xE0, 0x7F, 0xF8, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06,
|
||||
0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1,
|
||||
0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C, 0x18, 0x30,
|
||||
0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0x06, 0x0C,
|
||||
0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xFF };
|
||||
|
||||
const GFXglyph DSEG7Classic_BoldItalic12pt7bGlyphs[] PROGMEM = {
|
||||
{ 0, 0, 0, 5, 0, 1 }, // 0x20 ' '
|
||||
{ 0, 0, 0, 20, 0, 1 }, // 0x21 '!'
|
||||
{ 0, 7, 16, 9, 1, -15 }, // 0x22 '"'
|
||||
{ 14, 7, 16, 9, 1, -15 }, // 0x23 '#'
|
||||
{ 28, 7, 16, 9, 1, -15 }, // 0x24 '$'
|
||||
{ 42, 7, 16, 9, 1, -15 }, // 0x25 '%'
|
||||
{ 56, 7, 16, 9, 1, -15 }, // 0x26 '&'
|
||||
{ 70, 7, 16, 9, 1, -15 }, // 0x27 '''
|
||||
{ 84, 7, 16, 9, 1, -15 }, // 0x28 '('
|
||||
{ 98, 7, 16, 9, 1, -15 }, // 0x29 ')'
|
||||
{ 112, 7, 16, 9, 1, -15 }, // 0x2A '*'
|
||||
{ 126, 7, 16, 9, 1, -15 }, // 0x2B '+'
|
||||
{ 140, 7, 16, 9, 1, -15 }, // 0x2C ','
|
||||
{ 154, 11, 2, 20, 4, -12 }, // 0x2D '-'
|
||||
{ 157, 3, 3, 0, -3, -2 }, // 0x2E '.'
|
||||
{ 159, 7, 16, 9, 1, -15 }, // 0x2F '/'
|
||||
{ 173, 17, 24, 20, 1, -23 }, // 0x30 '0'
|
||||
{ 224, 5, 22, 20, 13, -22 }, // 0x31 '1'
|
||||
{ 238, 17, 24, 20, 1, -23 }, // 0x32 '2'
|
||||
{ 289, 16, 24, 20, 2, -23 }, // 0x33 '3'
|
||||
{ 337, 16, 22, 20, 2, -22 }, // 0x34 '4'
|
||||
{ 381, 15, 24, 20, 2, -23 }, // 0x35 '5'
|
||||
{ 426, 16, 24, 20, 1, -23 }, // 0x36 '6'
|
||||
{ 474, 16, 23, 20, 2, -23 }, // 0x37 '7'
|
||||
{ 520, 17, 24, 20, 1, -23 }, // 0x38 '8'
|
||||
{ 571, 16, 24, 20, 2, -23 }, // 0x39 '9'
|
||||
{ 619, 4, 13, 5, 0, -17 }, // 0x3A ':'
|
||||
{ 626, 7, 16, 9, 1, -15 }, // 0x3B ';'
|
||||
{ 640, 7, 16, 9, 1, -15 }, // 0x3C '<'
|
||||
{ 654, 7, 16, 9, 1, -15 }, // 0x3D '='
|
||||
{ 668, 7, 16, 9, 1, -15 }, // 0x3E '>'
|
||||
{ 682, 7, 16, 9, 1, -15 }, // 0x3F '?'
|
||||
{ 696, 7, 16, 9, 1, -15 }, // 0x40 '@'
|
||||
{ 710, 17, 23, 20, 1, -23 }, // 0x41 'A'
|
||||
{ 759, 16, 23, 20, 1, -22 }, // 0x42 'B'
|
||||
{ 805, 14, 13, 20, 1, -12 }, // 0x43 'C'
|
||||
{ 828, 17, 23, 20, 1, -22 }, // 0x44 'D'
|
||||
{ 877, 16, 24, 20, 1, -23 }, // 0x45 'E'
|
||||
{ 925, 16, 23, 20, 1, -23 }, // 0x46 'F'
|
||||
{ 971, 16, 24, 20, 1, -23 }, // 0x47 'G'
|
||||
{ 1019, 16, 22, 20, 1, -22 }, // 0x48 'H'
|
||||
{ 1063, 4, 11, 20, 13, -11 }, // 0x49 'I'
|
||||
{ 1069, 17, 23, 20, 1, -22 }, // 0x4A 'J'
|
||||
{ 1118, 16, 23, 20, 1, -23 }, // 0x4B 'K'
|
||||
{ 1164, 14, 23, 20, 1, -22 }, // 0x4C 'L'
|
||||
{ 1205, 17, 23, 20, 1, -23 }, // 0x4D 'M'
|
||||
{ 1254, 16, 12, 20, 1, -12 }, // 0x4E 'N'
|
||||
{ 1278, 16, 13, 20, 1, -12 }, // 0x4F 'O'
|
||||
{ 1304, 17, 23, 20, 1, -23 }, // 0x50 'P'
|
||||
{ 1353, 16, 23, 20, 2, -23 }, // 0x51 'Q'
|
||||
{ 1399, 14, 12, 20, 1, -12 }, // 0x52 'R'
|
||||
{ 1420, 15, 23, 20, 2, -22 }, // 0x53 'S'
|
||||
{ 1464, 14, 23, 20, 1, -22 }, // 0x54 'T'
|
||||
{ 1505, 16, 12, 20, 1, -11 }, // 0x55 'U'
|
||||
{ 1529, 17, 23, 20, 1, -22 }, // 0x56 'V'
|
||||
{ 1578, 17, 23, 20, 1, -22 }, // 0x57 'W'
|
||||
{ 1627, 17, 22, 20, 1, -22 }, // 0x58 'X'
|
||||
{ 1674, 16, 23, 20, 2, -22 }, // 0x59 'Y'
|
||||
{ 1720, 17, 24, 20, 1, -23 }, // 0x5A 'Z'
|
||||
{ 1771, 7, 16, 9, 1, -15 }, // 0x5B '['
|
||||
{ 1785, 7, 16, 9, 1, -15 }, // 0x5C '\'
|
||||
{ 1799, 7, 16, 9, 1, -15 }, // 0x5D ']'
|
||||
{ 1813, 7, 16, 9, 1, -15 }, // 0x5E '^'
|
||||
{ 1827, 13, 3, 20, 2, -2 }, // 0x5F '_'
|
||||
{ 1832, 7, 16, 9, 1, -15 }, // 0x60 '`'
|
||||
{ 1846, 17, 23, 20, 1, -23 }, // 0x61 'a'
|
||||
{ 1895, 16, 23, 20, 1, -22 }, // 0x62 'b'
|
||||
{ 1941, 14, 13, 20, 1, -12 }, // 0x63 'c'
|
||||
{ 1964, 17, 23, 20, 1, -22 }, // 0x64 'd'
|
||||
{ 2013, 16, 24, 20, 1, -23 }, // 0x65 'e'
|
||||
{ 2061, 16, 23, 20, 1, -23 }, // 0x66 'f'
|
||||
{ 2107, 16, 24, 20, 1, -23 }, // 0x67 'g'
|
||||
{ 2155, 16, 22, 20, 1, -22 }, // 0x68 'h'
|
||||
{ 2199, 4, 11, 20, 13, -11 }, // 0x69 'i'
|
||||
{ 2205, 17, 23, 20, 1, -22 }, // 0x6A 'j'
|
||||
{ 2254, 16, 23, 20, 1, -23 }, // 0x6B 'k'
|
||||
{ 2300, 14, 23, 20, 1, -22 }, // 0x6C 'l'
|
||||
{ 2341, 17, 23, 20, 1, -23 }, // 0x6D 'm'
|
||||
{ 2390, 16, 12, 20, 1, -12 }, // 0x6E 'n'
|
||||
{ 2414, 16, 13, 20, 1, -12 }, // 0x6F 'o'
|
||||
{ 2440, 17, 23, 20, 1, -23 }, // 0x70 'p'
|
||||
{ 2489, 16, 23, 20, 2, -23 }, // 0x71 'q'
|
||||
{ 2535, 14, 12, 20, 1, -12 }, // 0x72 'r'
|
||||
{ 2556, 15, 23, 20, 2, -22 }, // 0x73 's'
|
||||
{ 2600, 14, 23, 20, 1, -22 }, // 0x74 't'
|
||||
{ 2641, 16, 12, 20, 1, -11 }, // 0x75 'u'
|
||||
{ 2665, 17, 23, 20, 1, -22 }, // 0x76 'v'
|
||||
{ 2714, 17, 23, 20, 1, -22 }, // 0x77 'w'
|
||||
{ 2763, 17, 22, 20, 1, -22 }, // 0x78 'x'
|
||||
{ 2810, 16, 23, 20, 2, -22 }, // 0x79 'y'
|
||||
{ 2856, 17, 24, 20, 1, -23 }, // 0x7A 'z'
|
||||
{ 2907, 7, 16, 9, 1, -15 }, // 0x7B '{'
|
||||
{ 2921, 7, 16, 9, 1, -15 }, // 0x7C '|'
|
||||
{ 2935, 7, 16, 9, 1, -15 }, // 0x7D '}'
|
||||
{ 2949, 7, 16, 9, 1, -15 } }; // 0x7E '~'
|
||||
|
||||
const GFXfont DSEG7Classic_BoldItalic12pt7b PROGMEM = {
|
||||
(uint8_t *)DSEG7Classic_BoldItalic12pt7bBitmaps,
|
||||
(GFXglyph *)DSEG7Classic_BoldItalic12pt7bGlyphs,
|
||||
0x20, 0x7E, 26 };
|
||||
|
||||
// Approx. 3635 bytes
|
||||
@@ -20,7 +20,7 @@ import getopt
|
||||
import re
|
||||
import json
|
||||
|
||||
__version__ = "0.3"
|
||||
__version__ = "1.3"
|
||||
|
||||
def detect_pages(filename):
|
||||
# returns a dictionary with page name and the number of gui fields
|
||||
@@ -90,7 +90,7 @@ def create_json(device, no_of_pages, pagedata):
|
||||
|
||||
category = f"{device.upper()} Page {page_no}"
|
||||
capabilities = {device.lower(): "true"}
|
||||
visiblepages = [str(vp) for vp in range(page_no, no_of_pages + 1)]
|
||||
visiblepages = [vp for vp in range(page_no, no_of_pages + 1)]
|
||||
|
||||
page_data = {
|
||||
"name": f"page{page_no}type",
|
||||
@@ -118,8 +118,8 @@ def create_json(device, no_of_pages, pagedata):
|
||||
"category": category,
|
||||
"capabilities": capabilities,
|
||||
"condition": {
|
||||
f"page{page_no}type": [ p for p in pages if pagedata[p] >= field_no ]
|
||||
,"visiblePages": visiblepages
|
||||
f"page{page_no}type": [page for page in pages if pagedata[page] >= field_no],
|
||||
"visiblePages": visiblepages
|
||||
}
|
||||
}
|
||||
output.append(field_data)
|
||||
@@ -141,10 +141,7 @@ def create_json(device, no_of_pages, pagedata):
|
||||
"description": "Fluid type in tank",
|
||||
"category": category,
|
||||
"capabilities": capabilities,
|
||||
"condition": {
|
||||
f"page{page_no}type": "Fluid",
|
||||
"visiblePages": visiblepages
|
||||
}
|
||||
"condition":[{f"page{page_no}type":"Fluid"}]
|
||||
}
|
||||
output.append(fluid_data)
|
||||
|
||||
@@ -176,12 +173,13 @@ def usage():
|
||||
print("Command line options")
|
||||
print(" -d --device device name to use e.g. obp60")
|
||||
print(" -p --pages number of pages to create")
|
||||
print(" -m --merge json with device config to merge to")
|
||||
print(" -h show this help")
|
||||
print()
|
||||
|
||||
if __name__ == '__main__':
|
||||
try:
|
||||
options, remainder = getopt.getopt(sys.argv[1:], 'd:p:', ['device=','--pages='])
|
||||
options, remainder = getopt.getopt(sys.argv[1:], 'd:p:m:', ['device=','--pages=','--merge'])
|
||||
except getopt.GetoptError as err:
|
||||
print(err)
|
||||
usage()
|
||||
@@ -189,11 +187,14 @@ if __name__ == '__main__':
|
||||
|
||||
device = "obp60"
|
||||
no_of_pages = 10
|
||||
merge_json = None
|
||||
for opt, arg in options:
|
||||
if opt in ('-d', '--device'):
|
||||
device = arg
|
||||
elif opt in ('-p', '--pages'):
|
||||
no_of_pages = int(arg)
|
||||
elif opt in ('-m', '--merge'):
|
||||
merge_json = arg
|
||||
elif opt == '-h':
|
||||
usage()
|
||||
sys.exit(0)
|
||||
@@ -202,5 +203,12 @@ if __name__ == '__main__':
|
||||
pagedata = detect_pages("obp60task.cpp")
|
||||
|
||||
json_output = create_json(device, no_of_pages, pagedata)
|
||||
if merge_json and os.path.isfile(merge_json):
|
||||
with open(merge_json, 'r') as fh:
|
||||
device_json = json.load(fh)
|
||||
page_json = json.loads(json_output)
|
||||
device_json.extend(page_json)
|
||||
print(json.dumps(device_json, indent=4))
|
||||
else:
|
||||
# print omitting first line containing [ of JSON array
|
||||
print(json_output[1:])
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
git status
|
||||
git fetch upstream
|
||||
git diff --name-status upstream/master
|
||||
git checkout upstream/master platformio.ini
|
||||
|
||||
# how to reset my Repo to match norbert'status
|
||||
|
||||
git remote add upstream https://github.com/norbert-walter/esp32-nmea2000-obp60
|
||||
git fetch upstream
|
||||
git checkout master
|
||||
git reset --hard upstream/master
|
||||
git push origin master --force
|
||||
@@ -0,0 +1,88 @@
|
||||
/* History Buffer
|
||||
*
|
||||
* Storage backed buffer for sensordata
|
||||
* Permanent storage only supported type: FRAM on I2C-Bus
|
||||
*
|
||||
* Values can be 1 to 4 bytes in length
|
||||
*
|
||||
* Header: 32 bytes of size
|
||||
* 0 0x00 HB00 4 magic number
|
||||
* 4 0x04 xxxxxxxxxxxxxxxx 16 name, space padded
|
||||
* 20 0x14 n 1 byte size of values in buffer
|
||||
* 21 0x15 mm 2 buffer size in count of values
|
||||
* 23 0x17 dd 2 time step in seconds between values
|
||||
* 25 0x19 tttt 4 unix timestamp of head
|
||||
* 29 0x1d hh 2 head pointer
|
||||
* 31 0x1f 0xff 1 header end sign
|
||||
*
|
||||
* 32 0x20 ... start of buffer data
|
||||
*
|
||||
* Usage example: 7 hours of data collected every 75 seconds
|
||||
* TODO
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
class HistoryBuffer {
|
||||
|
||||
private:
|
||||
// Header prototype for permanent storage
|
||||
uint8_t header[32] = {
|
||||
0x41, 0x48, 0x30, 0x30, // magic: HB00
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // empty name
|
||||
0x01, // byte size
|
||||
0x50, 0x01, // value count
|
||||
0x4b, 0x00, // time step
|
||||
0x00, 0x00, 0x00, 0x00, // unix time stamp
|
||||
0x00, 0x00, // head pointer
|
||||
0xff // end sign
|
||||
};
|
||||
uint16_t head = 0; // head pointer to next new value position
|
||||
time_t timestamp; // last modification time of head
|
||||
uint16_t delta_t; // time step in seconds
|
||||
|
||||
public:
|
||||
HistoryBuffer(uint16_t size) {
|
||||
}
|
||||
~HistoryBuffer() {
|
||||
// free memory
|
||||
}
|
||||
void begin() {
|
||||
//
|
||||
}
|
||||
void finish() {
|
||||
}
|
||||
uint16_t add() {
|
||||
// returns new head value pointer
|
||||
return 0;
|
||||
}
|
||||
uint8_t* get() {
|
||||
// returns complete buffer in order new to old
|
||||
return 0;
|
||||
}
|
||||
uint8_t getvalue(uint16_t dt) {
|
||||
// Return a single value delta seconds ago
|
||||
uint16_t index = head - abs(dt) / delta_t;
|
||||
return 0;
|
||||
}
|
||||
uint8_t getvalue3() {
|
||||
return 0;
|
||||
}
|
||||
bool clear() {
|
||||
// clears buffer and permanent storage
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class History {
|
||||
public:
|
||||
History() {
|
||||
}
|
||||
~History() {
|
||||
}
|
||||
void *addSeries() {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef __HBUFFER_H__
|
||||
#define __HBUFFER_H__
|
||||
|
||||
class HistoryBuffer {
|
||||
public:
|
||||
HistoryBuffer(uint16_t size);
|
||||
void begin();
|
||||
void finish();
|
||||
uint16_t add();
|
||||
uint8_t* get() ;
|
||||
uint8_t getvalue(uint16_t dt);
|
||||
uint8_t getvalue3();
|
||||
void clear();
|
||||
};
|
||||
class History {
|
||||
public:
|
||||
History();
|
||||
void *addSeries();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
#define foxtrot_width 96
|
||||
#define foxtrot_height 64
|
||||
static unsigned char foxtrot_bits[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0xaa, 0x02, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xa8, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x00, 0x00,
|
||||
0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x00,
|
||||
0x00, 0x00, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00,
|
||||
0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00,
|
||||
0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00,
|
||||
0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x00,
|
||||
0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x00,
|
||||
0x00, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00,
|
||||
0x00, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00,
|
||||
0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00,
|
||||
0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00,
|
||||
0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01,
|
||||
0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a,
|
||||
0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a,
|
||||
0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
|
||||
0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a,
|
||||
0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05,
|
||||
0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x02,
|
||||
0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01,
|
||||
0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00,
|
||||
0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00,
|
||||
0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00,
|
||||
0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00,
|
||||
0x00, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00,
|
||||
0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00,
|
||||
0x00, 0x00, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00,
|
||||
0x00, 0x00, 0x50, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x15, 0x00, 0x00,
|
||||
0x00, 0x00, 0xa0, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x00, 0x00,
|
||||
0x00, 0x00, 0x40, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x01, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x54, 0x55, 0x55, 0x55, 0x55, 0x55, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0x0a, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x50, 0x55, 0x55, 0x55, 0x55, 0x05, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x80, 0xaa, 0xaa, 0xaa, 0xaa, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x55, 0x55, 0x01, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa, 0xaa, 0x2a, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0x55, 0x15, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0xaa, 0x0a, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x40, 0x55, 0x55, 0x05, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x80, 0xaa, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xa8, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
@@ -0,0 +1,67 @@
|
||||
// Arduino Moving Average Library
|
||||
// https://github.com/JChristensen/movingAvg
|
||||
// Copyright (C) 2018 by Jack Christensen and licensed under
|
||||
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
|
||||
|
||||
#include <movingAvg.h>
|
||||
|
||||
// initialize - allocate the interval array
|
||||
void movingAvg::begin()
|
||||
{
|
||||
m_readings = new int[m_interval];
|
||||
}
|
||||
|
||||
// add a new reading and return the new moving average
|
||||
int movingAvg::reading(int newReading)
|
||||
{
|
||||
// add each new data point to the sum until the m_readings array is filled
|
||||
if (m_nbrReadings < m_interval) {
|
||||
++m_nbrReadings;
|
||||
m_sum += newReading;
|
||||
}
|
||||
// once the array is filled, subtract the oldest data point and add the new one
|
||||
else {
|
||||
m_sum = m_sum - m_readings[m_next] + newReading;
|
||||
}
|
||||
|
||||
m_readings[m_next] = newReading;
|
||||
if (++m_next >= m_interval) m_next = 0;
|
||||
return (m_sum + m_nbrReadings / 2) / m_nbrReadings;
|
||||
}
|
||||
|
||||
// just return the current moving average
|
||||
int movingAvg::getAvg()
|
||||
{
|
||||
return (m_sum + m_nbrReadings / 2) / m_nbrReadings;
|
||||
}
|
||||
|
||||
// return the average for a subset of the data, the most recent nPoints readings.
|
||||
// for invalid values of nPoints, return zero.
|
||||
int movingAvg::getAvg(int nPoints)
|
||||
{
|
||||
if (nPoints < 1 || nPoints > m_interval || nPoints > m_nbrReadings) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
long sum{0};
|
||||
int i = m_next;
|
||||
for (int n=0; n<nPoints; ++n) {
|
||||
if (i == 0) {
|
||||
i = m_interval - 1;
|
||||
}
|
||||
else {
|
||||
--i;
|
||||
}
|
||||
sum += m_readings[i];
|
||||
}
|
||||
return (sum + nPoints / 2) / nPoints;
|
||||
}
|
||||
}
|
||||
|
||||
// start the moving average over again
|
||||
void movingAvg::reset()
|
||||
{
|
||||
m_nbrReadings = 0;
|
||||
m_sum = 0;
|
||||
m_next = 0;
|
||||
}
|
||||
@@ -3,64 +3,27 @@
|
||||
// Copyright (C) 2018 by Jack Christensen and licensed under
|
||||
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
|
||||
|
||||
// Extended to template class for handling of multiple data types
|
||||
|
||||
#ifndef MOVINGAVG_H_INCLUDED
|
||||
#define MOVINGAVG_H_INCLUDED
|
||||
|
||||
template <typename T>
|
||||
class movingAvg
|
||||
{
|
||||
public:
|
||||
movingAvg(int interval)
|
||||
: m_interval{interval}, m_nbrReadings{0}, m_sum{0}, m_next{0}, m_readings{nullptr} {}
|
||||
~movingAvg() { delete[] m_readings; }
|
||||
: m_interval{interval}, m_nbrReadings{0}, m_sum{0}, m_next{0} {}
|
||||
void begin();
|
||||
T reading(T newReading);
|
||||
T getAvg();
|
||||
T getAvg(int nPoints);
|
||||
int reading(int newReading);
|
||||
int getAvg();
|
||||
int getAvg(int nPoints);
|
||||
int getCount() {return m_nbrReadings;}
|
||||
void reset();
|
||||
T* getReadings() { return m_readings; }
|
||||
T to2PI(T a);
|
||||
int* getReadings() {return m_readings;}
|
||||
|
||||
private:
|
||||
int m_interval; // number of data points for the moving average
|
||||
int m_nbrReadings; // number of readings
|
||||
// Sum type adapts to T: long for integers, T for floating point
|
||||
using SumType = typename std::conditional<std::is_floating_point<T>::value, T, long>::type;
|
||||
SumType m_sum;
|
||||
long m_sum; // sum of the m_readings array
|
||||
int m_next; // index to the next reading
|
||||
T* m_readings; // pointer to the dynamically allocated interval array
|
||||
int* m_readings; // pointer to the dynamically allocated interval array
|
||||
};
|
||||
|
||||
// moving average for angle type of data (wind, course, rotation)
|
||||
// makes sense for data types double and float; angle in radians [0..2pi]
|
||||
template <typename T>
|
||||
class movingAvgAngle
|
||||
{
|
||||
public:
|
||||
movingAvgAngle(int interval)
|
||||
: m_interval{interval}, m_nbrReadings{0}, m_sumSin{0}, m_sumCos{0}, m_next{0}, m_buffer{nullptr} {}
|
||||
~movingAvgAngle() { delete[] m_buffer; }
|
||||
void begin();
|
||||
T reading(T newReading);
|
||||
T getAvg();
|
||||
T getAvg(int nPoints);
|
||||
int getCount() { return m_nbrReadings; }
|
||||
void reset();
|
||||
T* getReadings() { return m_buffer; }
|
||||
T to2PI(T a);
|
||||
|
||||
private:
|
||||
int m_interval; // number of data points for the moving average
|
||||
int m_nbrReadings; // number of readings
|
||||
double m_sumSin, m_sumCos; // sum for angle values should always be double for precision reasons, regardless of class type
|
||||
int m_next; // index to the next reading
|
||||
T* m_buffer; // pointer to the dynamically allocated interval array
|
||||
};
|
||||
|
||||
// Include the implementation to satisfy template instantiation requirements
|
||||
#include "movingAvg.tpp"
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
// Arduino Moving Average Library
|
||||
// https://github.com/JChristensen/movingAvg
|
||||
// Copyright (C) 2018 by Jack Christensen and licensed under
|
||||
// GNU GPL v3.0, https://www.gnu.org/licenses/gpl.html
|
||||
|
||||
// Extended to template class for handling of multiple data types
|
||||
|
||||
// initialize - allocate the interval array
|
||||
template <typename T>
|
||||
void movingAvg<T>::begin()
|
||||
{
|
||||
m_readings = new T[m_interval];
|
||||
}
|
||||
|
||||
// add a new reading and return the new moving average
|
||||
template <typename T>
|
||||
T movingAvg<T>::reading(T newReading)
|
||||
{
|
||||
// add each new data point to the sum until the m_readings array is filled
|
||||
if (m_nbrReadings < m_interval) {
|
||||
++m_nbrReadings;
|
||||
m_sum += newReading;
|
||||
}
|
||||
// once the array is filled, subtract the oldest data point and add the new one
|
||||
else {
|
||||
m_sum = m_sum - m_readings[m_next] + newReading;
|
||||
}
|
||||
|
||||
m_readings[m_next] = newReading;
|
||||
if (++m_next >= m_interval) m_next = 0;
|
||||
return getAvg();
|
||||
}
|
||||
|
||||
// just return the current moving average
|
||||
template <typename T>
|
||||
T movingAvg<T>::getAvg()
|
||||
{
|
||||
if (m_nbrReadings == 0) return 0;
|
||||
|
||||
// Apply rounding for integers only
|
||||
if (std::is_floating_point<T>::value) {
|
||||
return m_sum / m_nbrReadings;
|
||||
} else {
|
||||
return (m_sum + (SumType)m_nbrReadings / 2) / m_nbrReadings;
|
||||
}
|
||||
}
|
||||
|
||||
// return the average for a subset of the data, the most recent nPoints readings.
|
||||
// for invalid values of nPoints, return zero.
|
||||
template <typename T>
|
||||
T movingAvg<T>::getAvg(int nPoints)
|
||||
{
|
||||
if (nPoints < 1 || nPoints > m_interval || nPoints > m_nbrReadings) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
SumType sum{0};
|
||||
int i = m_next;
|
||||
for (int n=0; n<nPoints; ++n) {
|
||||
if (i == 0) {
|
||||
i = m_interval - 1;
|
||||
}
|
||||
else {
|
||||
--i;
|
||||
}
|
||||
sum += m_readings[i];
|
||||
}
|
||||
|
||||
if (std::is_floating_point<T>::value) {
|
||||
return sum / nPoints;
|
||||
} else {
|
||||
return (sum + (SumType)nPoints / 2) / nPoints; //
|
||||
}
|
||||
}
|
||||
|
||||
// start the moving average over again
|
||||
template <typename T>
|
||||
void movingAvg<T>::reset()
|
||||
{
|
||||
m_nbrReadings = 0;
|
||||
m_sum = 0;
|
||||
m_next = 0;
|
||||
}
|
||||
// --- End Class movingAvg ---------------
|
||||
|
||||
// --- Class MovingAvgAngle ---------------
|
||||
template <typename T>
|
||||
void movingAvgAngle<T>::begin()
|
||||
{
|
||||
m_buffer = new T[m_interval];
|
||||
}
|
||||
|
||||
// add a new reading and return the new moving average
|
||||
template <typename T>
|
||||
T movingAvgAngle<T>::reading(T newReading)
|
||||
{
|
||||
double s = std::sin(newReading);
|
||||
double c = std::cos(newReading);
|
||||
|
||||
// add each new data point to the sum until the m_readings array is filled
|
||||
if (m_nbrReadings < m_interval) {
|
||||
++m_nbrReadings;
|
||||
m_sumSin += s;
|
||||
m_sumCos += c;
|
||||
|
||||
} else {
|
||||
// array is filled; subtract the oldest data point and add the new one
|
||||
m_sumSin = m_sumSin - sin(m_buffer[m_next]) + s;
|
||||
m_sumCos = m_sumCos - cos(m_buffer[m_next]) + c;
|
||||
}
|
||||
m_buffer[m_next] = newReading;
|
||||
|
||||
if (++m_next >= m_interval)
|
||||
m_next = 0;
|
||||
|
||||
return getAvg();
|
||||
}
|
||||
|
||||
// return the current moving average
|
||||
template <typename T>
|
||||
T movingAvgAngle<T>::getAvg()
|
||||
{
|
||||
if (m_nbrReadings == 0)
|
||||
return 0;
|
||||
|
||||
// check size of vector; if near 0, set it to 0
|
||||
const double len = m_sumSin * m_sumSin + m_sumCos * m_sumCos;
|
||||
if (len < 1e-24)
|
||||
return 0.0; // average direction undefined
|
||||
|
||||
return static_cast<T>(to2PI(std::atan2(m_sumSin, m_sumCos)));
|
||||
}
|
||||
|
||||
// return the current moving average for a subset of the data, the most recent nPoints readings.
|
||||
// for invalid values of nPoints, return zero.
|
||||
template <typename T>
|
||||
T movingAvgAngle<T>::getAvg(int nPoints)
|
||||
{
|
||||
if (nPoints < 1 || nPoints > m_interval || nPoints > m_nbrReadings)
|
||||
return 0;
|
||||
|
||||
double sumSin = 0.0;
|
||||
double sumCos = 0.0;
|
||||
|
||||
int i = m_next;
|
||||
for (int n = 0; n < nPoints; ++n) {
|
||||
if (i == 0)
|
||||
i = m_interval - 1;
|
||||
else
|
||||
--i;
|
||||
|
||||
sumSin += std::sin(m_buffer[i]);
|
||||
sumCos += std::cos(m_buffer[i]);
|
||||
}
|
||||
|
||||
// check size of vector; if near 0, set it to 0
|
||||
const double len = m_sumSin * m_sumSin + m_sumCos * m_sumCos;
|
||||
if (len < 1e-24)
|
||||
return 0.0; // average direction undefined
|
||||
|
||||
return static_cast<T>(to2PI(std::atan2(sumSin, sumCos)));
|
||||
}
|
||||
|
||||
// start the moving average over again
|
||||
template <typename T>
|
||||
void movingAvgAngle<T>::reset()
|
||||
{
|
||||
m_nbrReadings = 0;
|
||||
m_sumSin = 0;
|
||||
m_sumCos = 0;
|
||||
m_next = 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T movingAvgAngle<T>::to2PI(T a)
|
||||
{
|
||||
a = fmod(a, M_TWOPI);
|
||||
if (a < 0.0) {
|
||||
a += M_TWOPI;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
// --- End class MovingAvgAngle ---------------
|
||||
@@ -0,0 +1,807 @@
|
||||
[DEFAULT]
|
||||
calibration_fields = AWA, AWS, COG, DBT, HDM, PRPOS, RPOS, SOG, STW, TWA, TWS, TWD, WTemp
|
||||
|
||||
[deviceName]
|
||||
label = system name
|
||||
type = string
|
||||
default = OBP40
|
||||
description = system name, used for the access point and for services
|
||||
check = checkSystemName
|
||||
category = system
|
||||
|
||||
[timeServer]
|
||||
label = time server
|
||||
type = string
|
||||
default = pool.ntp.org
|
||||
description = NTP time server. Use only one hostname or IP address
|
||||
category = wifi client
|
||||
capabilities = obp40:true
|
||||
|
||||
[timeZone]
|
||||
label = Time Zone
|
||||
type = number
|
||||
default = 0.00
|
||||
description = Time zone [UTC -12...+14]
|
||||
check = checkMinMax
|
||||
min = -12.0
|
||||
max = 14.0
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[homeLAT]
|
||||
label = Home latitude
|
||||
type = number
|
||||
default = 0.00000
|
||||
description = Latitude of boat home location [-90.0...+90.0]
|
||||
check = checkMinMax
|
||||
min = -90.0
|
||||
max = 90.0
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[homeLON]
|
||||
label = Home longitude
|
||||
type = number
|
||||
default = 0.00000
|
||||
description = Longitude of boat home location [-180.0...+180.0]
|
||||
check = checkMinMax
|
||||
min = -180.0
|
||||
max = 180.0
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[draft]
|
||||
label = Boat Draft [m]
|
||||
type = number
|
||||
default = 0.00
|
||||
description = The draft of the boat [0...50m]
|
||||
check = checkMinMax
|
||||
min = 0.0
|
||||
max = 50.0
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[chainLength]
|
||||
label = Anchor Chain Length [m]
|
||||
type = number
|
||||
default = 0
|
||||
description = The length of the anchor chain [0...255m]
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 255
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[fuelTank]
|
||||
label = Fuel Tank [l]
|
||||
type = number
|
||||
default = 0
|
||||
description = Fuel tank capacity [0...5000l]
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 5000
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[fuelConsumption]
|
||||
label = Fuel Consuption [l/h]
|
||||
type = number
|
||||
default = 0.00
|
||||
description = Medium fuel consumption [0...1000l/h]
|
||||
check = checkMinMax
|
||||
min = 0.0
|
||||
max = 1000.0
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[waterTank]
|
||||
label = Water Tank [l]
|
||||
type = number
|
||||
default = 0
|
||||
description = Water tank capacity [0...5000l]
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 5000
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[wasteTank]
|
||||
label = Waste Tank [l]
|
||||
type = number
|
||||
default = 0
|
||||
description = Waste tank capacity [0...5000l]
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 5000
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[batteryVoltage]
|
||||
label = Battery Voltage [V]
|
||||
type = list
|
||||
default = 12V
|
||||
description = Battery Voltage [12V|24V]
|
||||
list = 12V, 24V
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[batteryType]
|
||||
label = Battery Type
|
||||
type = list
|
||||
default = Pb
|
||||
description = Type of battery [Pb|Gel|AGM|LiFePo4]
|
||||
list = Pb, Gel, AGM, LiFePo4
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[batteryCapacity]
|
||||
label = Battery Capacity [Ah]
|
||||
type = number
|
||||
default = 0.0
|
||||
description = Battery capacity [0...10000Ah]
|
||||
check = checkMinMax
|
||||
min = 0.0
|
||||
max = 10000.0
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[solarPower]
|
||||
label = Solar Power [W]
|
||||
type = number
|
||||
default = 0.0
|
||||
description = Solar power [0...10000W]
|
||||
check = checkMinMax
|
||||
min = 0.0
|
||||
max = 10000.0
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[genPower]
|
||||
label = Genarator Power [W]
|
||||
type = number
|
||||
default = 0.0
|
||||
description = Generator power [0...10000W]
|
||||
check = checkMinMax
|
||||
min = 0.0
|
||||
max = 10000.0
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[trackStep]
|
||||
label = angle [deg]
|
||||
type = number
|
||||
default = 3.0
|
||||
description = track step offset [1...12deg]
|
||||
check = checkMinMax
|
||||
min = 1.0
|
||||
max = 12.0
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[calcTrueWnds]
|
||||
label = Calculate True Wind
|
||||
type = boolean
|
||||
default = false
|
||||
description = If not available, calculate true wind data from appearant wind and other boat data
|
||||
category = OBP40 Settings
|
||||
capabilities = obp40:true
|
||||
|
||||
[lengthFormat]
|
||||
label = Length Format
|
||||
type = list
|
||||
default = m
|
||||
description = Length format [m|ft]
|
||||
list = m, ft
|
||||
category = OBP40 Units
|
||||
capabilities = obp40:true
|
||||
|
||||
[distanceFormat]
|
||||
label = Distance Format
|
||||
type = list
|
||||
default = nm
|
||||
description = Distance format [m|km|nm]
|
||||
list = m, km, nm
|
||||
category = OBP40 Units
|
||||
capabilities = obp40:true
|
||||
|
||||
[speedFormat]
|
||||
label = Speed Format
|
||||
type = list
|
||||
default = kn
|
||||
description = Distance format [m/s|km/h|kn]
|
||||
list = m/s, km/h, kn
|
||||
category = OBP40 Units
|
||||
capabilities = obp40:true
|
||||
|
||||
[windspeedFormat]
|
||||
label = Wind Speed Format
|
||||
type = list
|
||||
default = kn
|
||||
description = Wind speed format [m/s|km/h|kn|bft]
|
||||
list = m/s, km/h, kn, bft
|
||||
category = OBP40 Units
|
||||
capabilities = obp40:true
|
||||
|
||||
[tempFormat]
|
||||
label = Temperature Format
|
||||
type = list
|
||||
default = C
|
||||
description = Temperature format [K|C|F]
|
||||
list = K, C, F
|
||||
category = OBP40 Units
|
||||
capabilities = obp40:true
|
||||
|
||||
[dateFormat]
|
||||
label = Date Format
|
||||
type = list
|
||||
default = DE
|
||||
description = Date format [DE|GB|US|ISO] DE: 31.12.2022, GB: 31/12/2022, US: 12/31/2022, ISO: 2022-12-31
|
||||
list = DE, GB, US, ISO
|
||||
category = OBP40 Units
|
||||
capabilities = obp40:true
|
||||
|
||||
[cpuSpeed]
|
||||
label = CPU Speed [MHz]
|
||||
type = list
|
||||
default = 160
|
||||
description = CPU speed in MHz [80|160|240]
|
||||
list = 80, 160, 240
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[useRTC]
|
||||
label = RTC Modul
|
||||
type = list
|
||||
default = off
|
||||
description = Use RTC module type [off|DS1388]
|
||||
list = off, DS1388
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[useGPS]
|
||||
label = GPS Sensor
|
||||
type = list
|
||||
default = off
|
||||
description = Use internal GPS module type [off|NEO-6M|NEO-M8N|ATGM336H]
|
||||
list = off, NEO-6M, NEO-M8N, ATGM336H
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[hdopAccuracy]
|
||||
label = HDOP Accuracy [m]
|
||||
type = number
|
||||
default = 20
|
||||
description = HDOP ccuracy in m for a valid GPS signal [1...50]
|
||||
check = checkMinMax
|
||||
min = 1
|
||||
max = 50
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[useEnvSensor]
|
||||
label = Env. Sensor
|
||||
type = list
|
||||
default = off
|
||||
description = Use internal or external environment sensor via I2C bus [off|BME280|BMP280|BMP180|BMP085|HTU21|SHT21]
|
||||
list = off, BME280, BMP280, BMP180, BMP085, HTU21, SHT21
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[usePowSensor1]
|
||||
label = Battery Sensor
|
||||
type = list
|
||||
default = off
|
||||
description = Use external power management sensor via I2C bus for battery [off|INA219|INA226|]
|
||||
list = off, INA219, INA226
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[shunt1]
|
||||
label = Battery Shunt
|
||||
type = list
|
||||
default = 10
|
||||
description = Shunt current value [10A|50A|100A|200A|300A|400A|500A]
|
||||
list = 10, 50, 100, 200, 300, 400, 500
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[usePowSensor2]
|
||||
label = Solar Sensor
|
||||
type = list
|
||||
default = off
|
||||
description = Use external power management sensor via I2C bus for solar panels [off|INA219|INA226|]
|
||||
list = off, INA219, INA226
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[shunt2]
|
||||
label = Solar Shunt
|
||||
type = list
|
||||
default = 10
|
||||
description = Shunt current value [10A|50A|100A|200A|300A|400A|500A]
|
||||
list = 10, 50, 100, 200, 300, 400, 500
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[usePowSensor3]
|
||||
label = Gen. Sensor
|
||||
type = list
|
||||
default = off
|
||||
description = Use external power management sensor via I2C bus for generator [off|INA219|INA226|]
|
||||
list = off, INA219, INA226
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[shunt3]
|
||||
label = Gen. Shunt
|
||||
type = list
|
||||
default = 10
|
||||
description = Shunt current value [10A|50A|100A|200A|300A|400A|500A] @ 75mV
|
||||
list = 10, 50, 100, 200, 300, 400, 500
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[useRotSensor]
|
||||
label = Rot. Sensor
|
||||
type = list
|
||||
default = off
|
||||
description = Use external rotation sensor via I2C bus [off|AS5600]
|
||||
list = off, AS5600
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[rotFunction]
|
||||
label = Rot. Function
|
||||
type = list
|
||||
default = off
|
||||
description = Function for rotation sensor [off|Rudder|Wind|Mast|Keel|Trim|Boom]
|
||||
list = off, Rudder, Wind, Mast, Keel, Trim, Boom
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[rotOffset]
|
||||
label = Rot. Offset
|
||||
type = number
|
||||
default = 0
|
||||
description = Offset for rotation sensor [-180°...+180°]
|
||||
check = checkMinMax
|
||||
min = -180
|
||||
max = 180
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[rollLimit]
|
||||
label = Roll Limit
|
||||
type = number
|
||||
default = 25
|
||||
description = Limit violation for roll angle [-90°...+90°]
|
||||
check = checkMinMax
|
||||
min = -90
|
||||
max = 90
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[rollOffset]
|
||||
label = Roll Offset
|
||||
type = number
|
||||
default = 0
|
||||
description = Roll offset angle [-45°...+45°]
|
||||
check = checkMinMax
|
||||
min = -45
|
||||
max = 45
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[pitchOffset]
|
||||
label = Pitch Offset
|
||||
type = number
|
||||
default = 0
|
||||
description = Pitch offset angle [-45°...+45°]
|
||||
check = checkMinMax
|
||||
min = -45
|
||||
max = 45
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[useTempSensor]
|
||||
label = Temp. Sensor
|
||||
type = boolean
|
||||
default = off
|
||||
description = Use max. 8 external 1Wire devices [off|DS18B20]
|
||||
list = off, DS18B20
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[useSDCard]
|
||||
label = SD Card
|
||||
type = boolean
|
||||
default = false
|
||||
description = Use internal SD card interface [off|on]
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[powerMode]
|
||||
label = Power Mode
|
||||
type = list
|
||||
default = Max Power
|
||||
description = Settings for power mode
|
||||
list = Max Power, Only 5.0V, Min Power
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[underVoltage]
|
||||
label = Undervoltage
|
||||
type = boolean
|
||||
default = false
|
||||
description = Switch off device if LiPo voltage drops below 3.65V [on|off]
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[useSimuData]
|
||||
label = Simulation Data
|
||||
type = boolean
|
||||
default = false
|
||||
description = Use simulation data when bus data are missing [on|off]
|
||||
category = OBP40 Hardware
|
||||
capabilities = obp40:true
|
||||
|
||||
[tSensitivity]
|
||||
label = Touch Sensitivity [%%]
|
||||
type = number
|
||||
default = 100
|
||||
description = Touch sensitivity [0...100%%] for sensor buttons
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 100
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:false
|
||||
|
||||
[vOffset]
|
||||
label = VSensor Offset
|
||||
type = number
|
||||
default = -1.00
|
||||
description = Offset for internal voltage sensor (ESP32)
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
|
||||
[vSlope]
|
||||
label = VSensor Slope
|
||||
type = number
|
||||
default = 1.00
|
||||
description = Slope for internal voltage sensor (ESP32)
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
|
||||
[calInstance1]
|
||||
label = Calibration Data Instance 1
|
||||
type = list
|
||||
default = ---
|
||||
description = Data instance for calibration
|
||||
list = ---, %(calibration_fields)s
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
|
||||
[calOffset1]
|
||||
label = Data Instance 1 Calibration Offset
|
||||
type = number
|
||||
default = 0.00
|
||||
description = Offset for data instance 1
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
condition = calInstance1 IN %(calibration_fields)s
|
||||
|
||||
[calSlope1]
|
||||
label = Data Instance 1 Calibration Slope
|
||||
type = number
|
||||
default = 1.00
|
||||
description = Slope for data instance 1
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
condition = calInstance1 IN %(calibration_fields)s
|
||||
|
||||
[calSmooth1]
|
||||
label = Data Instance 1 Smoothing
|
||||
type = number
|
||||
default = 0
|
||||
description = Smoothing factor [0..10]; 0 = no smoothing
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 10
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
condition = calInstance1 IN %(calibration_fields)s
|
||||
|
||||
[calInstance2]
|
||||
label = Calibration Data Instance 2
|
||||
type = list
|
||||
default = ---
|
||||
description = Data instance for calibration
|
||||
list = ---, %(calibration_fields)s
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
|
||||
[calOffset2]
|
||||
label = Data Instance 2 Calibration Offset
|
||||
type = number
|
||||
default = 0.00
|
||||
description = Offset for data instance 2
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
condition = calInstance2 IN %(calibration_fields)s
|
||||
|
||||
[calSlope2]
|
||||
label = Data Instance 2 Calibration Slope
|
||||
type = number
|
||||
default = 1.00
|
||||
description = Slope for data instance 2
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
condition = calInstance2 IN %(calibration_fields)s
|
||||
|
||||
[calSmooth2]
|
||||
label = Data Instance 2 Smoothing
|
||||
type = number
|
||||
default = 0
|
||||
description = Smoothing factor [0..10]; 0 = no smoothing
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 10
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
condition = calInstance2 IN %(calibration_fields)s
|
||||
|
||||
[calInstance3]
|
||||
label = Calibration Data Instance 3
|
||||
type = list
|
||||
default = ---
|
||||
description = Data instance for calibration
|
||||
list = ---, %(calibration_fields)s
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
|
||||
[calOffset3]
|
||||
label = Data Instance 3 Calibration Offset
|
||||
type = number
|
||||
default = 0.00
|
||||
description = Offset for data instance 3
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
condition = calinstance3 IN %(calibration_fields)s
|
||||
|
||||
[calSlope3]
|
||||
label = Data Instance 3 Calibration Slope
|
||||
type = number
|
||||
default = 1.00
|
||||
description = Slope for data instance 3
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
condition = calinstance3 IN %(calibration_fields)s
|
||||
|
||||
[calSmooth3]
|
||||
label = Data Instance 3 Smoothing
|
||||
type = number
|
||||
default = 0
|
||||
description = Smoothing factor [0..10]; 0 = no smoothing
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 10
|
||||
category = OBP40 Calibrations
|
||||
capabilities = obp40:true
|
||||
condition = calinstance3 IN %(calibration_fields)s
|
||||
|
||||
[display]
|
||||
label = Display Mode
|
||||
type = list
|
||||
default = Logo + QR Code
|
||||
description = Settings for startup display
|
||||
list = White Screen, Logo, Logo + QR Code, Off
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:true
|
||||
|
||||
[displaycolor]
|
||||
label = Inverted Display Mode
|
||||
type = list
|
||||
default = Normal
|
||||
description = Invert display to white letters on black background [Normal|Inverse]
|
||||
list = Normal, Inverse
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:true
|
||||
|
||||
[statusLine]
|
||||
label = Status Line
|
||||
type = boolean
|
||||
default = true
|
||||
description = Show status line [on|off]
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:true
|
||||
|
||||
[timeSource]
|
||||
label = Status Time Source
|
||||
type = list
|
||||
default = GPS
|
||||
description = Data source for date and time display in status line [RTC|iRTC|GPS]
|
||||
dict =
|
||||
iRTC:Internal real time clock (iRTC)
|
||||
RTC:External real time clock (RTC)
|
||||
GPS:External time via bus (GPS)
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:true
|
||||
|
||||
[refresh]
|
||||
label = Refresh
|
||||
type = boolean
|
||||
default = true
|
||||
description = Refresh e-paper display after each new page request to reduce ghost effects [on|off]
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:true
|
||||
|
||||
[fastRefresh]
|
||||
label = Fast Refresh
|
||||
type = boolean
|
||||
default = false
|
||||
description = Fast refresh for e-paper display [on|off]
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:true
|
||||
|
||||
[fullRefreshTime]
|
||||
label = Full Refresh Time [min]
|
||||
type = number
|
||||
default = 1
|
||||
description = E-Paper full refresh time all [1...10 min]
|
||||
check = checkMinMax
|
||||
min = 1
|
||||
max = 10
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:true
|
||||
|
||||
[holdvalues]
|
||||
label = Hold Values
|
||||
type = boolean
|
||||
default = false
|
||||
description = Retain old values when data stream stops [on|off]
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:true
|
||||
|
||||
[valueprecision]
|
||||
label = Display value precision
|
||||
type = list
|
||||
default = 2
|
||||
description = Maximum number of decimal places to display [1|2]
|
||||
list = 1, 2
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:true
|
||||
|
||||
[headerFormat]
|
||||
label = Header Format
|
||||
type = list
|
||||
default = TEXT
|
||||
description = Header format: Text or Symbols
|
||||
dict =
|
||||
TEXT:Text
|
||||
ICON:Symbols
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:true
|
||||
|
||||
[backlight]
|
||||
label = Backlight Mode
|
||||
type = list
|
||||
default = off
|
||||
description = Settings for automatic backlight mode
|
||||
list = Off, Control by Sun, Control by Bus, Control by Time, Control by Key, On
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:false
|
||||
|
||||
[blColor]
|
||||
label = Backlight Color
|
||||
type = list
|
||||
default = Red
|
||||
description = Backlight color
|
||||
list = Red, Orange, Yellow, Green, Blue, Aqua, Violet, White
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:false
|
||||
|
||||
[blBrightness]
|
||||
label = Brightness [%%]
|
||||
type = number
|
||||
default = 50
|
||||
description = Backlight brightness [20...100%%]
|
||||
check = checkMinMax
|
||||
min = 20
|
||||
max = 100
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:false
|
||||
|
||||
[flashLED]
|
||||
label = Flash LED Mode
|
||||
type = list
|
||||
default = Off
|
||||
description = Settings for flash LED
|
||||
list = Off, Bus Data, GPS Fix Lost, Limit Violation
|
||||
category = OBP40 Display
|
||||
capabilities = obp40:false
|
||||
|
||||
[buzzerError]
|
||||
label = Buzzer Error
|
||||
type = boolean
|
||||
default = false
|
||||
description = Sound on error [on|off]
|
||||
category = OBP40 Buzzer
|
||||
capabilities = obp40:false
|
||||
|
||||
[buzzerGps]
|
||||
label = Buzzer GPS Fix
|
||||
type = boolean
|
||||
default = false
|
||||
description = Sound on missing or lost GPS fix
|
||||
category = OBP40 Buzzer
|
||||
capabilities = obp40:false
|
||||
|
||||
[buzzerLim]
|
||||
label = Buzzer by Limits
|
||||
type = boolean
|
||||
default = false
|
||||
description = Sound on limit violation
|
||||
category = OBP40 Buzzer
|
||||
capabilities = obp40:false
|
||||
|
||||
[buzzerMode]
|
||||
label = Buzzer Mode
|
||||
type = list
|
||||
default = Off
|
||||
description = Settings for buzzer behaviour
|
||||
list = Off, Short Single Beep, Longer Single Beep, Beep until Confirmation
|
||||
category = OBP40 Buzzer
|
||||
capabilities = obp40:false
|
||||
|
||||
[buzzerPower]
|
||||
label = Buzzer Power [%%]
|
||||
type = number
|
||||
default = 50
|
||||
description = Buzzer loudness [0...100%%]
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 100
|
||||
category = OBP40 Buzzer
|
||||
capabilities = obp40:false
|
||||
|
||||
[visiblePages]
|
||||
label = Number of Pages
|
||||
type = number
|
||||
default = 10
|
||||
description = Number of visible data pages [1...10]
|
||||
check = checkMinMax
|
||||
min = 1
|
||||
max = 10
|
||||
category = OBP40 Pages
|
||||
capabilities = obp40:true
|
||||
|
||||
[startPage]
|
||||
label = Start Page
|
||||
type = number
|
||||
default = 1
|
||||
description = First page number to display after device startup
|
||||
check = checkMinMax
|
||||
min = 1
|
||||
max = 10
|
||||
category = OBP40 Pages
|
||||
capabilities = obp40:true
|
||||
|
||||
[systemPage]
|
||||
label = System Page
|
||||
type = boolean
|
||||
default = false
|
||||
description = Use wheel button for system page or direct deep sleep mode
|
||||
category = OBP40 Pages
|
||||
capabilities = obp40:true
|
||||
|
||||
[imageFormat]
|
||||
label = Screenshot Format
|
||||
type = list
|
||||
default = PBM
|
||||
description = Graphics file format for screenshots [GIF|PBM|BMP]
|
||||
dict =
|
||||
GIF:Compressed image (GIF)
|
||||
PBM:Portable bitmap (PBM)
|
||||
BMP:Windows bitmap (BMP)
|
||||
category = OBP40 Pages
|
||||
capabilities = obp40:true
|
||||
@@ -0,0 +1,857 @@
|
||||
[DEFAULT]
|
||||
calibration_fields = AWA, AWS, COG, DBT, HDM, PRPOS, RPOS, SOG, STW, TWA, TWS, TWD, WTemp
|
||||
|
||||
[deviceName]
|
||||
label = system name
|
||||
type = string
|
||||
default = OBP60V2
|
||||
description = system name, used for the access point and for services
|
||||
check = checkSystemName
|
||||
category = system
|
||||
|
||||
[timeServer]
|
||||
label = time server
|
||||
type = string
|
||||
default = pool.ntp.org
|
||||
description = NTP time server. Use only one hostname or IP address
|
||||
category = wifi client
|
||||
capabilities = obp60:true
|
||||
|
||||
[timeZone]
|
||||
label = Time Zone
|
||||
type = number
|
||||
default = 0.00
|
||||
description = Time zone [UTC -12...+14]
|
||||
check = checkMinMax
|
||||
min = -12.0
|
||||
max = 14.0
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[homeLAT]
|
||||
label = Home latitude
|
||||
type = number
|
||||
default =
|
||||
description = Latitude of boat home location [-90.0...+90.0]
|
||||
check = checkMinMax
|
||||
min = -90.0
|
||||
max = 90.0
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[homeLON]
|
||||
label = Home longitude
|
||||
type = number
|
||||
default =
|
||||
description = Longitude of boat home location [-180.0...+180.0]
|
||||
check = checkMinMax
|
||||
min = -180.0
|
||||
max = 180.0
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[draft]
|
||||
label = Boat Draft [m]
|
||||
type = number
|
||||
default = 0.00
|
||||
description = The draft of the boat [0...50m]
|
||||
check = checkMinMax
|
||||
min = 0.0
|
||||
max = 50.0
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[chainLength]
|
||||
label = Anchor Chain Length [m]
|
||||
type = number
|
||||
default = 0
|
||||
description = The length of the anchor chain [0...255m]
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 255
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[fuelTank]
|
||||
label = Fuel Tank [l]
|
||||
type = number
|
||||
default = 0
|
||||
description = Fuel tank capacity [0...5000l]
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 5000
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[fuelConsumption]
|
||||
label = Fuel Consuption [l/h]
|
||||
type = number
|
||||
default = 0.00
|
||||
description = Medium fuel consumption [0...1000l/h]
|
||||
check = checkMinMax
|
||||
min = 0.0
|
||||
max = 1000.0
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[waterTank]
|
||||
label = Water Tank [l]
|
||||
type = number
|
||||
default = 0
|
||||
description = Water tank capacity [0...5000l]
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 5000
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[wasteTank]
|
||||
label = Waste Tank [l]
|
||||
type = number
|
||||
default = 0
|
||||
description = Waste tank capacity [0...5000l]
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 5000
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[batteryVoltage]
|
||||
label = Battery Voltage [V]
|
||||
type = list
|
||||
default = 12V
|
||||
description = Battery Voltage [12V|24V]
|
||||
list = 12V, 24V
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[batteryType]
|
||||
label = Battery Type
|
||||
type = list
|
||||
default = Pb
|
||||
description = Type of battery [Pb|Gel|AGM|LiFePo4]
|
||||
list = Pb, Gel, AGM, LiFePo4
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[batteryCapacity]
|
||||
label = Battery Capacity [Ah]
|
||||
type = number
|
||||
default = 0.0
|
||||
description = Battery capacity [0...10000Ah]
|
||||
check = checkMinMax
|
||||
min = 0.0
|
||||
max = 10000.0
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[solarPower]
|
||||
label = Solar Power [W]
|
||||
type = number
|
||||
default = 0.0
|
||||
description = Solar power [0...10000W]
|
||||
check = checkMinMax
|
||||
min = 0.0
|
||||
max = 10000.0
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[genPower]
|
||||
label = Genarator Power [W]
|
||||
type = number
|
||||
default = 0.0
|
||||
description = Generator power [0...10000W]
|
||||
check = checkMinMax
|
||||
min = 0.0
|
||||
max = 10000.0
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[trackStep]
|
||||
label = angle [deg]
|
||||
type = number
|
||||
default = 3.0
|
||||
description = track step offset [1...12deg]
|
||||
check = checkMinMax
|
||||
min = 1.0
|
||||
max = 12.0
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[calcTrueWnds]
|
||||
label = Calculate True Wind
|
||||
type = boolean
|
||||
default = false
|
||||
description = If not available, calculate true wind data from appearant wind and other boat data
|
||||
category = OBP60 Settings
|
||||
capabilities = obp60:true
|
||||
|
||||
[lengthFormat]
|
||||
label = Length Format
|
||||
type = list
|
||||
default = m
|
||||
description = Length format [m|ft]
|
||||
list = m, ft
|
||||
category = OBP60 Units
|
||||
capabilities = obp60:true
|
||||
|
||||
[distanceFormat]
|
||||
label = Distance Format
|
||||
type = list
|
||||
default = nm
|
||||
description = Distance format [m|km|nm]
|
||||
list = m, km, nm
|
||||
category = OBP60 Units
|
||||
capabilities = obp60:true
|
||||
|
||||
[speedFormat]
|
||||
label = Speed Format
|
||||
type = list
|
||||
default = kn
|
||||
description = Distance format [m/s|km/h|kn]
|
||||
list = m/s, km/h, kn
|
||||
category = OBP60 Units
|
||||
capabilities = obp60:true
|
||||
|
||||
[windspeedFormat]
|
||||
label = Wind Speed Format
|
||||
type = list
|
||||
default = kn
|
||||
description = Wind speed format [m/s|km/h|kn|bft]
|
||||
list = m/s, km/h, kn, bft
|
||||
category = OBP60 Units
|
||||
capabilities = obp60:true
|
||||
|
||||
[tempFormat]
|
||||
label = Temperature Format
|
||||
type = list
|
||||
default = C
|
||||
description = Temperature format [K|C|F]
|
||||
list = K, C, F
|
||||
category = OBP60 Units
|
||||
capabilities = obp60:true
|
||||
|
||||
[dateFormat]
|
||||
label = Date Format
|
||||
type = list
|
||||
default = DE
|
||||
description = Date format [DE|GB|US|ISO] DE: 31.12.2022, GB: 31/12/2022, US: 12/31/2022, ISO: 2022-12-31
|
||||
list = DE, GB, US, ISO
|
||||
category = OBP60 Units
|
||||
capabilities = obp60:true
|
||||
|
||||
[cpuSpeed]
|
||||
label = CPU Speed [MHz]
|
||||
type = list
|
||||
default = 160
|
||||
description = CPU speed in MHz [80|160|240]
|
||||
list = 80, 160, 240
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[useRTC]
|
||||
label = RTC Modul
|
||||
type = list
|
||||
default = DS1388
|
||||
description = Use internal RTC module type [off|DS1388]
|
||||
list = off, DS1388
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[useGPS]
|
||||
label = GPS Sensor
|
||||
type = list
|
||||
default = ATGM336H
|
||||
description = Use internal GPS module type [off|NEO-6M|NEO-M8N|ATGM336H]
|
||||
list = off, NEO-6M, NEO-M8N, ATGM336H
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[hdopAccuracy]
|
||||
label = HDOP Accuracy [m]
|
||||
type = number
|
||||
default = 20
|
||||
description = HDOP ccuracy in m for a valid GPS signal [1...50]
|
||||
check = checkMinMax
|
||||
min = 1
|
||||
max = 50
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[useEnvSensor]
|
||||
label = Env. Sensor
|
||||
type = list
|
||||
default = BMP280
|
||||
description = Use internal or external environment sensor via I2C bus [off|BME280|BMP280|BMP180|BMP085|HTU21|SHT21]
|
||||
list = off, BME280, BMP280, BMP180, BMP085, HTU21, SHT21
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[usePowSensor1]
|
||||
label = Battery Sensor
|
||||
type = list
|
||||
default = off
|
||||
description = Use external power management sensor via I2C bus for battery [off|INA219|INA226|]
|
||||
list = off, INA219, INA226
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[shunt1]
|
||||
label = Battery Shunt
|
||||
type = list
|
||||
default = 10
|
||||
description = Shunt current value [10A|50A|100A|200A|300A|400A|500A]
|
||||
list = 10, 50, 100, 200, 300, 400, 500
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[usePowSensor2]
|
||||
label = Solar Sensor
|
||||
type = list
|
||||
default = off
|
||||
description = Use external power management sensor via I2C bus for solar panels [off|INA219|INA226|]
|
||||
list = off, INA219, INA226
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[shunt2]
|
||||
label = Solar Shunt
|
||||
type = list
|
||||
default = 10
|
||||
description = Shunt current value [10A|50A|100A|200A|300A|400A|500A]
|
||||
list = 10, 50, 100, 200, 300, 400, 500
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[usePowSensor3]
|
||||
label = Gen. Sensor
|
||||
type = list
|
||||
default = off
|
||||
description = Use external power management sensor via I2C bus for generator [off|INA219|INA226|]
|
||||
list = off, INA219, INA226
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[shunt3]
|
||||
label = Gen. Shunt
|
||||
type = list
|
||||
default = 10
|
||||
description = Shunt current value [10A|50A|100A|200A|300A|400A|500A] @ 75mV
|
||||
list = 10, 50, 100, 200, 300, 400, 500
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[useRotSensor]
|
||||
label = Rot. Sensor
|
||||
type = list
|
||||
default = off
|
||||
description = Use external rotation sensor via I2C bus [off|AS5600]
|
||||
list = off, AS5600
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[rotFunction]
|
||||
label = Rot. Function
|
||||
type = list
|
||||
default = off
|
||||
description = Function for rotation sensor [off|Rudder|Wind|Mast|Keel|Trim|Boom]
|
||||
list = off, Rudder, Wind, Mast, Keel, Trim, Boom
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[rotOffset]
|
||||
label = Rot. Offset
|
||||
type = number
|
||||
default = 0
|
||||
description = Offset for rotation sensor [-180°...+180°]
|
||||
check = checkMinMax
|
||||
min = -180
|
||||
max = 180
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[rollLimit]
|
||||
label = Roll Limit
|
||||
type = number
|
||||
default = 25
|
||||
description = Limit violation for roll angle [-90°...+90°]
|
||||
check = checkMinMax
|
||||
min = -90
|
||||
max = 90
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[rollOffset]
|
||||
label = Roll Offset
|
||||
type = number
|
||||
default = 0
|
||||
description = Roll offset angle [-45°...+45°]
|
||||
check = checkMinMax
|
||||
min = -45
|
||||
max = 45
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[pitchOffset]
|
||||
label = Pitch Offset
|
||||
type = number
|
||||
default = 0
|
||||
description = Pitch offset angle [-45°...+45°]
|
||||
check = checkMinMax
|
||||
min = -45
|
||||
max = 45
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[useTempSensor]
|
||||
label = Temp. Sensor
|
||||
type = boolean
|
||||
default = off
|
||||
description = Use max. 8 external 1Wire devices [off|DS18B20]
|
||||
list = off, DS18B20
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[powerMode]
|
||||
label = Power Mode
|
||||
type = list
|
||||
default = Max Power
|
||||
description = Settings for power mode
|
||||
list = Max Power, Only 5.0V, Min Power
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[underVoltage]
|
||||
label = Undervoltage
|
||||
type = boolean
|
||||
default = false
|
||||
description = Switch off device if voltage drops below 9V [on|off]
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[useSimuData]
|
||||
label = Simulation Data
|
||||
type = boolean
|
||||
default = false
|
||||
description = Use simulation data when bus data are missing [on|off]
|
||||
category = OBP60 Hardware
|
||||
capabilities = obp60:true
|
||||
|
||||
[tSensitivity]
|
||||
label = Touch Sensitivity [%%]
|
||||
type = number
|
||||
default = 100
|
||||
description = Touch sensitivity [0...100%%] for sensor buttons
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 100
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
|
||||
[vOffset]
|
||||
label = VSensor Offset
|
||||
type = number
|
||||
default = -1.00
|
||||
description = Offset for internal voltage sensor (ESP32)
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
|
||||
[vSlope]
|
||||
label = VSensor Slope
|
||||
type = number
|
||||
default = 1.00
|
||||
description = Slope for internal voltage sensor (ESP32)
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
|
||||
[calInstance1]
|
||||
label = Calibration Data Instance 1
|
||||
type = list
|
||||
default = ---
|
||||
description = Data instance for calibration
|
||||
list = ---, %(calibration_fields)s
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
|
||||
[calOffset1]
|
||||
label = Data Instance 1 Calibration Offset
|
||||
type = number
|
||||
default = 0.00
|
||||
description = Offset for data instance 1
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
condition = calInstance1 IN %(calibration_fields)s
|
||||
|
||||
[calSlope1]
|
||||
label = Data Instance 1 Calibration Slope
|
||||
type = number
|
||||
default = 1.00
|
||||
description = Slope for data instance 1
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
condition = calInstance1 IN %(calibration_fields)s
|
||||
|
||||
[calSmooth1]
|
||||
label = Data Instance 1 Smoothing
|
||||
type = number
|
||||
default = 0
|
||||
description = Smoothing factor [0..10]; 0 = no smoothing
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 10
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
condition = calInstance1 IN %(calibration_fields)s
|
||||
|
||||
[calInstance2]
|
||||
label = Calibration Data Instance 2
|
||||
type = list
|
||||
default = ---
|
||||
description = Data instance for calibration
|
||||
list = ---, %(calibration_fields)s
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
|
||||
[calOffset2]
|
||||
label = Data Instance 2 Calibration Offset
|
||||
type = number
|
||||
default = 0.00
|
||||
description = Offset for data instance 2
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
condition = calInstance2 IN %(calibration_fields)s
|
||||
|
||||
[calSlope2]
|
||||
label = Data Instance 2 Calibration Slope
|
||||
type = number
|
||||
default = 1.00
|
||||
description = Slope for data instance 2
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
condition = calInstance2 IN %(calibration_fields)s
|
||||
|
||||
[calSmooth2]
|
||||
label = Data Instance 2 Smoothing
|
||||
type = number
|
||||
default = 0
|
||||
description = Smoothing factor [0..10]; 0 = no smoothing
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 10
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
condition = calInstance2 IN %(calibration_fields)s
|
||||
|
||||
[calInstance3]
|
||||
label = Calibration Data Instance 3
|
||||
type = list
|
||||
default = ---
|
||||
description = Data instance for calibration
|
||||
list = ---, %(calibration_fields)s
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
|
||||
[calOffset3]
|
||||
label = Data Instance 3 Calibration Offset
|
||||
type = number
|
||||
default = 0.00
|
||||
description = Offset for data instance 3
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
condition = calinstance3 IN %(calibration_fields)s
|
||||
|
||||
[calSlope3]
|
||||
label = Data Instance 3 Calibration Slope
|
||||
type = number
|
||||
default = 1.00
|
||||
description = Slope for data instance 3
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
condition = calinstance3 IN %(calibration_fields)s
|
||||
|
||||
[calSmooth3]
|
||||
label = Data Instance 3 Smoothing
|
||||
type = number
|
||||
default = 0
|
||||
description = Smoothing factor [0..10]; 0 = no smoothing
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 10
|
||||
category = OBP60 Calibrations
|
||||
capabilities = obp60:true
|
||||
condition = calinstance3 IN %(calibration_fields)s
|
||||
|
||||
[display]
|
||||
label = Display Mode
|
||||
type = list
|
||||
default = Logo + QR Code
|
||||
description = Settings for startup display
|
||||
list = White Screen, Logo, Logo + QR Code, Off
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[displaycolor]
|
||||
label = Inverted Display Mode
|
||||
type = list
|
||||
default = Normal
|
||||
description = Invert display to white letters on black background [Normal|Inverse]
|
||||
list = Normal, Inverse
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[statusLine]
|
||||
label = Status Line
|
||||
type = boolean
|
||||
default = true
|
||||
description = Show status line [on|off]
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[timeSource]
|
||||
label = Status Time Source
|
||||
type = list
|
||||
default = GPS
|
||||
description = Data source for date and time display in status line [RTC|GPS]
|
||||
dict =
|
||||
RTC:Real time clock (RTC)
|
||||
GPS:Time via bus (GPS)
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[refresh]
|
||||
label = Refresh
|
||||
type = boolean
|
||||
default = true
|
||||
description = Refresh e-paper display after each new page request to reduce ghost effects [on|off]
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[fastRefresh]
|
||||
label = Fast Refresh
|
||||
type = boolean
|
||||
default = false
|
||||
description = Fast refresh for e-paper display [on|off]
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[fullRefreshTime]
|
||||
label = Full Refresh Time [min]
|
||||
type = number
|
||||
default = 1
|
||||
description = E-Paper full refresh time all [1...10 min]
|
||||
check = checkMinMax
|
||||
min = 1
|
||||
max = 10
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[holdvalues]
|
||||
label = Hold Values
|
||||
type = boolean
|
||||
default = false
|
||||
description = Retain old values when data stream stops [on|off]
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[valueprecision]
|
||||
label = Display value precision
|
||||
type = list
|
||||
default = 2
|
||||
description = Maximum number of decimal places to display [1|2]
|
||||
list = 1, 2
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[headerFormat]
|
||||
label = Header Format
|
||||
type = list
|
||||
default = TEXT
|
||||
description = Header format: Text or Symbols
|
||||
dict =
|
||||
TEXT:Text
|
||||
ICON:Symbols
|
||||
category = OBP60 Pages
|
||||
capabilities = obp60:true
|
||||
|
||||
[backlight]
|
||||
label = Backlight Mode
|
||||
type = list
|
||||
default = Control by Key
|
||||
description = Settings for automatic backlight mode
|
||||
list = Off, Control by Sun, Control by Bus, Control by Time, Control by Key, On
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[blColor]
|
||||
label = Backlight Color
|
||||
type = list
|
||||
default = Red
|
||||
description = Backlight color
|
||||
list = Red, Orange, Yellow, Green, Blue, Aqua, Violet, White
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[blBrightness]
|
||||
label = Brightness [%%]
|
||||
type = number
|
||||
default = 50
|
||||
description = Backlight brightness [20...100%%]
|
||||
check = checkMinMax
|
||||
min = 20
|
||||
max = 100
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[flashLED]
|
||||
label = Flash LED Mode
|
||||
type = list
|
||||
default = Limit Violation
|
||||
description = Settings for flash LED
|
||||
list = Off, Bus Data, GPS Fix Lost, Limit Violation
|
||||
category = OBP60 Display
|
||||
capabilities = obp60:true
|
||||
|
||||
[buzzerError]
|
||||
label = Buzzer Error
|
||||
type = boolean
|
||||
default = false
|
||||
description = Sound on error [on|off]
|
||||
category = OBP60 Buzzer
|
||||
capabilities = obp60:true
|
||||
|
||||
[buzzerGps]
|
||||
label = Buzzer GPS Fix
|
||||
type = boolean
|
||||
default = false
|
||||
description = Sound on missing or lost GPS fix
|
||||
category = OBP60 Buzzer
|
||||
capabilities = obp60:true
|
||||
|
||||
[buzzerLim]
|
||||
label = Buzzer by Limits
|
||||
type = boolean
|
||||
default = false
|
||||
description = Sound on limit violation
|
||||
category = OBP60 Buzzer
|
||||
capabilities = obp60:true
|
||||
|
||||
[buzzerMode]
|
||||
label = Buzzer Mode
|
||||
type = list
|
||||
default = Off
|
||||
description = Settings for buzzer behaviour
|
||||
list = Off, Short Single Beep, Longer Single Beep, Beep until Confirmation
|
||||
category = OBP60 Buzzer
|
||||
capabilities = obp60:true
|
||||
|
||||
[buzzerPower]
|
||||
label = Buzzer Power [%%]
|
||||
type = number
|
||||
default = 50
|
||||
description = Buzzer loudness [0...100%%]
|
||||
check = checkMinMax
|
||||
min = 0
|
||||
max = 100
|
||||
category = OBP60 Buzzer
|
||||
capabilities = obp60:true
|
||||
|
||||
[visiblePages]
|
||||
label = Number of Pages
|
||||
type = number
|
||||
default = 10
|
||||
description = Number of visible data pages [1...10]
|
||||
check = checkMinMax
|
||||
min = 1
|
||||
max = 10
|
||||
category = OBP60 Pages
|
||||
capabilities = obp60:true
|
||||
|
||||
[startPage]
|
||||
label = Start Page
|
||||
type = number
|
||||
default = 1
|
||||
description = First page number to display after device startup
|
||||
check = checkMinMax
|
||||
min = 1
|
||||
max = 10
|
||||
category = OBP60 Pages
|
||||
capabilities = obp60:true
|
||||
|
||||
[imageFormat]
|
||||
label = Screenshot Format
|
||||
type = list
|
||||
default = PBM
|
||||
description = Graphics file format for screenshots [GIF|PBM|BMP]
|
||||
dict =
|
||||
GIF:Compressed image (GIF)
|
||||
PBM:Portable bitmap (PBM)
|
||||
BMP:Windows bitmap (BMP)
|
||||
category = OBP60 Pages
|
||||
capabilities = obp60:true
|
||||
|
||||
# WIP
|
||||
|
||||
[trackerType]
|
||||
label = Tracker Type
|
||||
type = list
|
||||
default = off
|
||||
description = Type of tracker to use [OFF|SDCARD|SERVER|HERO]
|
||||
dict = OFF:No tracker
|
||||
SDCARD:Log to SD-Card
|
||||
SERVER:Log to Server
|
||||
HERO:Connect with Regatta Hero
|
||||
category = OBP60 Pages
|
||||
capabilities = obp60:true
|
||||
|
||||
[trackerOrganization]
|
||||
label = Tracker team
|
||||
type = string
|
||||
default = demo
|
||||
description = Tracker organization for login
|
||||
category = OBP60 Pages
|
||||
|
||||
[trackerPasscode]
|
||||
label = Tracker team
|
||||
type = password
|
||||
default = 291758
|
||||
description = Your tracker team you belong to. E.g. short name of association
|
||||
category = OBP60 Pages
|
||||
|
||||
[trackerTeam]
|
||||
label = Tracker team
|
||||
type = string
|
||||
default = none
|
||||
description = Your tracker team you belong to. E.g. short name of association
|
||||
category = OBP60 Pages
|
||||
|
||||
[trackerHandicap]
|
||||
label = Boat handicap
|
||||
type = number
|
||||
default = 100
|
||||
check = checkMinMax
|
||||
min = 50
|
||||
max = 1000
|
||||
description = The handicap value of your boat. E.g. yardstick value
|
||||
category = OBP60 Pages
|
||||
|
||||
[boatName]
|
||||
label = Boat Name
|
||||
type = string
|
||||
default = Unsinkbar II
|
||||
description = name of your boat
|
||||
category = OBP60 Pages
|
||||
|
||||
[boatClass]
|
||||
label = Boat Class
|
||||
type = string
|
||||
default = One off
|
||||
description = Class name of your boat if available or "One off"
|
||||
category = OBP60 Pages
|
||||
|
||||
[sailNumber]
|
||||
label = Sail number
|
||||
type = string
|
||||
default = GER 11
|
||||
description = Identification number on sail
|
||||
category = OBP60 Pages
|
||||
|
||||
+189
-226
@@ -1,6 +1,8 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
#include "obp60task.h"
|
||||
#include "Pagedata.h" // Data exchange for pages
|
||||
#include "OBP60Formatter.h" // Data formatting for boat values
|
||||
#include "OBP60Hardware.h" // PIN definitions
|
||||
#include <Wire.h> // I2C connections
|
||||
#include <MCP23017.h> // MCP23017 extension Port
|
||||
@@ -9,9 +11,14 @@
|
||||
#include <NMEA0183.h> // NMEA0183
|
||||
#include <NMEA0183Msg.h>
|
||||
#include <NMEA0183Messages.h>
|
||||
#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
|
||||
#include "OBPKeyboardTask.h" // Functions lib for keyboard handling
|
||||
#include "OBPDataOperations.h" // Functions lib for data operations such as true wind calculation
|
||||
#include "OBP60QRWiFi.h" // Functions lib for WiFi QR code
|
||||
#include "OBPSensorTask.h" // Functions lib for sensor data
|
||||
|
||||
#include "freertos/task.h" // WIP possible unused
|
||||
|
||||
#ifdef BOARD_OBP40S3
|
||||
#include "driver/rtc_io.h" // Needs for weakup from deep sleep
|
||||
@@ -19,12 +26,8 @@
|
||||
#endif
|
||||
|
||||
// Pictures
|
||||
//#include GxEPD_BitmapExamples // Example picture
|
||||
#include "MFD_OBP60_400x300_sw.h" // MFD with logo
|
||||
#include "Logo_OBP_400x300_sw.h" // OBP Logo
|
||||
#include "images/OBP_400x300.xbm" // 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
|
||||
|
||||
// Global vars
|
||||
bool initComplete = false; // Initialization complete
|
||||
@@ -62,7 +65,7 @@ void OBP60Init(GwApi *api){
|
||||
#endif
|
||||
|
||||
// Settings for e-paper display
|
||||
String fastrefresh = api->getConfig()->getConfigItem(api->getConfig()->fastRefresh,true)->asString();
|
||||
String fastrefresh = config->getConfigItem(config->fastRefresh,true)->asString();
|
||||
logger->logDebug(GwLog::DEBUG, "Fast Refresh Mode is: %s", fastrefresh.c_str());
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
if(fastrefresh == "true"){
|
||||
@@ -85,24 +88,24 @@ void OBP60Init(GwApi *api){
|
||||
logger->logDebug(GwLog::LOG,"CPU speed at boot: %i MHz", freq);
|
||||
|
||||
// Settings for backlight
|
||||
String backlightMode = api->getConfig()->getConfigItem(api->getConfig()->backlight,true)->asString();
|
||||
String backlightMode = config->getConfigItem(config->backlight,true)->asString();
|
||||
logger->logDebug(GwLog::DEBUG, "Backlight Mode is: %s", backlightMode.c_str());
|
||||
uint brightness = uint(api->getConfig()->getConfigItem(api->getConfig()->blBrightness,true)->asInt());
|
||||
String backlightColor = api->getConfig()->getConfigItem(api->getConfig()->blColor,true)->asString();
|
||||
if(String(backlightMode) == "On"){
|
||||
uint brightness = uint(config->getConfigItem(config->blBrightness,true)->asInt());
|
||||
String backlightColor = config->getConfigItem(config->blColor,true)->asString();
|
||||
if (backlightMode == "On") {
|
||||
setBacklightLED(brightness, colorMapping(backlightColor));
|
||||
}
|
||||
else if(String(backlightMode) == "Off"){
|
||||
else if (backlightMode == "Off") {
|
||||
setBacklightLED(0, COLOR_BLACK); // Backlight LEDs off (blue without britghness)
|
||||
}
|
||||
else if(String(backlightMode) == "Control by Key"){
|
||||
else if (backlightMode == "Control by Key") {
|
||||
setBacklightLED(0, COLOR_BLUE); // Backlight LEDs off (blue without britghness)
|
||||
}
|
||||
|
||||
// Settings flash LED mode
|
||||
String ledMode = api->getConfig()->getConfigItem(api->getConfig()->flashLED,true)->asString();
|
||||
String ledMode = config->getConfigItem(config->flashLED,true)->asString();
|
||||
logger->logDebug(GwLog::DEBUG,"LED Mode is: %s", ledMode.c_str());
|
||||
if(String(ledMode) == "Off"){
|
||||
if (ledMode == "Off") {
|
||||
setBlinkingLED(false);
|
||||
}
|
||||
|
||||
@@ -111,41 +114,32 @@ void OBP60Init(GwApi *api){
|
||||
initComplete = true;
|
||||
|
||||
// Buzzer tone for initialization finish
|
||||
setBuzzerPower(uint(api->getConfig()->getConfigItem(api->getConfig()->buzzerPower,true)->asInt()));
|
||||
setBuzzerPower(uint(config->getConfigItem(config->buzzerPower,true)->asInt()));
|
||||
buzzer(TONE4, 500);
|
||||
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int page0=0;
|
||||
QueueHandle_t queue;
|
||||
GwLog* logger = nullptr;
|
||||
// GwApi* api = nullptr;
|
||||
uint sensitivity = 100;
|
||||
bool use_syspage = true;
|
||||
} MyData;
|
||||
/* ux-functions not working WTF?
|
||||
bool listTasks(GwLog *logger) {
|
||||
UBaseType_t taskCount = uxTaskGetNumberOfTasks();
|
||||
TaskStatus_t *taskStatusArray;
|
||||
|
||||
// Keyboard Task
|
||||
void keyboardTask(void *param){
|
||||
MyData *data=(MyData *)param;
|
||||
|
||||
int keycode = 0;
|
||||
data->logger->logDebug(GwLog::LOG,"Start keyboard task");
|
||||
|
||||
// Loop for keyboard task
|
||||
while (true){
|
||||
keycode = readKeypad(data->logger, data->sensitivity, data->use_syspage);
|
||||
//send a key event
|
||||
if(keycode != 0){
|
||||
xQueueSend(data->queue, &keycode, 0);
|
||||
data->logger->logDebug(GwLog::LOG,"Send keycode: %d", keycode);
|
||||
taskStatusArray = (TaskStatus_t *)pvPortMalloc(taskCount * sizeof(TaskStatus_t));
|
||||
if (taskStatusArray != NULL) {
|
||||
taskCount = uxTaskGetSystemState(taskStatusArray, taskCount, NULL);
|
||||
for (UBaseType_t i = 0; i < taskCount; i++) {
|
||||
logger->logDebug(GwLog::LOG, "Task Name: %s (Stack=%d)", taskStatusArray[i].pcTaskName,
|
||||
taskStatusArray[i].usStackHighWaterMark);
|
||||
// more fields in task status
|
||||
// xHandle, uxCurrentPriority, uxBasePriority, usStackHighWaterMark
|
||||
}
|
||||
delay(20); // 50Hz update rate (20ms)
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
vPortFree(taskStatusArray);
|
||||
return true;
|
||||
}
|
||||
logger->logDebug(GwLog::ERROR, "Failed to allocate memory for task list");
|
||||
return false;
|
||||
} */
|
||||
|
||||
// --- Class BoatValueList --------------
|
||||
bool BoatValueList::addValueToList(GwApi::BoatValue *v){
|
||||
for (int i=0;i<numValues;i++){
|
||||
if (allBoatValues[i] == v){
|
||||
@@ -158,6 +152,7 @@ bool BoatValueList::addValueToList(GwApi::BoatValue *v){
|
||||
numValues++;
|
||||
return true;
|
||||
}
|
||||
|
||||
//helper to ensure that each BoatValue is only queried once
|
||||
GwApi::BoatValue *BoatValueList::findValueOrCreate(String name){
|
||||
for (int i=0;i<numValues;i++){
|
||||
@@ -169,7 +164,6 @@ GwApi::BoatValue *BoatValueList::findValueOrCreate(String name){
|
||||
addValueToList(rt);
|
||||
return rt;
|
||||
}
|
||||
// --- End Class BoatValueList --------------
|
||||
|
||||
//we want to have a list that has all our page definitions
|
||||
//this way each page can easily be added here
|
||||
@@ -196,12 +190,13 @@ class PageList{
|
||||
* each page should have defined a registerXXXPage variable of type
|
||||
* PageData that describes what it needs
|
||||
*/
|
||||
void registerAllPages(PageList &list){
|
||||
void registerAllPages(GwLog *logger, PageList &list){
|
||||
//the next line says that this variable is defined somewhere else
|
||||
//in our case in a separate C++ source file
|
||||
//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
|
||||
logger->logDebug(GwLog::LOG, "Memory before registering pages: stack=%d, heap=%d", uxTaskGetStackHighWaterMark(NULL), ESP.getFreeHeap());
|
||||
extern PageDescription registerPageSystem;
|
||||
//we add the variable to our list
|
||||
list.add(®isterPageSystem);
|
||||
@@ -233,8 +228,6 @@ void registerAllPages(PageList &list){
|
||||
list.add(®isterPageClock);
|
||||
extern PageDescription registerPageCompass;
|
||||
list.add(®isterPageCompass);
|
||||
extern PageDescription registerPageCurrent;
|
||||
list.add(®isterPageCurrent);
|
||||
extern PageDescription registerPageWhite;
|
||||
list.add(®isterPageWhite);
|
||||
extern PageDescription registerPageBME280;
|
||||
@@ -263,10 +256,15 @@ void registerAllPages(PageList &list){
|
||||
list.add(®isterPageNavigation);
|
||||
extern PageDescription registerPageDigitalOut;
|
||||
list.add(®isterPageDigitalOut);
|
||||
extern PageDescription registerPageAutopilot;
|
||||
list.add(®isterPageAutopilot);
|
||||
extern PageDescription registerPageWeather;
|
||||
list.add(®isterPageWeather);
|
||||
extern PageDescription registerPageAnchor;
|
||||
list.add(®isterPageAnchor);
|
||||
extern PageDescription registerPageAIS;
|
||||
list.add(®isterPageAIS);
|
||||
extern PageDescription registerPageBarograph;
|
||||
list.add(®isterPageBarograph);
|
||||
extern PageDescription registerPageTracker;
|
||||
list.add(®isterPageTracker);
|
||||
logger->logDebug(GwLog::LOG,"Memory after registering pages: stack=%d, heap=%d", uxTaskGetStackHighWaterMark(NULL), ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
// Undervoltage detection for shutdown display
|
||||
@@ -277,22 +275,18 @@ void underVoltageError(CommonData &common) {
|
||||
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_Bold20pt8b);
|
||||
getdisplay().setCursor(65, 150);
|
||||
getdisplay().print("Undervoltage");
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(65, 175);
|
||||
getdisplay().print("Charge battery and restart system");
|
||||
displayNextPage(); // Partial update
|
||||
#ifdef TFT_DISPLAY
|
||||
getpaneldisplay().powerSave(true); // Display power save
|
||||
#else
|
||||
getdisplay().powerOff(); // Display power off
|
||||
#endif
|
||||
epd->setFullWindow(); // Set full Refresh
|
||||
//epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->fillScreen(common.bgcolor);// Clear screen
|
||||
epd->setTextColor(common.fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(65, 150);
|
||||
epd->print("Undervoltage");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(65, 175);
|
||||
epd->print("Charge battery and restart system");
|
||||
epd->nextPage(); // Partial update
|
||||
epd->powerOff(); // Display power off
|
||||
setPortPin(OBP_POWER_EPD, false); // Power off ePaper display
|
||||
setPortPin(OBP_POWER_SD, false); // Power off SD card
|
||||
#else
|
||||
@@ -302,21 +296,17 @@ void underVoltageError(CommonData &common) {
|
||||
buzzer(TONE4, 20); // Buzzer tone 4kHz 20ms
|
||||
setPortPin(OBP_POWER_50, false); // Power rail 5.0V Off
|
||||
// Shutdown EInk display
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
getdisplay().fillScreen(common.bgcolor);// Clear screen
|
||||
getdisplay().setTextColor(common.fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt8b);
|
||||
getdisplay().setCursor(65, 150);
|
||||
getdisplay().print("Undervoltage");
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt8b);
|
||||
getdisplay().setCursor(65, 175);
|
||||
getdisplay().print("To wake up repower system");
|
||||
displayNextPage(); // Partial update
|
||||
#ifdef TFT_DISPLAY
|
||||
getpaneldisplay().powerSave(true); // Display power save
|
||||
#else
|
||||
getdisplay().powerOff(); // Display power off
|
||||
#endif
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->fillScreen(common.bgcolor);// Clear screen
|
||||
epd->setTextColor(common.fgcolor);
|
||||
epd->setFont(&Ubuntu_Bold20pt8b);
|
||||
epd->setCursor(65, 150);
|
||||
epd->print("Undervoltage");
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
epd->setCursor(65, 175);
|
||||
epd->print("To wake up repower system");
|
||||
epd->nextPage(); // Partial update
|
||||
epd->powerOff(); // Display power off
|
||||
#endif
|
||||
while (true) {
|
||||
esp_deep_sleep_start(); // Deep Sleep without wakeup. Wakeup only after power cycle (restart).
|
||||
@@ -327,7 +317,7 @@ inline bool underVoltageDetection(float voffset, float vslope) {
|
||||
// Read supply 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 voltage for 3,7V LiPo accu
|
||||
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;
|
||||
@@ -336,7 +326,6 @@ inline bool underVoltageDetection(float voffset, float vslope) {
|
||||
return (calVoltage < minVoltage);
|
||||
}
|
||||
|
||||
|
||||
// OBP60 Task
|
||||
//####################################################################################
|
||||
void OBP60Task(GwApi *api){
|
||||
@@ -344,16 +333,17 @@ void OBP60Task(GwApi *api){
|
||||
// return;
|
||||
GwLog *logger = api->getLogger();
|
||||
GwConfigHandler *config = api->getConfig();
|
||||
#ifdef BOARD_OBP60S3
|
||||
#ifdef HARDWARE_V21
|
||||
startLedTask(api);
|
||||
#endif
|
||||
PageList allPages;
|
||||
registerAllPages(allPages);
|
||||
registerAllPages(logger, allPages);
|
||||
CommonData commonData;
|
||||
commonData.logger = logger;
|
||||
commonData.config = config;
|
||||
commonData.fmt = new Formatter(config);
|
||||
|
||||
#ifdef BOARD_OBP60S3
|
||||
#ifdef HARDWARE_V21
|
||||
// Keyboard coordinates for page footer
|
||||
initKeys(commonData);
|
||||
#endif
|
||||
@@ -366,8 +356,8 @@ void OBP60Task(GwApi *api){
|
||||
}
|
||||
|
||||
// Init E-Ink display
|
||||
String displaymode = api->getConfig()->getConfigItem(api->getConfig()->display,true)->asString();
|
||||
String displaycolor = api->getConfig()->getConfigItem(api->getConfig()->displaycolor,true)->asString();
|
||||
String displaymode = config->getConfigItem(config->display,true)->asString();
|
||||
String displaycolor = config->getConfigItem(config->displaycolor,true)->asString();
|
||||
if (displaycolor == "Normal") {
|
||||
commonData.fgcolor = GxEPD_BLACK;
|
||||
commonData.bgcolor = GxEPD_WHITE;
|
||||
@@ -376,58 +366,48 @@ void OBP60Task(GwApi *api){
|
||||
commonData.fgcolor = GxEPD_WHITE;
|
||||
commonData.bgcolor = GxEPD_BLACK;
|
||||
}
|
||||
String systemname = api->getConfig()->getConfigItem(api->getConfig()->systemName,true)->asString();
|
||||
String wifipass = api->getConfig()->getConfigItem(api->getConfig()->apPassword,true)->asString();
|
||||
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());
|
||||
String systemname = config->getConfigItem(config->systemName, true)->asString();
|
||||
String wifipass = config->getConfigItem(config->apPassword, true)->asString();
|
||||
bool refreshmode = config->getConfigItem(config->refresh, true)->asBoolean();
|
||||
bool symbolmode = (config->getString(config->headerFormat) == "ICON");
|
||||
String fastrefresh = config->getConfigItem(config->fastRefresh, true)->asString();
|
||||
uint fullrefreshtime = uint(config->getConfigItem(config->fullRefreshTime, true)->asInt());
|
||||
#ifdef BOARD_OBP40S3
|
||||
bool syspage_enabled = config->getBool(config->systemPage);
|
||||
#endif
|
||||
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
#elif defined(TFT_DISPLAY)
|
||||
getpaneldisplay().init(); // Init for TFT LCD panel
|
||||
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
#else
|
||||
getdisplay().init(115200); // Init for normal displays
|
||||
epd->init(115200); // Init for normal displays
|
||||
#endif
|
||||
|
||||
#ifdef TFT_DISPLAY
|
||||
getpaneldisplay().setRotation(0); // Set display orientation (horizontal)
|
||||
getpaneldisplay().setPanelOffset(0, 0); // Use full native framebuffer coordinates
|
||||
getpaneldisplay().fillScreen(0x0000); // Initialize full TFT screen to black (native RGB565)
|
||||
getpaneldisplay().setPanelOffset(OBP_TFT_OFFSET_X, OBP_TFT_OFFSET_Y); // Restore configured operating panel offset
|
||||
#else
|
||||
getdisplay().setRotation(0); // Set display orientation (horizontal)
|
||||
#endif
|
||||
displaySetFullWindow(); // Set full Refresh (E-Ink only)
|
||||
displayFirstPage(); // set first page
|
||||
getdisplay().fillScreen(commonData.bgcolor);
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
displayNextPage(); // Full Refresh
|
||||
displaySetPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update (E-Ink only)
|
||||
getdisplay().fillScreen(commonData.bgcolor);
|
||||
displayNextPage(); // Fast Refresh
|
||||
displayNextPage(); // Fast Refresh
|
||||
epd->setRotation(0); // Set display orientation (horizontal)
|
||||
epd->setFullWindow(); // Set full Refresh
|
||||
epd->firstPage(); // set first page
|
||||
epd->fillScreen(commonData.bgcolor);
|
||||
epd->setTextColor(commonData.fgcolor);
|
||||
epd->nextPage(); // Full Refresh
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->fillScreen(commonData.bgcolor);
|
||||
epd->nextPage(); // Fast Refresh
|
||||
epd->nextPage(); // Fast Refresh
|
||||
if(String(displaymode) == "Logo + QR Code" || String(displaymode) == "Logo"){
|
||||
getdisplay().fillScreen(commonData.bgcolor);
|
||||
// draw the fixed-size logo via generic display wrapper
|
||||
displayDrawBitmap(0, 0, gImage_Logo_OBP_400x300_sw,
|
||||
400, 300, commonData.fgcolor);
|
||||
displayNextPage(); // Fast Refresh
|
||||
displayNextPage(); // Fast Refresh
|
||||
epd->fillScreen(commonData.bgcolor);
|
||||
epd->drawXBitmap(0, 0, OBP_400x300_bits, OBP_400x300_width, OBP_400x300_height, commonData.fgcolor);
|
||||
epd->nextPage(); // Fast Refresh
|
||||
epd->nextPage(); // Fast Refresh
|
||||
delay(SHOW_TIME); // Logo show time
|
||||
if(String(displaymode) == "Logo + QR Code"){
|
||||
getdisplay().fillScreen(commonData.bgcolor);
|
||||
epd->fillScreen(commonData.bgcolor);
|
||||
qrWiFi(systemname, wifipass, commonData.fgcolor, commonData.bgcolor); // Show QR code for WiFi connection
|
||||
displayNextPage(); // Fast Refresh
|
||||
displayNextPage(); // Fast Refresh
|
||||
epd->nextPage(); // Fast Refresh
|
||||
epd->nextPage(); // Fast Refresh
|
||||
delay(SHOW_TIME); // QR code show time
|
||||
}
|
||||
getdisplay().fillScreen(commonData.bgcolor);
|
||||
displayNextPage(); // Fast Refresh
|
||||
displayNextPage(); // Fast Refresh
|
||||
epd->fillScreen(commonData.bgcolor);
|
||||
epd->nextPage(); // Fast Refresh
|
||||
epd->nextPage(); // Fast Refresh
|
||||
}
|
||||
|
||||
// Init pages
|
||||
@@ -462,13 +442,6 @@ void OBP60Task(GwApi *api){
|
||||
WindUtils trueWind(&boatValues, logger); // Create helper object for true wind calculation
|
||||
CalibrationData calibrationDataList(logger); // all boat data types which are supposed to be calibrated
|
||||
|
||||
// Read user settings from config file
|
||||
bool calcTrueWnds = api->getConfig()->getBool(api->getConfig()->calcTrueWnds, false);
|
||||
bool smoothCharts = api->getConfig()->getBool(api->getConfig()->smoothCharts, false);
|
||||
bool useSimuData = api->getConfig()->getBool(api->getConfig()->useSimuData, false);
|
||||
// Read user calibration data settings from config file
|
||||
calibrationDataList.readConfig(config);
|
||||
|
||||
//fill the page data from config
|
||||
numPages=config->getInt(config->visiblePages,1);
|
||||
if (numPages < 1) numPages=1;
|
||||
@@ -509,21 +482,26 @@ void OBP60Task(GwApi *api){
|
||||
pages[i].parameters.values.push_back(value);
|
||||
}
|
||||
|
||||
// Read the specified boat data types of relevant pages and create a history buffer for each type for later use in charts
|
||||
// applies only to pages that uses charts
|
||||
if (pages[i].parameters.pageName == "OneValue" || pages[i].parameters.pageName == "TwoValues"
|
||||
|| pages[i].parameters.pageName == "WindPlot" || pages[i].parameters.pageName == "Weather") {
|
||||
// Read the specified boat data types of relevant pages and create a history buffer for each type
|
||||
if (pages[i].parameters.pageName == "OneValue" || pages[i].parameters.pageName == "TwoValues" || pages[i].parameters.pageName == "WindPlot") {
|
||||
for (auto pVal : pages[i].parameters.values) {
|
||||
hstryBufferList.addBuffer(pVal->getName(), smoothCharts);
|
||||
hstryBufferList.addBuffer(pVal->getName());
|
||||
}
|
||||
}
|
||||
// Add list of history buffers to page parameters
|
||||
pages[i].parameters.hstryBuffers = &hstryBufferList;
|
||||
|
||||
}
|
||||
|
||||
// add out of band system page (always available)
|
||||
Page *syspage = allPages.pages[0]->creator(commonData);
|
||||
|
||||
// Read user settings from config file
|
||||
bool calcTrueWnds = api->getConfig()->getBool(api->getConfig()->calcTrueWnds, false);
|
||||
bool useSimuData = api->getConfig()->getBool(api->getConfig()->useSimuData, false);
|
||||
// Read user calibration data settings from config file
|
||||
calibrationDataList.readConfig(config);
|
||||
|
||||
// Display screenshot handler for HTTP request
|
||||
// http://192.168.15.1/api/user/OBP60Task/screenshot
|
||||
api->registerRequestHandler("screenshot", [api, &pageNumber, pages](AsyncWebServerRequest *request) {
|
||||
@@ -532,15 +510,15 @@ void OBP60Task(GwApi *api){
|
||||
|
||||
// now we have prepared the page data
|
||||
// we start a separate task that will fetch our keys...
|
||||
MyData allParameters;
|
||||
allParameters.logger=api->getLogger();
|
||||
allParameters.page0=3;
|
||||
allParameters.queue=xQueueCreate(10,sizeof(int));
|
||||
allParameters.sensitivity= api->getConfig()->getInt(GwConfigDefinitions::tSensitivity);
|
||||
KbTaskData kbparams;
|
||||
kbparams.logger = api->getLogger();
|
||||
kbparams.queue = xQueueCreate(10, sizeof(int));
|
||||
kbparams.sensitivity = api->getConfig()->getInt(GwConfigDefinitions::tSensitivity);
|
||||
#ifdef BOARD_OBP40S3
|
||||
allParameters.use_syspage = syspage_enabled;
|
||||
kbparams.use_syspage = syspage_enabled;
|
||||
#endif
|
||||
xTaskCreate(keyboardTask,"keyboard",2000,&allParameters,configMAX_PRIORITIES-1,NULL);
|
||||
createKeyboardTask(&kbparams);
|
||||
// we start a separate task to collect sensor data
|
||||
SharedData *shared = new SharedData(api);
|
||||
createSensorTask(shared);
|
||||
|
||||
@@ -548,28 +526,28 @@ void OBP60Task(GwApi *api){
|
||||
//####################################################################################
|
||||
|
||||
// Configuration values for main loop
|
||||
String gpsFix = api->getConfig()->getConfigItem(api->getConfig()->flashLED,true)->asString();
|
||||
String gpsOn=api->getConfig()->getConfigItem(api->getConfig()->useGPS,true)->asString();
|
||||
float tz = api->getConfig()->getConfigItem(api->getConfig()->timeZone,true)->asFloat();
|
||||
String gpsFix = config->getConfigItem(config->flashLED,true)->asString();
|
||||
String gpsOn = config->getConfigItem(config->useGPS,true)->asString();
|
||||
float tz = config->getConfigItem(config->timeZone,true)->asFloat();
|
||||
|
||||
commonData.backlight.mode = backlightMapping(config->getConfigItem(config->backlight, true)->asString());
|
||||
commonData.backlight.color = colorMapping(config->getConfigItem(config->blColor, true)->asString());
|
||||
commonData.backlight.brightness = uint(config->getConfigItem(config->blBrightness,true)->asInt());
|
||||
commonData.backlight.brightness = 2.55 * uint(config->getConfigItem(config->blBrightness, true)->asInt());
|
||||
commonData.powermode = api->getConfig()->getConfigItem(api->getConfig()->powerMode, true)->asString();
|
||||
|
||||
bool uvoltage = config->getConfigItem(config->underVoltage, true)->asBoolean();
|
||||
float voffset = (config->getConfigItem(config->vOffset,true)->asString()).toFloat();
|
||||
float vslope = (config->getConfigItem(config->vSlope,true)->asString()).toFloat();
|
||||
String cpuspeed = api->getConfig()->getConfigItem(api->getConfig()->cpuSpeed,true)->asString();
|
||||
uint hdopAccuracy = uint(api->getConfig()->getConfigItem(api->getConfig()->hdopAccuracy,true)->asInt());
|
||||
String cpuspeed = config->getConfigItem(config->cpuSpeed, true)->asString();
|
||||
uint hdopAccuracy = uint(config->getConfigItem(config->hdopAccuracy, true)->asInt());
|
||||
|
||||
double homelat = commonData.config->getString(commonData.config->homeLAT).toDouble();
|
||||
double homelon = commonData.config->getString(commonData.config->homeLON).toDouble();
|
||||
double homelat = config->getString(config->homeLAT).toDouble();
|
||||
double homelon = config->getString(config->homeLON).toDouble();
|
||||
bool homevalid = homelat >= -180.0 and homelat <= 180 and homelon >= -90.0 and homelon <= 90.0;
|
||||
if (homevalid) {
|
||||
LOG_DEBUG(GwLog::LOG, "Home location set to lat=%f, lon=%f", homelat, homelon);
|
||||
logger->logDebug(GwLog::LOG, "Home location set to lat=%f, lon=%f", homelat, homelon);
|
||||
} else {
|
||||
LOG_DEBUG(GwLog::LOG, "No valid home location found");
|
||||
logger->logDebug(GwLog::LOG, "No valid home location found");
|
||||
}
|
||||
|
||||
// refreshmode defined in init section
|
||||
@@ -597,6 +575,8 @@ void OBP60Task(GwApi *api){
|
||||
|
||||
pages[pageNumber].page->setupKeys(); // Initialize keys for first page
|
||||
|
||||
// listTasks(logger);
|
||||
|
||||
// Main loop runs with 100ms
|
||||
//####################################################################################
|
||||
|
||||
@@ -648,7 +628,7 @@ void OBP60Task(GwApi *api){
|
||||
|
||||
// Check the keyboard message
|
||||
int keyboardMessage=0;
|
||||
while (xQueueReceive(allParameters.queue,&keyboardMessage,0)){
|
||||
while (xQueueReceive(kbparams.queue,&keyboardMessage, 0)) {
|
||||
LOG_DEBUG(GwLog::LOG,"new key from keyboard %d",keyboardMessage);
|
||||
keypressed = true;
|
||||
|
||||
@@ -681,6 +661,8 @@ void OBP60Task(GwApi *api){
|
||||
// if(String(backlight) == "Control by Key"){
|
||||
if(keyboardMessage == 6){
|
||||
LOG_DEBUG(GwLog::LOG,"Toggle Backlight LED");
|
||||
// TODO config: toogle vs steps
|
||||
// toggleBacklightLED(commonData.backlight.brightness, commonData.backlight.color);
|
||||
stepsBacklightLED(commonData.backlight.brightness, commonData.backlight.color);
|
||||
}
|
||||
}
|
||||
@@ -747,29 +729,24 @@ void OBP60Task(GwApi *api){
|
||||
if (millis() > starttime4 + 8000 && delayedDisplayUpdate == true) {
|
||||
starttime1 = millis();
|
||||
starttime2 = millis();
|
||||
displaySetFullWindow(); // Set full update
|
||||
#ifdef TFT_DISPLAY
|
||||
// TFT LCD doesn't need refresh operations
|
||||
#else
|
||||
epd->setFullWindow(); // Set full update
|
||||
if(fastrefresh == "true"){
|
||||
displayNextPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
}
|
||||
else{
|
||||
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
||||
epd->fillScreen(commonData.fgcolor); // Clear display
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
getdisplay().hibernate(); // Set display in hibenate mode
|
||||
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
#else
|
||||
getdisplay().init(115200); // Init for normal displays
|
||||
epd->init(115200); // Init for normal displays
|
||||
#endif
|
||||
displayFirstPage(); // Full update
|
||||
displayNextPage(); // Full update
|
||||
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
// getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
epd->firstPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
// epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
// epd->fillScreen(commonData.bgcolor); // Clear display
|
||||
// epd->nextPage(); // Partial update
|
||||
// epd->nextPage(); // Partial update
|
||||
}
|
||||
#endif
|
||||
delayedDisplayUpdate = false;
|
||||
}
|
||||
|
||||
@@ -779,58 +756,48 @@ void OBP60Task(GwApi *api){
|
||||
starttime1 = millis();
|
||||
starttime2 = millis();
|
||||
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh first 5 min");
|
||||
displaySetFullWindow(); // Set full update
|
||||
#ifdef TFT_DISPLAY
|
||||
// TFT LCD doesn't need refresh operations
|
||||
#else
|
||||
epd->setFullWindow(); // Set full update
|
||||
if(fastrefresh == "true"){
|
||||
displayNextPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
}
|
||||
else{
|
||||
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
||||
epd->fillScreen(commonData.fgcolor); // Clear display
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
getdisplay().hibernate(); // Set display in hibernate mode
|
||||
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
#else
|
||||
getdisplay().init(115200); // Init for normal displays
|
||||
epd->init(115200); // Init for normal displays
|
||||
#endif
|
||||
displayFirstPage(); // Full update
|
||||
displayNextPage(); // Full update
|
||||
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
// getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
epd->firstPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
// epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
// epd->fillScreen(commonData.bgcolor); // Clear display
|
||||
// epd->nextPage(); // Partial update
|
||||
// epd->nextPage(); // Partial update
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Subtask E-Ink full refresh
|
||||
if(millis() > starttime2 + fullrefreshtime * 60 * 1000){
|
||||
starttime2 = millis();
|
||||
LOG_DEBUG(GwLog::DEBUG,"E-Ink full refresh");
|
||||
#ifdef TFT_DISPLAY
|
||||
// TFT LCD: no special refresh
|
||||
#else
|
||||
getdisplay().setFullWindow(); // Set full update
|
||||
epd->setFullWindow(); // Set full update
|
||||
if(fastrefresh == "true"){
|
||||
getdisplay().nextPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
}
|
||||
else{
|
||||
getdisplay().fillScreen(commonData.fgcolor); // Clear display
|
||||
epd->fillScreen(commonData.fgcolor); // Clear display
|
||||
#ifdef DISPLAY_GDEY042T81
|
||||
getdisplay().hibernate(); // Set display in hibernate mode
|
||||
getdisplay().init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
epd->init(115200, true, 2, false); // Init for Waveshare boards with "clever" reset circuit, 2ms reset pulse
|
||||
#else
|
||||
getdisplay().init(115200); // Init for normal displays
|
||||
epd->init(115200); // Init for normal displays
|
||||
#endif
|
||||
getdisplay().firstPage(); // Full update
|
||||
getdisplay().nextPage(); // Full update
|
||||
// getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
// getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
// getdisplay().nextPage(); // Partial update
|
||||
epd->firstPage(); // Full update
|
||||
epd->nextPage(); // Full update
|
||||
// epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
// epd->fillScreen(commonData.bgcolor); // Clear display
|
||||
// epd->nextPage(); // Partial update
|
||||
// epd->nextPage(); // Partial update
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Refresh display data, default all 1s
|
||||
@@ -843,27 +810,25 @@ void OBP60Task(GwApi *api){
|
||||
if(millis() > starttime3 + pagetime){
|
||||
LOG_DEBUG(GwLog::DEBUG,"Page with refreshtime=%d", pagetime);
|
||||
starttime3 = millis();
|
||||
bool pageChanged = (lastPage != pageNumber);
|
||||
|
||||
//refresh data from api
|
||||
api->getBoatDataValues(boatValues.numValues,boatValues.allBoatValues);
|
||||
api->getStatus(commonData.status);
|
||||
|
||||
// ulong startHandl = millis();
|
||||
trueWind.handleWinds(calcTrueWnds); // calculate true wind data from apparent wind values
|
||||
trueWind.setMaxWs(); // maintain MaxTWS value in any case; invalid TWS value is considered automatically; MaxAWS is provided by core gateway if AWS is available
|
||||
if (calcTrueWnds) {
|
||||
trueWind.addWinds(); // calculate true wind data from apparent wind values
|
||||
}
|
||||
calibrationDataList.handleCalibration(&boatValues); // Process calibration for all boat data in <calibrationDataList>
|
||||
hstryBufferList.handleHstryBufs(useSimuData, commonData); // Handle history buffers for certain boat data for charts and other usage
|
||||
// LOG_DEBUG(GwLog::DEBUG, "obp60task: data handling: %d ms", millis() - startHandl);
|
||||
hstryBufferList.handleHstryBufs(useSimuData, commonData); // Handle history buffers for certain boat data for windplot page and other usage
|
||||
|
||||
// Clear display
|
||||
// getdisplay().fillRect(0, 0, getdisplay().width(), getdisplay().height(), commonData.bgcolor);
|
||||
getdisplay().fillScreen(commonData.bgcolor); // Clear display
|
||||
// epd->fillRect(0, 0, epd->width(), epd->height(), commonData.bgcolor);
|
||||
epd->fillScreen(commonData.bgcolor); // Clear display
|
||||
|
||||
// Show header if enabled
|
||||
if (pages[pageNumber].description && pages[pageNumber].description->header or systemPage){
|
||||
// build header using commonData
|
||||
displayHeader(commonData, date, time, hdop); // Show page header
|
||||
displayHeader(commonData, symbolmode, date, time, hdop); // Show page header
|
||||
}
|
||||
|
||||
// Call the particular page
|
||||
@@ -881,17 +846,17 @@ void OBP60Task(GwApi *api){
|
||||
if (currentPage == NULL){
|
||||
LOG_DEBUG(GwLog::ERROR,"page number %d not found", pageNumber);
|
||||
// Error handling for missing page
|
||||
displaySetPartialWindow(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!");
|
||||
displayNextPage(); // Partial update (fast)
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
epd->fillScreen(commonData.bgcolor); // Clear display
|
||||
epd->drawXBitmap(200 - unknown_width / 2, 150 - unknown_height / 2, unknown_bits, unknown_width, unknown_height, commonData.fgcolor);
|
||||
epd->setCursor(140, 250);
|
||||
epd->setFont(&Atari16px);
|
||||
epd->print("Here be dragons!");
|
||||
epd->nextPage(); // Partial update (fast)
|
||||
}
|
||||
else {
|
||||
if (pageChanged){
|
||||
if (lastPage != -1){ // skip cleanup if we are during startup, and no page has been displayed yet.
|
||||
if (lastPage != pageNumber) {
|
||||
if (lastPage != -1) { // skip cleanup if we are during startup, and no page has been displayed yet
|
||||
pages[lastPage].page->leavePage(pages[lastPage].parameters); // call page cleanup code
|
||||
if (hasFRAM) fram.write(FRAM_PAGE_NO, pageNumber); // remember new page for device restart
|
||||
}
|
||||
@@ -910,12 +875,10 @@ void OBP60Task(GwApi *api){
|
||||
displayAlarm(commonData);
|
||||
}
|
||||
if (ret & PAGE_UPDATE) {
|
||||
displayNextPage(); // Partial update (fast)
|
||||
epd->nextPage(); // Partial update (fast)
|
||||
}
|
||||
if (ret & PAGE_HIBERNATE) {
|
||||
#ifndef TFT_DISPLAY
|
||||
getdisplay().hibernate();
|
||||
#endif
|
||||
epd->hibernate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
#include "GwApi.h"
|
||||
//we only compile for some boards
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
#define USBSerial Serial
|
||||
#ifdef BOARD_OBP60S3
|
||||
#ifdef HARDWARE_V21
|
||||
// CAN NMEA2000
|
||||
#define ESP32_CAN_TX_PIN 46
|
||||
#define ESP32_CAN_RX_PIN 3
|
||||
@@ -35,19 +36,13 @@
|
||||
// OBP60 Task
|
||||
void OBP60Task(GwApi *param);
|
||||
DECLARE_USERTASK_PARAM(OBP60Task, 35000); // Need 35k RAM as stack size
|
||||
#if defined(BOARD_OBP60S3) && defined(TFT_DISPLAY)
|
||||
DECLARE_CAPABILITY(obp70,true);
|
||||
#endif
|
||||
#if defined(BOARD_OBP60S3) && !defined(TFT_DISPLAY)
|
||||
#ifdef HARDWARE_V21
|
||||
DECLARE_CAPABILITY(obp60,true);
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
DECLARE_CAPABILITY(obp40,true)
|
||||
#endif
|
||||
#if defined(BOARD_OBP60S3) && defined(TFT_DISPLAY)
|
||||
DECLARE_STRING_CAPABILITY(HELP_URL, "https://obp60-v2-docu.readthedocs.io/en/latest/"); // Link to help pages
|
||||
#endif
|
||||
#if defined(BOARD_OBP60S3) && !defined(TFT_DISPLAY)
|
||||
#ifdef BOARD_OBP60S3
|
||||
DECLARE_STRING_CAPABILITY(HELP_URL, "https://obp60-v2-docu.readthedocs.io/en/latest/"); // Link to help pages
|
||||
#endif
|
||||
#ifdef BOARD_OBP40S3
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
diff --git a/lib/api/GwApi.h b/lib/api/GwApi.h
|
||||
index 88f9690..9663a65 100644
|
||||
--- a/lib/api/GwApi.h
|
||||
+++ b/lib/api/GwApi.h
|
||||
@@ -2,6 +2,8 @@
|
||||
#define _GWAPI_H
|
||||
#include "GwMessage.h"
|
||||
#include "N2kMsg.h"
|
||||
+#include "Nmea2kTwai.h"
|
||||
+#include "N2kDeviceList.h"
|
||||
#include "NMEA0183Msg.h"
|
||||
#include "GWConfig.h"
|
||||
#include "GwBoatData.h"
|
||||
@@ -222,6 +224,8 @@ class GwApi{
|
||||
* accessing boat data must only be executed from within the main thread
|
||||
* you need to use the request pattern as shown in GwExampleTask.cpp
|
||||
*/
|
||||
+ virtual Nmea2kTwai *getNMEA2000()=0;
|
||||
+ virtual tN2kDeviceList *getN2kDeviceList()=0;
|
||||
virtual GwBoatData *getBoatData()=0;
|
||||
virtual ~GwApi(){}
|
||||
};
|
||||
diff --git a/lib/obp60task/OBP60Extensions.h b/lib/obp60task/OBP60Extensions.h
|
||||
index 9e2bc99..34eaeac 100644
|
||||
--- a/lib/obp60task/OBP60Extensions.h
|
||||
+++ b/lib/obp60task/OBP60Extensions.h
|
||||
@@ -29,6 +29,9 @@
|
||||
#define MOUNT_POINT "/sdcard"
|
||||
#endif
|
||||
|
||||
+// Patches to apply to gateway code
|
||||
+#define PATCH_N2K
|
||||
+
|
||||
// FRAM address reservations 32kB: 0x0000 - 0x7FFF
|
||||
// 0x0000 - 0x03ff: single variables
|
||||
#define FRAM_PAGE_NO 0x0002
|
||||
diff --git a/lib/usercode/GwUserCode.cpp b/lib/usercode/GwUserCode.cpp
|
||||
index 1b007f8..90087d4 100644
|
||||
--- a/lib/usercode/GwUserCode.cpp
|
||||
+++ b/lib/usercode/GwUserCode.cpp
|
||||
@@ -216,6 +216,14 @@ public:
|
||||
{
|
||||
return api->getLogger();
|
||||
}
|
||||
+ virtual Nmea2kTwai *getNMEA2000()
|
||||
+ {
|
||||
+ return api->getNMEA2000();
|
||||
+ }
|
||||
+ virtual tN2kDeviceList *getN2kDeviceList()
|
||||
+ {
|
||||
+ return api->getN2kDeviceList();
|
||||
+ }
|
||||
virtual GwBoatData *getBoatData()
|
||||
{
|
||||
return api->getBoatData();
|
||||
@@ -428,4 +436,4 @@ void GwUserCode::handleWebRequest(const String &url,AsyncWebServerRequest *req){
|
||||
}
|
||||
LOG_DEBUG(GwLog::DEBUG,"no task found for web request %s[%s]",url.c_str(),tname.c_str());
|
||||
req->send(404, "text/plain", "not found");
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
diff --git a/src/main.cpp b/src/main.cpp
|
||||
index 95d5d1e..01fcd32 100644
|
||||
--- a/src/main.cpp
|
||||
+++ b/src/main.cpp
|
||||
@@ -100,6 +100,7 @@ GwLog logger(LOGLEVEL,NULL);
|
||||
GwConfigHandler config(&logger);
|
||||
|
||||
#include "Nmea2kTwai.h"
|
||||
+#include <N2kDeviceList.h>
|
||||
static const unsigned long CAN_RECOVERY_PERIOD=3000; //ms
|
||||
static const unsigned long NMEA2000_HEARTBEAT_INTERVAL=5000;
|
||||
class Nmea2kTwaiLog : public Nmea2kTwai{
|
||||
@@ -126,6 +127,7 @@ class Nmea2kTwaiLog : public Nmea2kTwai{
|
||||
#endif
|
||||
|
||||
Nmea2kTwai &NMEA2000=*(new Nmea2kTwaiLog((gpio_num_t)ESP32_CAN_TX_PIN,(gpio_num_t)ESP32_CAN_RX_PIN,CAN_RECOVERY_PERIOD,&logger));
|
||||
+tN2kDeviceList *pN2kDeviceList;
|
||||
|
||||
#ifdef GWBUTTON_PIN
|
||||
bool fixedApPass=false;
|
||||
@@ -333,6 +335,12 @@ public:
|
||||
status.n2kTx=countNMEA2KOut.getGlobal();
|
||||
channels.fillStatus(status);
|
||||
}
|
||||
+ virtual Nmea2kTwai *getNMEA2000(){
|
||||
+ return &NMEA2000;
|
||||
+ }
|
||||
+ virtual tN2kDeviceList *getN2kDeviceList(){
|
||||
+ return pN2kDeviceList;
|
||||
+ }
|
||||
virtual GwBoatData *getBoatData(){
|
||||
return &boatData;
|
||||
}
|
||||
@@ -935,6 +943,7 @@ void setup() {
|
||||
NMEA2000.SetMsgHandler([](const tN2kMsg &n2kMsg){
|
||||
handleN2kMessage(n2kMsg,N2K_CHANNEL_ID);
|
||||
});
|
||||
+ pN2kDeviceList = new tN2kDeviceList(&NMEA2000);
|
||||
NMEA2000.Open();
|
||||
logger.logDebug(GwLog::LOG,"starting addon tasks");
|
||||
logger.flush();
|
||||
@@ -1,115 +0,0 @@
|
||||
diff --git a/lib/boatData/GwBoatData.cpp b/lib/boatData/GwBoatData.cpp
|
||||
index 424ebe4..b717097 100644
|
||||
--- a/lib/boatData/GwBoatData.cpp
|
||||
+++ b/lib/boatData/GwBoatData.cpp
|
||||
@@ -6,6 +6,7 @@
|
||||
#define GWTYPE_UINT32 2
|
||||
#define GWTYPE_UINT16 3
|
||||
#define GWTYPE_INT16 4
|
||||
+#define GWTYPE_STRING 5
|
||||
#define GWTYPE_USER 100
|
||||
|
||||
class GwBoatItemTypes
|
||||
@@ -15,6 +16,7 @@ public:
|
||||
static int getType(const uint16_t &x) { return GWTYPE_UINT16; }
|
||||
static int getType(const int16_t &x) { return GWTYPE_INT16; }
|
||||
static int getType(const double &x) { return GWTYPE_DOUBLE; }
|
||||
+ static int getType(const String &x) { return GWTYPE_STRING; }
|
||||
static int getType(const GwSatInfoList &x) { return GWTYPE_USER + 1; }
|
||||
};
|
||||
|
||||
@@ -252,6 +254,10 @@ static void writeToString(GwTextWriter *writer, const int16_t &value)
|
||||
{
|
||||
writer->writeInteger(value);
|
||||
}
|
||||
+static void writeToString(GwTextWriter *writer, String value)
|
||||
+{
|
||||
+ writer->writeString(value.c_str());
|
||||
+}
|
||||
static void writeToString(GwTextWriter *writer, GwSatInfoList &value)
|
||||
{
|
||||
writer->writeInteger(value.getNumSats());
|
||||
@@ -288,6 +294,8 @@ template class GwBoatItem<double>;
|
||||
template class GwBoatItem<uint32_t>;
|
||||
template class GwBoatItem<uint16_t>;
|
||||
template class GwBoatItem<int16_t>;
|
||||
+template class GwBoatItem<String>;
|
||||
+
|
||||
void GwSatInfoList::houseKeeping(unsigned long ts)
|
||||
{
|
||||
if (ts == 0)
|
||||
diff --git a/lib/boatData/GwBoatData.h b/lib/boatData/GwBoatData.h
|
||||
index ae50b3f..5b32f70 100644
|
||||
--- a/lib/boatData/GwBoatData.h
|
||||
+++ b/lib/boatData/GwBoatData.h
|
||||
@@ -58,6 +58,7 @@ class GwBoatItemBase{
|
||||
GWSC(formatRot);
|
||||
GWSC(formatDate);
|
||||
GWSC(formatTime);
|
||||
+ GWSC(formatName);
|
||||
protected:
|
||||
int type;
|
||||
unsigned long lastSet=0;
|
||||
@@ -92,6 +93,7 @@ class GwBoatItemBase{
|
||||
virtual int getLastSource(){return lastUpdateSource;}
|
||||
virtual void refresh(unsigned long ts=0){uls(ts);}
|
||||
virtual double getDoubleValue()=0;
|
||||
+ virtual String getStringValue()=0;
|
||||
String getName(){return name;}
|
||||
const String & getFormat() const{return format;}
|
||||
virtual void setInvalidTime(GwConfigHandler *cfg);
|
||||
@@ -120,7 +122,19 @@ template<class T> class GwBoatItem : public GwBoatItemBase{
|
||||
if (! isValid(millis())) return defaultv;
|
||||
return data;
|
||||
}
|
||||
- virtual double getDoubleValue(){return (double)data;}
|
||||
+ virtual double getDoubleValue(){
|
||||
+ if constexpr (std::is_same<T, String>::value) {
|
||||
+ return 0.0;
|
||||
+ // TODO any better ideas?
|
||||
+ // perhaps return std::numeric_limits<double>::quiet_NaN();
|
||||
+ } else {
|
||||
+ return (double)data;
|
||||
+ }
|
||||
+ }
|
||||
+ virtual String getStringValue(){
|
||||
+ return (String)data;
|
||||
+ }
|
||||
+
|
||||
virtual void fillString();
|
||||
virtual void toJsonDoc(GwJsonDocument *doc, unsigned long minTime);
|
||||
virtual int getLastSource(){return lastUpdateSource;}
|
||||
@@ -235,6 +249,7 @@ class GwBoatData{
|
||||
GWBOATDATA(double,XTE,formatXte) // cross track error
|
||||
GWBOATDATA(double,WPLat,formatLatitude) // waypoint latitude
|
||||
GWBOATDATA(double,WPLon,formatLongitude) // waypoint longitude
|
||||
+ GWBOATDATA(String,WPName,formatName) // waypoint name
|
||||
GWSPECBOATDATA(GwBoatDataSatList,SatInfo,GwSatInfoList::toType,formatFixed0);
|
||||
public:
|
||||
GwBoatData(GwLog *logger, GwConfigHandler *cfg);
|
||||
diff --git a/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp b/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp
|
||||
index 6989570..238af38 100644
|
||||
--- a/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp
|
||||
+++ b/lib/nmea0183ton2k/NMEA0183DataToN2K.cpp
|
||||
@@ -355,6 +355,7 @@ private:
|
||||
AppendN2kRouteWPInfo(n2kMsg,destinationId,rmb.destID,rmb.latitude,rmb.longitude);
|
||||
send(n2kMsg,msg.sourceId);
|
||||
}
|
||||
+ boatData->WPName->update(String(rmb.destID), msg.sourceId);
|
||||
}
|
||||
void convertRMC(const SNMEA0183Msg &msg)
|
||||
{
|
||||
diff --git a/platformio.ini b/platformio.ini
|
||||
index b738131..e131a6e 100644
|
||||
--- a/platformio.ini
|
||||
+++ b/platformio.ini
|
||||
@@ -68,6 +68,9 @@ lib_ldf_mode = off
|
||||
monitor_speed = 115200
|
||||
build_flags =
|
||||
-D PIO_ENV_BUILD=$PIOENV
|
||||
+ -std=gnu++17
|
||||
+build_unflags =
|
||||
+ -std=gnu++11
|
||||
|
||||
[sensors]
|
||||
; collect the libraries for sensors here
|
||||
@@ -1,248 +0,0 @@
|
||||
diff --git a/lib/api/GwApi.h b/lib/api/GwApi.h
|
||||
index 9663a65..901ee5a 100644
|
||||
--- a/lib/api/GwApi.h
|
||||
+++ b/lib/api/GwApi.h
|
||||
@@ -139,6 +139,7 @@ class GwApi{
|
||||
* thread safe methods - can directly be called from a user task
|
||||
*/
|
||||
virtual GwRequestQueue *getQueue()=0;
|
||||
+ virtual QueueHandle_t getKbQueue()=0;
|
||||
virtual void sendN2kMessage(const tN2kMsg &msg, bool convert=true)=0;
|
||||
/**
|
||||
* deprecated - sourceId will be ignored
|
||||
diff --git a/lib/config/GwConverterConfig.h b/lib/config/GwConverterConfig.h
|
||||
index 25ca39e..569bc34 100644
|
||||
--- a/lib/config/GwConverterConfig.h
|
||||
+++ b/lib/config/GwConverterConfig.h
|
||||
@@ -71,6 +71,7 @@ class GwConverterConfig{
|
||||
int rmcInterval=1000;
|
||||
int rmcCheckTime=4000;
|
||||
int winst312=256;
|
||||
+ int swBankInstance=0;
|
||||
bool unmappedXdr=false;
|
||||
unsigned long xdrTimeout=60000;
|
||||
std::vector<WindMapping> windMappings;
|
||||
@@ -113,4 +114,4 @@ class GwConverterConfig{
|
||||
|
||||
|
||||
};
|
||||
-#endif
|
||||
\ No newline at end of file
|
||||
+#endif
|
||||
diff --git a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp
|
||||
index 0c0e68c..508d849 100644
|
||||
--- a/lib/nmea2kto0183/N2kDataToNMEA0183.cpp
|
||||
+++ b/lib/nmea2kto0183/N2kDataToNMEA0183.cpp
|
||||
@@ -1449,6 +1449,29 @@ private:
|
||||
finalizeXdr();
|
||||
}
|
||||
|
||||
+ void Handle127502(const tN2kMsg &msg){
|
||||
+ // switch bank control / receive remote key strokes
|
||||
+ unsigned char instance=0;
|
||||
+ tN2kBinaryStatus bankstatus;
|
||||
+ LOG_DEBUG(GwLog::LOG,"received switch bank control");
|
||||
+ // check if we are addressed and our configured instance is used
|
||||
+ if (! ParseN2kPGN127502(msg,instance,bankstatus)) {
|
||||
+ LOG_DEBUG(GwLog::DEBUG,"unable to parse PGN %d",msg.PGN);
|
||||
+ return;
|
||||
+ }
|
||||
+ if (! (instance == config.swBankInstance)) {
|
||||
+ LOG_DEBUG(GwLog::DEBUG,"switch bank instance #%d ignored",instance);
|
||||
+ return;
|
||||
+ }
|
||||
+ for (uint8_t i=1; i<=28; i++) {
|
||||
+ tN2kOnOff keystatus = N2kGetStatusOnBinaryStatus(bankstatus, i);
|
||||
+ if (keystatus == 1) {
|
||||
+ // key pressed: send key to queue
|
||||
+ xQueueSend(keyboardQueue, &i, 0);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
void registerConverters()
|
||||
{
|
||||
//register all converter functions
|
||||
@@ -1484,6 +1507,7 @@ private:
|
||||
converters.registerConverter(127488UL, &N2kToNMEA0183Functions::Handle127488);
|
||||
converters.registerConverter(130316UL, &N2kToNMEA0183Functions::Handle130316);
|
||||
converters.registerConverter(127257UL, &N2kToNMEA0183Functions::Handle127257);
|
||||
+ converters.registerConverter(127502UL, &N2kToNMEA0183Functions::Handle127502);
|
||||
#define HANDLE_AIS
|
||||
#ifdef HANDLE_AIS
|
||||
converters.registerConverter(129038UL, &N2kToNMEA0183Functions::HandleAISClassAPosReport); // AIS Class A Position Report, Message Type 1
|
||||
@@ -1498,13 +1522,15 @@ private:
|
||||
public:
|
||||
N2kToNMEA0183Functions(GwLog *logger, GwBoatData *boatData,
|
||||
SendNMEA0183MessageCallback callback,
|
||||
- String talkerId, GwXDRMappings *xdrMappings, const GwConverterConfig &cfg)
|
||||
+ String talkerId, GwXDRMappings *xdrMappings, const GwConverterConfig &cfg,
|
||||
+ QueueHandle_t kbQueue)
|
||||
: N2kDataToNMEA0183(logger, boatData, callback,talkerId)
|
||||
{
|
||||
this->logger = logger;
|
||||
this->boatData = boatData;
|
||||
this->xdrMappings=xdrMappings;
|
||||
this->config=cfg;
|
||||
+ this->keyboardQueue=kbQueue;
|
||||
registerConverters();
|
||||
}
|
||||
virtual void loop(unsigned long lastExtRmc) override
|
||||
@@ -1520,8 +1546,8 @@ private:
|
||||
|
||||
N2kDataToNMEA0183* N2kDataToNMEA0183::create(GwLog *logger, GwBoatData *boatData,
|
||||
SendNMEA0183MessageCallback callback, String talkerId, GwXDRMappings *xdrMappings,
|
||||
- const GwConverterConfig &cfg){
|
||||
- LOG_DEBUG(GwLog::LOG,"creating N2kToNMEA0183");
|
||||
- return new N2kToNMEA0183Functions(logger,boatData,callback, talkerId,xdrMappings,cfg);
|
||||
+ const GwConverterConfig &cfg, QueueHandle_t kbQueue){
|
||||
+ LOG_DEBUG(GwLog::LOG,"creating N2kToNMEA0183");
|
||||
+ return new N2kToNMEA0183Functions(logger,boatData,callback, talkerId,xdrMappings,cfg,kbQueue);
|
||||
}
|
||||
//*****************************************************************************
|
||||
diff --git a/lib/nmea2kto0183/N2kDataToNMEA0183.h b/lib/nmea2kto0183/N2kDataToNMEA0183.h
|
||||
index 61e8ee2..f7d8c75 100644
|
||||
--- a/lib/nmea2kto0183/N2kDataToNMEA0183.h
|
||||
+++ b/lib/nmea2kto0183/N2kDataToNMEA0183.h
|
||||
@@ -43,6 +43,7 @@ protected:
|
||||
GwBoatData *boatData;
|
||||
int sourceId=0;
|
||||
char talkerId[3];
|
||||
+ QueueHandle_t keyboardQueue;
|
||||
SendNMEA0183MessageCallback sendNMEA0183MessageCallback;
|
||||
void SendMessage(const tNMEA0183Msg &NMEA0183Msg);
|
||||
N2kDataToNMEA0183(GwLog *logger, GwBoatData *boatData,
|
||||
@@ -50,7 +51,8 @@ protected:
|
||||
|
||||
public:
|
||||
static N2kDataToNMEA0183* create(GwLog *logger, GwBoatData *boatData, SendNMEA0183MessageCallback callback,
|
||||
- String talkerId, GwXDRMappings *xdrMappings,const GwConverterConfig &cfg);
|
||||
+ String talkerId, GwXDRMappings *xdrMappings,const GwConverterConfig &cfg,
|
||||
+ QueueHandle_t kbQueue);
|
||||
virtual void HandleMsg(const tN2kMsg &N2kMsg, int sourceId) = 0;
|
||||
virtual void loop(unsigned long lastRmc);
|
||||
virtual ~N2kDataToNMEA0183(){}
|
||||
@@ -59,4 +61,4 @@ public:
|
||||
virtual void toJson(GwJsonDocument *json)=0;
|
||||
virtual String handledKeys()=0;
|
||||
};
|
||||
-#endif
|
||||
\ No newline at end of file
|
||||
+#endif
|
||||
diff --git a/lib/obp60task/obp60task.cpp b/lib/obp60task/obp60task.cpp
|
||||
index 6a24c3b..81ac5e3 100644
|
||||
--- a/lib/obp60task/obp60task.cpp
|
||||
+++ b/lib/obp60task/obp60task.cpp
|
||||
@@ -360,6 +360,8 @@ void OBP60Task(GwApi *api){
|
||||
|
||||
tN2kMsg N2kMsg;
|
||||
|
||||
+ QueueHandle_t keyboardQueue = api->getKbQueue();
|
||||
+
|
||||
LOG_DEBUG(GwLog::LOG,"obp60task started");
|
||||
for (auto it=allPages.pages.begin();it != allPages.pages.end();it++){
|
||||
LOG_DEBUG(GwLog::LOG,"found registered page %s",(*it)->pageName.c_str());
|
||||
@@ -645,7 +647,16 @@ void OBP60Task(GwApi *api){
|
||||
if((String(gpsFix) == "GPS Fix Lost" && hdop->value > hdopAccuracy && hdop->valid == true) || (String(gpsFix) == "GPS Fix Lost" && hdop->valid == false)){
|
||||
setFlashLED(true);
|
||||
}
|
||||
-
|
||||
+
|
||||
+ // Keyboard messages from remote
|
||||
+ uint8_t remotekey = 0;
|
||||
+ if (xQueueReceive(keyboardQueue, &remotekey, 0) == pdPASS) {
|
||||
+ LOG_DEBUG(GwLog::LOG, "OBP received remote key: %d", remotekey);
|
||||
+ // inject into internal keyboard queue
|
||||
+ int injectkey = static_cast<int>(remotekey);
|
||||
+ xQueueSend(allParameters.queue, &injectkey, 0);
|
||||
+ }
|
||||
+
|
||||
// Check the keyboard message
|
||||
int keyboardMessage=0;
|
||||
while (xQueueReceive(allParameters.queue,&keyboardMessage,0)){
|
||||
diff --git a/lib/usercode/GwUserCode.cpp b/lib/usercode/GwUserCode.cpp
|
||||
index 90087d4..9d8e3db 100644
|
||||
--- a/lib/usercode/GwUserCode.cpp
|
||||
+++ b/lib/usercode/GwUserCode.cpp
|
||||
@@ -189,6 +189,10 @@ public:
|
||||
{
|
||||
return api->getQueue();
|
||||
}
|
||||
+ virtual QueueHandle_t getKbQueue()
|
||||
+ {
|
||||
+ return api->getKbQueue();
|
||||
+ }
|
||||
virtual void sendN2kMessage(const tN2kMsg &msg,bool convert)
|
||||
{
|
||||
GWSYNCHRONIZED(mainLock);
|
||||
diff --git a/src/main.cpp b/src/main.cpp
|
||||
index 01fcd32..ff353fb 100644
|
||||
--- a/src/main.cpp
|
||||
+++ b/src/main.cpp
|
||||
@@ -160,6 +160,8 @@ GwCounter<unsigned long> countNMEA2KIn("countNMEA2000in");
|
||||
GwCounter<unsigned long> countNMEA2KOut("countNMEA2000out");
|
||||
GwIntervalRunner timers;
|
||||
|
||||
+QueueHandle_t keyboardQueue = NULL;
|
||||
+
|
||||
bool checkPass(String hash){
|
||||
return config.checkPass(hash);
|
||||
}
|
||||
@@ -271,6 +273,10 @@ public:
|
||||
{
|
||||
return &mainQueue;
|
||||
}
|
||||
+ virtual QueueHandle_t getKbQueue()
|
||||
+ {
|
||||
+ return keyboardQueue;
|
||||
+ }
|
||||
virtual void sendN2kMessage(const tN2kMsg &msg,bool convert)
|
||||
{
|
||||
handleN2kMessage(msg,sourceId,!convert);
|
||||
@@ -868,6 +874,8 @@ void setup() {
|
||||
webserver.begin();
|
||||
xdrMappings.begin();
|
||||
logger.flush();
|
||||
+ // remote keyboard support
|
||||
+ keyboardQueue = xQueueCreate(10, sizeof(uint8_t));
|
||||
GwConverterConfig converterConfig;
|
||||
converterConfig.init(&config,&logger);
|
||||
nmea0183Converter= N2kDataToNMEA0183::create(&logger, &boatData,
|
||||
@@ -877,7 +885,8 @@ void setup() {
|
||||
,
|
||||
config.getString(config.talkerId,String("GP")),
|
||||
&xdrMappings,
|
||||
- converterConfig
|
||||
+ converterConfig,
|
||||
+ keyboardQueue
|
||||
);
|
||||
|
||||
toN2KConverter= NMEA0183DataToN2K::create(&logger,&boatData,[](const tN2kMsg &msg, int sourceId)->bool{
|
||||
diff --git a/web/config.json b/web/config.json
|
||||
index 26d3166..bef7790 100644
|
||||
--- a/web/config.json
|
||||
+++ b/web/config.json
|
||||
@@ -88,6 +88,16 @@
|
||||
"description":"the brightness of the led (0..255)",
|
||||
"category":"system"
|
||||
},
|
||||
+ {
|
||||
+ "name": "swBankInstance",
|
||||
+ "type": "number",
|
||||
+ "default": 0,
|
||||
+ "min": 0,
|
||||
+ "max": 252,
|
||||
+ "check": "checkMinMax",
|
||||
+ "description": "the instance of switch bank to receive data for (0..252)",
|
||||
+ "category": "system"
|
||||
+ },
|
||||
{
|
||||
"name": "talkerId",
|
||||
"label": "NMEA0183 ID",
|
||||
@@ -1287,4 +1297,4 @@
|
||||
"check": "checkXDR",
|
||||
"category": "xdr30"
|
||||
}
|
||||
-]
|
||||
\ No newline at end of file
|
||||
+]
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user