Compare commits

..

No commits in common. "494acbf0d056595857b456014c74abdc0855d032" and "c4406fd00945fdafcd00aef1a8cda09bf630452b" have entirely different histories.

8 changed files with 115 additions and 202 deletions

View File

@ -81,7 +81,7 @@ void hardwareInit(GwApi *api)
Wire.begin();
// Init PCF8574 digital outputs
Wire.setClock(I2C_SPEED); // Set I2C clock as defined
Wire.setClock(I2C_SPEED); // Set I2C clock on 10 kHz
if(pcf8574_Out.begin()){ // Initialize PCF8574
pcf8574_Out.write8(255); // Clear all outputs
}

View File

@ -1,9 +1,9 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#ifndef _OBP60FUNCTIONS_H
#define _OBP60FUNCTIONS_H
#include <Arduino.h>
#include "OBP60Hardware.h"
#include "OBPKeyboardTask.h"
// Global vars
// Touch keypad over ESP32 touch sensor inputs
@ -58,10 +58,10 @@ void initKeys(CommonData &commonData) {
commonData.keydata[5].h = height;
}
#ifdef HARDWARE_V21
// Keypad functions for original OBP60 hardware
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
#ifdef HARDWARE_V21
// Keypad functions for original OBP60 hardware
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
// Touch sensor values
// 35000 - Not touched
// 50000 - Light toched with fingertip
@ -233,35 +233,35 @@ int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
keycodeold2 = keycode2;
return keystatus;
}
#endif
}
#endif
#ifdef BOARD_OBP40S3
int readSensorpads(){
// Read key code
if (digitalRead(UP) == LOW) {
#ifdef BOARD_OBP40S3
int readSensorpads(){
// Read key code
if(digitalRead(UP) == LOW){
keycode = 10; // Left swipe
}
else if (digitalRead(DOWN) == LOW) {
}
else if(digitalRead(DOWN) == LOW){
keycode = 9; // Right swipe
}
else if (digitalRead(CONF) == LOW) {
}
else if(digitalRead(CONF) == LOW){
keycode = 3; // Key 3
}
else if (digitalRead(MENUE) == LOW) {
}
else if(digitalRead(MENUE) == LOW){
keycode = 1; // Key 1
}
else if (digitalRead(EXIT) == LOW) {
}
else if(digitalRead(EXIT) == LOW){
keycode = 2; // Key 2
}
else {
}
else{
keycode = 0; // No key activ
}
return keycode;
}
return keycode;
}
// Keypad functions for OBP60 clone (thSensitivity is inactiv)
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
// Keypad functions for OBP60 clone (thSensitivity is inactiv)
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
pinMode(UP, INPUT);
pinMode(DOWN, INPUT);
pinMode(CONF, INPUT);
@ -273,64 +273,31 @@ int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
// Detect key
if (keycode > 0 ){
if(keycode != keycodeold){
starttime = millis(); // Start key pressed
keycodeold = keycode;
}
// If key pressed longer than 100ms
if(millis() > starttime + 100 && keycode == keycodeold) {
if (use_syspage and keycode == 3) {
keystatus = 12;
} else {
keystatus = keycode;
}
// Copy keycode
keycodeold = keycode;
// 100% Task-CPU RLY?
while(readSensorpads() > 0){} // Wait for pad release
delay(keydelay);
if(keycode != keycodeold){
starttime = millis(); // Start key pressed
keycodeold = keycode;
}
// If key pressed longer than 100ms
if(millis() > starttime + 100 && keycode == keycodeold) {
if (use_syspage and keycode == 3) {
keystatus = 12;
} else {
keystatus = keycode;
}
// Copy keycode
keycodeold = keycode;
while(readSensorpads() > 0){} // Wait for pad release
delay(keydelay);
}
}
else {
keycode = 0;
keycodeold = 0;
keystatus = 0;
else{
keycode = 0;
keycodeold = 0;
keystatus = 0;
}
return keystatus;
}
#endif
void keyboardTask(void *param) {
// params needed:
// queue
// logger
// sensitivity
// use_syspage for deep sleep activation
KbTaskData *data = (KbTaskData *)param;
int keycode = 0;
data->logger->logDebug(GwLog::LOG, "Start keyboard task");
while (true) {
keycode = readKeypad(data->logger, data->sensitivity, data->use_syspage);
//send a key event
if (keycode != 0) {
xQueueSend(data->queue, &keycode, 0);
data->logger->logDebug(GwLog::LOG,"kbtask: send keycode: %d", keycode);
}
delay(20); // 50Hz update rate (20ms)
}
vTaskDelete(NULL);
}
void createKeyboardTask(KbTaskData *param) {
TaskHandle_t xHandle = NULL;
if (xTaskCreate(keyboardTask, "keyboard", configMINIMAL_STACK_SIZE + 1024, param, configMAX_PRIORITIES-1, &xHandle) != pdPASS) {
param->logger->logDebug(GwLog::ERROR, "Failed to create keyboard task!");
};
}
}
#endif
#endif

View File

@ -1,16 +0,0 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "GwLog.h"
#include "Pagedata.h"
typedef struct {
QueueHandle_t queue;
GwLog* logger = nullptr;
uint sensitivity = 100;
#ifdef BOARD_OBP40S3
bool use_syspage = true;
#endif
} KbTaskData;
void initKeys(CommonData &commonData);
void createKeyboardTask(KbTaskData *param);

View File

@ -1,4 +1,3 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include <Adafruit_Sensor.h> // Adafruit Lib for sensors
#include <Adafruit_BME280.h> // Adafruit Lib for BME280
@ -569,11 +568,6 @@ void sensorTask(void *param){
// Send data from environment sensor all 2s
if(millis() > starttime6 + 2000){
starttime6 = millis();
// DEBUG
UBaseType_t stackfree = uxTaskGetStackHighWaterMark(NULL);
api->getLogger()->logDebug(GwLog::LOG, "obpSensortask Stack=%d", stackfree);
unsigned char TempSource = 2; // Inside temperature
unsigned char PressureSource = 0; // Atmospheric pressure
unsigned char HumiditySource = 0; // Inside humidity
@ -791,12 +785,8 @@ void sensorTask(void *param){
vTaskDelete(NULL);
}
void createSensorTask(SharedData *shared) {
TaskHandle_t xHandle = NULL;
GwLog *logger = shared->api->getLogger();
esp_err_t err = xTaskCreate(sensorTask, "readSensors", configMINIMAL_STACK_SIZE + 2048, shared, 3, &xHandle);
if ( err != pdPASS) {
logger->logDebug(GwLog::ERROR, "Failed to create sensor task! (err=%d)", err);
};
void createSensorTask(SharedData *shared){
xTaskCreate(sensorTask,"readSensors",10000,shared,3,NULL);
}
#endif

View File

@ -1,4 +1,3 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "GwSynchronized.h"
#include "GwApi.h"

View File

@ -8,7 +8,7 @@
* 1. Hard and software information
* 2. System settings
* 3. System configuration: running and NVRAM
* 4. NMEA2000 device list if NMEA2000 enabled
* 4. NMEA2000 device list
* 5. SD Card information if available
*
* TODO
@ -43,8 +43,6 @@
#define DISPLAYINFO STRINGIZE(EPDTYPE)
#define GXEPD2INFO STRINGIZE(GXEPD2VERS)
#define N2K_INACTIVE_AGE 30000
class PageSystem : public Page
{
private:
@ -70,10 +68,6 @@ private:
double homelon;
Nmea2kTwai *NMEA2000;
unsigned long n2kRxOld = 0; // to detect bus activity
unsigned long n2kTxOld = 0;
long n2k_ts = 0; // timestamp of last activity
bool n2k_active = false;
char mode = 'N'; // (N)ormal, (S)ettings, (C)onfiguration, (D)evice list, c(A)rd
int8_t editmode = -1; // marker for menu/edit/set function
@ -239,7 +233,7 @@ private:
epd->print(String(Heap_free));
// RAM free for task
UBaseType_t RAM_free = uxTaskGetStackHighWaterMark(NULL);
int RAM_free = uxTaskGetStackHighWaterMark(NULL);
epd->setCursor(202, y0 + 32);
epd->print("Task free:");
epd->setCursor(300, y0 + 32);
@ -396,6 +390,7 @@ private:
epd->setFont(&Ubuntu_Bold8pt8b);
epd->setCursor(x0, y0);
epd->print("Work in progress...");
#ifdef BOARD_OBP60S3
// This mode should not be callable by devices without card hardware
// In case of accidential reaching this, display a friendly message
@ -407,39 +402,32 @@ private:
magic.dat
version.dat
readme.txt
BAK/
CHARTS/
DATA/
IMAGES/
CHARTS/
LOGS/
DATA/
*/
// Simple test for magic file in root
epd->setCursor(x0, y0 + 16);
const char* file_magic = MOUNT_POINT "/magic.dat";
logger->logDebug(GwLog::LOG, "Test magicfile: %s", file_magic);
// Simple test for one file in root
epd->setCursor(x0, y0 + 32);
String file_test = MOUNT_POINT "/IMG/icon-settings2.pbm";
logger->logDebug(GwLog::LOG, "Testfile: %s", file_test.c_str());
struct stat st;
if (stat(file_magic, &st) == 0) {
epd->printf("Magicfile %s exists", file_magic);
if (stat(file_test.c_str(), &st) == 0) {
epd->printf("File %s exists", file_test.c_str());
} else {
epd->printf("Magicfile %s not found", file_magic);
epd->printf("File %s not found", file_test.c_str());
}
// Root directory check
DIR* dir = opendir(MOUNT_POINT);
int dy = 0;
if (dir != NULL) {
logger->logDebug(GwLog::LOG, "Root directory: %s", MOUNT_POINT);
struct dirent* entry;
while (((entry = readdir(dir)) != NULL) and (dy < 140)) {
epd->setCursor(x0, y0 + 64 + dy);
epd->print(entry->d_name);
// type 1 is file, type 2 is dir
if (entry->d_type == 2) {
epd->print("/");
}
dy += 20;
while ((entry = readdir(dir)) != NULL) {
logger->logDebug(GwLog::LOG, " %s type %d", entry->d_name, entry->d_type);
// type 1 is file
// type 2 is dir
}
closedir(dir);
} else {
@ -448,7 +436,7 @@ private:
// try to load example pbm file
// TODO create PBM load function in imglib
String filepath = MOUNT_POINT "/IMAGES/icon-settings2.pbm";
String filepath = MOUNT_POINT "/IMG/icon-settings2.pbm";
const char* file_img = filepath.c_str();
FILE* fh = fopen(file_img, "r");
if (fh != NULL) {
@ -506,12 +494,8 @@ private:
#endif
}
void displayModeDevicelist(bool bus_active) {
void displayModeDevicelist() {
// NMEA2000 device list
// TODO Check if NMEA2000 enabled globally
// if disabled this page should not be shown
epd->setFont(&Ubuntu_Bold12pt8b);
epd->setCursor(8, 48);
epd->print("NMEA2000 device list");
@ -524,11 +508,6 @@ private:
epd->print("TxD: ");
epd->print(String(commonData->status.n2kTx));
// show bus activity
epd->setCursor(20, 120);
epd->print("Bus: ");
epd->print(bus_active ? "active" : "inactive");
epd->setCursor(20, 140);
epd->printf("N2k source address: %d", NMEA2000->GetN2kSource());
@ -706,15 +685,7 @@ public:
displayModeSDCard();
break;
case 'D':
// check bus status
if (commonData->status.n2kRx != n2kRxOld || commonData->status.n2kTx != n2kTxOld) {
n2kRxOld = commonData->status.n2kRx;
n2kTxOld = commonData->status.n2kTx;
n2k_ts = millis();
} else {
n2k_active = (millis() - n2k_ts <= N2K_INACTIVE_AGE);
}
displayModeDevicelist(n2k_active);
displayModeDevicelist();
break;
}

View File

@ -331,8 +331,7 @@ public:
//*******************************************************************************************
// Show value6 (=fourth user-configured parameter) and ssource, so that they do not collide with the wind pointer
if (cos(value1) > 0) {
// pointer points upwards
if (cos(value1) > 0) {
epd->setFont(&DSEG7Classic_BoldItalic16pt7b);
epd->setCursor(160, 200);
epd->print(svalue6); // Value
@ -347,8 +346,7 @@ public:
}
epd->print(ssource); // true or app.
}
else {
// pointer points downwards
else {
epd->setFont(&DSEG7Classic_BoldItalic16pt7b);
epd->setCursor(160, 130);
epd->print(svalue6);
@ -357,11 +355,11 @@ public:
epd->print(" ");
epd->print(holdvalues ? unit6old : unit6);
if (sin(value1) > 0) {
epd->setCursor(160, 200);
epd->setCursor(160, 130);
} else {
epd->setCursor(220, 200);
epd->setCursor(220, 130);
}
epd->print(ssource); //true or app.
epd->print(ssource); //true or app.
}
return PAGE_UPDATE;

View File

@ -13,14 +13,10 @@
#include <NMEA0183Messages.h>
#include <GxEPD2_BW.h> // GxEPD2 lib for b/w E-Ink displays
#include "OBP60Extensions.h" // Functions lib for extension board
#include "OBPKeyboardTask.h" // Functions lib for keyboard handling
#include "OBP60Keypad.h" // Functions for keypad
#include "BoatDataCalibration.h" // Functions lib for data instance calibration
#include "OBPRingBuffer.h" // Functions lib with ring buffer for history storage of some boat data
#include "OBPDataOperations.h" // Functions lib for data operations such as true wind calculation
#include "OBP60QRWiFi.h" // Functions lib for WiFi QR code
#include "OBPSensorTask.h" // Functions lib for sensor data
#include "freertos/task.h" // WIP possible unused
#ifdef BOARD_OBP40S3
#include "driver/rtc_io.h" // Needs for weakup from deep sleep
@ -30,6 +26,8 @@
// Pictures
#include "images/OBP_400x300.xbm" // OBP Logo
#include "images/unknown.xbm" // unknown page indicator
#include "OBP60QRWiFi.h" // Functions lib for WiFi QR code
#include "OBPSensorTask.h" // Functions lib for sensor data
// Global vars
bool initComplete = false; // Initialization complete
@ -121,26 +119,34 @@ void OBP60Init(GwApi *api){
}
/* ux-functions not working WTF?
bool listTasks(GwLog *logger) {
UBaseType_t taskCount = uxTaskGetNumberOfTasks();
TaskStatus_t *taskStatusArray;
typedef struct {
int page0 = 0;
QueueHandle_t queue;
GwLog* logger = nullptr;
// GwApi* api = NULL;
uint sensitivity = 100;
bool use_syspage = true;
} MyData;
taskStatusArray = (TaskStatus_t *)pvPortMalloc(taskCount * sizeof(TaskStatus_t));
if (taskStatusArray != NULL) {
taskCount = uxTaskGetSystemState(taskStatusArray, taskCount, NULL);
for (UBaseType_t i = 0; i < taskCount; i++) {
logger->logDebug(GwLog::LOG, "Task Name: %s (Stack=%d)", taskStatusArray[i].pcTaskName,
taskStatusArray[i].usStackHighWaterMark);
// more fields in task status
// xHandle, uxCurrentPriority, uxBasePriority, usStackHighWaterMark
// Keyboard Task
void keyboardTask(void *param){
MyData *data=(MyData *)param;
int keycode = 0;
data->logger->logDebug(GwLog::LOG,"Start keyboard task");
// Loop for keyboard task
while (true){
keycode = readKeypad(data->logger, data->sensitivity, data->use_syspage);
//send a key event
if(keycode != 0){
xQueueSend(data->queue, &keycode, 0);
data->logger->logDebug(GwLog::LOG,"Send keycode: %d", keycode);
}
vPortFree(taskStatusArray);
return true;
delay(20); // 50Hz update rate (20ms)
}
logger->logDebug(GwLog::ERROR, "Failed to allocate memory for task list");
return false;
} */
vTaskDelete(NULL);
}
class BoatValueList{
public:
@ -712,18 +718,18 @@ void OBP60Task(GwApi *api){
doImageRequest(api, &pageNumber, pages, request);
});
// now we have prepared the page data
// we start a separate task that will fetch our keys...
KbTaskData kbparams;
kbparams.logger = api->getLogger();
kbparams.queue = xQueueCreate(10, sizeof(int));
kbparams.sensitivity = api->getConfig()->getInt(GwConfigDefinitions::tSensitivity);
//now we have prepared the page data
//we start a separate task that will fetch our keys...
MyData allParameters;
allParameters.logger=api->getLogger();
allParameters.page0=3;
allParameters.queue=xQueueCreate(10,sizeof(int));
allParameters.sensitivity= api->getConfig()->getInt(GwConfigDefinitions::tSensitivity);
#ifdef BOARD_OBP40S3
kbparams.use_syspage = syspage_enabled;
allParameters.use_syspage = syspage_enabled;
#endif
createKeyboardTask(&kbparams);
// we start a separate task to collect sensor data
SharedData *shared = new SharedData(api);
xTaskCreate(keyboardTask,"keyboard",2000,&allParameters,configMAX_PRIORITIES-1,NULL);
SharedData *shared=new SharedData(api);
createSensorTask(shared);
// Task Loop
@ -779,8 +785,6 @@ void OBP60Task(GwApi *api){
pages[pageNumber].page->setupKeys(); // Initialize keys for first page
// listTasks(logger);
// Main loop runs with 100ms
//####################################################################################
@ -832,7 +836,7 @@ void OBP60Task(GwApi *api){
// Check the keyboard message
int keyboardMessage=0;
while (xQueueReceive(kbparams.queue,&keyboardMessage, 0)) {
while (xQueueReceive(allParameters.queue,&keyboardMessage,0)){
LOG_DEBUG(GwLog::LOG,"new key from keyboard %d",keyboardMessage);
keypressed = true;