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(); Wire.begin();
// Init PCF8574 digital outputs // 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 if(pcf8574_Out.begin()){ // Initialize PCF8574
pcf8574_Out.write8(255); // Clear all outputs pcf8574_Out.write8(255); // Clear all outputs
} }

View File

@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later #ifndef _OBP60FUNCTIONS_H
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3 #define _OBP60FUNCTIONS_H
#include <Arduino.h> #include <Arduino.h>
#include "OBP60Hardware.h" #include "OBP60Hardware.h"
#include "OBPKeyboardTask.h"
// Global vars // Global vars
@ -58,9 +58,9 @@ void initKeys(CommonData &commonData) {
commonData.keydata[5].h = height; commonData.keydata[5].h = height;
} }
#ifdef HARDWARE_V21 #ifdef HARDWARE_V21
// Keypad functions for original OBP60 hardware // Keypad functions for original OBP60 hardware
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) { int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
// Touch sensor values // Touch sensor values
// 35000 - Not touched // 35000 - Not touched
@ -233,35 +233,35 @@ int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
keycodeold2 = keycode2; keycodeold2 = keycode2;
return keystatus; return keystatus;
} }
#endif #endif
#ifdef BOARD_OBP40S3 #ifdef BOARD_OBP40S3
int readSensorpads(){ int readSensorpads(){
// Read key code // Read key code
if (digitalRead(UP) == LOW) { if(digitalRead(UP) == LOW){
keycode = 10; // Left swipe keycode = 10; // Left swipe
} }
else if (digitalRead(DOWN) == LOW) { else if(digitalRead(DOWN) == LOW){
keycode = 9; // Right swipe keycode = 9; // Right swipe
} }
else if (digitalRead(CONF) == LOW) { else if(digitalRead(CONF) == LOW){
keycode = 3; // Key 3 keycode = 3; // Key 3
} }
else if (digitalRead(MENUE) == LOW) { else if(digitalRead(MENUE) == LOW){
keycode = 1; // Key 1 keycode = 1; // Key 1
} }
else if (digitalRead(EXIT) == LOW) { else if(digitalRead(EXIT) == LOW){
keycode = 2; // Key 2 keycode = 2; // Key 2
} }
else { else{
keycode = 0; // No key activ keycode = 0; // No key activ
}
return keycode;
} }
return keycode;
}
// Keypad functions for OBP60 clone (thSensitivity is inactiv) // Keypad functions for OBP60 clone (thSensitivity is inactiv)
int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) { int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
pinMode(UP, INPUT); pinMode(UP, INPUT);
pinMode(DOWN, INPUT); pinMode(DOWN, INPUT);
pinMode(CONF, INPUT); pinMode(CONF, INPUT);
@ -273,64 +273,31 @@ int readKeypad(GwLog* logger, uint thSensitivity, bool use_syspage) {
// Detect key // Detect key
if (keycode > 0 ){ if (keycode > 0 ){
if(keycode != keycodeold){ if(keycode != keycodeold){
starttime = millis(); // Start key pressed starttime = millis(); // Start key pressed
keycodeold = keycode; keycodeold = keycode;
} }
// If key pressed longer than 100ms // If key pressed longer than 100ms
if(millis() > starttime + 100 && keycode == keycodeold) { if(millis() > starttime + 100 && keycode == keycodeold) {
if (use_syspage and keycode == 3) { if (use_syspage and keycode == 3) {
keystatus = 12; keystatus = 12;
} else { } else {
keystatus = keycode; keystatus = keycode;
}
// Copy keycode
keycodeold = keycode;
// 100% Task-CPU RLY?
while(readSensorpads() > 0){} // Wait for pad release
delay(keydelay);
} }
// Copy keycode
keycodeold = keycode;
while(readSensorpads() > 0){} // Wait for pad release
delay(keydelay);
}
} }
else { else{
keycode = 0; keycode = 0;
keycodeold = 0; keycodeold = 0;
keystatus = 0; keystatus = 0;
} }
return keystatus; return keystatus;
} }
#endif #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 #if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
#include <Adafruit_Sensor.h> // Adafruit Lib for sensors #include <Adafruit_Sensor.h> // Adafruit Lib for sensors
#include <Adafruit_BME280.h> // Adafruit Lib for BME280 #include <Adafruit_BME280.h> // Adafruit Lib for BME280
@ -569,11 +568,6 @@ void sensorTask(void *param){
// Send data from environment sensor all 2s // Send data from environment sensor all 2s
if(millis() > starttime6 + 2000){ if(millis() > starttime6 + 2000){
starttime6 = millis(); 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 TempSource = 2; // Inside temperature
unsigned char PressureSource = 0; // Atmospheric pressure unsigned char PressureSource = 0; // Atmospheric pressure
unsigned char HumiditySource = 0; // Inside humidity unsigned char HumiditySource = 0; // Inside humidity
@ -791,12 +785,8 @@ void sensorTask(void *param){
vTaskDelete(NULL); vTaskDelete(NULL);
} }
void createSensorTask(SharedData *shared) {
TaskHandle_t xHandle = NULL; void createSensorTask(SharedData *shared){
GwLog *logger = shared->api->getLogger(); xTaskCreate(sensorTask,"readSensors",10000,shared,3,NULL);
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);
};
} }
#endif #endif

View File

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

View File

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

View File

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

View File

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