mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2025-12-24 11:13:06 +01:00
Compare commits
1 Commits
9af781318f
...
barograph
| Author | SHA1 | Date | |
|---|---|---|---|
| c5e346f4eb |
@@ -1,56 +0,0 @@
|
|||||||
{
|
|
||||||
"build": {
|
|
||||||
"arduino":{
|
|
||||||
"ldscript": "esp32s3_out.ld",
|
|
||||||
"partitions": "default_8MB.csv",
|
|
||||||
"memory_type": "qio_opi"
|
|
||||||
},
|
|
||||||
"core": "esp32",
|
|
||||||
"extra_flags": [
|
|
||||||
"-DBOARD_HAS_PSRAM",
|
|
||||||
"-DARDUINO_ESP32S3_DEV",
|
|
||||||
"-DARDUINO_USB_MODE=1",
|
|
||||||
"-DARDUINO_USB_CDC_ON_BOOT=0",
|
|
||||||
"-DARDUINO_RUNNING_CORE=1",
|
|
||||||
"-DARDUINO_EVENT_RUNNING_CORE=1"
|
|
||||||
],
|
|
||||||
"f_cpu": "240000000L",
|
|
||||||
"f_flash": "80000000L",
|
|
||||||
"flash_mode": "qio",
|
|
||||||
"hwids": [
|
|
||||||
[
|
|
||||||
"0x303A",
|
|
||||||
"0x1001"
|
|
||||||
]
|
|
||||||
],
|
|
||||||
"mcu": "esp32s3",
|
|
||||||
"variant": "obp60s3_light"
|
|
||||||
},
|
|
||||||
"connectivity": [
|
|
||||||
"bluetooth",
|
|
||||||
"wifi"
|
|
||||||
],
|
|
||||||
"debug": {
|
|
||||||
"default_tool": "esp-builtin",
|
|
||||||
"onboard_tools": [
|
|
||||||
"esp-builtin"
|
|
||||||
],
|
|
||||||
"openocd_target": "esp32s3.cfg"
|
|
||||||
},
|
|
||||||
"frameworks": [
|
|
||||||
"arduino",
|
|
||||||
"espidf"
|
|
||||||
],
|
|
||||||
"name": "OBP60 Light ESP32-S3-N8R8 (8 MB QD, 8 MB PSRAM)",
|
|
||||||
"upload": {
|
|
||||||
"flash_size": "8MB",
|
|
||||||
"maximum_ram_size": 327680,
|
|
||||||
"maximum_size": 8388608,
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "GwApi.h"
|
#include "GwApi.h"
|
||||||
#include "OBP60Hardware.h"
|
#include "OBP60Hardware.h"
|
||||||
|
|
||||||
|
|
||||||
class Color{
|
class Color{
|
||||||
public:
|
public:
|
||||||
uint8_t r;
|
uint8_t r;
|
||||||
@@ -91,4 +92,5 @@ class LedTaskData{
|
|||||||
//task function
|
//task function
|
||||||
void createSpiLedTask(LedTaskData *param);
|
void createSpiLedTask(LedTaskData *param);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
#ifdef BOARD_OBP60S3
|
#ifdef BOARD_OBP60S3
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
#define FASTLED_ALL_PINS_HARDWARE_SPI
|
||||||
|
#define FASTLED_ESP32_SPI_BUS FSPI
|
||||||
|
#define FASTLED_ESP32_FLASH_LOCK 1
|
||||||
#include <PCF8574.h> // Driver for PCF8574 output modul from Horter
|
#include <PCF8574.h> // Driver for PCF8574 output modul from Horter
|
||||||
#include <Wire.h> // I2C
|
#include <Wire.h> // I2C
|
||||||
#include <RTClib.h> // Driver for DS1388 RTC
|
#include <RTClib.h> // Driver for DS1388 RTC
|
||||||
@@ -8,7 +11,6 @@
|
|||||||
#include "Pagedata.h"
|
#include "Pagedata.h"
|
||||||
#include "OBP60Hardware.h"
|
#include "OBP60Hardware.h"
|
||||||
#include "OBP60Extensions.h"
|
#include "OBP60Extensions.h"
|
||||||
#include "imglib.h"
|
|
||||||
|
|
||||||
// Character sets
|
// Character sets
|
||||||
#include "Ubuntu_Bold8pt7b.h"
|
#include "Ubuntu_Bold8pt7b.h"
|
||||||
@@ -58,10 +60,6 @@ GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay(){r
|
|||||||
// Horter I2C moduls
|
// Horter I2C moduls
|
||||||
PCF8574 pcf8574_Out(PCF8574_I2C_ADDR1); // First digital output modul PCF8574 from Horter
|
PCF8574 pcf8574_Out(PCF8574_I2C_ADDR1); // First digital output modul PCF8574 from Horter
|
||||||
|
|
||||||
// FRAM
|
|
||||||
Adafruit_FRAM_I2C fram;
|
|
||||||
bool hasFRAM = false;
|
|
||||||
|
|
||||||
// Global vars
|
// Global vars
|
||||||
bool blinkingLED = false; // Enable / disable blinking flash LED
|
bool blinkingLED = false; // Enable / disable blinking flash LED
|
||||||
bool statusLED = false; // Actual status of flash LED on/off
|
bool statusLED = false; // Actual status of flash LED on/off
|
||||||
@@ -71,7 +69,7 @@ int uvDuration = 0; // Under voltage duration in n x 100ms
|
|||||||
|
|
||||||
LedTaskData *ledTaskData=nullptr;
|
LedTaskData *ledTaskData=nullptr;
|
||||||
|
|
||||||
void hardwareInit(GwApi *api)
|
void hardwareInit()
|
||||||
{
|
{
|
||||||
Wire.begin();
|
Wire.begin();
|
||||||
// Init PCF8574 digital outputs
|
// Init PCF8574 digital outputs
|
||||||
@@ -79,27 +77,12 @@ void hardwareInit(GwApi *api)
|
|||||||
if(pcf8574_Out.begin()){ // Initialize PCF8574
|
if(pcf8574_Out.begin()){ // Initialize PCF8574
|
||||||
pcf8574_Out.write8(255); // Clear all outputs
|
pcf8574_Out.write8(255); // Clear all outputs
|
||||||
}
|
}
|
||||||
fram = Adafruit_FRAM_I2C();
|
|
||||||
if (esp_reset_reason() == ESP_RST_POWERON) {
|
|
||||||
// help initialize FRAM
|
|
||||||
api->getLogger()->logDebug(GwLog::LOG,"Delaying I2C init for 250ms due to cold boot");
|
|
||||||
delay(250);
|
|
||||||
}
|
|
||||||
// FRAM (e.g. MB85RC256V)
|
|
||||||
if (fram.begin(FRAM_I2C_ADDR)) {
|
|
||||||
hasFRAM = true;
|
|
||||||
uint16_t manufacturerID;
|
|
||||||
uint16_t productID;
|
|
||||||
fram.getDeviceID(&manufacturerID, &productID);
|
|
||||||
// Boot counter
|
|
||||||
uint8_t framcounter = fram.read(0x0000);
|
|
||||||
fram.write(0x0000, framcounter+1);
|
|
||||||
api->getLogger()->logDebug(GwLog::LOG,"FRAM detected: 0x%04x/0x%04x (counter=%d)", manufacturerID, productID, framcounter);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
hasFRAM = false;
|
|
||||||
api->getLogger()->logDebug(GwLog::LOG,"NO FRAM detected");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void startLedTask(GwApi *api){
|
||||||
|
ledTaskData=new LedTaskData(api);
|
||||||
|
createSpiLedTask(ledTaskData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPortPin(uint pin, bool value){
|
void setPortPin(uint pin, bool value){
|
||||||
@@ -112,11 +95,6 @@ void togglePortPin(uint pin){
|
|||||||
digitalWrite(pin, !digitalRead(pin));
|
digitalWrite(pin, !digitalRead(pin));
|
||||||
}
|
}
|
||||||
|
|
||||||
void startLedTask(GwApi *api){
|
|
||||||
ledTaskData=new LedTaskData(api);
|
|
||||||
createSpiLedTask(ledTaskData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Valid colors see hue
|
// Valid colors see hue
|
||||||
Color colorMapping(const String &colorString){
|
Color colorMapping(const String &colorString){
|
||||||
Color color = COLOR_RED;
|
Color color = COLOR_RED;
|
||||||
@@ -201,30 +179,6 @@ String xdrDelete(String input){
|
|||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
||||||
Point rotatePoint(const Point& origin, const Point& p, double angle) {
|
|
||||||
// rotate poind around origin by degrees
|
|
||||||
Point rotated;
|
|
||||||
double phi = angle * M_PI / 180.0;
|
|
||||||
double dx = p.x - origin.x;
|
|
||||||
double dy = p.y - origin.y;
|
|
||||||
rotated.x = origin.x + cos(phi) * dx - sin(phi) * dy;
|
|
||||||
rotated.y = origin.y + sin(phi) * dx + cos(phi) * dy;
|
|
||||||
return rotated;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle) {
|
|
||||||
std::vector<Point> rotatedPoints;
|
|
||||||
for (const auto& p : pts) {
|
|
||||||
rotatedPoints.push_back(rotatePoint(origin, p, angle));
|
|
||||||
}
|
|
||||||
return rotatedPoints;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fillPoly4(const std::vector<Point>& p4, uint16_t color) {
|
|
||||||
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[1].x, p4[1].y, p4[2].x, p4[2].y, color);
|
|
||||||
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[2].x, p4[2].y, p4[3].x, p4[3].y, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw centered text
|
// Draw centered text
|
||||||
void drawTextCenter(int16_t cx, int16_t cy, String text) {
|
void drawTextCenter(int16_t cx, int16_t cy, String text) {
|
||||||
int16_t x1, y1;
|
int16_t x1, y1;
|
||||||
@@ -468,45 +422,4 @@ void generatorGraphic(uint x, uint y, int pcolor, int bcolor){
|
|||||||
getdisplay().print("G");
|
getdisplay().print("G");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to handle HTTP image request
|
|
||||||
// http://192.168.15.1/api/user/OBP60Task/screenshot
|
|
||||||
void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUMBER], AsyncWebServerRequest *request) {
|
|
||||||
GwLog *logger = api->getLogger();
|
|
||||||
|
|
||||||
String imgformat = api->getConfig()->getConfigItem(api->getConfig()->imageFormat,true)->asString();
|
|
||||||
imgformat.toLowerCase();
|
|
||||||
String filename = "Page" + String(*pageno) + "_" + pages[*pageno].description->pageName + "." + imgformat;
|
|
||||||
|
|
||||||
logger->logDebug(GwLog::LOG,"handle image request [%s]: %s", imgformat, filename);
|
|
||||||
|
|
||||||
uint8_t *fb = getdisplay().getBuffer(); // EPD framebuffer
|
|
||||||
std::vector<uint8_t> imageBuffer; // image in webserver transferbuffer
|
|
||||||
String mimetype;
|
|
||||||
|
|
||||||
if (imgformat == "gif") {
|
|
||||||
// GIF is commpressed with LZW, so small
|
|
||||||
mimetype = "image/gif";
|
|
||||||
if (!createGIF(fb, &imageBuffer, GxEPD_WIDTH, GxEPD_HEIGHT)) {
|
|
||||||
logger->logDebug(GwLog::LOG,"GIF creation failed: Hashtable init error!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (imgformat == "bmp") {
|
|
||||||
// Microsoft BMP bitmap
|
|
||||||
mimetype = "image/bmp";
|
|
||||||
createBMP(fb, &imageBuffer, GxEPD_WIDTH, GxEPD_HEIGHT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// PBM simple portable bitmap
|
|
||||||
mimetype = "image/x-portable-bitmap";
|
|
||||||
createPBM(fb, &imageBuffer, GxEPD_WIDTH, GxEPD_HEIGHT);
|
|
||||||
}
|
|
||||||
|
|
||||||
AsyncWebServerResponse *response = request->beginResponse_P(200, mimetype, (const uint8_t*)imageBuffer.data(), imageBuffer.size());
|
|
||||||
response->addHeader("Content-Disposition", "inline; filename=" + filename);
|
|
||||||
request->send(response);
|
|
||||||
|
|
||||||
imageBuffer.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -3,24 +3,11 @@
|
|||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "OBP60Hardware.h"
|
#include "OBP60Hardware.h"
|
||||||
|
#define FASTLED_ALL_PINS_HARDWARE_SPI
|
||||||
|
#define FASTLED_ESP32_SPI_BUS FSPI
|
||||||
|
#define FASTLED_ESP32_FLASH_LOCK 1
|
||||||
#include "LedSpiTask.h"
|
#include "LedSpiTask.h"
|
||||||
#include <GxEPD2_BW.h> // E-paper lib V2
|
#include <GxEPD2_BW.h> // E-paper lib V2
|
||||||
#include <Adafruit_FRAM_I2C.h> // I2C FRAM
|
|
||||||
|
|
||||||
// FRAM address reservations 32kB: 0x0000 - 0x7FFF
|
|
||||||
// 0x0000 - 0x03ff: single variables
|
|
||||||
#define FRAM_VOLTAGE_AVG 0x000A
|
|
||||||
#define FRAM_VOLTAGE_TREND 0x000B
|
|
||||||
#define FRAM_VOLTAGE_MODE 0x000C
|
|
||||||
#define FRAM_WIND_SIZE 0x000D
|
|
||||||
#define FRAM_WIND_SRC 0x000E
|
|
||||||
#define FRAM_WIND_MODE 0x000F
|
|
||||||
// Barograph history data
|
|
||||||
#define FRAM_BAROGRAPH_START 0x0400
|
|
||||||
#define FRAM_BAROGRAPH_END 0x13FF
|
|
||||||
|
|
||||||
extern Adafruit_FRAM_I2C fram;
|
|
||||||
extern bool hasFRAM;
|
|
||||||
|
|
||||||
// Fonts declarations for display (#inclues see OBP60Extensions.cpp)
|
// Fonts declarations for display (#inclues see OBP60Extensions.cpp)
|
||||||
extern const GFXfont Ubuntu_Bold8pt7b;
|
extern const GFXfont Ubuntu_Bold8pt7b;
|
||||||
@@ -52,15 +39,7 @@ GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay();
|
|||||||
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay();
|
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct Point {
|
void hardwareInit();
|
||||||
double x;
|
|
||||||
double y;
|
|
||||||
};
|
|
||||||
Point rotatePoint(const Point& origin, const Point& p, double angle);
|
|
||||||
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle);
|
|
||||||
void fillPoly4(const std::vector<Point>& p4, uint16_t color);
|
|
||||||
|
|
||||||
void hardwareInit(GwApi *api);
|
|
||||||
|
|
||||||
void setPortPin(uint pin, bool value); // Set port pin for extension port
|
void setPortPin(uint pin, bool value); // Set port pin for extension port
|
||||||
|
|
||||||
@@ -94,13 +73,4 @@ void solarGraphic(uint x, uint y, int pcolor, int bcolor); // S
|
|||||||
void generatorGraphic(uint x, uint y, int pcolor, int bcolor); // Generator graphic with fill level
|
void generatorGraphic(uint x, uint y, int pcolor, int bcolor); // Generator graphic with fill level
|
||||||
void startLedTask(GwApi *api);
|
void startLedTask(GwApi *api);
|
||||||
|
|
||||||
void doImageRequest(GwApi *api, int *pageno, const PageStruct pages[MAX_PAGE_NUMBER], AsyncWebServerRequest *request);
|
|
||||||
|
|
||||||
#define fram_width 16
|
|
||||||
#define fram_height 16
|
|
||||||
static unsigned char fram_bits[] = {
|
|
||||||
0xf8, 0x1f, 0xff, 0xff, 0x9f, 0xff, 0x98, 0x1f, 0xf8, 0x1f, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xf8, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f,
|
|
||||||
0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f };
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// General hardware definitions
|
// General hardware definitions
|
||||||
// CAN and RS485 bus pin definitions see obp60task.h
|
// CAN and RS485 bus pin definitions see obp60task.h
|
||||||
|
|
||||||
#ifdef HARDWARE_V21
|
|
||||||
// Direction pin for RS485 NMEA0183
|
// Direction pin for RS485 NMEA0183
|
||||||
#define OBP_DIRECTION_PIN 18
|
#define OBP_DIRECTION_PIN 18
|
||||||
// I2C
|
// I2C
|
||||||
@@ -31,8 +30,6 @@
|
|||||||
#define INA226_I2C_ADDR3 0x45 // Addr. 0x45 (fix A0 = 5V, A1 = 5V) for generator
|
#define INA226_I2C_ADDR3 0x45 // Addr. 0x45 (fix A0 = 5V, A1 = 5V) for generator
|
||||||
// Horter modules
|
// Horter modules
|
||||||
#define PCF8574_I2C_ADDR1 0x20 // First digital out module
|
#define PCF8574_I2C_ADDR1 0x20 // First digital out module
|
||||||
// FRAM (e.g. MB85RC256V)
|
|
||||||
#define FRAM_I2C_ADDR 0x50
|
|
||||||
// SPI (E-Ink display, Extern Bus)
|
// SPI (E-Ink display, Extern Bus)
|
||||||
#define OBP_SPI_CS 39
|
#define OBP_SPI_CS 39
|
||||||
#define OBP_SPI_DC 40
|
#define OBP_SPI_DC 40
|
||||||
@@ -42,6 +39,11 @@
|
|||||||
#define OBP_SPI_DIN 48
|
#define OBP_SPI_DIN 48
|
||||||
#define SHOW_TIME 6000 // Show time in [ms] for logo and WiFi QR code
|
#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 FULL_REFRESH_TIME 600 // Refresh cycle time in [s][600...3600] for full display update (very important healcy function)
|
||||||
|
#define MAX_PAGE_NUMBER 10 // Max number of pages for show data
|
||||||
|
#define FONT1 "Ubuntu_Bold8pt7b"
|
||||||
|
#define FONT2 "Ubuntu_Bold24pt7b"
|
||||||
|
#define FONT3 "Ubuntu_Bold32pt7b"
|
||||||
|
#define FONT4 "DSEG7Classic_BoldItalic80pt7b"
|
||||||
|
|
||||||
// GPS (NEO-6M, NEO-M8N, ATGM336H)
|
// GPS (NEO-6M, NEO-M8N, ATGM336H)
|
||||||
#define OBP_GPS_RX 2
|
#define OBP_GPS_RX 2
|
||||||
@@ -55,7 +57,7 @@
|
|||||||
#define TONE3 3500 // 3500Hz
|
#define TONE3 3500 // 3500Hz
|
||||||
#define TONE4 4000 // 4000Hz
|
#define TONE4 4000 // 4000Hz
|
||||||
// Analog Input
|
// Analog Input
|
||||||
#define OBP_ANALOG0 4 // Analog input for voltage power supply
|
#define OBP_ANALOG0 4 // Analog input for voltage power supplay
|
||||||
#define MIN_VOLTAGE 10.0 // Min voltage for under voltage detection (then goto deep sleep)
|
#define MIN_VOLTAGE 10.0 // Min voltage for under voltage detection (then goto deep sleep)
|
||||||
#define POWER_FAIL_TIME 2 // in [ms] Accept min voltage until 2 x 1ms (for under voltage gaps by engine start)
|
#define POWER_FAIL_TIME 2 // in [ms] Accept min voltage until 2 x 1ms (for under voltage gaps by engine start)
|
||||||
// Touch buttons
|
// Touch buttons
|
||||||
@@ -70,92 +72,9 @@
|
|||||||
#define NUM_FLASH_LED 1 // Number of flash LED
|
#define NUM_FLASH_LED 1 // Number of flash LED
|
||||||
#define OBP_FLASH_LED 7 // GPIO port
|
#define OBP_FLASH_LED 7 // GPIO port
|
||||||
// Backlight LEDs (6x WS2812B)
|
// Backlight LEDs (6x WS2812B)
|
||||||
#define NUM_BACKLIGHT_LED 6 // Number of Backlight LEDs
|
#define NUM_BACKLIGHT_LED 6 // Numebr of Backlight LEDs
|
||||||
#define OBP_BACKLIGHT_LED 15 // GPIO port
|
#define OBP_BACKLIGHT_LED 15 // GPIO port
|
||||||
// Power Rail
|
// Power Rail
|
||||||
#define OBP_POWER_50 5 // 5.0V power rail
|
#define OBP_POWER_50 5 // 5.0V power rail
|
||||||
#endif
|
|
||||||
|
|
||||||
// Hardware configuration for OBP60 LIGHT
|
|
||||||
|
|
||||||
#ifdef HARDWARE_LIGHT
|
|
||||||
// Direction pin for RS485 NMEA0183
|
|
||||||
#define OBP_DIRECTION_PIN 8
|
|
||||||
// I2C
|
|
||||||
#define I2C_SPEED 10000UL // 10kHz clock speed on I2C bus
|
|
||||||
#define OBP_I2C_SDA 21
|
|
||||||
#define OBP_I2C_SCL 38
|
|
||||||
// DS1388 RTC
|
|
||||||
#define DS1388_I2C_ADDR 0x68 // Addr. 0x68
|
|
||||||
// BME280
|
|
||||||
#define BME280_I2C_ADDR 0x76 // Addr. 0x76 (0x77)
|
|
||||||
// BMP280
|
|
||||||
#define BMP280_I2C_ADDR 0x77 // Addr. 0x77 (0x76) Attention: Pull up resistor
|
|
||||||
// BMP085 / BMP180
|
|
||||||
#define BMP180_I2C_ADDR 0x77 // Addr. 0x77 (fix)
|
|
||||||
// SHT21 / HUT21
|
|
||||||
#define SHT21_I2C_ADDR 0x40 // Addr. 0x40 (fix)
|
|
||||||
// AS5600
|
|
||||||
#define AS5600_I2C_ADDR 0x36 // Addr. 0x36 (fix)
|
|
||||||
// INA219
|
|
||||||
#define SHUNT_VOLTAGE 0.075 // Shunt voltage in V by max. current (75mV)
|
|
||||||
#define INA219_I2C_ADDR1 0x40 // Addr. 0x41 (fix A0 = 5V, A1 = GND) for battery
|
|
||||||
#define INA219_I2C_ADDR2 0x41 // Addr. 0x44 (fix A0 = GND, A1 = 5V) for solar panels
|
|
||||||
#define INA219_I2C_ADDR3 0x45 // Addr. 0x45 (fix A0 = 5V, A1 = 5V) for generator
|
|
||||||
// INA226
|
|
||||||
#define INA226_I2C_ADDR1 0x41 // Addr. 0x41 (fix A0 = 5V, A1 = GND) for battery
|
|
||||||
#define INA226_I2C_ADDR2 0x44 // Addr. 0x44 (fix A0 = GND, A1 = 5V) for solar panels
|
|
||||||
#define INA226_I2C_ADDR3 0x45 // Addr. 0x45 (fix A0 = 5V, A1 = 5V) for generator
|
|
||||||
// Horter modules
|
|
||||||
#define PCF8574_I2C_ADDR1 0x20 // First digital out module
|
|
||||||
// FRAM (e.g. MB85RC256V)
|
|
||||||
#define FRAM_I2C_ADDR 0x50
|
|
||||||
// SPI (E-Ink display, Extern Bus)
|
|
||||||
#define OBP_SPI_CS 45
|
|
||||||
#define OBP_SPI_DC 46
|
|
||||||
#define OBP_SPI_RST 47
|
|
||||||
#define OBP_SPI_BUSY 48
|
|
||||||
#define OBP_SPI_CLK 12
|
|
||||||
#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)
|
|
||||||
// SPI SD-Card
|
|
||||||
#define SD_SPI_CS 10
|
|
||||||
#define SD_SPI_MOSI 40
|
|
||||||
#define SD_SPI_CLK 39
|
|
||||||
#define SD_SPI_MISO 13
|
|
||||||
|
|
||||||
// GPS (NEO-6M, NEO-M8N, ATGM336H)
|
|
||||||
#define OBP_GPS_RX 19
|
|
||||||
#define OBP_GPS_TX 20
|
|
||||||
// 1Wire (DS18B20)
|
|
||||||
#define OBP_1WIRE 17 // External 1Wire
|
|
||||||
// Buzzer
|
|
||||||
#define OBP_BUZZER 18
|
|
||||||
#define TONE1 1500 // 1500Hz
|
|
||||||
#define TONE2 2500 // 2500Hz
|
|
||||||
#define TONE3 3500 // 3500Hz
|
|
||||||
#define TONE4 4000 // 4000Hz
|
|
||||||
// Analog Input
|
|
||||||
#define OBP_ANALOG0 3 // Analog input for voltage power supply
|
|
||||||
#define MIN_VOLTAGE 10.0 // Min voltage for under voltage detection (then goto deep sleep)
|
|
||||||
#define POWER_FAIL_TIME 2 // in [ms] Accept min voltage until 2 x 1ms (for under voltage gaps by engine start)
|
|
||||||
// Buttons
|
|
||||||
#define UP 6 // Wheel up
|
|
||||||
#define DOWN 4 // Wheel down
|
|
||||||
#define CONF 5 // Wheel press
|
|
||||||
#define MENUE 2 // Button top
|
|
||||||
#define EXIT 1 // Button bottom
|
|
||||||
|
|
||||||
// Flash LED (1x WS2812B)
|
|
||||||
#define NUM_FLASH_LED 1 // Number of flash LED
|
|
||||||
#define OBP_FLASH_LED 10 // GPIO port
|
|
||||||
// Backlight LEDs (6x WS2812B)
|
|
||||||
#define NUM_BACKLIGHT_LED 6 // Number of Backlight LEDs
|
|
||||||
#define OBP_BACKLIGHT_LED 40 // GPIO port
|
|
||||||
// Power Rail
|
|
||||||
#define OBP_POWER_50 41 // Power LED
|
|
||||||
#define OBP_POWER_EPD 7 // ePaper power
|
|
||||||
#define OBP_POWER_SD 42 // SD card power
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,14 +14,12 @@ int keycode = 0; // Keycode of pressed key [0...8], 0 = nothing touched
|
|||||||
int keycode2 = 0; // Keycode of very short pressed key [0...8], 0 = nothing touched
|
int keycode2 = 0; // Keycode of very short pressed key [0...8], 0 = nothing touched
|
||||||
int keycodeold = 0; // Old keycode
|
int keycodeold = 0; // Old keycode
|
||||||
int keycodeold2 = 0; // Old keycode for short pressed key
|
int keycodeold2 = 0; // Old keycode for short pressed key
|
||||||
int keystatus = 0; // Status of key [0...11]
|
|
||||||
bool keyoff = false; // Disable all keys
|
bool keyoff = false; // Disable all keys
|
||||||
int keydelay = 250; // Delay after key pressed in [ms]
|
int keydelay = 250; // Delay after key pressed in [ms]
|
||||||
bool keylock = false; // Key lock after pressed key is valid (repeat protection by conginous pressing)
|
bool keylock = false; // Key lock after pressed key is valid (repeat protection by conginous pressing)
|
||||||
long starttime = 0; // Start time point for pressed key
|
long starttime = 0; // Start time point for pressed key
|
||||||
|
|
||||||
#ifdef HARDWARE_V21
|
|
||||||
// Keypad functions for original OBP60 hardware
|
|
||||||
int readKeypad(uint thSensitivity) {
|
int readKeypad(uint thSensitivity) {
|
||||||
|
|
||||||
// Touch sensor values
|
// Touch sensor values
|
||||||
@@ -31,7 +29,7 @@ long starttime = 0; // Start time point for pressed key
|
|||||||
// 170000 - Strong touched
|
// 170000 - Strong touched
|
||||||
uint32_t touchthreshold = (thSensitivity * -1200) + 170000; // thSensitivity 0...100%
|
uint32_t touchthreshold = (thSensitivity * -1200) + 170000; // thSensitivity 0...100%
|
||||||
|
|
||||||
keystatus = 0; // Status of key [0...11], 0 = processed, 1...8 = key 1..8, 9 = right swipe , 10 = left swipe, 11 keys disabled
|
int keystatus = 0; // Status of key [0...11], 0 = processed, 1...8 = key 1..8, 9 = right swipe , 10 = left swipe, 11 keys disabled
|
||||||
keycode = 0;
|
keycode = 0;
|
||||||
|
|
||||||
// Read key code
|
// Read key code
|
||||||
@@ -178,59 +176,5 @@ long starttime = 0; // Start time point for pressed key
|
|||||||
|
|
||||||
return keystatus;
|
return keystatus;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef HARDWARE_LIGHT
|
|
||||||
// Keypad functions for OBP60 clone (thSensitivity is inactiv)
|
|
||||||
int readKeypad(uint thSensitivity) {
|
|
||||||
pinMode(UP, INPUT);
|
|
||||||
pinMode(DOWN, INPUT);
|
|
||||||
pinMode(CONF, INPUT);
|
|
||||||
pinMode(MENUE, INPUT);
|
|
||||||
pinMode(EXIT, INPUT);
|
|
||||||
|
|
||||||
// Read key code
|
|
||||||
if(digitalRead(UP) == LOW){
|
|
||||||
keycode = 10; // Left swipe
|
|
||||||
}
|
|
||||||
else if(digitalRead(DOWN) == LOW){
|
|
||||||
keycode = 9; // Right swipe
|
|
||||||
}
|
|
||||||
else if(digitalRead(CONF) == LOW){
|
|
||||||
keycode = 3; // Key 3
|
|
||||||
}
|
|
||||||
else if(digitalRead(MENUE) == LOW){
|
|
||||||
keycode = 1; // Key 1
|
|
||||||
}
|
|
||||||
else if(digitalRead(EXIT) == LOW){
|
|
||||||
keycode = 2; // Key 2
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
keycode = 0; // No key activ
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect key
|
|
||||||
if (keycode > 0 ){
|
|
||||||
if(keycode != keycodeold){
|
|
||||||
starttime = millis(); // Start key pressed
|
|
||||||
keycodeold = keycode;
|
|
||||||
}
|
|
||||||
// If key pressed longer than 200ms
|
|
||||||
if(millis() > starttime + 200 && keycode == keycodeold) {
|
|
||||||
keystatus = keycode;
|
|
||||||
// Copy keycode
|
|
||||||
keycodeold = keycode;
|
|
||||||
delay(keydelay);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
keycode = 0;
|
|
||||||
keycodeold = 0;
|
|
||||||
keystatus = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return keystatus;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -456,7 +456,7 @@ void sensorTask(void *param){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send supply voltage value all 1s
|
// Send supplay voltage value all 1s
|
||||||
if(millis() > starttime5 + 1000 && String(powsensor1) == "off"){
|
if(millis() > starttime5 + 1000 && String(powsensor1) == "off"){
|
||||||
starttime5 = millis();
|
starttime5 = millis();
|
||||||
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20
|
sensors.batteryVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // Vin = 1/20
|
||||||
|
|||||||
192
lib/obp60task/PageApparentWind.cpp
Normal file
192
lib/obp60task/PageApparentWind.cpp
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
#ifdef BOARD_OBP60S3
|
||||||
|
|
||||||
|
#include "Pagedata.h"
|
||||||
|
#include "OBP60Extensions.h"
|
||||||
|
|
||||||
|
class PageApparentWind : public Page
|
||||||
|
{
|
||||||
|
bool keylock = false; // Keylock
|
||||||
|
int16_t lp = 80; // Pointer length
|
||||||
|
|
||||||
|
public:
|
||||||
|
PageApparentWind(CommonData &common){
|
||||||
|
common.logger->logDebug(GwLog::LOG,"Show PageApparentWind");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key functions
|
||||||
|
virtual int handleKey(int key){
|
||||||
|
// Reduce instrument size
|
||||||
|
if(key == 2){ // Code for reduce
|
||||||
|
lp = lp - 10;
|
||||||
|
if(lp < 10){
|
||||||
|
lp = 10;
|
||||||
|
}
|
||||||
|
return 0; // Commit the key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enlarge instrument size
|
||||||
|
if(key == 5){ // Code for enlarge
|
||||||
|
lp = lp + 10;
|
||||||
|
if(lp > 80){
|
||||||
|
lp = 80;
|
||||||
|
}
|
||||||
|
return 0; // Commit the key
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keylock function
|
||||||
|
if(key == 11){ // Code for keylock
|
||||||
|
keylock = !keylock; // Toggle keylock
|
||||||
|
return 0; // Commit the key
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void displayPage(CommonData &commonData, PageData &pageData)
|
||||||
|
{
|
||||||
|
GwConfigHandler *config = commonData.config;
|
||||||
|
GwLog *logger=commonData.logger;
|
||||||
|
|
||||||
|
static String svalue1old = "";
|
||||||
|
static String unit1old = "";
|
||||||
|
static String svalue2old = "";
|
||||||
|
static String unit2old = "";
|
||||||
|
|
||||||
|
// Get config data
|
||||||
|
String lengthformat = config->getString(config->lengthFormat);
|
||||||
|
// bool simulation = config->getBool(config->useSimuData);
|
||||||
|
bool holdvalues = config->getBool(config->holdvalues);
|
||||||
|
String flashLED = config->getString(config->flashLED);
|
||||||
|
String backlightMode = config->getString(config->backlight);
|
||||||
|
|
||||||
|
// Get boat values for AWS
|
||||||
|
GwApi::BoatValue *bvalue1 = pageData.values[0]; // First element in list (only one value by PageOneValue)
|
||||||
|
String name1 = bvalue1->getName().c_str(); // Value name
|
||||||
|
name1 = name1.substring(0, 6); // String length limit for value name
|
||||||
|
double value1 = bvalue1->value; // Value as double in SI unit
|
||||||
|
// bool valid1 = bvalue1->valid; // Valid information
|
||||||
|
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
// Get boat values for AWD
|
||||||
|
GwApi::BoatValue *bvalue2 = pageData.values[1]; // First element in list (only one value by PageOneValue)
|
||||||
|
String name2 = bvalue2->getName().c_str(); // Value name
|
||||||
|
name2 = name2.substring(0, 6); // String length limit for value name
|
||||||
|
double value2 = bvalue2->value; // Value as double in SI unit
|
||||||
|
// bool valid2 = bvalue2->valid; // Valid information
|
||||||
|
String svalue2 = formatValue(bvalue2, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
||||||
|
String unit2 = formatValue(bvalue2, commonData).unit; // Unit of value
|
||||||
|
|
||||||
|
// Optical warning by limit violation (unused)
|
||||||
|
if(String(flashLED) == "Limit Violation"){
|
||||||
|
setBlinkingLED(false);
|
||||||
|
setFlashLED(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logging boat values
|
||||||
|
if (bvalue1 == NULL) return;
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageApparentWind, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
||||||
|
|
||||||
|
// Draw page
|
||||||
|
//***********************************************************
|
||||||
|
|
||||||
|
// Set display in partial refresh mode
|
||||||
|
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||||
|
|
||||||
|
getdisplay().setTextColor(commonData.fgcolor);
|
||||||
|
|
||||||
|
// Show values AWS
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold20pt7b);
|
||||||
|
getdisplay().setCursor(20, 50);
|
||||||
|
if(holdvalues == false){
|
||||||
|
getdisplay().print(name1); // Value name
|
||||||
|
getdisplay().print(": ");
|
||||||
|
getdisplay().print(svalue1); // Value
|
||||||
|
getdisplay().print(" ");
|
||||||
|
getdisplay().print(unit1); // Unit
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
getdisplay().print(name1); // Value name
|
||||||
|
getdisplay().print(": ");
|
||||||
|
getdisplay().print(svalue1old); // Value old
|
||||||
|
getdisplay().print(" ");
|
||||||
|
getdisplay().print(unit1old); // Unit old
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show values AWD
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold20pt7b);
|
||||||
|
getdisplay().setCursor(20, 260);
|
||||||
|
if(holdvalues == false){
|
||||||
|
getdisplay().print(name2); // Value name
|
||||||
|
getdisplay().print(": ");
|
||||||
|
getdisplay().print(svalue2); // Value
|
||||||
|
getdisplay().print(" ");
|
||||||
|
getdisplay().print(unit2); // Unit
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
getdisplay().print(name2); // Value name
|
||||||
|
getdisplay().print(": ");
|
||||||
|
getdisplay().print(svalue2old); // Value old
|
||||||
|
getdisplay().print(" ");
|
||||||
|
getdisplay().print(unit2old); // Unit old
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw wind pointer
|
||||||
|
static int16_t x0 = 200; // Center point
|
||||||
|
static int16_t y0 = 145;
|
||||||
|
static int16_t x1 = x0; // Start point for pointer
|
||||||
|
static int16_t y1 = y0;
|
||||||
|
static int16_t x2 = x0; // End point for pointer
|
||||||
|
static int16_t y2 = y0;
|
||||||
|
|
||||||
|
//Draw instrument
|
||||||
|
getdisplay().fillCircle(x0, y0, lp + 5, commonData.fgcolor);
|
||||||
|
getdisplay().fillCircle(x0, y0, lp + 1, commonData.bgcolor);
|
||||||
|
|
||||||
|
// Calculation end point of pointer
|
||||||
|
value2 = value2 - 3.14 / 2;
|
||||||
|
x1 = x0 + cos(value2) * lp * 0.6;
|
||||||
|
y1 = y0 + sin(value2) * lp * 0.6;
|
||||||
|
x2 = x0 + cos(value2) * lp;
|
||||||
|
y2 = y0 + sin(value2) * lp;
|
||||||
|
getdisplay().drawLine(x1, y1, x2, y2, commonData.fgcolor);
|
||||||
|
|
||||||
|
// Key Layout
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
|
if(keylock == false){
|
||||||
|
getdisplay().setCursor(130, 290);
|
||||||
|
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
|
||||||
|
if(String(backlightMode) == "Control by Key"){ // Key for illumination
|
||||||
|
getdisplay().setCursor(343, 290);
|
||||||
|
getdisplay().print("[ILUM]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
getdisplay().setCursor(130, 290);
|
||||||
|
getdisplay().print(" [ Keylock active ]");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
static Page *createPage(CommonData &common){
|
||||||
|
return new PageApparentWind(common);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* with the code below we make this page known to the PageTask
|
||||||
|
* we give it a type (name) that can be selected in the config
|
||||||
|
* we define which function is to be called
|
||||||
|
* and we provide the number of user parameters we expect (0 here)
|
||||||
|
* and will will provide the names of the fixed values we need
|
||||||
|
*/
|
||||||
|
PageDescription registerPageApparentWind(
|
||||||
|
"ApparentWind", // Page name
|
||||||
|
createPage, // Action
|
||||||
|
0, // Number of bus values depends on selection in Web configuration
|
||||||
|
{"AWS","AWA"}, // Bus values we need in the page
|
||||||
|
true // Show display header on/off
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
||||||
228
lib/obp60task/PageBarograph.cpp
Normal file
228
lib/obp60task/PageBarograph.cpp
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
#ifdef BOARD_OBP60S3
|
||||||
|
|
||||||
|
#include "Pagedata.h"
|
||||||
|
#include "OBP60Extensions.h"
|
||||||
|
|
||||||
|
class PageBarograph : public Page{
|
||||||
|
|
||||||
|
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){
|
||||||
|
common.logger->logDebug(GwLog::LOG,"Instantiate PageBarograph");
|
||||||
|
// Get config data
|
||||||
|
flashLED = common.config->getString(common.config->flashLED);
|
||||||
|
useenvsensor = common.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
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void displayPage(CommonData &commonData, PageData &pageData){
|
||||||
|
GwLog *logger=commonData.logger;
|
||||||
|
|
||||||
|
// Optical warning by limit violation (unused)
|
||||||
|
if (String(flashLED) == "Limit Violation") {
|
||||||
|
setBlinkingLED(false);
|
||||||
|
setFlashLED(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Logging boat values
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageBarograph");
|
||||||
|
|
||||||
|
// Draw page
|
||||||
|
//***********************************************************
|
||||||
|
|
||||||
|
// Set display in partial refresh mode
|
||||||
|
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||||
|
|
||||||
|
// Frames
|
||||||
|
getdisplay().fillRect(0, 75, 400, 2, commonData.fgcolor); // fillRect: x, y, w, h
|
||||||
|
getdisplay().fillRect(130, 20, 2, 55, commonData.fgcolor);
|
||||||
|
getdisplay().fillRect(270, 20, 2, 55, commonData.fgcolor);
|
||||||
|
getdisplay().fillRect(325, 20, 2, 55, commonData.fgcolor);
|
||||||
|
|
||||||
|
getdisplay().setTextColor(commonData.fgcolor);
|
||||||
|
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
|
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
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold16pt7b);
|
||||||
|
drawTextCenter(200, 40, String(commonData.data.airPressure / 100, 1));
|
||||||
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
|
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;
|
||||||
|
|
||||||
|
// getdisplay().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);
|
||||||
|
getdisplay().drawLine(x0 - i * xstep, y0, x0 - i * xstep, y0 - h, commonData.fgcolor);
|
||||||
|
drawTextCenter(x0 - i * xstep, y0 - 10, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
// y-axis
|
||||||
|
getdisplay().drawLine(x0 + 5, y0, x0 + 5, y0 - h, commonData.fgcolor); // drawLine: x1, y1, x2, y2
|
||||||
|
getdisplay().drawLine(x0 - w, y0, x0 - w, y0 - h, commonData.fgcolor);
|
||||||
|
getdisplay().drawLine(x0 - w - 5, y0, x0 - w - 5, y0 - h, commonData.fgcolor);
|
||||||
|
getdisplay().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
|
||||||
|
getdisplay().setCursor(x0 + 10, y + 5);
|
||||||
|
getdisplay().print(String(ys));
|
||||||
|
getdisplay().drawLine(x0 + 5, y, x0 - w - 5, y, commonData.fgcolor);
|
||||||
|
} else {
|
||||||
|
// small step, only short lines left and right
|
||||||
|
getdisplay().drawLine(x0 + 5, y, x0, y, commonData.fgcolor);
|
||||||
|
getdisplay().drawLine(x0 - w - 5, y, x0 - w, y, commonData.fgcolor);
|
||||||
|
}
|
||||||
|
y -= dy;
|
||||||
|
ys += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update display
|
||||||
|
getdisplay().nextPage(); // Partial update (fast)
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
@@ -22,6 +22,43 @@ TODO
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
struct Point {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
};
|
||||||
|
|
||||||
|
Point rotatePoint(const Point& origin, const Point& p, double angle) {
|
||||||
|
// rotate poind around origin by degrees
|
||||||
|
Point rotated;
|
||||||
|
double phi = angle * M_PI / 180.0;
|
||||||
|
double dx = p.x - origin.x;
|
||||||
|
double dy = p.y - origin.y;
|
||||||
|
rotated.x = origin.x + cos(phi) * dx - sin(phi) * dy;
|
||||||
|
rotated.y = origin.y + sin(phi) * dx + cos(phi) * dy;
|
||||||
|
return rotated;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle) {
|
||||||
|
std::vector<Point> rotatedPoints;
|
||||||
|
for (const auto& p : pts) {
|
||||||
|
rotatedPoints.push_back(rotatePoint(origin, p, angle));
|
||||||
|
}
|
||||||
|
return rotatedPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fillPoly4(const std::vector<Point>& p4, uint16_t color) {
|
||||||
|
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[1].x, p4[1].y, p4[2].x, p4[2].y, color);
|
||||||
|
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[2].x, p4[2].y, p4[3].x, p4[3].y, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawTextCentered(int16_t tx, int16_t ty, String text) {
|
||||||
|
int16_t x, y;
|
||||||
|
uint16_t w, h;
|
||||||
|
getdisplay().getTextBounds(text, 0, 0, &x, &y, &w, &h);
|
||||||
|
getdisplay().setCursor(tx - w / 2, ty + h / 2);
|
||||||
|
getdisplay().print(text);
|
||||||
|
}
|
||||||
|
|
||||||
#define fuel_width 16
|
#define fuel_width 16
|
||||||
#define fuel_height 16
|
#define fuel_height 16
|
||||||
static unsigned char fuel_bits[] = {
|
static unsigned char fuel_bits[] = {
|
||||||
@@ -59,13 +96,12 @@ static unsigned char gasoline_bits[] = {
|
|||||||
|
|
||||||
class PageFluid : public Page{
|
class PageFluid : public Page{
|
||||||
bool keylock = false; // Keylock
|
bool keylock = false; // Keylock
|
||||||
bool holdvalues = false;
|
|
||||||
int fluidtype;
|
int fluidtype;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PageFluid(CommonData &common){
|
PageFluid(CommonData &common){
|
||||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageFluid");
|
common.logger->logDebug(GwLog::LOG,"Show PageFluid");
|
||||||
holdvalues = common.config->getBool(common.config->holdvalues);
|
fluidtype = common.config->getInt("page" + String(common.data.actpage) + "fluid", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual int handleKey(int key){
|
virtual int handleKey(int key){
|
||||||
@@ -76,18 +112,10 @@ class PageFluid : public Page{
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void displayNew(CommonData &commonData, PageData &pageData){
|
|
||||||
fluidtype = commonData.config->getInt("page" + String(pageData.pageNumber) + "fluid", 0);
|
|
||||||
commonData.logger->logDebug(GwLog::LOG,"New PageFluid: fluidtype=%d", fluidtype);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void displayPage(CommonData &commonData, PageData &pageData){
|
virtual void displayPage(CommonData &commonData, PageData &pageData){
|
||||||
GwConfigHandler *config = commonData.config;
|
GwConfigHandler *config = commonData.config;
|
||||||
GwLog *logger=commonData.logger;
|
GwLog *logger=commonData.logger;
|
||||||
|
|
||||||
// Old values for hold function
|
|
||||||
static double value1old;
|
|
||||||
|
|
||||||
// Get config data
|
// Get config data
|
||||||
String flashLED = config->getString(config->flashLED);
|
String flashLED = config->getString(config->flashLED);
|
||||||
String backlightMode = config->getString(config->backlight);
|
String backlightMode = config->getString(config->backlight);
|
||||||
@@ -98,14 +126,13 @@ class PageFluid : public Page{
|
|||||||
setFlashLED(false);
|
setFlashLED(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Logging boat values
|
||||||
|
LOG_DEBUG(GwLog::LOG,"Drawing at PageFluid");
|
||||||
|
|
||||||
GwApi::BoatValue *bvalue1 = pageData.values[0];
|
GwApi::BoatValue *bvalue1 = pageData.values[0];
|
||||||
String name1 = bvalue1->getName();
|
String name1 = bvalue1->getName();
|
||||||
if (holdvalues and bvalue1->valid) {
|
double value1 = bvalue1->value;
|
||||||
value1old = bvalue1->value;
|
bool valid1 = bvalue1->valid;
|
||||||
}
|
|
||||||
|
|
||||||
// Logging boat values
|
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageFluid: value=%f", bvalue1->value);
|
|
||||||
|
|
||||||
// Draw page
|
// Draw page
|
||||||
//***********************************************************
|
//***********************************************************
|
||||||
@@ -144,7 +171,7 @@ class PageFluid : public Page{
|
|||||||
} else {
|
} else {
|
||||||
strcpy(buffer, "---");
|
strcpy(buffer, "---");
|
||||||
}
|
}
|
||||||
drawTextCenter(c.x, c.y + r - 20, String(buffer));
|
drawTextCentered(c.x, c.y + r - 20, String(buffer));
|
||||||
|
|
||||||
// draw symbol (as bitmap)
|
// draw symbol (as bitmap)
|
||||||
switch (fluidtype) {
|
switch (fluidtype) {
|
||||||
@@ -170,18 +197,18 @@ class PageFluid : public Page{
|
|||||||
// scale texts
|
// scale texts
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
p = {c.x, c.y - r + 30};
|
p = {c.x, c.y - r + 30};
|
||||||
drawTextCenter(p.x, p.y, "1/2");
|
drawTextCentered(p.x, p.y, "1/2");
|
||||||
pr = rotatePoint(c, p, -60);
|
pr = rotatePoint(c, p, -60);
|
||||||
drawTextCenter(pr.x, pr.y, "1/4");
|
drawTextCentered(pr.x, pr.y, "1/4");
|
||||||
pr = rotatePoint(c, p, 60);
|
pr = rotatePoint(c, p, 60);
|
||||||
drawTextCenter(pr.x, pr.y, "3/4");
|
drawTextCentered(pr.x, pr.y, "3/4");
|
||||||
|
|
||||||
// empty and full
|
// empty and full
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
||||||
p = rotatePoint(c, {c.x, c.y - r + 30}, -130);
|
p = rotatePoint(c, {c.x, c.y - r + 30}, -130);
|
||||||
drawTextCenter(p.x, p.y, "E");
|
drawTextCentered(p.x, p.y, "E");
|
||||||
p = rotatePoint(c, {c.x, c.y - r + 30}, 130);
|
p = rotatePoint(c, {c.x, c.y - r + 30}, 130);
|
||||||
drawTextCenter(p.x, p.y, "F");
|
drawTextCentered(p.x, p.y, "F");
|
||||||
|
|
||||||
// lines
|
// lines
|
||||||
std::vector<Point> pts = {
|
std::vector<Point> pts = {
|
||||||
|
|||||||
@@ -342,9 +342,9 @@ static Page *createPage(CommonData &common){
|
|||||||
PageDescription registerPageRollPitch(
|
PageDescription registerPageRollPitch(
|
||||||
"RollPitch", // Page name
|
"RollPitch", // Page name
|
||||||
createPage, // Action
|
createPage, // Action
|
||||||
2, // Number of bus values depends on selection in Web configuration
|
0, // Number of bus values depends on selection in Web configuration
|
||||||
// {"xdrROLL", "xdrPTCH"},// Bus values we need in the page
|
// {"xdrROLL", "xdrPTCH"},// Bus values we need in the page
|
||||||
//{"xdrRoll", "xdrPitch"},// Bus values we need in the page
|
{"xdrRoll", "xdrPitch"},// Bus values we need in the page
|
||||||
true // Show display header on/off
|
true // Show display header on/off
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -8,44 +8,25 @@ class PageVoltage : public Page
|
|||||||
{
|
{
|
||||||
bool init = false; // Marker for init done
|
bool init = false; // Marker for init done
|
||||||
bool keylock = false; // Keylock
|
bool keylock = false; // Keylock
|
||||||
uint8_t average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s
|
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
|
bool trend = true; // Trend indicator [0|1], 0=off, 1=on
|
||||||
double raw = 0;
|
double raw = 0;
|
||||||
char mode = 'D'; // display mode (A)nalog | (D)igital
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PageVoltage(CommonData &common){
|
PageVoltage(CommonData &common){
|
||||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageVoltage");
|
common.logger->logDebug(GwLog::LOG,"Show PageVoltage");
|
||||||
if (hasFRAM) {
|
|
||||||
average = fram.read(FRAM_VOLTAGE_AVG);
|
|
||||||
trend = fram.read(FRAM_VOLTAGE_TREND);
|
|
||||||
mode = fram.read(FRAM_VOLTAGE_MODE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
virtual int handleKey(int key){
|
virtual int handleKey(int key){
|
||||||
// Change average
|
// Change average
|
||||||
if(key == 1){
|
if(key == 1){
|
||||||
average ++;
|
average ++;
|
||||||
average = average % 4; // Modulo 4
|
average = average % 4; // Modulo 4
|
||||||
if (hasFRAM) fram.write(FRAM_VOLTAGE_AVG, average);
|
|
||||||
return 0; // Commit the key
|
return 0; // Commit the key
|
||||||
}
|
}
|
||||||
|
|
||||||
// Switch display mode
|
|
||||||
if (key == 2) {
|
|
||||||
if (mode == 'A') {
|
|
||||||
mode = 'D';
|
|
||||||
} else {
|
|
||||||
mode = 'A';
|
|
||||||
}
|
|
||||||
if (hasFRAM) fram.write(FRAM_VOLTAGE_MODE, mode);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trend indicator
|
// Trend indicator
|
||||||
if(key == 5){
|
if(key == 5){
|
||||||
trend = !trend;
|
trend = !trend;
|
||||||
if (hasFRAM) fram.write(FRAM_VOLTAGE_TREND, trend);
|
|
||||||
return 0; // Commit the key
|
return 0; // Commit the key
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,41 +38,6 @@ public:
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void printAvg(int avg, uint16_t x, uint16_t y, bool prefix) {
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
|
||||||
getdisplay().setCursor(x, y);
|
|
||||||
if (prefix) {
|
|
||||||
getdisplay().print("Avg: ");
|
|
||||||
}
|
|
||||||
switch (average) {
|
|
||||||
case 0:
|
|
||||||
getdisplay().print("1s");
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
getdisplay().print("10s");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
getdisplay().print("60s");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
getdisplay().print("300s");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
getdisplay().print("1s");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void printVoltageSymbol(uint16_t x, uint16_t y, uint16_t color) {
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold16pt7b);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void displayPage(CommonData &commonData, PageData &pageData)
|
virtual void displayPage(CommonData &commonData, PageData &pageData)
|
||||||
{
|
{
|
||||||
GwConfigHandler *config = commonData.config;
|
GwConfigHandler *config = commonData.config;
|
||||||
@@ -189,9 +135,6 @@ public:
|
|||||||
// Set display in partial refresh mode
|
// Set display in partial refresh mode
|
||||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||||
|
|
||||||
if (mode == 'D') {
|
|
||||||
// Display mode digital
|
|
||||||
|
|
||||||
// Show name
|
// Show name
|
||||||
getdisplay().setTextColor(commonData.fgcolor);
|
getdisplay().setTextColor(commonData.fgcolor);
|
||||||
getdisplay().setFont(&Ubuntu_Bold32pt7b);
|
getdisplay().setFont(&Ubuntu_Bold32pt7b);
|
||||||
@@ -209,7 +152,25 @@ public:
|
|||||||
getdisplay().print(batType);
|
getdisplay().print(batType);
|
||||||
|
|
||||||
// Show average settings
|
// Show average settings
|
||||||
printAvg(average, 320, 84, true);
|
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||||
|
getdisplay().setCursor(320, 84);
|
||||||
|
switch (average) {
|
||||||
|
case 0:
|
||||||
|
getdisplay().print("Avg: 1s");
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
getdisplay().print("Avg: 10s");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
getdisplay().print("Avg: 60s");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
getdisplay().print("Avg: 300s");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
getdisplay().print("Avg: 1s");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Reading bus data or using simulation data
|
// Reading bus data or using simulation data
|
||||||
getdisplay().setFont(&DSEG7Classic_BoldItalic60pt7b);
|
getdisplay().setFont(&DSEG7Classic_BoldItalic60pt7b);
|
||||||
@@ -260,111 +221,6 @@ public:
|
|||||||
getdisplay().fillRect(310, 240, 40, 120, commonData.bgcolor); // Clear area
|
getdisplay().fillRect(310, 240, 40, 120, commonData.bgcolor); // Clear area
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Display mode analog
|
|
||||||
|
|
||||||
// center
|
|
||||||
Point c = {260, 270};
|
|
||||||
uint8_t r = 240;
|
|
||||||
|
|
||||||
Point p1, p2;
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Scale
|
|
||||||
// angle to voltage scale mapping
|
|
||||||
std::map<int, String> mapping = {
|
|
||||||
{15, "10"}, {30, "11"}, {45, "12"}, {60, "13"}, {75, "14"}
|
|
||||||
};
|
|
||||||
pts = {
|
|
||||||
{c.x - r, c.y - 1},
|
|
||||||
{c.x - r + 12, c.y - 1},
|
|
||||||
{c.x - r + 12, c.y + 1},
|
|
||||||
{c.x - r, c.y + 1}
|
|
||||||
};
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold10pt7b);
|
|
||||||
for (int angle = 3; angle < 90; angle += 3) {
|
|
||||||
if (angle % 15 == 0) {
|
|
||||||
fillPoly4(rotatePoints(c, pts, angle), commonData.fgcolor);
|
|
||||||
p1 = rotatePoint(c, {c.x - r + 30, c.y}, angle);
|
|
||||||
drawTextCenter(p1.x, p1.y, mapping[angle]);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pointer rotation and limits
|
|
||||||
double angle;
|
|
||||||
if (not valid1) {
|
|
||||||
angle = -0.5;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (value1 > 15.0) {
|
|
||||||
angle = 91;
|
|
||||||
}
|
|
||||||
else if (value1 <= 9) {
|
|
||||||
angle = -0.5;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
angle = (value1 - 9) * 15;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pointer
|
|
||||||
// thick part
|
|
||||||
pts = {
|
|
||||||
{c.x - 2, c.y + 3},
|
|
||||||
{c.x - r + 38, c.y + 2},
|
|
||||||
{c.x - r + 38, c.y - 2},
|
|
||||||
{c.x - 2, c.y - 3}
|
|
||||||
};
|
|
||||||
fillPoly4(rotatePoints(c, pts, angle), commonData.fgcolor);
|
|
||||||
// thin part
|
|
||||||
pts = {
|
|
||||||
{c.x - r + 40, c.y + 1},
|
|
||||||
{c.x - r + 5, c.y + 1},
|
|
||||||
{c.x - r + 5, c.y -1},
|
|
||||||
{c.x - r + 40, c.y - 1},
|
|
||||||
};
|
|
||||||
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);
|
|
||||||
|
|
||||||
// Symbol
|
|
||||||
printVoltageSymbol(40, 60, commonData.fgcolor);
|
|
||||||
|
|
||||||
// Additional information at right side
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
|
||||||
getdisplay().setCursor(300, 60);
|
|
||||||
getdisplay().print("Source:");
|
|
||||||
getdisplay().setCursor(300, 80);
|
|
||||||
getdisplay().print(name1);
|
|
||||||
|
|
||||||
getdisplay().setCursor(300, 110);
|
|
||||||
getdisplay().print("Type:");
|
|
||||||
getdisplay().setCursor(300, 130);
|
|
||||||
getdisplay().print(batType);
|
|
||||||
|
|
||||||
getdisplay().setCursor(300, 160);
|
|
||||||
getdisplay().print("Avg:");
|
|
||||||
printAvg(average, 300, 180, false);
|
|
||||||
|
|
||||||
// FRAM indicator
|
|
||||||
if (hasFRAM) {
|
|
||||||
getdisplay().drawXBitmap(300, 240, fram_bits, fram_width, fram_height, commonData.fgcolor);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key Layout
|
// Key Layout
|
||||||
getdisplay().setTextColor(commonData.fgcolor);
|
getdisplay().setTextColor(commonData.fgcolor);
|
||||||
@@ -372,8 +228,6 @@ public:
|
|||||||
if(keylock == false){
|
if(keylock == false){
|
||||||
getdisplay().setCursor(10, 290);
|
getdisplay().setCursor(10, 290);
|
||||||
getdisplay().print("[AVG]");
|
getdisplay().print("[AVG]");
|
||||||
getdisplay().setCursor(62, 290);
|
|
||||||
getdisplay().print("[MODE]");
|
|
||||||
getdisplay().setCursor(130, 290);
|
getdisplay().setCursor(130, 290);
|
||||||
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
|
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
|
||||||
getdisplay().setCursor(293, 290);
|
getdisplay().setCursor(293, 290);
|
||||||
|
|||||||
@@ -1,650 +0,0 @@
|
|||||||
#ifdef BOARD_OBP60S3
|
|
||||||
|
|
||||||
#include "Pagedata.h"
|
|
||||||
#include "OBP60Extensions.h"
|
|
||||||
#include "N2kMessages.h"
|
|
||||||
|
|
||||||
#define front_width 120
|
|
||||||
#define front_height 162
|
|
||||||
static unsigned char front_bits[] PROGMEM = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x03,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xf0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xf0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xfc, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf7, 0x7f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
|
|
||||||
0xff, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xc0, 0xff, 0xe1, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xc1, 0xff, 0x01, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x80, 0xff,
|
|
||||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
|
|
||||||
0x7f, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xf0, 0x7f, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0xfe, 0x0f, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0xfe,
|
|
||||||
0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
|
|
||||||
0x1f, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xfc, 0x0f, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0xf8, 0x3f, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0xf0,
|
|
||||||
0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
|
||||||
0x03, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x80, 0xff, 0x03, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x80,
|
|
||||||
0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
|
|
||||||
0x00, 0x00, 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x00,
|
|
||||||
0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f,
|
|
||||||
0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,
|
|
||||||
0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07,
|
|
||||||
0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00,
|
|
||||||
0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xfe, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x3f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xfe, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80,
|
|
||||||
0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
|
|
||||||
0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0,
|
|
||||||
0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
|
|
||||||
0x07, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xf0,
|
|
||||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
|
|
||||||
0x1f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xfc,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x7f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x3f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xfc, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0x80, 0x0f,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00,
|
|
||||||
0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xf0, 0x03, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x03,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00,
|
|
||||||
0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xe0, 0x07, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0xf0, 0x01,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00,
|
|
||||||
0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x80, 0x0f, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x78, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
|
|
||||||
0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x3e, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x3c, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
|
|
||||||
0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x7c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x0e, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00,
|
|
||||||
0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xf8, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x07, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01,
|
|
||||||
0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xe0, 0x01, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x80, 0x03, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03,
|
|
||||||
0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0xc0, 0x03, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xc0, 0x01, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07,
|
|
||||||
0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x80, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0xe0, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
|
|
||||||
0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x0f, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x70, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
|
|
||||||
0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x0e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
|
|
||||||
0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x1c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x18, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
|
|
||||||
0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1c, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
|
|
||||||
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x38, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0c, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
|
|
||||||
0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x70, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x0e, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
|
|
||||||
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
|
|
||||||
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
|
|
||||||
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
|
|
||||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
|
|
||||||
0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xc0 };
|
|
||||||
|
|
||||||
class PageWind : public Page
|
|
||||||
{
|
|
||||||
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){
|
|
||||||
common.logger->logDebug(GwLog::LOG,"Instantiate PageWind");
|
|
||||||
if (hasFRAM) {
|
|
||||||
lp = fram.read(FRAM_WIND_SIZE);
|
|
||||||
source = fram.read(FRAM_WIND_SRC);
|
|
||||||
mode = fram.read(FRAM_WIND_MODE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key functions
|
|
||||||
virtual int handleKey(int key){
|
|
||||||
|
|
||||||
if(key == 1){ // Mode switch
|
|
||||||
if(mode == 'N'){
|
|
||||||
mode = 'L';
|
|
||||||
} else if (mode == 'L') {
|
|
||||||
mode = 'X';
|
|
||||||
} else {
|
|
||||||
mode = 'N';
|
|
||||||
}
|
|
||||||
if (hasFRAM) fram.write(FRAM_WIND_MODE, mode);
|
|
||||||
return 0; // Commit the key
|
|
||||||
}
|
|
||||||
|
|
||||||
if(key == 3){ // Source switch
|
|
||||||
if(source == 'A'){
|
|
||||||
source = 'T';
|
|
||||||
} else {
|
|
||||||
source = 'A';
|
|
||||||
}
|
|
||||||
if (hasFRAM) fram.write(FRAM_WIND_SRC, source);
|
|
||||||
return 0; // Commit the key
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reduce instrument size
|
|
||||||
if(key == 2 && mode == 'X'){ // Code for reduce
|
|
||||||
lp = lp - 10;
|
|
||||||
if(lp < 10){
|
|
||||||
lp = 10;
|
|
||||||
}
|
|
||||||
if (hasFRAM) fram.write(FRAM_WIND_SIZE, lp);
|
|
||||||
return 0; // Commit the key
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enlarge instrument size
|
|
||||||
if(key == 5 && mode == 'X'){ // Code for enlarge
|
|
||||||
lp = lp + 10;
|
|
||||||
if(lp > 80){
|
|
||||||
lp = 80;
|
|
||||||
}
|
|
||||||
if (hasFRAM) fram.write(FRAM_WIND_SIZE, lp);
|
|
||||||
return 0; // Commit the key
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keylock function
|
|
||||||
if(key == 11){ // Code for keylock
|
|
||||||
keylock = !keylock; // Toggle keylock
|
|
||||||
return 0; // Commit the key
|
|
||||||
}
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void displayPage(CommonData &commonData, PageData &pageData)
|
|
||||||
{
|
|
||||||
GwConfigHandler *config = commonData.config;
|
|
||||||
GwLog *logger=commonData.logger;
|
|
||||||
|
|
||||||
static String svalue1old = "";
|
|
||||||
static String unit1old = "";
|
|
||||||
static String svalue2old = "";
|
|
||||||
static String unit2old = "";
|
|
||||||
|
|
||||||
// Get config data
|
|
||||||
String lengthformat = config->getString(config->lengthFormat);
|
|
||||||
// bool simulation = config->getBool(config->useSimuData);
|
|
||||||
bool holdvalues = config->getBool(config->holdvalues);
|
|
||||||
String flashLED = config->getString(config->flashLED);
|
|
||||||
String backlightMode = config->getString(config->backlight);
|
|
||||||
|
|
||||||
GwApi::BoatValue *bvalue1; // Value 1 for speed on top
|
|
||||||
GwApi::BoatValue *bvalue2; // Value 2 for angle on bottom
|
|
||||||
|
|
||||||
// Get boat values for speed (AWS/TWS)
|
|
||||||
if (source == 'A') {
|
|
||||||
bvalue1 = pageData.values[0];
|
|
||||||
} else {
|
|
||||||
bvalue1 = pageData.values[2];
|
|
||||||
}
|
|
||||||
String name1 = bvalue1->getName().c_str(); // Value name
|
|
||||||
name1 = name1.substring(0, 6); // String length limit for value name
|
|
||||||
double value1 = bvalue1->value; // Value as double in SI unit
|
|
||||||
// bool valid1 = bvalue1->valid; // Valid information
|
|
||||||
String svalue1 = formatValue(bvalue1, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
|
||||||
String unit1 = formatValue(bvalue1, commonData).unit; // Unit of value
|
|
||||||
|
|
||||||
// Get boat values for angle (AWD/TWD)
|
|
||||||
if (source == 'A') {
|
|
||||||
bvalue2 = pageData.values[1];
|
|
||||||
} else {
|
|
||||||
bvalue2 = pageData.values[3];
|
|
||||||
}
|
|
||||||
String name2 = bvalue2->getName().c_str(); // Value name
|
|
||||||
name2 = name2.substring(0, 6); // String length limit for value name
|
|
||||||
double value2 = bvalue2->value; // Value as double in SI unit
|
|
||||||
// bool valid2 = bvalue2->valid; // Valid information
|
|
||||||
String svalue2 = formatValue(bvalue2, commonData).svalue; // Formatted value as string including unit conversion and switching decimal places
|
|
||||||
String unit2 = formatValue(bvalue2, commonData).unit; // Unit of value
|
|
||||||
|
|
||||||
// Optical warning by limit violation (unused)
|
|
||||||
if(String(flashLED) == "Limit Violation"){
|
|
||||||
setBlinkingLED(false);
|
|
||||||
setFlashLED(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logging boat values
|
|
||||||
if (bvalue1 == NULL) return;
|
|
||||||
LOG_DEBUG(GwLog::LOG,"Drawing at PageWind, %s:%f, %s:%f", name1.c_str(), value1, name2.c_str(), value2);
|
|
||||||
|
|
||||||
// Draw page
|
|
||||||
//***********************************************************
|
|
||||||
|
|
||||||
// Set display in partial refresh mode
|
|
||||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
|
||||||
|
|
||||||
getdisplay().setTextColor(commonData.fgcolor);
|
|
||||||
|
|
||||||
|
|
||||||
if (mode == 'X') {
|
|
||||||
// Original example code with scaling circle
|
|
||||||
|
|
||||||
// Show values AWS/TWS
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold20pt7b);
|
|
||||||
getdisplay().setCursor(20, 50);
|
|
||||||
getdisplay().print(name1); // Value name
|
|
||||||
getdisplay().print(": ");
|
|
||||||
if(holdvalues == false){
|
|
||||||
getdisplay().print(svalue1); // Value
|
|
||||||
getdisplay().print(" ");
|
|
||||||
getdisplay().print(unit1); // Unit
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
getdisplay().print(svalue1old); // Value old
|
|
||||||
getdisplay().print(" ");
|
|
||||||
getdisplay().print(unit1old); // Unit old
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show values AWD/TWD
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold20pt7b);
|
|
||||||
getdisplay().setCursor(20, 260);
|
|
||||||
getdisplay().print(name2); // Value name
|
|
||||||
getdisplay().print(": ");
|
|
||||||
if(holdvalues == false){
|
|
||||||
getdisplay().print(svalue2); // Value
|
|
||||||
getdisplay().print(" ");
|
|
||||||
getdisplay().print(unit2); // Unit
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
getdisplay().print(svalue2old); // Value old
|
|
||||||
getdisplay().print(" ");
|
|
||||||
getdisplay().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);
|
|
||||||
|
|
||||||
// Wind pointer
|
|
||||||
if (bvalue2->valid) {
|
|
||||||
uint8_t lp0 = lp * 0.6; // effective pointer outside size
|
|
||||||
uint8_t lp1 = lp * 0.4; // effective pointer inside size
|
|
||||||
// zero position
|
|
||||||
std::vector<Point> pts = {
|
|
||||||
{c.x, c.y - lp},
|
|
||||||
{c.x - 7, c.y - lp + lp0},
|
|
||||||
{c.x, c.y - lp + lp1},
|
|
||||||
{c.x + 7, c.y - lp + lp0}
|
|
||||||
};
|
|
||||||
fillPoly4(rotatePoints(c, pts, RadToDeg(value2)), commonData.fgcolor);
|
|
||||||
} else {
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
|
||||||
drawTextCenter(c.x, c.y, "no data");
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (mode == 'L') { // Mode (L)ens
|
|
||||||
|
|
||||||
Point c = {200, 155};
|
|
||||||
uint16_t r = 150;
|
|
||||||
|
|
||||||
Point p;
|
|
||||||
std::vector<Point> pts = { // polygon lines
|
|
||||||
{c.x - 2, c.y - r},
|
|
||||||
{c.x + 2, c.y - r},
|
|
||||||
{c.x + 2, c.y - (r - 16)},
|
|
||||||
{c.x - 2, c.y - (r - 16)}
|
|
||||||
};
|
|
||||||
int angle;
|
|
||||||
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
|
||||||
|
|
||||||
// starbord
|
|
||||||
// text with line
|
|
||||||
angle = 20;
|
|
||||||
for (int i = 30; i < 150; i += 30) {
|
|
||||||
p = rotatePoint(c, {c.x, c.y - r + 40}, i);
|
|
||||||
drawTextCenter(p.x, p.y, String(angle));
|
|
||||||
angle += 10;
|
|
||||||
fillPoly4(rotatePoints(c, pts, i), commonData.fgcolor);
|
|
||||||
}
|
|
||||||
// dots
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// port
|
|
||||||
angle = 50;
|
|
||||||
// text with line
|
|
||||||
for (int i = 240; i <= 330; i += 30) {
|
|
||||||
p = rotatePoint(c, {c.x, c.y - r + 40}, i);
|
|
||||||
drawTextCenter(p.x, p.y, String(angle));
|
|
||||||
angle -= 10;
|
|
||||||
fillPoly4(rotatePoints(c, pts, i), commonData.fgcolor);
|
|
||||||
}
|
|
||||||
// dots
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// data source
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
|
||||||
getdisplay().setCursor(8, 50);
|
|
||||||
if (source == 'A') {
|
|
||||||
getdisplay().print("APP");
|
|
||||||
} else {
|
|
||||||
getdisplay().print("TRUE");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wind pointer (angle)
|
|
||||||
if (bvalue2->valid) {
|
|
||||||
float alpha = RadToDeg(value2);
|
|
||||||
bool port = (alpha > 180);
|
|
||||||
if (port) {
|
|
||||||
alpha = 360 - alpha;
|
|
||||||
}
|
|
||||||
if (alpha < 15) {
|
|
||||||
alpha = 15; // stop at start of scale
|
|
||||||
} else if (alpha > 55) {
|
|
||||||
alpha = 55; // stop at end of scale
|
|
||||||
}
|
|
||||||
alpha = 3 * alpha - 30; // convert to lens scale
|
|
||||||
if (port) {
|
|
||||||
alpha *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
getdisplay().fillCircle(c.x, c.y, 8, commonData.fgcolor);
|
|
||||||
pts = {
|
|
||||||
{c.x - 1, c.y - (r - 20)},
|
|
||||||
{c.x + 1, c.y - (r - 20)},
|
|
||||||
{c.x + 6, c.y + 15},
|
|
||||||
{c.x - 6, c.y + 15}
|
|
||||||
};
|
|
||||||
fillPoly4(rotatePoints(c, pts, alpha), commonData.fgcolor);
|
|
||||||
getdisplay().fillCircle(c.x, c.y, 6, commonData.bgcolor);
|
|
||||||
} else {
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
|
||||||
drawTextCenter(c.x, c.y, "no data");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wind speed as decimal number
|
|
||||||
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
|
|
||||||
getdisplay().setCursor(150, 250);
|
|
||||||
if (holdvalues == false) {
|
|
||||||
getdisplay().print(svalue1);
|
|
||||||
} else {
|
|
||||||
getdisplay().print(svalue1old);
|
|
||||||
}
|
|
||||||
// unit
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
|
||||||
getdisplay().setCursor(220, 265);
|
|
||||||
getdisplay().print("kts");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Normal mode
|
|
||||||
|
|
||||||
// data source
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
|
||||||
getdisplay().setCursor(8, 50);
|
|
||||||
if (source == 'A') {
|
|
||||||
getdisplay().print("APP");
|
|
||||||
} else {
|
|
||||||
getdisplay().print("TRUE");
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw ship front symbol (as bitmap)
|
|
||||||
getdisplay().drawXBitmap(140, 30, front_bits, front_width, front_height, commonData.fgcolor);
|
|
||||||
|
|
||||||
Point c = {200, 155};
|
|
||||||
uint16_t r = 150;
|
|
||||||
|
|
||||||
Point p;
|
|
||||||
std::vector<Point> pts = { // polygon lines
|
|
||||||
{c.x - 2, c.y - r},
|
|
||||||
{c.x + 2, c.y - r},
|
|
||||||
{c.x + 2, c.y - (r - 16)},
|
|
||||||
{c.x - 2, c.y - (r - 16)}
|
|
||||||
};
|
|
||||||
int angle;
|
|
||||||
|
|
||||||
// starbord
|
|
||||||
// text with line
|
|
||||||
for (int i = 30; i < 150; i += 30) {
|
|
||||||
p = rotatePoint(c, {c.x, c.y - r + 40}, i);
|
|
||||||
drawTextCenter(p.x, p.y, String(i));
|
|
||||||
fillPoly4(rotatePoints(c, pts, i), commonData.fgcolor);
|
|
||||||
}
|
|
||||||
// dots
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// port
|
|
||||||
// text with line
|
|
||||||
angle = 120;
|
|
||||||
for (int i = 240; i <= 330; i += 30) {
|
|
||||||
p = rotatePoint(c, {c.x, c.y - r + 40}, i);
|
|
||||||
drawTextCenter(p.x, p.y, String(angle));
|
|
||||||
angle -= 30;
|
|
||||||
fillPoly4(rotatePoints(c, pts, i), commonData.fgcolor);
|
|
||||||
}
|
|
||||||
// dots
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wind speed as decimal number
|
|
||||||
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
|
|
||||||
getdisplay().setCursor(150, 250);
|
|
||||||
if (holdvalues == false) {
|
|
||||||
getdisplay().print(svalue1);
|
|
||||||
} else {
|
|
||||||
getdisplay().print(svalue1old);
|
|
||||||
}
|
|
||||||
// unit
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
|
||||||
getdisplay().setCursor(220, 265);
|
|
||||||
getdisplay().print("kts");
|
|
||||||
|
|
||||||
// Wind pointer (angle)
|
|
||||||
if (bvalue2->valid) {
|
|
||||||
float alpha = RadToDeg(value2);
|
|
||||||
getdisplay().fillCircle(c.x, c.y, 8, commonData.fgcolor);
|
|
||||||
pts = {
|
|
||||||
{c.x - 1, c.y - (r - 20)},
|
|
||||||
{c.x + 1, c.y - (r - 20)},
|
|
||||||
{c.x + 6, c.y + 15},
|
|
||||||
{c.x - 6, c.y + 15}
|
|
||||||
};
|
|
||||||
fillPoly4(rotatePoints(c, pts, alpha), commonData.fgcolor);
|
|
||||||
getdisplay().fillCircle(c.x, c.y, 6, commonData.bgcolor);
|
|
||||||
} else {
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
|
||||||
drawTextCenter(c.x, c.y, "no data");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key Layout
|
|
||||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
|
||||||
if(keylock == false){
|
|
||||||
getdisplay().setCursor(10, 290);
|
|
||||||
getdisplay().print("[MODE]");
|
|
||||||
getdisplay().setCursor(130, 290);
|
|
||||||
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
|
|
||||||
|
|
||||||
if (mode == 'X') {
|
|
||||||
getdisplay().setCursor(85, 290);
|
|
||||||
getdisplay().print("[ - ]");
|
|
||||||
getdisplay().setCursor(295, 290);
|
|
||||||
getdisplay().print("[ + ]");
|
|
||||||
}
|
|
||||||
|
|
||||||
if(String(backlightMode) == "Control by Key"){ // Key for illumination
|
|
||||||
getdisplay().setCursor(343, 290);
|
|
||||||
getdisplay().print("[ILUM]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
getdisplay().setCursor(130, 290);
|
|
||||||
getdisplay().print(" [ Keylock active ]");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update display
|
|
||||||
getdisplay().nextPage(); // Partial update (fast)
|
|
||||||
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
static Page *createPage(CommonData &common){
|
|
||||||
return new PageWind(common);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* with the code below we make this page known to the PageTask
|
|
||||||
* we give it a type (name) that can be selected in the config
|
|
||||||
* we define which function is to be called
|
|
||||||
* and we provide the number of user parameters we expect (0 here)
|
|
||||||
* and will will provide the names of the fixed values we need
|
|
||||||
*/
|
|
||||||
PageDescription registerPageWind(
|
|
||||||
"Wind", // Page name
|
|
||||||
createPage, // Action
|
|
||||||
0, // Number of bus values depends on selection in Web configuration
|
|
||||||
{"AWS","AWA", "TWS", "TWA"}, // Bus values we need in the page
|
|
||||||
true // Show display header on/off
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -186,8 +186,7 @@ public:
|
|||||||
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
|
getdisplay().setFont(&DSEG7Classic_BoldItalic20pt7b);
|
||||||
getdisplay().setCursor(295, 65);
|
getdisplay().setCursor(295, 65);
|
||||||
if(valid3 == true){
|
if(valid3 == true){
|
||||||
// getdisplay().print(abs(value3 * 180 / PI), 0); // Value
|
getdisplay().print(abs(value3 * 180 / PI), 0); // Value
|
||||||
getdisplay().print(svalue3); // Value
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
getdisplay().print("---"); // Value
|
getdisplay().print("---"); // Value
|
||||||
|
|||||||
@@ -4,12 +4,9 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#define MAX_PAGE_NUMBER 10 // Max number of pages for show data
|
|
||||||
|
|
||||||
typedef std::vector<GwApi::BoatValue *> ValueList;
|
typedef std::vector<GwApi::BoatValue *> ValueList;
|
||||||
typedef struct{
|
typedef struct{
|
||||||
String pageName;
|
String pageName;
|
||||||
uint8_t pageNumber; // page number in sequence of visible pages
|
|
||||||
//the values will always contain the user defined values first
|
//the values will always contain the user defined values first
|
||||||
ValueList values;
|
ValueList values;
|
||||||
} PageData;
|
} PageData;
|
||||||
@@ -117,13 +114,6 @@ class PageDescription{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class PageStruct{
|
|
||||||
public:
|
|
||||||
Page *page=NULL;
|
|
||||||
PageData parameters;
|
|
||||||
PageDescription *description=NULL;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Structure for formated boat values
|
// Structure for formated boat values
|
||||||
typedef struct{
|
typedef struct{
|
||||||
double value;
|
double value;
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
OBP40
|
|
||||||
=====
|
|
||||||
|
|
||||||
Important information:
|
|
||||||
|
|
||||||
***************************************************
|
|
||||||
THIS BRANCH IS NOT INTENDED TO MERGE INTO "master"!
|
|
||||||
***************************************************
|
|
||||||
|
|
||||||
platformio.ini adapted to compile directly
|
|
||||||
|
|
||||||
Differences to OBP60
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
- no GPS
|
|
||||||
- no RTC
|
|
||||||
- no LEDs
|
|
||||||
- no environment sensor
|
|
||||||
- no key lock
|
|
||||||
- no swipe
|
|
||||||
- only 5 keys
|
|
||||||
|
|
||||||
+ SD card interface
|
|
||||||
|
|
||||||
|
|
||||||
Keyboard
|
|
||||||
--------
|
|
||||||
|
|
||||||
Keycode Key Function
|
|
||||||
-------- ---------------- -------------------------
|
|
||||||
1 Menu key Key 1 of OBP60 (left)
|
|
||||||
2 Exit key Key 2 of OBP60
|
|
||||||
3 Jog-Dial press
|
|
||||||
9 Jog-Dial down Next page
|
|
||||||
10 Jog-Dial up Previous page
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
|||||||
#!/bin/perl -w
|
#!/bin/perl -w
|
||||||
#A tool to generate the part of config.json that deals with pages and fields.
|
#A tool to generate the part of config.json that deals with pages and fields.
|
||||||
#DEPRECATED, moved to get_set.py
|
|
||||||
die "Please use gen_set.py instead";
|
|
||||||
#List of all pages and the number of parameters they expect.
|
#List of all pages and the number of parameters they expect.
|
||||||
%NoOfFieldsPerPage=qw(
|
%NoOfFieldsPerPage=qw(
|
||||||
ApparentWind 0
|
ApparentWind 0
|
||||||
@@ -82,7 +81,7 @@ for ($PageNo=1;$PageNo<=$NoOfPages;$PageNo++){
|
|||||||
print "\t",'"condition":[';
|
print "\t",'"condition":[';
|
||||||
foreach $page (@Pages) {
|
foreach $page (@Pages) {
|
||||||
if($NoOfFieldsPerPage{$page}>=$FieldNo){
|
if($NoOfFieldsPerPage{$page}>=$FieldNo){
|
||||||
print '{"page',$PageNo,'type":"',$page,'"},';
|
print '{"page1type":"',$page,'"},';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print "\b],\n";
|
print "\b],\n";
|
||||||
|
|||||||
@@ -1,123 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# A tool to generate that part of config.json that deals with pages and fields.
|
|
||||||
|
|
||||||
import json
|
|
||||||
|
|
||||||
# List of all pages and the number of parameters they expect.
|
|
||||||
no_of_fields_per_page = {
|
|
||||||
"ApparentWind": 0,
|
|
||||||
"XTETrack": 0,
|
|
||||||
"Battery2": 0,
|
|
||||||
"Battery": 0,
|
|
||||||
"BME280": 0,
|
|
||||||
"Clock": 0,
|
|
||||||
"DST810": 0,
|
|
||||||
"Fluid": 0,
|
|
||||||
"FourValues2": 4,
|
|
||||||
"FourValues": 4,
|
|
||||||
"Generator": 0,
|
|
||||||
"KeelPosition": 0,
|
|
||||||
"OneValue": 1,
|
|
||||||
"RollPitch": 2,
|
|
||||||
"RudderPosition": 0,
|
|
||||||
"Solar": 0,
|
|
||||||
"ThreeValues": 3,
|
|
||||||
"TwoValues": 2,
|
|
||||||
"Voltage": 0,
|
|
||||||
"White": 0,
|
|
||||||
"WindRose": 0,
|
|
||||||
"WindRoseFlex": 6,
|
|
||||||
}
|
|
||||||
|
|
||||||
# No changes needed beyond this point
|
|
||||||
# max number of pages supported by OBP60
|
|
||||||
no_of_pages = 10
|
|
||||||
# Default selection for each page
|
|
||||||
default_pages = [
|
|
||||||
"Voltage",
|
|
||||||
"WindRose",
|
|
||||||
"OneValue",
|
|
||||||
"TwoValues",
|
|
||||||
"ThreeValues",
|
|
||||||
"FourValues",
|
|
||||||
"FourValues2",
|
|
||||||
"Clock",
|
|
||||||
"RollPitch",
|
|
||||||
"Battery2",
|
|
||||||
]
|
|
||||||
numbers = [
|
|
||||||
"one",
|
|
||||||
"two",
|
|
||||||
"three",
|
|
||||||
"four",
|
|
||||||
"five",
|
|
||||||
"six",
|
|
||||||
"seven",
|
|
||||||
"eight",
|
|
||||||
"nine",
|
|
||||||
"ten",
|
|
||||||
]
|
|
||||||
pages = sorted(no_of_fields_per_page.keys())
|
|
||||||
max_no_of_fields_per_page = max(no_of_fields_per_page.values())
|
|
||||||
|
|
||||||
output = []
|
|
||||||
|
|
||||||
for page_no in range(1, no_of_pages + 1):
|
|
||||||
page_data = {
|
|
||||||
"name": f"page{page_no}type",
|
|
||||||
"label": "Type",
|
|
||||||
"type": "list",
|
|
||||||
"default": default_pages[page_no - 1],
|
|
||||||
"description": f"Type of page for page {page_no}",
|
|
||||||
"list": pages,
|
|
||||||
"category": f"OBP60 Page {page_no}",
|
|
||||||
"capabilities": {"obp60": "true"},
|
|
||||||
"condition": [{"visiblePages": vp} for vp in range(page_no, no_of_pages + 1)],
|
|
||||||
#"fields": [],
|
|
||||||
}
|
|
||||||
output.append(page_data)
|
|
||||||
|
|
||||||
for field_no in range(1, max_no_of_fields_per_page + 1):
|
|
||||||
field_data = {
|
|
||||||
"name": f"page{page_no}value{field_no}",
|
|
||||||
"label": f"Field {field_no}",
|
|
||||||
"type": "boatData",
|
|
||||||
"default": "",
|
|
||||||
"description": f"The display for field {numbers[field_no - 1]}",
|
|
||||||
"category": f"OBP60 Page {page_no}",
|
|
||||||
"capabilities": {"obp60": "true"},
|
|
||||||
"condition": [
|
|
||||||
{f"page{page_no}type": page}
|
|
||||||
for page in pages
|
|
||||||
if no_of_fields_per_page[page] >= field_no
|
|
||||||
],
|
|
||||||
}
|
|
||||||
output.append(field_data)
|
|
||||||
|
|
||||||
fluid_data ={
|
|
||||||
"name": f"page{page_no}fluid",
|
|
||||||
"label": "Fluid type",
|
|
||||||
"type": "list",
|
|
||||||
"default": "0",
|
|
||||||
"list": [
|
|
||||||
{"l":"Fuel (0)","v":"0"},
|
|
||||||
{"l":"Water (1)","v":"1"},
|
|
||||||
{"l":"Gray Water (2)","v":"2"},
|
|
||||||
{"l":"Live Well (3)","v":"3"},
|
|
||||||
{"l":"Oil (4)","v":"4"},
|
|
||||||
{"l":"Black Water (5)","v":"5"},
|
|
||||||
{"l":"Fuel Gasoline (6)","v":"6"}
|
|
||||||
],
|
|
||||||
"description": "Fluid type in tank",
|
|
||||||
"category": f"OBP60 Page {page_no}",
|
|
||||||
"capabilities": {
|
|
||||||
"obp60":"true"
|
|
||||||
},
|
|
||||||
"condition":[{f"page{page_no}type":"Fluid"}]
|
|
||||||
}
|
|
||||||
output.append(fluid_data)
|
|
||||||
|
|
||||||
json_output = json.dumps(output, indent=4)
|
|
||||||
# print omitting first and last line containing [ ] of JSON array
|
|
||||||
print(json_output[1:-1])
|
|
||||||
# print(",")
|
|
||||||
84
lib/obp60task/hbuffer.cpp
Normal file
84
lib/obp60task/hbuffer.cpp
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/* 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
|
||||||
|
}
|
||||||
|
uint8_t* get() {
|
||||||
|
// returns complete buffer in order new to old
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
}
|
||||||
|
bool clear() {
|
||||||
|
// clears buffer and permanent storage
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class History {
|
||||||
|
public:
|
||||||
|
History() {
|
||||||
|
}
|
||||||
|
~History() {
|
||||||
|
}
|
||||||
|
void *addSeries() {
|
||||||
|
}
|
||||||
|
};
|
||||||
21
lib/obp60task/hbuffer.h
Normal file
21
lib/obp60task/hbuffer.h
Normal file
@@ -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
|
||||||
@@ -1,347 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
* Image functions:
|
|
||||||
* - Convert a 1bit framebuffer in RAM to
|
|
||||||
* - GIF, compressed, based on giflib and gif_hash
|
|
||||||
* - PBM, portable bitmap, very simple copy
|
|
||||||
* - BMP, bigger with a little bit fiddling around
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#include <Arduino.h> // needed for PROGMEM
|
|
||||||
#include <vector>
|
|
||||||
#include "GwLog.h" // needed for logger
|
|
||||||
#include "imglib.h"
|
|
||||||
|
|
||||||
GifFilePrivateType gifprivate;
|
|
||||||
|
|
||||||
void ClearHashTable(GifHashTableType *HashTable) {
|
|
||||||
memset(HashTable->HTable, 0xFF, HT_SIZE * sizeof(uint32_t));
|
|
||||||
}
|
|
||||||
|
|
||||||
GifHashTableType *InitHashTable(void) {
|
|
||||||
GifHashTableType *HashTable;
|
|
||||||
if ((HashTable = (GifHashTableType *)ps_malloc(sizeof(GifHashTableType))) == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
ClearHashTable(HashTable);
|
|
||||||
return HashTable;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int KeyItem(uint32_t Item) {
|
|
||||||
return ((Item >> 12) ^ Item) & HT_KEY_MASK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void InsertHashTable(GifHashTableType *HashTable, uint32_t Key, int Code) {
|
|
||||||
int HKey = KeyItem(Key);
|
|
||||||
uint32_t *HTable = HashTable->HTable;
|
|
||||||
while (HT_GET_KEY(HTable[HKey]) != 0xFFFFFL) {
|
|
||||||
HKey = (HKey + 1) & HT_KEY_MASK;
|
|
||||||
}
|
|
||||||
HTable[HKey] = HT_PUT_KEY(Key) | HT_PUT_CODE(Code);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ExistsHashTable(GifHashTableType *HashTable, uint32_t Key) {
|
|
||||||
int HKey = KeyItem(Key);
|
|
||||||
uint32_t *HTable = HashTable->HTable, HTKey;
|
|
||||||
while ((HTKey = HT_GET_KEY(HTable[HKey])) != 0xFFFFFL) {
|
|
||||||
if (Key == HTKey) {
|
|
||||||
return HT_GET_CODE(HTable[HKey]);
|
|
||||||
}
|
|
||||||
HKey = (HKey + 1) & HT_KEY_MASK;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
Put 2 bytes (a word) into the given file in little-endian order:
|
|
||||||
******************************************************************************/
|
|
||||||
void GifPutWord(std::vector<uint8_t>* gifBuffer, uint16_t Word) {
|
|
||||||
/*cuint8_t c[2];
|
|
||||||
[0] = LOBYTE(Word);
|
|
||||||
c[1] = HIBYTE(Word);
|
|
||||||
gifBuffer->push_back(c[0]);
|
|
||||||
gifBuffer->push_back(c[1]); */
|
|
||||||
gifBuffer->push_back(LOBYTE(Word));
|
|
||||||
gifBuffer->push_back(HIBYTE(Word));
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
This routines buffers the given characters until 255 characters are ready
|
|
||||||
to be output. If Code is equal to -1 the buffer is flushed (EOF).
|
|
||||||
The buffer is Dumped with first byte as its size, as GIF format requires.
|
|
||||||
******************************************************************************/
|
|
||||||
void GifBufferedOutput(std::vector<uint8_t>* gifBuffer, GifByteType *Buf, int c) {
|
|
||||||
if (c == FLUSH_OUTPUT) {
|
|
||||||
// Flush everything out.
|
|
||||||
for (int i = 0; i < Buf[0] + 1; i++) {
|
|
||||||
gifBuffer->push_back(Buf[i]);
|
|
||||||
}
|
|
||||||
// Mark end of compressed data, by an empty block (see GIF doc):
|
|
||||||
Buf[0] = 0;
|
|
||||||
gifBuffer->push_back(0);
|
|
||||||
} else {
|
|
||||||
if (Buf[0] == 255) {
|
|
||||||
// Dump out this buffer - it is full:
|
|
||||||
for (int i = 0; i < Buf[0] + 1; i++) {
|
|
||||||
gifBuffer->push_back(Buf[i]);
|
|
||||||
}
|
|
||||||
Buf[0] = 0;
|
|
||||||
}
|
|
||||||
Buf[++Buf[0]] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
The LZ compression output routine:
|
|
||||||
This routine is responsible for the compression of the bit stream into
|
|
||||||
8 bits (bytes) packets.
|
|
||||||
******************************************************************************/
|
|
||||||
void GifCompressOutput(std::vector<uint8_t>* gifBuffer, const int Code) {
|
|
||||||
|
|
||||||
if (Code == FLUSH_OUTPUT) {
|
|
||||||
while (gifprivate.CrntShiftState > 0) {
|
|
||||||
// Get Rid of what is left in DWord, and flush it.
|
|
||||||
GifBufferedOutput(gifBuffer, gifprivate.Buf, gifprivate.CrntShiftDWord & 0xff);
|
|
||||||
gifprivate.CrntShiftDWord >>= 8;
|
|
||||||
gifprivate.CrntShiftState -= 8;
|
|
||||||
}
|
|
||||||
gifprivate.CrntShiftState = 0; // For next time.
|
|
||||||
GifBufferedOutput(gifBuffer, gifprivate.Buf, FLUSH_OUTPUT);
|
|
||||||
} else {
|
|
||||||
gifprivate.CrntShiftDWord |= ((long)Code) << gifprivate.CrntShiftState;
|
|
||||||
gifprivate.CrntShiftState += gifprivate.RunningBits;
|
|
||||||
while (gifprivate.CrntShiftState >= 8) {
|
|
||||||
// Dump out full bytes:
|
|
||||||
GifBufferedOutput(gifBuffer, gifprivate.Buf, gifprivate.CrntShiftDWord & 0xff);
|
|
||||||
gifprivate.CrntShiftDWord >>= 8;
|
|
||||||
gifprivate.CrntShiftState -= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If code cannt fit into RunningBits bits, must raise its size. Note */
|
|
||||||
/* however that codes above LZ_MAX_CODE are used for special signaling. */
|
|
||||||
if (gifprivate.RunningCode >= gifprivate.MaxCode1 && Code <= LZ_MAX_CODE) {
|
|
||||||
gifprivate.MaxCode1 = 1 << ++gifprivate.RunningBits;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
Setup the LZ compression for this image:
|
|
||||||
******************************************************************************/
|
|
||||||
void GifSetupCompress(std::vector<uint8_t>* gifBuffer) {
|
|
||||||
gifBuffer->push_back(0x02);// Bits per pixel wit minimum 2
|
|
||||||
|
|
||||||
gifprivate.Buf[0] = 0; // Nothing was output yet
|
|
||||||
gifprivate.BitsPerPixel = 2; // Minimum is 2
|
|
||||||
gifprivate.ClearCode = (1 << 2);
|
|
||||||
gifprivate.EOFCode = gifprivate.ClearCode + 1;
|
|
||||||
gifprivate.RunningCode = gifprivate.EOFCode + 1;
|
|
||||||
gifprivate.RunningBits = 2 + 1; // Number of bits per code
|
|
||||||
gifprivate.MaxCode1 = 1 << gifprivate.RunningBits; // Max. code + 1
|
|
||||||
gifprivate.CrntCode = FIRST_CODE; // Signal that this is first one!
|
|
||||||
gifprivate.CrntShiftState = 0; // No information in CrntShiftDWord
|
|
||||||
gifprivate.CrntShiftDWord = 0;
|
|
||||||
|
|
||||||
GifCompressOutput(gifBuffer, gifprivate.ClearCode);
|
|
||||||
}
|
|
||||||
|
|
||||||
void createGifHeader(std::vector<uint8_t>* gifBuffer, uint16_t width, uint16_t height) {
|
|
||||||
|
|
||||||
// SCREEN DESCRIPTOR
|
|
||||||
gifBuffer->push_back('G');
|
|
||||||
gifBuffer->push_back('I');
|
|
||||||
gifBuffer->push_back('F');
|
|
||||||
gifBuffer->push_back('8');
|
|
||||||
gifBuffer->push_back('7');
|
|
||||||
gifBuffer->push_back('a');
|
|
||||||
|
|
||||||
GifPutWord(gifBuffer, width);
|
|
||||||
GifPutWord(gifBuffer, height);
|
|
||||||
|
|
||||||
gifBuffer->push_back(0x80 | (1 << 4));
|
|
||||||
gifBuffer->push_back(0x00); // Index into the ColorTable for background color
|
|
||||||
gifBuffer->push_back(0x00); // Pixel Aspect Ratio
|
|
||||||
|
|
||||||
// Colormap
|
|
||||||
gifBuffer->push_back(0xff); // Color 0
|
|
||||||
gifBuffer->push_back(0xff);
|
|
||||||
gifBuffer->push_back(0xff);
|
|
||||||
gifBuffer->push_back(0x00); // Color 1
|
|
||||||
gifBuffer->push_back(0x00);
|
|
||||||
gifBuffer->push_back(0x00);
|
|
||||||
|
|
||||||
// IMAGE DESCRIPTOR
|
|
||||||
gifBuffer->push_back(DESCRIPTOR_INTRODUCER);
|
|
||||||
|
|
||||||
GifPutWord(gifBuffer, 0);
|
|
||||||
GifPutWord(gifBuffer, 0);
|
|
||||||
GifPutWord(gifBuffer, width);
|
|
||||||
GifPutWord(gifBuffer, height);
|
|
||||||
|
|
||||||
gifBuffer->push_back(0x00); // No colormap here , we use the global one
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
The LZ compression routine:
|
|
||||||
This version compresses the given buffer Line of length LineLen.
|
|
||||||
This routine can be called a few times (one per scan line, for example), in
|
|
||||||
order to complete the whole image.
|
|
||||||
******************************************************************************/
|
|
||||||
void GifCompressLine(std::vector<uint8_t>* gifBuffer, const GifPixelType *Line, const int LineLen) {
|
|
||||||
int i = 0, CrntCode;
|
|
||||||
GifHashTableType *HashTable;
|
|
||||||
|
|
||||||
HashTable = gifprivate.HashTable;
|
|
||||||
|
|
||||||
if (gifprivate.CrntCode == FIRST_CODE) { // Its first time!
|
|
||||||
CrntCode = Line[i++];
|
|
||||||
} else {
|
|
||||||
CrntCode =
|
|
||||||
gifprivate.CrntCode; // Get last code in compression
|
|
||||||
}
|
|
||||||
while (i < LineLen) { // Decode LineLen items
|
|
||||||
GifPixelType Pixel = Line[i++]; // Get next pixel from stream.
|
|
||||||
/* Form a new unique key to search hash table for the code
|
|
||||||
* combines CrntCode as Prefix string with Pixel as postfix
|
|
||||||
* char.
|
|
||||||
*/
|
|
||||||
int NewCode;
|
|
||||||
unsigned long NewKey = (((uint32_t)CrntCode) << 8) + Pixel;
|
|
||||||
if ((NewCode = ExistsHashTable(HashTable, NewKey)) >= 0) {
|
|
||||||
/* This Key is already there, or the string is old one,
|
|
||||||
* so simple take new code as our CrntCode:
|
|
||||||
*/
|
|
||||||
CrntCode = NewCode;
|
|
||||||
} else {
|
|
||||||
/* Put it in hash table, output the prefix code, and
|
|
||||||
* make our CrntCode equal to Pixel.
|
|
||||||
*/
|
|
||||||
GifCompressOutput(gifBuffer, CrntCode);
|
|
||||||
CrntCode = Pixel;
|
|
||||||
|
|
||||||
/* If however the HashTable if full, we send a clear
|
|
||||||
* first and Clear the hash table.
|
|
||||||
*/
|
|
||||||
if (gifprivate.RunningCode >= LZ_MAX_CODE) {
|
|
||||||
// Time to do some clearance:
|
|
||||||
GifCompressOutput(gifBuffer, gifprivate.ClearCode);
|
|
||||||
gifprivate.RunningCode = gifprivate.EOFCode + 1;
|
|
||||||
gifprivate.RunningBits = gifprivate.BitsPerPixel + 1;
|
|
||||||
gifprivate.MaxCode1 = 1 << gifprivate.RunningBits;
|
|
||||||
ClearHashTable(HashTable);
|
|
||||||
} else {
|
|
||||||
// Put this unique key with its relative Code in hash table:
|
|
||||||
InsertHashTable(HashTable, NewKey, gifprivate.RunningCode++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preserve the current state of the compression algorithm:
|
|
||||||
gifprivate.CrntCode = CrntCode;
|
|
||||||
|
|
||||||
if (gifprivate.PixelCount == 0) {
|
|
||||||
// We are done - output last Code and flush output buffers:
|
|
||||||
GifCompressOutput(gifBuffer, CrntCode);
|
|
||||||
GifCompressOutput(gifBuffer, gifprivate.EOFCode);
|
|
||||||
GifCompressOutput(gifBuffer, FLUSH_OUTPUT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool createBMP(uint8_t *frameBuffer, std::vector<uint8_t>* imageBuffer, uint16_t width, uint16_t height) {
|
|
||||||
// For BMP the line size has to be a multiple of 4 bytes.
|
|
||||||
// So padding is needed. Also the lines have to be in reverded
|
|
||||||
// order compared to plain buffer
|
|
||||||
|
|
||||||
// BMP header for black-and-white image (1 bit per pixel)
|
|
||||||
const uint8_t bmp_header[] PROGMEM = {
|
|
||||||
// BITMAPFILEHEADER (14 Bytes)
|
|
||||||
0x42, 0x4D, // bfType: 'BM' signature
|
|
||||||
0x2e, 0x3d, 0x00, 0x00, // bfSize: file size in bytes
|
|
||||||
0x00, 0x00, // bfReserved1
|
|
||||||
0x00, 0x00, // bfReserved2
|
|
||||||
0x3e, 0x00, 0x00, 0x00, // bfOffBits: offset in bytes to pixeldata
|
|
||||||
// BITMAPINFOHEADER (40 Bytes)
|
|
||||||
0x28, 0x00, 0x00, 0x00, // biSize: DIB header size
|
|
||||||
(uint8_t)LOBYTE(width), (uint8_t)HIBYTE(width), 0x00, 0x00, // biWidth
|
|
||||||
(uint8_t)LOBYTE(height), (uint8_t)HIBYTE(height), 0x00, 0x00, // biHeight
|
|
||||||
0x01, 0x00, // biPlanes: Number of color planes (1)
|
|
||||||
0x01, 0x00, // biBitCount: Color depth (1 bit per pixel)
|
|
||||||
0x00, 0x00, 0x00, 0x00, // biCompression: Compression (none)
|
|
||||||
0xf0, 0x3c, 0x00, 0x00, // biSizeImage: Image data size (calculate)
|
|
||||||
0x13, 0x0b, 0x00, 0x00, // biXPelsPerMeter: Horizontal resolution (2835 pixels/meter)
|
|
||||||
0x13, 0x0b, 0x00, 0x00, // biYPelsPerMeter: Vertical resolution (2835 pixels/meter)
|
|
||||||
0x02, 0x00, 0x00, 0x00, // biClrUsed: Colors in color palette (2)
|
|
||||||
0x00, 0x00, 0x00, 0x00, // biClrImportant: Important colors (all)
|
|
||||||
// PALETTE: COLORTRIPLES of RGBQUAD (n * 4 Bytes)
|
|
||||||
0x00, 0x00, 0x00, 0x00, // Color palette: Black
|
|
||||||
0xff, 0xff, 0xff, 0x00 // Color palette: White
|
|
||||||
};
|
|
||||||
size_t bmp_headerSize = sizeof(bmp_header);
|
|
||||||
|
|
||||||
size_t lineSize = (width / 8);
|
|
||||||
size_t paddingSize = 0;
|
|
||||||
if (lineSize % 4 != 0) {
|
|
||||||
paddingSize = 4 - lineSize % 4;
|
|
||||||
}
|
|
||||||
size_t imageSize = bmp_headerSize + (lineSize + paddingSize) * height;
|
|
||||||
|
|
||||||
imageBuffer->resize(imageSize);
|
|
||||||
memcpy(imageBuffer->data(), bmp_header, bmp_headerSize);
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
uint8_t* srcRow = frameBuffer + (y * lineSize);
|
|
||||||
uint8_t* destRow = imageBuffer->data() + bmp_headerSize + ((height - 1 - y) * (lineSize + paddingSize));
|
|
||||||
memcpy(destRow, srcRow, lineSize);
|
|
||||||
for (int j = 0; j < paddingSize; j++) {
|
|
||||||
destRow[lineSize + j] = 0x00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool createPBM(uint8_t *frameBuffer, std::vector<uint8_t>* imageBuffer, uint16_t width, uint16_t height) {
|
|
||||||
// creates binary PBM image inside imagebuffer
|
|
||||||
// returns bytesize of created image
|
|
||||||
const char pbm_header[] PROGMEM = "P4\n#Created by OBP60\n400 300\n";
|
|
||||||
size_t pbm_headerSize = sizeof(pbm_header) - 1; // We don't want trailing zero
|
|
||||||
size_t imageSize = pbm_headerSize + width / 8 * height;
|
|
||||||
imageBuffer->resize(imageSize);
|
|
||||||
memcpy(imageBuffer->data(), pbm_header, pbm_headerSize);
|
|
||||||
memcpy(imageBuffer->data() + pbm_headerSize, frameBuffer, width / 8 * height);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool createGIF(uint8_t *framebuffer, std::vector<uint8_t>* gifBuffer, uint16_t width, uint16_t height) {
|
|
||||||
|
|
||||||
size_t imageSize = 0;
|
|
||||||
uint16_t bufOffset = 0; // Offset into imageBuffer for next write access
|
|
||||||
|
|
||||||
gifprivate.HashTable = InitHashTable();
|
|
||||||
if (gifprivate.HashTable == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
gifprivate.PixelCount = width * height;
|
|
||||||
|
|
||||||
createGifHeader(gifBuffer, width, height);
|
|
||||||
|
|
||||||
// Reset compress algorithm parameters.
|
|
||||||
GifSetupCompress(gifBuffer);
|
|
||||||
|
|
||||||
gifBuffer->reserve(4096); // to avoid lots of alloactions
|
|
||||||
GifPixelType line[width];
|
|
||||||
for (int y = 0; y < height; y++) {
|
|
||||||
// convert uint8_t pixels to single pixels
|
|
||||||
for (int x = 0; x < width; x++) {
|
|
||||||
int byteIndex = (y * width + x) / 8;
|
|
||||||
uint8_t bitIndex = 7 - ((y * width + x) % 8);
|
|
||||||
line[x] = (framebuffer[byteIndex] & (uint8_t)(1 << bitIndex)) == 0;
|
|
||||||
}
|
|
||||||
gifprivate.PixelCount -= width;
|
|
||||||
GifCompressLine(gifBuffer, line, width);
|
|
||||||
}
|
|
||||||
|
|
||||||
gifBuffer->push_back(TERMINATOR_INTRODUCER);
|
|
||||||
free((GifHashTableType *)gifprivate.HashTable);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
/******************************************************************************
|
|
||||||
*
|
|
||||||
* imglib.h
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
#ifndef _IMGLIB_H_
|
|
||||||
#define _IMGLIB_H_ 1
|
|
||||||
|
|
||||||
// extract bytes from an unsigned word
|
|
||||||
#define LOBYTE(x) ((x)&0xff)
|
|
||||||
#define HIBYTE(x) (((x) >> 8) & 0xff)
|
|
||||||
|
|
||||||
// GIF encoding constants
|
|
||||||
#define DESCRIPTOR_INTRODUCER 0x2c
|
|
||||||
#define TERMINATOR_INTRODUCER 0x3b
|
|
||||||
|
|
||||||
#define LZ_MAX_CODE 4095 // Biggest code possible in 12 bits
|
|
||||||
#define LZ_BITS 12
|
|
||||||
|
|
||||||
#define FLUSH_OUTPUT 4096 // Impossible code, to signal flush
|
|
||||||
#define FIRST_CODE 4097 // Impossible code, to signal first
|
|
||||||
#define NO_SUCH_CODE 4098 // Impossible code, to signal empty
|
|
||||||
|
|
||||||
// magfic constants and declarations for GIF LZW
|
|
||||||
|
|
||||||
#define HT_SIZE 8192 /* 12bits = 4096 or twice as big! */
|
|
||||||
#define HT_KEY_MASK 0x1FFF /* 13bits keys */
|
|
||||||
#define HT_KEY_NUM_BITS 13 /* 13bits keys */
|
|
||||||
#define HT_MAX_KEY 8191 /* 13bits - 1, maximal code possible */
|
|
||||||
#define HT_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
|
|
||||||
|
|
||||||
/* The 32 bits of the long are divided into two parts for the key & code: */
|
|
||||||
/* 1. The code is 12 bits as our compression algorithm is limited to 12bits */
|
|
||||||
/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits. */
|
|
||||||
/* The key is the upper 20 bits. The code is the lower 12. */
|
|
||||||
#define HT_GET_KEY(l) (l >> 12)
|
|
||||||
#define HT_GET_CODE(l) (l & 0x0FFF)
|
|
||||||
#define HT_PUT_KEY(l) (l << 12)
|
|
||||||
#define HT_PUT_CODE(l) (l & 0x0FFF)
|
|
||||||
|
|
||||||
typedef unsigned char GifPixelType;
|
|
||||||
typedef unsigned char GifByteType;
|
|
||||||
|
|
||||||
typedef struct GifHashTableType {
|
|
||||||
uint32_t HTable[HT_SIZE];
|
|
||||||
} GifHashTableType;
|
|
||||||
|
|
||||||
typedef struct GifFilePrivateType {
|
|
||||||
uint8_t BitsPerPixel; // Bits per pixel (Codes uses at least this + 1)
|
|
||||||
uint16_t ClearCode; // The CLEAR LZ code
|
|
||||||
uint16_t EOFCode; // The EOF LZ code
|
|
||||||
uint16_t RunningCode; // The next code algorithm can generate
|
|
||||||
uint16_t RunningBits; // The number of bits required to represent RunningCode
|
|
||||||
uint16_t MaxCode1; // 1 bigger than max. possible code, in RunningBits bits
|
|
||||||
uint16_t LastCode; // The code before the current code.
|
|
||||||
uint16_t CrntCode; // Current algorithm code
|
|
||||||
uint16_t CrntShiftState; // Number of bits in CrntShiftDWord
|
|
||||||
uint32_t CrntShiftDWord; // For bytes decomposition into codes
|
|
||||||
uint32_t PixelCount; // Number of pixels in image
|
|
||||||
GifByteType Buf[256]; // Compressed input is buffered here
|
|
||||||
GifHashTableType *HashTable;
|
|
||||||
} GifFilePrivateType;
|
|
||||||
|
|
||||||
bool createGIF(uint8_t *framebuffer, std::vector<uint8_t>* imageBuffer, uint16_t width, uint16_t height);
|
|
||||||
bool createBMP(uint8_t *framebuffer, std::vector<uint8_t>* imageBuffer, uint16_t width, uint16_t height);
|
|
||||||
bool createPBM(uint8_t *framebuffer, std::vector<uint8_t>* gifBuffer, uint16_t width, uint16_t height);
|
|
||||||
|
|
||||||
#endif /* _IMGLIB_H */
|
|
||||||
@@ -13,10 +13,6 @@
|
|||||||
#include "OBP60Extensions.h" // Functions lib for extension board
|
#include "OBP60Extensions.h" // Functions lib for extension board
|
||||||
#include "OBP60Keypad.h" // Functions for keypad
|
#include "OBP60Keypad.h" // Functions for keypad
|
||||||
|
|
||||||
#include <FS.h> // SD-Card access
|
|
||||||
#include <SD.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
|
|
||||||
// True type character sets includes
|
// True type character sets includes
|
||||||
// See OBP60ExtensionPort.cpp
|
// See OBP60ExtensionPort.cpp
|
||||||
|
|
||||||
@@ -27,6 +23,8 @@
|
|||||||
#include "OBP60QRWiFi.h" // Functions lib for WiFi QR code
|
#include "OBP60QRWiFi.h" // Functions lib for WiFi QR code
|
||||||
#include "OBPSensorTask.h" // Functions lib for sensor data
|
#include "OBPSensorTask.h" // Functions lib for sensor data
|
||||||
|
|
||||||
|
#include "LedSpiTask.h"
|
||||||
|
|
||||||
// Global vars
|
// Global vars
|
||||||
bool initComplete = false; // Initialization complete
|
bool initComplete = false; // Initialization complete
|
||||||
int taskRunCounter = 0; // Task couter for loop section
|
int taskRunCounter = 0; // Task couter for loop section
|
||||||
@@ -35,9 +33,6 @@ int taskRunCounter = 0; // Task couter for loop section
|
|||||||
//####################################################################################
|
//####################################################################################
|
||||||
void OBP60Init(GwApi *api){
|
void OBP60Init(GwApi *api){
|
||||||
|
|
||||||
GwLog *logger = api->getLogger();
|
|
||||||
GwConfigHandler *config = api->getConfig();
|
|
||||||
|
|
||||||
// Set a new device name and hidden the original name in the main config
|
// Set a new device name and hidden the original name in the main config
|
||||||
String devicename = api->getConfig()->getConfigItem(api->getConfig()->deviceName,true)->asString();
|
String devicename = api->getConfig()->getConfigItem(api->getConfig()->deviceName,true)->asString();
|
||||||
api->getConfig()->setValue(GwConfigDefinitions::systemName, devicename, GwConfigInterface::ConfigType::HIDDEN);
|
api->getConfig()->setValue(GwConfigDefinitions::systemName, devicename, GwConfigInterface::ConfigType::HIDDEN);
|
||||||
@@ -48,51 +43,16 @@ void OBP60Init(GwApi *api){
|
|||||||
|
|
||||||
|
|
||||||
// Init hardware
|
// Init hardware
|
||||||
hardwareInit(api);
|
hardwareInit();
|
||||||
|
|
||||||
String sdcard = config->getConfigItem(config->useSDCard, true)->asString();
|
|
||||||
if (sdcard == "on") {
|
|
||||||
setPortPin(OBP_POWER_SD, true); // Power on SD
|
|
||||||
delay(10);
|
|
||||||
SPIClass SD_SPI = SPIClass(HSPI);
|
|
||||||
SD_SPI.begin(SD_SPI_CLK, SD_SPI_MISO, SD_SPI_MOSI);
|
|
||||||
if (SD.begin(SD_SPI_CS, SD_SPI, 80000000)) {
|
|
||||||
String sdtype = "unknown";
|
|
||||||
uint8_t cardType = SD.cardType();
|
|
||||||
switch (cardType) {
|
|
||||||
case CARD_MMC:
|
|
||||||
sdtype = "MMC";
|
|
||||||
break;
|
|
||||||
case CARD_SD:
|
|
||||||
sdtype = "SDSC";
|
|
||||||
break;
|
|
||||||
case CARD_SDHC:
|
|
||||||
sdtype = "SDHC";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
|
|
||||||
LOG_DEBUG(GwLog::LOG,"SD card type %s of size %d MB detected", sdtype, cardSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init power rail 5.0V
|
// Init power rail 5.0V
|
||||||
String powermode = api->getConfig()->getConfigItem(api->getConfig()->powerMode,true)->asString();
|
String powermode = api->getConfig()->getConfigItem(api->getConfig()->powerMode,true)->asString();
|
||||||
api->getLogger()->logDebug(GwLog::DEBUG,"Power Mode is: %s", powermode.c_str());
|
api->getLogger()->logDebug(GwLog::DEBUG,"Power Mode is: %s", powermode.c_str());
|
||||||
if(powermode == "Max Power" || powermode == "Only 5.0V"){
|
if(powermode == "Max Power" || powermode == "Only 5.0V"){
|
||||||
#ifdef HARDWARE_V21
|
|
||||||
setPortPin(OBP_POWER_50, true); // Power on 5.0V rail
|
setPortPin(OBP_POWER_50, true); // Power on 5.0V rail
|
||||||
#endif
|
|
||||||
#ifdef HARDWARE_LIGHT
|
|
||||||
setPortPin(OBP_POWER_EPD, true);// Power on ePaper display
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
#ifdef HARDWARE_V21
|
|
||||||
setPortPin(OBP_POWER_50, false); // Power off 5.0V rail
|
setPortPin(OBP_POWER_50, false); // Power off 5.0V rail
|
||||||
#endif
|
|
||||||
#ifdef HARDWARE_LIGHT
|
|
||||||
setPortPin(OBP_POWER_EPD, false);// Power off ePaper display
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Settings for e-paper display
|
// Settings for e-paper display
|
||||||
@@ -223,6 +183,13 @@ class PageList{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PageStruct{
|
||||||
|
public:
|
||||||
|
Page *page=NULL;
|
||||||
|
PageData parameters;
|
||||||
|
PageDescription *description=NULL;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this function will add all the pages we know to the pagelist
|
* this function will add all the pages we know to the pagelist
|
||||||
* each page should have defined a registerXXXPage variable of type
|
* each page should have defined a registerXXXPage variable of type
|
||||||
@@ -245,8 +212,8 @@ void registerAllPages(PageList &list){
|
|||||||
list.add(®isterPageFourValues);
|
list.add(®isterPageFourValues);
|
||||||
extern PageDescription registerPageFourValues2;
|
extern PageDescription registerPageFourValues2;
|
||||||
list.add(®isterPageFourValues2);
|
list.add(®isterPageFourValues2);
|
||||||
extern PageDescription registerPageWind;
|
extern PageDescription registerPageApparentWind;
|
||||||
list.add(®isterPageWind);
|
list.add(®isterPageApparentWind);
|
||||||
extern PageDescription registerPageWindRose;
|
extern PageDescription registerPageWindRose;
|
||||||
list.add(®isterPageWindRose);
|
list.add(®isterPageWindRose);
|
||||||
extern PageDescription registerPageWindRoseFlex;
|
extern PageDescription registerPageWindRoseFlex;
|
||||||
@@ -279,6 +246,8 @@ void registerAllPages(PageList &list){
|
|||||||
list.add(®isterPageXTETrack);
|
list.add(®isterPageXTETrack);
|
||||||
extern PageDescription registerPageFluid;
|
extern PageDescription registerPageFluid;
|
||||||
list.add(®isterPageFluid);
|
list.add(®isterPageFluid);
|
||||||
|
extern PageDescription registerPageBarograph;
|
||||||
|
list.add(®isterPageBarograph);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Undervoltage detection for shutdown display
|
// Undervoltage detection for shutdown display
|
||||||
@@ -286,7 +255,7 @@ void underVoltageDetection(GwApi *api, CommonData &common){
|
|||||||
// Read settings
|
// Read settings
|
||||||
float vslope = uint(api->getConfig()->getConfigItem(api->getConfig()->vSlope,true)->asFloat());
|
float vslope = uint(api->getConfig()->getConfigItem(api->getConfig()->vSlope,true)->asFloat());
|
||||||
float voffset = uint(api->getConfig()->getConfigItem(api->getConfig()->vOffset,true)->asFloat());
|
float voffset = uint(api->getConfig()->getConfigItem(api->getConfig()->vOffset,true)->asFloat());
|
||||||
// Read supply voltage
|
// Read supplay voltage
|
||||||
float actVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // V = 1/20 * Vin
|
float actVoltage = (float(analogRead(OBP_ANALOG0)) * 3.3 / 4096 + 0.17) * 20; // V = 1/20 * Vin
|
||||||
actVoltage = actVoltage * vslope + voffset;
|
actVoltage = actVoltage * vslope + voffset;
|
||||||
if(actVoltage < MIN_VOLTAGE){
|
if(actVoltage < MIN_VOLTAGE){
|
||||||
@@ -318,9 +287,7 @@ void OBP60Task(GwApi *api){
|
|||||||
// return;
|
// return;
|
||||||
GwLog *logger=api->getLogger();
|
GwLog *logger=api->getLogger();
|
||||||
GwConfigHandler *config=api->getConfig();
|
GwConfigHandler *config=api->getConfig();
|
||||||
#ifdef HARDWARE_V21
|
|
||||||
startLedTask(api);
|
startLedTask(api);
|
||||||
#endif
|
|
||||||
PageList allPages;
|
PageList allPages;
|
||||||
registerAllPages(allPages);
|
registerAllPages(allPages);
|
||||||
CommonData commonData;
|
CommonData commonData;
|
||||||
@@ -388,10 +355,6 @@ void OBP60Task(GwApi *api){
|
|||||||
// Init pages
|
// Init pages
|
||||||
int numPages=1;
|
int numPages=1;
|
||||||
PageStruct pages[MAX_PAGE_NUMBER];
|
PageStruct pages[MAX_PAGE_NUMBER];
|
||||||
// Set start page
|
|
||||||
int pageNumber = int(api->getConfig()->getConfigItem(api->getConfig()->startPage,true)->asInt()) - 1;
|
|
||||||
int lastPage=pageNumber;
|
|
||||||
|
|
||||||
BoatValueList boatValues; //all the boat values for the api query
|
BoatValueList boatValues; //all the boat values for the api query
|
||||||
//commonData.distanceformat=config->getString(xxx);
|
//commonData.distanceformat=config->getString(xxx);
|
||||||
//add all necessary data to common data
|
//add all necessary data to common data
|
||||||
@@ -415,7 +378,6 @@ void OBP60Task(GwApi *api){
|
|||||||
pages[i].description=description;
|
pages[i].description=description;
|
||||||
pages[i].page=description->creator(commonData);
|
pages[i].page=description->creator(commonData);
|
||||||
pages[i].parameters.pageName=pageType;
|
pages[i].parameters.pageName=pageType;
|
||||||
pages[i].parameters.pageNumber = i + 1;
|
|
||||||
LOG_DEBUG(GwLog::DEBUG,"found page %s for number %d",pageType.c_str(),i);
|
LOG_DEBUG(GwLog::DEBUG,"found page %s for number %d",pageType.c_str(),i);
|
||||||
//fill in all the user defined parameters
|
//fill in all the user defined parameters
|
||||||
for (int uid=0;uid<description->userParam;uid++){
|
for (int uid=0;uid<description->userParam;uid++){
|
||||||
@@ -435,13 +397,6 @@ void OBP60Task(GwApi *api){
|
|||||||
pages[i].parameters.values.push_back(value);
|
pages[i].parameters.values.push_back(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display screenshot handler for HTTP request
|
|
||||||
// http://192.168.15.1/api/user/OBP60Task/screenshot
|
|
||||||
api->registerRequestHandler("screenshot", [api, &pageNumber, pages](AsyncWebServerRequest *request) {
|
|
||||||
doImageRequest(api, &pageNumber, pages, request);
|
|
||||||
});
|
|
||||||
|
|
||||||
//now we have prepared the page data
|
//now we have prepared the page data
|
||||||
//we start a separate task that will fetch our keys...
|
//we start a separate task that will fetch our keys...
|
||||||
MyData allParameters;
|
MyData allParameters;
|
||||||
@@ -478,6 +433,9 @@ void OBP60Task(GwApi *api){
|
|||||||
GwApi::BoatValue *hdop = boatValues.findValueOrCreate("HDOP"); // Load GpsHDOP
|
GwApi::BoatValue *hdop = boatValues.findValueOrCreate("HDOP"); // Load GpsHDOP
|
||||||
|
|
||||||
LOG_DEBUG(GwLog::LOG,"obp60task: start mainloop");
|
LOG_DEBUG(GwLog::LOG,"obp60task: start mainloop");
|
||||||
|
// Set start page
|
||||||
|
int pageNumber = int(api->getConfig()->getConfigItem(api->getConfig()->startPage,true)->asInt()) - 1;
|
||||||
|
int lastPage=pageNumber;
|
||||||
|
|
||||||
commonData.time = boatValues.findValueOrCreate("GPST"); // Load GpsTime
|
commonData.time = boatValues.findValueOrCreate("GPST"); // Load GpsTime
|
||||||
commonData.date = boatValues.findValueOrCreate("GPSD"); // Load GpsTime
|
commonData.date = boatValues.findValueOrCreate("GPSD"); // Load GpsTime
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
//we only compile for some boards
|
//we only compile for some boards
|
||||||
#ifdef BOARD_OBP60S3
|
#ifdef BOARD_OBP60S3
|
||||||
#define USBSerial Serial
|
#define USBSerial Serial
|
||||||
#ifdef HARDWARE_V21
|
|
||||||
// CAN NMEA2000
|
// CAN NMEA2000
|
||||||
#define ESP32_CAN_TX_PIN 46
|
#define ESP32_CAN_TX_PIN 46
|
||||||
#define ESP32_CAN_RX_PIN 3
|
#define ESP32_CAN_RX_PIN 3
|
||||||
@@ -13,18 +12,6 @@
|
|||||||
#define GWSERIAL_TX 17
|
#define GWSERIAL_TX 17
|
||||||
#define GWSERIAL_RX 8
|
#define GWSERIAL_RX 8
|
||||||
#define GWSERIAL_MODE "UNI"
|
#define GWSERIAL_MODE "UNI"
|
||||||
#endif
|
|
||||||
#ifdef HARDWARE_LIGHT
|
|
||||||
// CAN NMEA2000
|
|
||||||
#define ESP32_CAN_TX_PIN 15
|
|
||||||
#define ESP32_CAN_RX_PIN 16
|
|
||||||
// Bus load in 50mA steps
|
|
||||||
#define N2K_LOAD_LEVEL 2 // 5x50mA = 100mA max bus load with back light on
|
|
||||||
// RS485 NMEA0183
|
|
||||||
#define GWSERIAL_TX 9
|
|
||||||
#define GWSERIAL_RX 14
|
|
||||||
#define GWSERIAL_MODE "UNI"
|
|
||||||
#endif
|
|
||||||
// Allowed to set a new password for access point
|
// Allowed to set a new password for access point
|
||||||
#define FORCE_AP_PWCHANGE
|
#define FORCE_AP_PWCHANGE
|
||||||
|
|
||||||
|
|||||||
@@ -9,25 +9,22 @@ board_build.variants_dir = variants
|
|||||||
#board = obp60_s3_n8 #ESP32-S3 N8, 8MB flash, no PSRAM
|
#board = obp60_s3_n8 #ESP32-S3 N8, 8MB flash, no PSRAM
|
||||||
#board = obp60_s3_n16 #ESP32-S3 N16,16MB flash, no PSRAM, zero series
|
#board = obp60_s3_n16 #ESP32-S3 N16,16MB flash, no PSRAM, zero series
|
||||||
#board = obp60_s3_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM
|
#board = obp60_s3_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM
|
||||||
#board = obp60_s3_n16r8 #ESP32-S3 N16R8, 16MB flash, 8MB PSRAM, production series
|
board = obp60_s3_n16r8 #ESP32-S3 N16R8, 16MB flash, 8MB PSRAM, production series
|
||||||
board = obp60_s3_light_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM, OBP60 clone
|
#board_build.partitions = default_8MB.csv #ESP32-S3 N8, 8MB flash
|
||||||
board_build.partitions = default_8MB.csv #ESP32-S3 N8, 8MB flash
|
board_build.partitions = default_16MB.csv #ESP32-S3 N16, 16MB flash
|
||||||
#board_build.partitions = default_16MB.csv #ESP32-S3 N16, 16MB flash
|
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
${basedeps.lib_deps}
|
${basedeps.lib_deps}
|
||||||
Wire
|
Wire
|
||||||
SPI
|
SPI
|
||||||
SD
|
|
||||||
esphome/AsyncTCP-esphome@2.0.1
|
esphome/AsyncTCP-esphome@2.0.1
|
||||||
robtillaart/PCF8574@0.3.9
|
robtillaart/PCF8574@0.3.9
|
||||||
adafruit/Adafruit Unified Sensor @ 1.1.13
|
adafruit/Adafruit Unified Sensor @ 1.1.13
|
||||||
blemasle/MCP23017@2.0.0
|
blemasle/MCP23017@2.0.0
|
||||||
adafruit/Adafruit BusIO@1.5.0
|
adafruit/Adafruit BusIO@1.5.0
|
||||||
adafruit/Adafruit GFX Library@1.11.9
|
adafruit/Adafruit GFX Library@1.11.9
|
||||||
#zinggjm/GxEPD2@1.5.8
|
zinggjm/GxEPD2@1.5.8
|
||||||
#https://github.com/ZinggJM/GxEPD2
|
#https://github.com/ZinggJM/GxEPD2
|
||||||
https://github.com/thooge/GxEPD2
|
|
||||||
sstaub/Ticker@4.4.0
|
sstaub/Ticker@4.4.0
|
||||||
adafruit/Adafruit BMP280 Library@2.6.2
|
adafruit/Adafruit BMP280 Library@2.6.2
|
||||||
adafruit/Adafruit BME280 Library@2.2.2
|
adafruit/Adafruit BME280 Library@2.2.2
|
||||||
@@ -37,26 +34,23 @@ lib_deps =
|
|||||||
paulstoffregen/OneWire@2.3.8
|
paulstoffregen/OneWire@2.3.8
|
||||||
milesburton/DallasTemperature@3.11.0
|
milesburton/DallasTemperature@3.11.0
|
||||||
signetica/SunRise@2.0.2
|
signetica/SunRise@2.0.2
|
||||||
adafruit/Adafruit FRAM I2C@^2.0.3
|
|
||||||
build_flags=
|
build_flags=
|
||||||
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
|
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
|
||||||
# -D ARDUINO_USB_MODE=1 #0=OTG (to implement other external devices), 1=CDC (is a serial device)
|
# -D ARDUINO_USB_MODE=1 #0=OTG (to implement other external devices), 1=CDC (is a serial device)
|
||||||
# -D ARDUINO_USB_CDC_ON_BOOT=0 #0=JTAG, 1=CDC (serial device)
|
# -D ARDUINO_USB_CDC_ON_BOOT=1 #0=JTAG, 1=CDC (serial device)
|
||||||
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (seral device)
|
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (seral device)
|
||||||
# -D TIME=$UNIX_TIME #Set PC time for RTC (only settable via VSC)
|
# -D TIME=$UNIX_TIME #Set PC time for RTC (only settable via VSC)
|
||||||
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
|
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
|
||||||
-D BOARD_OBP60S3 #Board OBP60 V2.1 with ESP32S3
|
-D BOARD_OBP60S3 #Board OBP60 V2.1 with ESP32S3
|
||||||
# -D HARDWARE_V20 #OBP60 hardware revision V2.0
|
# -D HARDWARE_V20 #Hardware revision V2.0
|
||||||
# -D HARDWARE_V21 #OBP60 hardware revision V2.1
|
-D HARDWARE_V21 #Hardware revision V2.1
|
||||||
-D HARDWARE_LIGHT #OBP60 hardware clone
|
|
||||||
# -D DISPLAY_GDEW042T2 #old E-Ink display from Waveshare, R10 0.47 ohm
|
# -D DISPLAY_GDEW042T2 #old E-Ink display from Waveshare, R10 0.47 ohm
|
||||||
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
|
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
|
||||||
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm
|
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm
|
||||||
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm
|
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm
|
||||||
${env.build_flags}
|
${env.build_flags}
|
||||||
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
|
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
|
||||||
#upload_port = /dev/ttyACM0 #OBP60 original
|
upload_port = /dev/ttyACM0
|
||||||
upload_port = /dev/ttyUSB0 #OBP60 clone
|
|
||||||
upload_protocol = esptool #firmware upload via USB OTG seriell, by first upload need to set the ESP32-S3 in the upload mode with shortcut GND to Pin27
|
upload_protocol = esptool #firmware upload via USB OTG seriell, by first upload need to set the ESP32-S3 in the upload mode with shortcut GND to Pin27
|
||||||
upload_speed = 230400
|
upload_speed = 230400
|
||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
|
|||||||
@@ -1,61 +0,0 @@
|
|||||||
[platformio]
|
|
||||||
#if you want a pio run to only build
|
|
||||||
#your special environments you can set this here
|
|
||||||
#by uncommenting the next line
|
|
||||||
default_envs = obp60_s3
|
|
||||||
[env:obp60_s3]
|
|
||||||
platform = espressif32@6.8.1
|
|
||||||
board_build.variants_dir = variants
|
|
||||||
#board = obp60_s3_n8 #ESP32-S3 N8, 8MB flash, no PSRAM
|
|
||||||
#board = obp60_s3_n16 #ESP32-S3 N16,16MB flash, no PSRAM, zero series
|
|
||||||
#board = obp60_s3_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM
|
|
||||||
#board = obp60_s3_n16r8 #ESP32-S3 N16R8, 16MB flash, 8MB PSRAM, production series
|
|
||||||
board = obp60_s3_light_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM, OBP60 clone
|
|
||||||
board_build.partitions = default_8MB.csv #ESP32-S3 N8, 8MB flash
|
|
||||||
#board_build.partitions = default_16MB.csv #ESP32-S3 N16, 16MB flash
|
|
||||||
framework = arduino
|
|
||||||
lib_deps =
|
|
||||||
${basedeps.lib_deps}
|
|
||||||
Wire
|
|
||||||
SPI
|
|
||||||
esphome/AsyncTCP-esphome@2.0.1
|
|
||||||
robtillaart/PCF8574@0.3.9
|
|
||||||
adafruit/Adafruit Unified Sensor @ 1.1.13
|
|
||||||
blemasle/MCP23017@2.0.0
|
|
||||||
adafruit/Adafruit BusIO@1.5.0
|
|
||||||
adafruit/Adafruit GFX Library@1.11.9
|
|
||||||
#zinggjm/GxEPD2@1.5.8
|
|
||||||
#https://github.com/ZinggJM/GxEPD2
|
|
||||||
https://github.com/thooge/GxEPD2
|
|
||||||
sstaub/Ticker@4.4.0
|
|
||||||
adafruit/Adafruit BMP280 Library@2.6.2
|
|
||||||
adafruit/Adafruit BME280 Library@2.2.2
|
|
||||||
adafruit/Adafruit BMP085 Library@1.2.1
|
|
||||||
enjoyneering/HTU21D@1.2.1
|
|
||||||
robtillaart/INA226@0.2.0
|
|
||||||
paulstoffregen/OneWire@2.3.8
|
|
||||||
milesburton/DallasTemperature@3.11.0
|
|
||||||
signetica/SunRise@2.0.2
|
|
||||||
adafruit/Adafruit FRAM I2C@^2.0.3
|
|
||||||
build_flags=
|
|
||||||
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
|
|
||||||
# -D ARDUINO_USB_MODE=1 #0=OTG (to implement other external devices), 1=CDC (is a serial device)
|
|
||||||
# -D ARDUINO_USB_CDC_ON_BOOT=1 #0=JTAG, 1=CDC (serial device)
|
|
||||||
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (seral device)
|
|
||||||
# -D TIME=$UNIX_TIME #Set PC time for RTC (only settable via VSC)
|
|
||||||
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
|
|
||||||
-D BOARD_OBP60S3 #Board OBP60 V2.1 with ESP32S3
|
|
||||||
# -D HARDWARE_V20 #OBP60 hardware revision V2.0
|
|
||||||
# -D HARDWARE_V21 #OBP60 hardware revision V2.1
|
|
||||||
-D HARDWARE_LIGHT #OBP60 hardware clone
|
|
||||||
# -D DISPLAY_GDEW042T2 #old E-Ink display from Waveshare, R10 0.47 ohm
|
|
||||||
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
|
|
||||||
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm
|
|
||||||
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm
|
|
||||||
${env.build_flags}
|
|
||||||
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
|
|
||||||
#upload_port = /dev/ttyACM0 #OBP60 original
|
|
||||||
upload_port = /dev/ttyUSB0 #OBP60 clone
|
|
||||||
upload_protocol = esptool #firmware upload via USB OTG seriell, by first upload need to set the ESP32-S3 in the upload mode with shortcut GND to Pin27
|
|
||||||
upload_speed = 230400
|
|
||||||
monitor_speed = 115200
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
[platformio]
|
|
||||||
#if you want a pio run to only build
|
|
||||||
#your special environments you can set this here
|
|
||||||
#by uncommenting the next line
|
|
||||||
default_envs = obp60_s3
|
|
||||||
[env:obp60_s3]
|
|
||||||
platform = espressif32@6.8.1
|
|
||||||
board_build.variants_dir = variants
|
|
||||||
#board = obp60_s3_n8 #ESP32-S3 N8, 8MB flash, no PSRAM
|
|
||||||
#board = obp60_s3_n16 #ESP32-S3 N16,16MB flash, no PSRAM, zero series
|
|
||||||
#board = obp60_s3_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM
|
|
||||||
board = obp60_s3_n16r8 #ESP32-S3 N16R8, 16MB flash, 8MB PSRAM, production series
|
|
||||||
#board = obp60_s3_light_n8r8 #ESP32-S3 N8R8, 8MB flash, 8MB PSRAM, OBP60 clone
|
|
||||||
#board_build.partitions = default_8MB.csv #ESP32-S3 N8, 8MB flash
|
|
||||||
board_build.partitions = default_16MB.csv #ESP32-S3 N16, 16MB flash
|
|
||||||
framework = arduino
|
|
||||||
lib_deps =
|
|
||||||
${basedeps.lib_deps}
|
|
||||||
Wire
|
|
||||||
SPI
|
|
||||||
esphome/AsyncTCP-esphome@2.0.1
|
|
||||||
robtillaart/PCF8574@0.3.9
|
|
||||||
adafruit/Adafruit Unified Sensor @ 1.1.13
|
|
||||||
blemasle/MCP23017@2.0.0
|
|
||||||
adafruit/Adafruit BusIO@1.5.0
|
|
||||||
adafruit/Adafruit GFX Library@1.11.9
|
|
||||||
#zinggjm/GxEPD2@1.5.8
|
|
||||||
#https://github.com/ZinggJM/GxEPD2
|
|
||||||
https://github.com/thooge/GxEPD2
|
|
||||||
sstaub/Ticker@4.4.0
|
|
||||||
adafruit/Adafruit BMP280 Library@2.6.2
|
|
||||||
adafruit/Adafruit BME280 Library@2.2.2
|
|
||||||
adafruit/Adafruit BMP085 Library@1.2.1
|
|
||||||
enjoyneering/HTU21D@1.2.1
|
|
||||||
robtillaart/INA226@0.2.0
|
|
||||||
paulstoffregen/OneWire@2.3.8
|
|
||||||
milesburton/DallasTemperature@3.11.0
|
|
||||||
signetica/SunRise@2.0.2
|
|
||||||
adafruit/Adafruit FRAM I2C@^2.0.3
|
|
||||||
build_flags=
|
|
||||||
#https://thingpulse.com/usb-settings-for-logging-with-the-esp32-s3-in-platformio/?srsltid=AfmBOopGskbkr4GoeVkNlFaZXe_zXkLceKF6Rn-tmoXABCeAR2vWsdHL
|
|
||||||
# -D ARDUINO_USB_MODE=1 #0=OTG (to implement other external devices), 1=CDC (is a serial device)
|
|
||||||
# -D ARDUINO_USB_CDC_ON_BOOT=1 #0=JTAG, 1=CDC (serial device)
|
|
||||||
# -D CORE_DEBUG_LEVEL=1 #Debug level for CPU core via CDC (seral device)
|
|
||||||
# -D TIME=$UNIX_TIME #Set PC time for RTC (only settable via VSC)
|
|
||||||
-D DISABLE_DIAGNOSTIC_OUTPUT #Disable diagnostic output for GxEPD2 lib
|
|
||||||
-D BOARD_OBP60S3 #Board OBP60 V2.1 with ESP32S3
|
|
||||||
# -D HARDWARE_V20 #OBP60 hardware revision V2.0
|
|
||||||
-D HARDWARE_V21 #OBP60 hardware revision V2.1
|
|
||||||
# -D HARDWARE_LIGHT #OBP60 hardware clone
|
|
||||||
# -D DISPLAY_GDEW042T2 #old E-Ink display from Waveshare, R10 0.47 ohm
|
|
||||||
-D DISPLAY_GDEY042T81 #new E-Ink display from Waveshare, R10 2.2 ohm
|
|
||||||
# -D DISPLAY_GYE042A87 #alternativ E-Ink display from Genyo Optical, R10 2.2 ohm
|
|
||||||
# -D DISPLAY_SE0420NQ04 #alternativ E-Ink display from SID Technology, R10 2.2 ohm
|
|
||||||
${env.build_flags}
|
|
||||||
#CONFIG_ESP_TASK_WDT_TIMEOUT_S = 10 #Task Watchdog timeout period (seconds) [1...60] 5 default
|
|
||||||
upload_port = /dev/ttyACM0 #OBP60 original
|
|
||||||
#upload_port = /dev/ttyUSB0 #OBP60 clone
|
|
||||||
upload_protocol = esptool #firmware upload via USB OTG seriell, by first upload need to set the ESP32-S3 in the upload mode with shortcut GND to Pin27
|
|
||||||
upload_speed = 230400
|
|
||||||
monitor_speed = 115200
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
#ifndef Pins_Arduino_h
|
|
||||||
#define Pins_Arduino_h
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "soc/soc_caps.h"
|
|
||||||
|
|
||||||
#define USB_VID 0x303a
|
|
||||||
#define USB_PID 0x1001
|
|
||||||
|
|
||||||
/*
|
|
||||||
#define EXTERNAL_NUM_INTERRUPTS 46
|
|
||||||
#define NUM_DIGITAL_PINS 48
|
|
||||||
#define NUM_ANALOG_INPUTS 20
|
|
||||||
|
|
||||||
// Multi Function Display OBP60 V2.0
|
|
||||||
static const uint8_t LED_BUILTIN = SOC_GPIO_PIN_COUNT+48;
|
|
||||||
#define BUILTIN_LED LED_BUILTIN // backward compatibility
|
|
||||||
#define LED_BUILTIN LED_BUILTIN
|
|
||||||
#define RGB_BUILTIN LED_BUILTIN
|
|
||||||
#define RGB_BRIGHTNESS 64
|
|
||||||
|
|
||||||
#define analogInputToDigitalPin(p) (((p)<20)?(analogChannelToDigitalPin(p)):-1)
|
|
||||||
#define digitalPinToInterrupt(p) (((p)<48)?(p):-1)
|
|
||||||
#define digitalPinHasPWM(p) (p < 46)
|
|
||||||
*/
|
|
||||||
|
|
||||||
static const uint8_t TX = 43;
|
|
||||||
static const uint8_t RX = 44;
|
|
||||||
|
|
||||||
static const uint8_t SDA = 21;
|
|
||||||
static const uint8_t SCL = 38;
|
|
||||||
|
|
||||||
static const uint8_t SS = 45;
|
|
||||||
static const uint8_t MOSI = 11;
|
|
||||||
static const uint8_t MISO = 13;
|
|
||||||
static const uint8_t SCK = 12;
|
|
||||||
|
|
||||||
static const uint8_t A0 = 1;
|
|
||||||
static const uint8_t A1 = 2;
|
|
||||||
static const uint8_t A2 = 3;
|
|
||||||
static const uint8_t A3 = 4;
|
|
||||||
static const uint8_t A4 = 5;
|
|
||||||
static const uint8_t A5 = 6;
|
|
||||||
static const uint8_t A6 = 7;
|
|
||||||
static const uint8_t A7 = 8;
|
|
||||||
static const uint8_t A8 = 9;
|
|
||||||
static const uint8_t A9 = 10;
|
|
||||||
static const uint8_t A10 = 11;
|
|
||||||
static const uint8_t A11 = 12;
|
|
||||||
static const uint8_t A12 = 13;
|
|
||||||
static const uint8_t A13 = 14;
|
|
||||||
static const uint8_t A14 = 15;
|
|
||||||
static const uint8_t A15 = 16;
|
|
||||||
static const uint8_t A16 = 17;
|
|
||||||
static const uint8_t A17 = 18;
|
|
||||||
static const uint8_t A18 = 19;
|
|
||||||
static const uint8_t A19 = 20;
|
|
||||||
|
|
||||||
static const uint8_t T1 = 1;
|
|
||||||
static const uint8_t T2 = 2;
|
|
||||||
static const uint8_t T3 = 3;
|
|
||||||
static const uint8_t T4 = 4;
|
|
||||||
static const uint8_t T5 = 5;
|
|
||||||
static const uint8_t T6 = 6;
|
|
||||||
static const uint8_t T7 = 7;
|
|
||||||
static const uint8_t T8 = 8;
|
|
||||||
static const uint8_t T9 = 9;
|
|
||||||
static const uint8_t T10 = 10;
|
|
||||||
static const uint8_t T11 = 11;
|
|
||||||
static const uint8_t T12 = 12;
|
|
||||||
static const uint8_t T13 = 13;
|
|
||||||
static const uint8_t T14 = 14;
|
|
||||||
|
|
||||||
#endif /* Pins_Arduino_h */
|
|
||||||
Reference in New Issue
Block a user