mirror of
https://github.com/thooge/esp32-nmea2000-obp60.git
synced 2025-12-14 06:23:07 +01:00
Merge branch 'wellenvogel:master' into master
This commit is contained in:
@@ -182,6 +182,13 @@ class GwApi{
|
||||
* The name should be similar to the function name of the user task (although not mandatory)
|
||||
*/
|
||||
virtual bool addUserTask(GwUserTaskFunction task,const String Name, int stackSize=2000)=0;
|
||||
/**
|
||||
* set a value that is used for calibration in config values
|
||||
* for cfg types calset, calvalue
|
||||
* @param name: the config name this value is used for
|
||||
* @param value: the current value
|
||||
*/
|
||||
virtual void setCalibrationValue(const String &name, double value);
|
||||
|
||||
/**
|
||||
* not thread safe methods
|
||||
|
||||
@@ -192,7 +192,8 @@ class GwBoatData{
|
||||
GWBOATDATA(double,HDOP,4000,formatDop)
|
||||
GWBOATDATA(double,PDOP,4000,formatDop)
|
||||
GWBOATDATA(double,VDOP,4000,formatDop)
|
||||
GWBOATDATA(double,RPOS,4000,formatCourse) //RudderPosition
|
||||
GWBOATDATA(double,RPOS,4000,formatWind) //RudderPosition
|
||||
GWBOATDATA(double,PRPOS,4000,formatWind) //second rudder pos
|
||||
GWBOATDATA(double,LAT,4000,formatLatitude)
|
||||
GWBOATDATA(double,LON,4000,formatLongitude)
|
||||
GWBOATDATA(double,ALT,4000,formatFixed0) //altitude
|
||||
|
||||
@@ -106,20 +106,34 @@ void GwChannel::setImpl(GwChannelInterface *impl){
|
||||
}
|
||||
void GwChannel::updateCounter(const char *msg, bool out)
|
||||
{
|
||||
char key[6];
|
||||
char key[7];
|
||||
key[0]=0;
|
||||
if (msg[0] == '$')
|
||||
{
|
||||
strncpy(key, &msg[3], 3);
|
||||
for (int i=0;i<6 && msg[i] != 0;i++){
|
||||
if (i>=3) {
|
||||
if (isalnum(msg[i]))key[i-3]=msg[i];
|
||||
else key[i-3]='_';
|
||||
}
|
||||
key[i-2]=0;
|
||||
}
|
||||
key[3] = 0;
|
||||
}
|
||||
else if (msg[0] == '!')
|
||||
{
|
||||
strncpy(key, &msg[1], 5);
|
||||
for (int i=0;i<6 && msg[i] != 0;i++){
|
||||
if (i>=1) {
|
||||
if (isalnum(msg[i]))key[i-1]=msg[i];
|
||||
else key[i-1]='_';
|
||||
}
|
||||
key[i]=0;
|
||||
}
|
||||
key[5] = 0;
|
||||
}
|
||||
else{
|
||||
return;
|
||||
}
|
||||
if (key[0] == 0) return;
|
||||
if (out){
|
||||
countOut->add(key);
|
||||
}
|
||||
@@ -159,7 +173,7 @@ void GwChannel::toJson(GwJsonDocument &doc){
|
||||
if (countIn) countIn->toJson(doc);
|
||||
}
|
||||
String GwChannel::toString(){
|
||||
String rt="CH:"+name;
|
||||
String rt="CH"+name+"("+sourceId+"):";
|
||||
rt+=enabled?"[ena]":"[dis]";
|
||||
rt+=NMEAin?"in,":"";
|
||||
rt+=NMEAout?"out,":"";
|
||||
|
||||
@@ -1,9 +1,33 @@
|
||||
#include "GwChannelList.h"
|
||||
#include "GwApi.h"
|
||||
//check for duplicate groove usages
|
||||
#define GW_PINDEFS
|
||||
#include "GwHardware.h"
|
||||
#include "GwSocketServer.h"
|
||||
#include "GwSerial.h"
|
||||
#include "GwTcpClient.h"
|
||||
class SerInit{
|
||||
public:
|
||||
int serial=-1;
|
||||
int rx=-1;
|
||||
int tx=-1;
|
||||
int mode=-1;
|
||||
int fixedBaud=-1;
|
||||
SerInit(int s,int r,int t, int m, int b=-1):
|
||||
serial(s),rx(r),tx(t),mode(m),fixedBaud(b){}
|
||||
};
|
||||
std::vector<SerInit> serialInits;
|
||||
|
||||
#define CFG_SERIAL(ser,...) \
|
||||
__MSG("serial config " #ser); \
|
||||
static GwInitializer<SerInit> __serial ## ser ## _init \
|
||||
(serialInits,SerInit(ser,__VA_ARGS__));
|
||||
#ifdef _GWI_SERIAL1
|
||||
CFG_SERIAL(1,_GWI_SERIAL1)
|
||||
#endif
|
||||
#ifdef _GWI_SERIAL2
|
||||
CFG_SERIAL(2,_GWI_SERIAL2)
|
||||
#endif
|
||||
class GwSerialLog : public GwLogWriter
|
||||
{
|
||||
static const size_t bufferSize = 4096;
|
||||
@@ -11,12 +35,13 @@ class GwSerialLog : public GwLogWriter
|
||||
int wp = 0;
|
||||
GwSerial *writer;
|
||||
bool disabled = false;
|
||||
|
||||
long flushTimeout=200;
|
||||
public:
|
||||
GwSerialLog(GwSerial *writer, bool disabled)
|
||||
GwSerialLog(GwSerial *writer, bool disabled,long flushTimeout=200)
|
||||
{
|
||||
this->writer = writer;
|
||||
this->disabled = disabled;
|
||||
this->flushTimeout=flushTimeout;
|
||||
logBuffer = new char[bufferSize];
|
||||
wp = 0;
|
||||
}
|
||||
@@ -39,16 +64,63 @@ public:
|
||||
{
|
||||
while (handled < wp)
|
||||
{
|
||||
writer->flush();
|
||||
if ( !writer->flush(flushTimeout)) break;
|
||||
size_t rt = writer->sendToClients(logBuffer + handled, -1, true);
|
||||
handled += rt;
|
||||
}
|
||||
if (handled < wp){
|
||||
if (handled > 0){
|
||||
memmove(logBuffer,logBuffer+handled,wp-handled);
|
||||
wp-=handled;
|
||||
logBuffer[handled]=0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
wp = 0;
|
||||
logBuffer[0] = 0;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class SerialWrapper : public GwChannelList::SerialWrapperBase{
|
||||
private:
|
||||
template<class C>
|
||||
void beginImpl(C *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){}
|
||||
void beginImpl(HardwareSerial *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){
|
||||
s->begin(baud,config,rxPin,txPin);
|
||||
}
|
||||
template<class C>
|
||||
void setError(C* s, GwLog *logger){}
|
||||
void setError(HardwareSerial *s,GwLog *logger){
|
||||
LOG_DEBUG(GwLog::LOG,"enable serial errors for channel %d",id);
|
||||
s->onReceiveError([logger,this](hardwareSerial_error_t err){
|
||||
LOG_DEBUG(GwLog::ERROR,"serial error on id %d: %d",this->id,(int)err);
|
||||
});
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
|
||||
void beginImpl(HWCDC *s,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1){
|
||||
s->begin(baud);
|
||||
}
|
||||
#endif
|
||||
T *serial;
|
||||
int id;
|
||||
public:
|
||||
SerialWrapper(T* s,int i):serial(s),id(i){}
|
||||
virtual void begin(GwLog* logger,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1) override{
|
||||
beginImpl(serial,baud,config,rxPin,txPin);
|
||||
setError(serial,logger);
|
||||
};
|
||||
virtual Stream *getStream() override{
|
||||
return serial;
|
||||
}
|
||||
virtual int getId() override{
|
||||
return id;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
GwChannelList::GwChannelList(GwLog *logger, GwConfigHandler *config){
|
||||
this->logger=logger;
|
||||
this->config=config;
|
||||
@@ -101,8 +173,18 @@ static SerialParam *getSerialParam(int id){
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void GwChannelList:: addSerial(HardwareSerial *stream,int id,int type,int rx,int tx){
|
||||
void GwChannelList::addSerial(int id, int rx, int tx, int type){
|
||||
if (id == 1){
|
||||
addSerial(new SerialWrapper<decltype(Serial1)>(&Serial1,SERIAL1_CHANNEL_ID),type,rx,tx);
|
||||
return;
|
||||
}
|
||||
if (id == 2){
|
||||
addSerial(new SerialWrapper<decltype(Serial2)>(&Serial2,SERIAL2_CHANNEL_ID),type,rx,tx);
|
||||
return;
|
||||
}
|
||||
LOG_DEBUG(GwLog::ERROR,"invalid serial config with id %d",id);
|
||||
}
|
||||
void GwChannelList::addSerial(GwChannelList::SerialWrapperBase *stream,int type,int rx,int tx){
|
||||
const char *mode=nullptr;
|
||||
switch (type)
|
||||
{
|
||||
@@ -123,9 +205,16 @@ void GwChannelList:: addSerial(HardwareSerial *stream,int id,int type,int rx,int
|
||||
LOG_DEBUG(GwLog::ERROR,"unknown serial type %d",type);
|
||||
return;
|
||||
}
|
||||
addSerial(stream,id,mode,rx,tx);
|
||||
addSerial(stream,mode,rx,tx);
|
||||
}
|
||||
void GwChannelList::addSerial(HardwareSerial *serialStream,int id,const String &mode,int rx,int tx){
|
||||
void GwChannelList::addSerial(GwChannelList::SerialWrapperBase *serialStream,const String &mode,int rx,int tx){
|
||||
int id=serialStream->getId();
|
||||
for (auto &&it:theChannels){
|
||||
if (it->isOwnSource(id)){
|
||||
LOG_DEBUG(GwLog::ERROR,"trying to re-add serial id=%d, ignoring",id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
SerialParam *param=getSerialParam(id);
|
||||
if (param == nullptr){
|
||||
logger->logDebug(GwLog::ERROR,"trying to set up an unknown serial channel: %d",id);
|
||||
@@ -161,8 +250,8 @@ void GwChannelList::addSerial(HardwareSerial *serialStream,int id,const String &
|
||||
if (tx < 0) canWrite=false;
|
||||
LOG_DEBUG(GwLog::DEBUG,"serial set up: mode=%s,rx=%d,canRead=%d,tx=%d,canWrite=%d",
|
||||
mode.c_str(),rx,(int)canRead,tx,(int)canWrite);
|
||||
serialStream->begin(config->getInt(param->baud,115200),SERIAL_8N1,rx,tx);
|
||||
GwSerial *serial = new GwSerial(logger, serialStream, id, canRead);
|
||||
serialStream->begin(logger,config->getInt(param->baud,115200),SERIAL_8N1,rx,tx);
|
||||
GwSerial *serial = new GwSerial(logger, serialStream->getStream(), id, canRead);
|
||||
LOG_DEBUG(GwLog::LOG, "starting serial %d ", id);
|
||||
GwChannel *channel = new GwChannel(logger, param->name, id);
|
||||
channel->setImpl(serial);
|
||||
@@ -179,7 +268,36 @@ void GwChannelList::addSerial(HardwareSerial *serialStream,int id,const String &
|
||||
LOG_DEBUG(GwLog::LOG, "%s", channel->toString().c_str());
|
||||
theChannels.push_back(channel);
|
||||
}
|
||||
|
||||
void GwChannelList::preinit(){
|
||||
for (auto &&init:serialInits){
|
||||
if (init.fixedBaud >= 0){
|
||||
switch(init.serial){
|
||||
case 1:
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG,"setting fixed baud %d for serial",init.fixedBaud);
|
||||
config->setValue(GwConfigDefinitions::serialBaud,String(init.fixedBaud),GwConfigInterface::READONLY);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG,"setting fixed baud %d for serial2",init.fixedBaud);
|
||||
config->setValue(GwConfigDefinitions::serial2Baud,String(init.fixedBaud),GwConfigInterface::READONLY);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_DEBUG(GwLog::ERROR,"invalid serial definition %d found",init.serial)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
template<typename S>
|
||||
long getFlushTimeout(S &s){
|
||||
return 200;
|
||||
}
|
||||
template<>
|
||||
long getFlushTimeout(HardwareSerial &s){
|
||||
return 2000;
|
||||
}
|
||||
void GwChannelList::begin(bool fallbackSerial){
|
||||
LOG_DEBUG(GwLog::DEBUG,"GwChannelList::begin");
|
||||
GwChannel *channel=NULL;
|
||||
@@ -187,7 +305,7 @@ void GwChannelList::begin(bool fallbackSerial){
|
||||
if (! fallbackSerial){
|
||||
GwSerial *usb=new GwSerial(NULL,&USBSerial,USB_CHANNEL_ID);
|
||||
USBSerial.begin(config->getInt(config->usbBaud));
|
||||
logger->setWriter(new GwSerialLog(usb,config->getBool(config->usbActisense)));
|
||||
logger->setWriter(new GwSerialLog(usb,config->getBool(config->usbActisense),getFlushTimeout(USBSerial)));
|
||||
logger->prefix="GWSERIAL:";
|
||||
channel=new GwChannel(logger,"USB",USB_CHANNEL_ID);
|
||||
channel->setImpl(usb);
|
||||
@@ -223,6 +341,11 @@ void GwChannelList::begin(bool fallbackSerial){
|
||||
LOG_DEBUG(GwLog::LOG,"%s",channel->toString().c_str());
|
||||
theChannels.push_back(channel);
|
||||
|
||||
//new serial config handling
|
||||
for (auto &&init:serialInits){
|
||||
addSerial(init.serial,init.rx,init.tx,init.mode);
|
||||
}
|
||||
//handle separate defines
|
||||
//serial 1
|
||||
#ifndef GWSERIAL_TX
|
||||
#define GWSERIAL_TX -1
|
||||
@@ -231,10 +354,10 @@ void GwChannelList::begin(bool fallbackSerial){
|
||||
#define GWSERIAL_RX -1
|
||||
#endif
|
||||
#ifdef GWSERIAL_TYPE
|
||||
addSerial(&Serial1,SERIAL1_CHANNEL_ID,GWSERIAL_TYPE,GWSERIAL_RX,GWSERIAL_TX);
|
||||
addSerial(new SerialWrapper<decltype(Serial1)>(&Serial1,SERIAL1_CHANNEL_ID),GWSERIAL_TYPE,GWSERIAL_RX,GWSERIAL_TX);
|
||||
#else
|
||||
#ifdef GWSERIAL_MODE
|
||||
addSerial(&Serial1,SERIAL1_CHANNEL_ID,GWSERIAL_MODE,GWSERIAL_RX,GWSERIAL_TX);
|
||||
addSerial(new SerialWrapper<decltype(Serial1)>(&Serial1,SERIAL1_CHANNEL_ID),GWSERIAL_MODE,GWSERIAL_RX,GWSERIAL_TX);
|
||||
#endif
|
||||
#endif
|
||||
//serial 2
|
||||
@@ -245,10 +368,10 @@ void GwChannelList::begin(bool fallbackSerial){
|
||||
#define GWSERIAL2_RX -1
|
||||
#endif
|
||||
#ifdef GWSERIAL2_TYPE
|
||||
addSerial(&Serial2,SERIAL2_CHANNEL_ID,GWSERIAL2_TYPE,GWSERIAL2_RX,GWSERIAL2_TX);
|
||||
addSerial(new SerialWrapper<decltype(Serial2)>(&Serial2,SERIAL2_CHANNEL_ID),GWSERIAL2_TYPE,GWSERIAL2_RX,GWSERIAL2_TX);
|
||||
#else
|
||||
#ifdef GWSERIAL2_MODE
|
||||
addSerial(&Serial2,SERIAL2_CHANNEL_ID,GWSERIAL2_MODE,GWSERIAL2_RX,GWSERIAL2_TX);
|
||||
addSerial(new SerialWrapper<decltype(Serial2)>(&Serial2,SERIAL2_CHANNEL_ID),GWSERIAL2_MODE,GWSERIAL2_RX,GWSERIAL2_TX);
|
||||
#endif
|
||||
#endif
|
||||
//tcp client
|
||||
|
||||
@@ -23,6 +23,12 @@ class GwSocketServer;
|
||||
class GwTcpClient;
|
||||
class GwChannelList{
|
||||
private:
|
||||
class SerialWrapperBase{
|
||||
public:
|
||||
virtual void begin(GwLog* logger,unsigned long baud, uint32_t config=SERIAL_8N1, int8_t rxPin=-1, int8_t txPin=-1)=0;
|
||||
virtual Stream *getStream()=0;
|
||||
virtual int getId()=0;
|
||||
};
|
||||
GwLog *logger;
|
||||
GwConfigHandler *config;
|
||||
typedef std::vector<GwChannel *> ChannelList;
|
||||
@@ -30,12 +36,16 @@ class GwChannelList{
|
||||
std::map<int,String> modes;
|
||||
GwSocketServer *sockets;
|
||||
GwTcpClient *client;
|
||||
void addSerial(HardwareSerial *stream,int id,const String &mode,int rx,int tx);
|
||||
void addSerial(HardwareSerial *stream,int id,int type,int rx,int tx);
|
||||
void addSerial(SerialWrapperBase *stream,const String &mode,int rx,int tx);
|
||||
void addSerial(SerialWrapperBase *stream,int type,int rx,int tx);
|
||||
public:
|
||||
void addSerial(int id, int rx, int tx, int type);
|
||||
GwChannelList(GwLog *logger, GwConfigHandler *config);
|
||||
typedef std::function<void(GwChannel *)> ChannelAction;
|
||||
void allChannels(ChannelAction action);
|
||||
//called to allow setting some predefined configs
|
||||
//e.g. from serial definitions
|
||||
void preinit();
|
||||
//initialize
|
||||
void begin(bool fallbackSerial=false);
|
||||
//status
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
#include <ArduinoJson.h>
|
||||
#include <string.h>
|
||||
#include <MD5Builder.h>
|
||||
using CfgInit=std::function<void(GwConfigHandler *)>;
|
||||
static std::vector<CfgInit> cfgInits;
|
||||
#define CFG_INIT(name,value,mode) \
|
||||
__MSG("config set " #name " " #value " " #mode); \
|
||||
static GwInitializer<CfgInit> _ ## name ## _init(cfgInits,[](GwConfigHandler *cfg){ \
|
||||
cfg->setValue(GwConfigDefinitions::name,value,GwConfigInterface::mode); \
|
||||
});
|
||||
#include "GwHardware.h"
|
||||
#include "GwConfigDefImpl.h"
|
||||
|
||||
@@ -61,6 +68,9 @@ GwConfigHandler::GwConfigHandler(GwLog *logger): GwConfigDefinitions(){
|
||||
saltBase=esp_random();
|
||||
configs=new GwConfigInterface*[getNumConfig()];
|
||||
populateConfigs(configs);
|
||||
for (auto &&init:cfgInits){
|
||||
init(this);
|
||||
}
|
||||
prefs=new Preferences();
|
||||
}
|
||||
GwConfigHandler::~GwConfigHandler(){
|
||||
@@ -126,11 +136,16 @@ void GwConfigHandler::stopChanges(){
|
||||
allowChanges=false;
|
||||
}
|
||||
bool GwConfigHandler::setValue(String name,String value, bool hide){
|
||||
return setValue(name,value,hide?GwConfigInterface::HIDDEN:GwConfigInterface::READONLY);
|
||||
}
|
||||
bool GwConfigHandler::setValue(String name, String value, GwConfigInterface::ConfigType type){
|
||||
if (! allowChanges) return false;
|
||||
LOG_DEBUG(GwLog::LOG,"setValue for %s to %s, mode %d",
|
||||
name.c_str(),value.c_str(),(int)type);
|
||||
GwConfigInterface *i=getConfigItem(name,false);
|
||||
if (!i) return false;
|
||||
i->value=value;
|
||||
i->type=hide?GwConfigInterface::HIDDEN:GwConfigInterface::READONLY;
|
||||
i->type=type;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ class GwConfigHandler: public GwConfigDefinitions{
|
||||
* !use with care! no checks of the value
|
||||
*/
|
||||
bool setValue(String name, String value, bool hide=false);
|
||||
bool setValue(String name, String value, GwConfigInterface::ConfigType type);
|
||||
static void toHex(unsigned long v,char *buffer,size_t bsize);
|
||||
unsigned long getSaltBase(){return saltBase;}
|
||||
~GwConfigHandler();
|
||||
@@ -70,6 +71,15 @@ class GwConfigHandler: public GwConfigDefinitions{
|
||||
target=i->asInt();
|
||||
return true;
|
||||
}
|
||||
bool getValue(float &target, const String &name, float defaultv=0){
|
||||
GwConfigInterface *i=getConfigItem(name);
|
||||
if (!i){
|
||||
target=defaultv;
|
||||
return false;
|
||||
}
|
||||
target=i->asFloat();
|
||||
return true;
|
||||
}
|
||||
bool getValue(bool &target, const String name, bool defaultv=false){
|
||||
GwConfigInterface *i=getConfigItem(name);
|
||||
if (!i){
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#define _GWCONFIGITEM_H
|
||||
#include "WString.h"
|
||||
#include <vector>
|
||||
|
||||
class GwConfigHandler;
|
||||
class GwConfigInterface{
|
||||
public:
|
||||
@@ -37,6 +36,9 @@ class GwConfigInterface{
|
||||
virtual int asInt() const{
|
||||
return (int)value.toInt();
|
||||
}
|
||||
virtual float asFloat() const{
|
||||
return value.toFloat();
|
||||
}
|
||||
String getName() const{
|
||||
return name;
|
||||
}
|
||||
@@ -75,5 +77,20 @@ class GwNmeaFilter{
|
||||
|
||||
#define __XSTR(x) __STR(x)
|
||||
#define __STR(x) #x
|
||||
#define __EXPAND(x,sf) x ## sf
|
||||
#define __EXPAND3(prfx,x,sf) prfx ## x ## sf
|
||||
#define __MSG(x) _Pragma (__STR(message (x)))
|
||||
//https://curiouser.cheshireeng.com/2014/08/19/c-compile-time-assert/
|
||||
#define CASSERT(predicate, text) _impl_CASSERT_LINE(predicate,__LINE__)
|
||||
#define _impl_PASTE(a,b) a##b
|
||||
#define _impl_CASSERT_LINE(predicate, line) typedef char _impl_PASTE(assertion_failed_CASSERT_,line)[(predicate)?1:-1];
|
||||
template<typename F>
|
||||
class GwInitializer{
|
||||
public:
|
||||
using List=std::vector<F>;
|
||||
GwInitializer(List &l,F f){
|
||||
l.push_back(f);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
41
lib/config/GwConverterConfig.h
Normal file
41
lib/config/GwConverterConfig.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
(C) Andreas Vogel andreas@wellenvogel.de
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _GWCONVERTERCONFIG_H
|
||||
#define _GWCONVERTERCONFIG_H
|
||||
|
||||
#include "GWConfig.h"
|
||||
|
||||
class GwConverterConfig{
|
||||
public:
|
||||
int minXdrInterval=100;
|
||||
int starboardRudderInstance=0;
|
||||
int portRudderInstance=-1; //ignore
|
||||
int min2KInterval=50;
|
||||
int rmcInterval=1000;
|
||||
int rmcCheckTime=4000;
|
||||
void init(GwConfigHandler *config){
|
||||
minXdrInterval=config->getInt(GwConfigDefinitions::minXdrInterval,100);
|
||||
starboardRudderInstance=config->getInt(GwConfigDefinitions::stbRudderI,0);
|
||||
portRudderInstance=config->getInt(GwConfigDefinitions::portRudderI,-1);
|
||||
min2KInterval=config->getInt(GwConfigDefinitions::min2KInterval,50);
|
||||
if (min2KInterval < 10)min2KInterval=10;
|
||||
rmcCheckTime=config->getInt(GwConfigDefinitions::checkRMCt,4000);
|
||||
if (rmcCheckTime < 1000) rmcCheckTime=1000;
|
||||
rmcInterval=config->getInt(GwConfigDefinitions::sendRMCi,1000);
|
||||
if (rmcInterval < 0) rmcInterval=0;
|
||||
if (rmcInterval > 0 && rmcInterval <100) rmcInterval=100;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
@@ -116,6 +116,10 @@ bool GwWebServer::registerMainHandler(const char *url,RequestCreator creator){
|
||||
});
|
||||
return true;
|
||||
}
|
||||
bool GwWebServer::registerHandler(const char * url,GwWebServer::HandlerFunction handler){
|
||||
server->on(url,HTTP_GET,handler);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GwWebServer::registerPostHandler(const char *url, ArRequestHandlerFunction requestHandler,
|
||||
ArBodyHandlerFunction bodyHandler){
|
||||
|
||||
@@ -11,10 +11,12 @@ class GwWebServer{
|
||||
GwLog *logger;
|
||||
public:
|
||||
typedef GwRequestMessage *(RequestCreator)(AsyncWebServerRequest *request);
|
||||
using HandlerFunction=std::function<void(AsyncWebServerRequest *)>;
|
||||
GwWebServer(GwLog *logger, GwRequestQueue *queue,int port);
|
||||
~GwWebServer();
|
||||
void begin();
|
||||
bool registerMainHandler(const char *url,RequestCreator creator);
|
||||
bool registerHandler(const char * url,HandlerFunction handler);
|
||||
bool registerPostHandler(const char *url, ArRequestHandlerFunction requestHandler, ArBodyHandlerFunction bodyHandler);
|
||||
void handleAsyncWebRequest(AsyncWebServerRequest *request, GwRequestMessage *msg);
|
||||
AsyncWebServer * getServer(){return server;}
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
unfortunately there is some typo here: M5 uses GROVE for their connections
|
||||
but we have GROOVE here.
|
||||
But to maintain compatibility to older build commands we keep the (wrong) wording
|
||||
*/
|
||||
#ifdef _NOGWHARDWAREUT
|
||||
#error "you are not allowed to include GwHardware.h in your user task header"
|
||||
@@ -25,6 +29,20 @@
|
||||
#include "GwAppInfo.h"
|
||||
#include "GwUserTasks.h"
|
||||
|
||||
#ifdef GW_PINDEFS
|
||||
#define GWRESOURCE_USE(RES,USER) \
|
||||
__MSG(#RES " used by " #USER) \
|
||||
static int _resourceUsed ## RES =1;
|
||||
#define __USAGE __MSG
|
||||
#else
|
||||
#define GWRESOURCE_USE(...)
|
||||
#define __USAGE(...)
|
||||
#endif
|
||||
|
||||
#ifndef CFG_INIT
|
||||
#define CFG_INIT(...)
|
||||
#endif
|
||||
|
||||
//general definitions for M5AtomLite
|
||||
//hint for groove pins:
|
||||
//according to some schematics the numbering is 1,2,3(VCC),4(GND)
|
||||
@@ -42,8 +60,13 @@
|
||||
#define GWBUTTON_PULLUPDOWN
|
||||
#define BOARD_LEFT1 GPIO_NUM_22
|
||||
#define BOARD_LEFT2 GPIO_NUM_19
|
||||
#define BOARD_LEFT3 GPIO_NUM_23
|
||||
#define BOARD_LEFT4 GPIO_NUM_33
|
||||
#define BOARD_RIGHT1 GPIO_NUM_21
|
||||
#define BOARD_RIGHT2 GPIO_NUM_25
|
||||
#define USBSerial Serial
|
||||
#endif
|
||||
|
||||
//general definitiones for M5AtomS3
|
||||
#ifdef PLATFORM_BOARD_M5STACK_ATOMS3
|
||||
#define GROOVE_PIN_2 GPIO_NUM_2
|
||||
@@ -59,8 +82,11 @@
|
||||
#define GWBUTTON_PULLUPDOWN
|
||||
#define BOARD_LEFT1 GPIO_NUM_5
|
||||
#define BOARD_LEFT2 GPIO_NUM_6
|
||||
#define BOARD_LEFT3 GPIO_NUM_7
|
||||
#define BOARD_LEFT4 GPIO_NUM_8
|
||||
#define BOARD_RIGHT1 GPIO_NUM_39
|
||||
#define BOARD_RIGHT2 GPIO_NUM_38
|
||||
#endif
|
||||
|
||||
//M5Stick C
|
||||
#ifdef PLATFORM_BOARD_M5STICK_C
|
||||
#define GROOVE_PIN_2 GPIO_NUM_32
|
||||
@@ -78,13 +104,13 @@
|
||||
//150mA if we power from the bus
|
||||
#define N2K_LOAD_LEVEL 3
|
||||
//if using tail485
|
||||
#define SERIAL_GROOVE_485
|
||||
#define SERIAL_GROOVE_485 1
|
||||
//brightness 0...255
|
||||
#define GWLED_BRIGHTNESS 64
|
||||
#endif
|
||||
|
||||
#ifdef BOARD_M5ATOMS3
|
||||
#define M5_CAN_KIT
|
||||
#define M5_CAN_KIT 1
|
||||
//150mA if we power from the bus
|
||||
#define N2K_LOAD_LEVEL 3
|
||||
//if using tail485
|
||||
@@ -94,33 +120,33 @@
|
||||
#endif
|
||||
|
||||
#ifdef BOARD_M5ATOM_CANUNIT
|
||||
#define M5_CANUNIT
|
||||
#define M5_CANUNIT 1
|
||||
#define GWLED_BRIGHTNESS 64
|
||||
//150mA if we power from the bus
|
||||
#define N2K_LOAD_LEVEL 3
|
||||
#endif
|
||||
|
||||
#ifdef BOARD_M5ATOMS3_CANUNIT
|
||||
#define M5_CANUNIT
|
||||
#define M5_CANUNIT 1
|
||||
#define GWLED_BRIGHTNESS 64
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BOARD_M5ATOM_RS232_CANUNIT
|
||||
#define M5_CANUNIT
|
||||
#define M5_CANUNIT 1
|
||||
#define M5_SERIAL_KIT_232
|
||||
#define GWLED_BRIGHTNESS 64
|
||||
#endif
|
||||
|
||||
#ifdef BOARD_M5ATOM_RS485_CANUNIT
|
||||
#define M5_SERIAL_KIT_485
|
||||
#define M5_CANUNIT
|
||||
#define M5_CANUNIT 1
|
||||
#define GWLED_BRIGHTNESS 64
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BOARD_M5STICK_CANUNIT
|
||||
#define M5_CANUNIT
|
||||
#define M5_CANUNIT 1
|
||||
#endif
|
||||
|
||||
#ifdef BOARD_HOMBERGER
|
||||
@@ -136,137 +162,14 @@
|
||||
#define GWBUTTON_PULLUPDOWN
|
||||
#endif
|
||||
|
||||
//M5 Serial (Atomic RS232 Base)
|
||||
#ifdef M5_SERIAL_KIT_232
|
||||
#define _GWM5_BOARD
|
||||
#define GWSERIAL_TX BOARD_LEFT2
|
||||
#define GWSERIAL_RX BOARD_LEFT1
|
||||
#define GWSERIAL_TYPE GWSERIAL_TYPE_BI
|
||||
#endif
|
||||
#include "GwM5Base.h"
|
||||
#include "GwM5Grove.h"
|
||||
|
||||
//M5 Serial (Atomic RS485 Base)
|
||||
#ifdef M5_SERIAL_KIT_485
|
||||
#ifdef _GWM5_BOARD
|
||||
#error "can only define one M5 base"
|
||||
#endif
|
||||
#define _GWM5_BOARD
|
||||
#define GWSERIAL_TX BOARD_LEFT2
|
||||
#define GWSERIAL_RX BOARD_LEFT1
|
||||
#define GWSERIAL_TYPE GWSERIAL_TYPE_UNI
|
||||
#endif
|
||||
|
||||
//M5 GPS (Atomic GPS Base)
|
||||
#ifdef M5_GPS_KIT
|
||||
#ifdef _GWM5_BOARD
|
||||
#error "can only define one M5 base"
|
||||
#endif
|
||||
#define _GWM5_BOARD
|
||||
#define GWSERIAL_RX BOARD_LEFT1
|
||||
#define GWSERIAL_TYPE GWSERIAL_TYPE_RX
|
||||
#define CFGDEFAULT_serialBaud "9600"
|
||||
#define CFGMODE_serialBaud GwConfigInterface::READONLY
|
||||
#endif
|
||||
|
||||
//below we define the final device config based on the above
|
||||
//boards and peripherals
|
||||
//this allows us to easily also set them from outside
|
||||
//serial adapter at the M5 groove pins
|
||||
//we use serial2 for groove serial if serial1 is already defined
|
||||
//before (e.g. by serial kit)
|
||||
#ifdef SERIAL_GROOVE_485
|
||||
#define _GWM5_GROOVE
|
||||
#ifdef GWSERIAL_TYPE
|
||||
#define GWSERIAL2_TX GROOVE_PIN_2
|
||||
#define GWSERIAL2_RX GROOVE_PIN_1
|
||||
#define GWSERIAL2_TYPE GWSERIAL_TYPE_UNI
|
||||
#else
|
||||
#define GWSERIAL_TX GROOVE_PIN_2
|
||||
#define GWSERIAL_RX GROOVE_PIN_1
|
||||
#define GWSERIAL_TYPE GWSERIAL_TYPE_UNI
|
||||
#endif
|
||||
#endif
|
||||
#ifdef SERIAL_GROOVE_232
|
||||
#ifdef _GWM5_GROOVE
|
||||
#error "can only have one groove device"
|
||||
#endif
|
||||
#define _GWM5_GROOVE
|
||||
#ifdef GWSERIAL_TYPE
|
||||
#define GWSERIAL2_TX GROOVE_PIN_2
|
||||
#define GWSERIAL2_RX GROOVE_PIN_1
|
||||
#define GWSERIAL2_TYPE GWSERIAL_TYPE_BI
|
||||
#else
|
||||
#define GWSERIAL_TX GROOVE_PIN_2
|
||||
#define GWSERIAL_RX GROOVE_PIN_1
|
||||
#define GWSERIAL_TYPE GWSERIAL_TYPE_BI
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//http://docs.m5stack.com/en/unit/gps
|
||||
#ifdef M5_GPS_UNIT
|
||||
#ifdef _GWM5_GROOVE
|
||||
#error "can only have one M5 groove"
|
||||
#endif
|
||||
#define _GWM5_GROOVE
|
||||
#ifdef GWSERIAL_TYPE
|
||||
#define GWSERIAL2_RX GROOVE_PIN_1
|
||||
#define GWSERIAL2_TYPE GWSERIAL_TYPE_RX
|
||||
#define CFGDEFAULT_serialBaud "9600"
|
||||
#define CFGMODE_serialBaud GwConfigInterface::READONLY
|
||||
#else
|
||||
#define GWSERIAL_RX GROOVE_PIN_1
|
||||
#define GWSERIAL_TYPE GWSERIAL_TYPE_RX
|
||||
#define CFGDEFAULT_serial2Baud "9600"
|
||||
#define CFGMODE_serial2Baud GwConfigInterface::READONLY
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//can kit for M5 Atom
|
||||
#ifdef M5_CAN_KIT
|
||||
#ifdef _GWM5_BOARD
|
||||
#error "can only define one M5 base"
|
||||
#endif
|
||||
#define _GWM5_BOARD
|
||||
#define ESP32_CAN_TX_PIN BOARD_LEFT1
|
||||
#define ESP32_CAN_RX_PIN BOARD_LEFT2
|
||||
#endif
|
||||
//CAN via groove
|
||||
#ifdef M5_CANUNIT
|
||||
#ifdef _GWM5_GROOVE
|
||||
#error "can only have one M5 groove"
|
||||
#endif
|
||||
#define _GWM5_GROOVE
|
||||
#define ESP32_CAN_TX_PIN GROOVE_PIN_2
|
||||
#define ESP32_CAN_RX_PIN GROOVE_PIN_1
|
||||
#endif
|
||||
|
||||
#ifdef M5_ENV3
|
||||
#ifndef M5_GROOVEIIC
|
||||
#define M5_GROOVEIIC
|
||||
#endif
|
||||
#ifndef GWSHT3X
|
||||
#define GWSHT3X -1
|
||||
#endif
|
||||
#ifndef GWQMP6988
|
||||
#define GWQMP6988 -1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef M5_GROOVEIIC
|
||||
#ifdef _GWM5_GROOVE
|
||||
#error "can only have one M5 groove"
|
||||
#endif
|
||||
#define _GWM5_GROOVE
|
||||
#ifdef GWIIC_SCL
|
||||
#error "you cannot define both GWIIC_SCL and M5_GROOVEIIC"
|
||||
#endif
|
||||
#define GWIIC_SCL GROOVE_PIN_1
|
||||
#ifdef GWIIC_SDA
|
||||
#error "you cannot define both GWIIC_SDA and M5_GROOVEIIC"
|
||||
#endif
|
||||
#define GWIIC_SDA GROOVE_PIN_2
|
||||
#endif
|
||||
|
||||
#ifdef GWIIC_SDA
|
||||
#ifdef _GWI_IIC1
|
||||
#error "you must not define IIC1 on grove and GWIIC_SDA"
|
||||
#endif
|
||||
#ifndef GWIIC_SCL
|
||||
#error "you must both define GWIIC_SDA and GWIIC_SCL"
|
||||
#endif
|
||||
@@ -278,6 +181,9 @@
|
||||
#define _GWIIC
|
||||
#endif
|
||||
#ifdef GWIIC_SDA2
|
||||
#ifdef _GWI_IIC2
|
||||
#error "you must not define IIC2 on grove and GWIIC_SDA2"
|
||||
#endif
|
||||
#ifndef GWIIC_SCL2
|
||||
#error "you must both define GWIIC_SDA2 and GWIIC_SCL2"
|
||||
#endif
|
||||
@@ -314,12 +220,13 @@
|
||||
#endif
|
||||
|
||||
#ifdef GWLED_FASTLED
|
||||
#define CFGMODE_ledBrightness GwConfigInterface::NORMAL
|
||||
#ifdef GWLED_BRIGHTNESS
|
||||
#define CFGDEFAULT_ledBrightness GWSTRINGIFY(GWLED_BRIGHTNESS)
|
||||
CFG_INIT(ledBrightness,GWSTRINGIFY(GWLED_BRIGHTNESS),NORMAL)
|
||||
#else
|
||||
CFG_INIT(ledBrightness,"64",NORMAL)
|
||||
#endif
|
||||
#else
|
||||
#define CFGMODE_ledBrightness GwConfigInterface::HIDDEN
|
||||
CFG_INIT(ledBrightness,"64",HIDDEN)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
71
lib/hardware/GwM5Base.h
Normal file
71
lib/hardware/GwM5Base.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
unfortunately there is some typo here: M5 uses GROVE for their connections
|
||||
but we have GROOVE here.
|
||||
But to maintain compatibility to older build commands we keep the (wrong) wording
|
||||
*/
|
||||
//M5 Base Boards
|
||||
#ifndef _GWM5BASE_H
|
||||
#define _GWM5BASE_H
|
||||
//M5 Serial (Atomic RS232 Base)
|
||||
#ifdef M5_SERIAL_KIT_232
|
||||
GWRESOURCE_USE(BASE,M5_SERIAL_KIT_232)
|
||||
GWRESOURCE_USE(SERIAL1,M5_SERIAL_KIT_232)
|
||||
#define _GWI_SERIAL1 BOARD_LEFT1,BOARD_LEFT2,GWSERIAL_TYPE_BI
|
||||
#endif
|
||||
|
||||
//M5 Serial (Atomic RS485 Base)
|
||||
#ifdef M5_SERIAL_KIT_485
|
||||
GWRESOURCE_USE(BASE,M5_SERIAL_KIT_485)
|
||||
GWRESOURCE_USE(SERIAL1,M5_SERIAL_KIT_485)
|
||||
#define _GWI_SERIAL1 BOARD_LEFT1,BOARD_LEFT2,GWSERIAL_TYPE_UNI
|
||||
#endif
|
||||
//M5 GPS (Atomic GPS Base)
|
||||
#ifdef M5_GPS_KIT
|
||||
GWRESOURCE_USE(BASE,M5_GPS_KIT)
|
||||
GWRESOURCE_USE(SERIAL1,M5_GPS_KIT)
|
||||
#define _GWI_SERIAL1 BOARD_LEFT1,-1,GWSERIAL_TYPE_UNI,"9600"
|
||||
#endif
|
||||
|
||||
//M5 ProtoHub
|
||||
#ifdef M5_PROTO_HUB
|
||||
GWRESOURCE_USE(BASE,M5_PROTO_HUB)
|
||||
#define PPIN22 BOARD_LEFT1
|
||||
#define PPIN19 BOARD_LEFT2
|
||||
#define PPIN23 BOARD_LEFT3
|
||||
#define PPIN33 BOARD_LEFT4
|
||||
#define PPIN21 BOARD_RIGHT1
|
||||
#define PPIN25 BOARD_RIGHT2
|
||||
#endif
|
||||
|
||||
//M5 PortABC extension
|
||||
#ifdef M5_PORTABC
|
||||
GWRESOURCE_USE(BASE,M5_PORTABC)
|
||||
#define GROOVEA_PIN_2 BOARD_RIGHT2
|
||||
#define GROOVEA_PIN_1 BOARD_RIGHT1
|
||||
#define GROOVEB_PIN_2 BOARD_LEFT3
|
||||
#define GROOVEB_PIN_1 BOARD_LEFT4
|
||||
#define GROOVEC_PIN_2 BOARD_LEFT1
|
||||
#define GROOVEC_PIN_1 BOARD_LEFT2
|
||||
#endif
|
||||
|
||||
//can kit for M5 Atom
|
||||
#ifdef M5_CAN_KIT
|
||||
GWRESOURCE_USE(BASE,M5_CAN_KIT)
|
||||
GWRESOURCE_USE(CAN,M5_CANKIT)
|
||||
#define ESP32_CAN_TX_PIN BOARD_LEFT1
|
||||
#define ESP32_CAN_RX_PIN BOARD_LEFT2
|
||||
#endif
|
||||
|
||||
#endif
|
||||
31
lib/hardware/GwM5Grove.h
Normal file
31
lib/hardware/GwM5Grove.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
unfortunately there is some typo here: M5 uses GROVE for their connections
|
||||
but we have GROOVE here.
|
||||
But to maintain compatibility to older build commands we keep the (wrong) wording
|
||||
*/
|
||||
//M5 Grove stuff
|
||||
#ifndef _GW5MGROVE_H
|
||||
#define _GW5MGROVE_H
|
||||
#ifndef GROOVE_IIC
|
||||
#define GROOVE_IIC(...)
|
||||
#endif
|
||||
#include "GwM5GroveGen.h"
|
||||
|
||||
#if defined(_GWI_IIC1) || defined (_GWI_IIC2)
|
||||
#define _GWIIC
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
145
lib/hardware/GwM5Grove.in
Normal file
145
lib/hardware/GwM5Grove.in
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
unfortunately there is some typo here: M5 uses GROVE for their connections
|
||||
but we have GROOVE here.
|
||||
But to maintain compatibility to older build commands we keep the (wrong) wording
|
||||
|
||||
This file contains M5 grove definitions.
|
||||
They will be expanded to match the supported groves
|
||||
|
||||
Each definition must start with a line that start starts with #GROVE
|
||||
Afterwards you can use normal C header style
|
||||
$GS$ will be replaced with a grove suffix with _ (empty for first)
|
||||
$G$ will be replaced by the simple grove name (empty for base)
|
||||
$Z$ will be replaced by the simple name using "Z" for the first grove
|
||||
*/
|
||||
#GROVE
|
||||
#ifdef SERIAL_GROOVE_485$GS$
|
||||
GWRESOURCE_USE(GROOVE$G$,SERIAL_GROOVE_485$GS$)
|
||||
#define _GWI_SERIAL_GROOVE$GS$ GWSERIAL_TYPE_UNI
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
#ifdef SERIAL_GROOVE_232$GS$
|
||||
GWRESOURCE_USE(GROOVE$G$,SERIAL_GROOVE_232$GS$)
|
||||
#define _GWI_SERIAL_GROOVE$GS$ GWSERIAL_TYPE_BI
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
//http://docs.m5stack.com/en/unit/gps
|
||||
#ifdef M5_GPS_UNIT$GS$
|
||||
GWRESOURCE_USE(GROOVE$G$,M5_GPS_UNIT$GS$)
|
||||
#define _GWI_SERIAL_GROOVE$GS$ GWSERIAL_TYPE_RX,9600
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
//CAN via groove
|
||||
#ifdef M5_CANUNIT$GS$
|
||||
GWRESOURCE_USE(GROOVE$G$,M5_CANUNIT$GS$)
|
||||
GWRESOURCE_USE(CAN,M5_CANUNIT$GS$)
|
||||
#define ESP32_CAN_TX_PIN GROOVE$G$_PIN_2
|
||||
#define ESP32_CAN_RX_PIN GROOVE$G$_PIN_1
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
#ifdef M5_ENV3$GS$
|
||||
#ifndef M5_GROOVEIIC$GS$
|
||||
#define M5_GROOVEIIC$GS$
|
||||
#endif
|
||||
GROOVE_IIC(SHT3X,$Z$,1)
|
||||
GROOVE_IIC(QMP6988,$Z$,1)
|
||||
#define _GWSHT3X
|
||||
#define _GWQMP6988
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
//example: -DSHT3XG1_A : defines STH3Xn1 on grove A - x depends on the other devices
|
||||
#ifdef GWSHT3XG1$GS$
|
||||
#ifndef M5_GROOVEIIC$GS$
|
||||
#define M5_GROOVEIIC$GS$
|
||||
#endif
|
||||
GROOVE_IIC(SHT3X,$Z$,1)
|
||||
#define _GWSHT3X
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
#ifdef GWSHT3XG2$GS$
|
||||
#ifndef M5_GROOVEIIC$GS$
|
||||
#define M5_GROOVEIIC$GS$
|
||||
#endif
|
||||
GROOVE_IIC(SHT3X,$Z$,2)
|
||||
#define _GWSHT3X
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
#ifdef GWQMP6988G1$GS$
|
||||
#ifndef M5_GROOVEIIC$GS$
|
||||
#define M5_GROOVEIIC$GS$
|
||||
#endif
|
||||
GROOVE_IIC(QMP6988,$Z$,1)
|
||||
#define _GWQMP6988
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
#ifdef GWQMP6988G2$GS$
|
||||
#ifndef M5_GROOVEIIC$GS$
|
||||
#define M5_GROOVEIIC$GS$
|
||||
#endif
|
||||
GROOVE_IIC(QMP6988,$Z$,2)
|
||||
#define _GWQMP6988
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
#ifdef GWBME280G1$GS$
|
||||
#ifndef M5_GROOVEIIC$GS$
|
||||
#define M5_GROOVEIIC$GS$
|
||||
#endif
|
||||
GROOVE_IIC(BME280,$Z$,1)
|
||||
#define _GWBME280
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
#ifdef GWBME280G2$GS$
|
||||
#ifndef M5_GROOVEIIC$GS$
|
||||
#define M5_GROOVEIIC$GS$
|
||||
#endif
|
||||
GROOVE_IIC(BME280,$Z$,2)
|
||||
#define _GWBME280
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
//select up to 2 IIC devices for grove usage
|
||||
#ifdef M5_GROOVEIIC$GS$
|
||||
GWRESOURCE_USE(GROOVE$G$,M5_GROOVEIIC$GS$)
|
||||
#ifndef _GWI_IIC1
|
||||
__USAGE("IIC1 used by GROVE$GS$")
|
||||
#define _GWI_IIC1 "$Z$",GROOVE$G$_PIN_1,GROOVE$G$_PIN_2
|
||||
#elif ! defined(_GWI_IIC2)
|
||||
__USAGE("IIC2 used by GROVE$GS$")
|
||||
#define _GWI_IIC2 "$Z$",GROOVE$G$_PIN_1,GROOVE$G$_PIN_2
|
||||
#else
|
||||
#error "both iic buses already in use"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#GROVE
|
||||
#ifdef _GWI_SERIAL_GROOVE$GS$
|
||||
#ifndef _GWI_SERIAL1
|
||||
#define _GWI_SERIAL1 GROOVE$G$_PIN_1,GROOVE$G$_PIN_2,_GWI_SERIAL_GROOVE$GS$
|
||||
#elif ! defined(_GWI_SERIAL2)
|
||||
#define _GWI_SERIAL2 GROOVE$G$_PIN_1,GROOVE$G$_PIN_2,_GWI_SERIAL_GROOVE$GS$
|
||||
#else
|
||||
#error "both serial devices already in use"
|
||||
#endif
|
||||
#endif
|
||||
@@ -2,8 +2,6 @@
|
||||
#ifdef _GWIIC
|
||||
#if defined(GWBME280) || defined(GWBME28011) || defined(GWBME28012)|| defined(GWBME28021)|| defined(GWBME28022)
|
||||
#define _GWBME280
|
||||
#else
|
||||
#undef _GWBME280
|
||||
#endif
|
||||
#else
|
||||
#undef _GWBME280
|
||||
@@ -17,11 +15,12 @@
|
||||
#include <Adafruit_BME280.h>
|
||||
#endif
|
||||
#ifdef _GWBME280
|
||||
#define PRFX1 "BME28011"
|
||||
#define PRFX2 "BME28012"
|
||||
#define PRFX3 "BME28021"
|
||||
#define PRFX4 "BME28022"
|
||||
class BME280Config : public SensorBase{
|
||||
#define TYPE "BME280"
|
||||
#define PRFX1 TYPE "11"
|
||||
#define PRFX2 TYPE "12"
|
||||
#define PRFX3 TYPE "21"
|
||||
#define PRFX4 TYPE "22"
|
||||
class BME280Config : public IICSensorBase{
|
||||
public:
|
||||
bool prAct=true;
|
||||
bool tmAct=true;
|
||||
@@ -36,7 +35,7 @@ class BME280Config : public SensorBase{
|
||||
float prOff=0;
|
||||
Adafruit_BME280 *device=nullptr;
|
||||
uint32_t sensorId=-1;
|
||||
BME280Config(GwApi * api, const String &prfx):SensorBase(api,prfx){
|
||||
BME280Config(GwApi * api, const String &prfx):SensorBase(TYPE,api,prfx){
|
||||
}
|
||||
virtual bool isActive(){return prAct||huAct||tmAct;}
|
||||
virtual bool initDevice(GwApi *api,TwoWire *wire){
|
||||
@@ -106,6 +105,7 @@ class BME280Config : public SensorBase{
|
||||
|
||||
virtual void readConfig(GwConfigHandler *cfg) override
|
||||
{
|
||||
if (ok) return;
|
||||
if (prefix == PRFX1)
|
||||
{
|
||||
busId = 1;
|
||||
@@ -137,11 +137,13 @@ class BME280Config : public SensorBase{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void registerBME280(GwApi *api,SensorList &sensors){
|
||||
static IICSensorBase::Creator creator([](GwApi *api, const String &prfx){
|
||||
return new BME280Config(api,prfx);
|
||||
});
|
||||
IICSensorBase::Creator registerBME280(GwApi *api,IICSensorList &sensors){
|
||||
#if defined(GWBME280) || defined(GWBME28011)
|
||||
{
|
||||
BME280Config *cfg=new BME280Config(api,PRFX1);
|
||||
auto *cfg=creator(api,PRFX1);
|
||||
sensors.add(api,cfg);
|
||||
CHECK_IIC1();
|
||||
#pragma message "GWBME28011 defined"
|
||||
@@ -149,7 +151,7 @@ void registerBME280(GwApi *api,SensorList &sensors){
|
||||
#endif
|
||||
#if defined(GWBME28012)
|
||||
{
|
||||
BME280Config *cfg=new BME280Config(api,PRFX2);
|
||||
auto *cfg=creator(api,PRFX2);
|
||||
sensors.add(api,cfg);
|
||||
CHECK_IIC1();
|
||||
#pragma message "GWBME28012 defined"
|
||||
@@ -157,7 +159,7 @@ void registerBME280(GwApi *api,SensorList &sensors){
|
||||
#endif
|
||||
#if defined(GWBME28021)
|
||||
{
|
||||
BME280Config *cfg=new BME280Config(api,PRFX3);
|
||||
auto *cfg=creator(api,PRFX3);
|
||||
sensors.add(api,cfg);
|
||||
CHECK_IIC2();
|
||||
#pragma message "GWBME28021 defined"
|
||||
@@ -165,15 +167,17 @@ void registerBME280(GwApi *api,SensorList &sensors){
|
||||
#endif
|
||||
#if defined(GWBME28022)
|
||||
{
|
||||
BME280Config *cfg=new BME280Config(api,PRFX4);
|
||||
auto *cfg=creator(api,PRFX4);
|
||||
sensors.add(api,cfg);
|
||||
CHECK_IIC1();
|
||||
#pragma message "GWBME28022 defined"
|
||||
}
|
||||
#endif
|
||||
return creator;
|
||||
}
|
||||
#else
|
||||
void registerBME280(GwApi *api,SensorList &sensors){
|
||||
IICSensorBase::Creator registerBME280(GwApi *api,IICSensorList &sensors){
|
||||
return IICSensorBase::Creator();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef _GWBME280_H
|
||||
#define _GWBME280_H
|
||||
#include "GwIicSensors.h"
|
||||
void registerBME280(GwApi *api,SensorList &sensors);
|
||||
IICSensorBase::Creator registerBME280(GwApi *api,IICSensorList &sensors);
|
||||
#endif
|
||||
@@ -4,14 +4,17 @@
|
||||
#include "N2kMessages.h"
|
||||
#include "GwXdrTypeMappings.h"
|
||||
#include "GwHardware.h"
|
||||
#include "GwSensor.h"
|
||||
#ifdef _GWIIC
|
||||
#include <Wire.h>
|
||||
#else
|
||||
class TwoWire;
|
||||
#endif
|
||||
|
||||
#define CFG_GET(name,prefix) \
|
||||
cfg->getValue(name, GwConfigDefinitions::prefix ## name)
|
||||
using BusType=TwoWire;
|
||||
using IICSensorList=SensorList<BusType>;
|
||||
using IICSensorBase=SensorBase<BusType>;
|
||||
|
||||
|
||||
template <class CFG>
|
||||
bool addPressureXdr(GwApi *api, CFG &cfg)
|
||||
@@ -100,35 +103,15 @@ void sendN2kTemperature(GwApi *api,CFG &cfg,double value, int counterId){
|
||||
}
|
||||
|
||||
|
||||
class SensorBase{
|
||||
public:
|
||||
int busId=0;
|
||||
int iid=99; //N2K instanceId
|
||||
int addr=-1;
|
||||
String prefix;
|
||||
long intv=0;
|
||||
bool ok=false;
|
||||
virtual void readConfig(GwConfigHandler *cfg)=0;
|
||||
SensorBase(GwApi *api,const String &prfx):prefix(prfx){
|
||||
}
|
||||
virtual bool isActive(){return false;};
|
||||
virtual bool initDevice(GwApi *api,TwoWire *wire){return false;};
|
||||
virtual bool preinit(GwApi * api){return false;}
|
||||
virtual void measure(GwApi * api,TwoWire *wire, int counterId){};
|
||||
virtual ~SensorBase(){}
|
||||
};
|
||||
|
||||
class SensorList : public std::vector<SensorBase*>{
|
||||
public:
|
||||
void add(GwApi *api, SensorBase *sensor){
|
||||
sensor->readConfig(api->getConfig());
|
||||
api->getLogger()->logDebug(GwLog::LOG,"configured sensor %s, status %d",sensor->prefix.c_str(),(int)sensor->ok);
|
||||
push_back(sensor);
|
||||
}
|
||||
using std::vector<SensorBase*>::vector;
|
||||
};
|
||||
|
||||
#define CHECK_IIC1() checkDef(GWIIC_SCL,GWIIC_SDA)
|
||||
#define CHECK_IIC2() checkDef(GWIIC_SCL2,GWIIC_SDA2)
|
||||
#ifndef _GWI_IIC1
|
||||
#define CHECK_IIC1() checkDef(GWIIC_SCL,GWIIC_SDA)
|
||||
#else
|
||||
#define CHECK_IIC1()
|
||||
#endif
|
||||
#ifndef _GWI_IIC2
|
||||
#define CHECK_IIC2() checkDef(GWIIC_SCL2,GWIIC_SDA2)
|
||||
#else
|
||||
#define CHECK_IIC2()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,4 +1,23 @@
|
||||
#include "GwIicTask.h"
|
||||
class IICGrove
|
||||
{
|
||||
public:
|
||||
String base;
|
||||
String grove;
|
||||
String suffix;
|
||||
IICGrove(const String &b, const String &g, const String &s) : base(b), grove(g), suffix(s) {}
|
||||
String item(const String &grove, const String &bus)
|
||||
{
|
||||
if (grove == this->grove)
|
||||
return base + bus + suffix;
|
||||
return "";
|
||||
}
|
||||
};
|
||||
static std::vector<IICGrove> iicGroveList;
|
||||
#define GROOVE_IIC(base, grove, suffix) \
|
||||
static GwInitializer<IICGrove> base##grove##suffix(iicGroveList, IICGrove(#base, #grove, #suffix));
|
||||
|
||||
|
||||
#include "GwIicSensors.h"
|
||||
#include "GwHardware.h"
|
||||
#include "GwBME280.h"
|
||||
@@ -6,6 +25,8 @@
|
||||
#include "GwSHT3X.h"
|
||||
#include <map>
|
||||
|
||||
#include "GwTimer.h"
|
||||
|
||||
#ifndef GWIIC_SDA
|
||||
#define GWIIC_SDA -1
|
||||
#endif
|
||||
@@ -19,14 +40,46 @@
|
||||
#define GWIIC_SCL2 -1
|
||||
#endif
|
||||
|
||||
#include "GwTimer.h"
|
||||
#include "GwHardware.h"
|
||||
|
||||
|
||||
|
||||
void runIicTask(GwApi *api);
|
||||
|
||||
static SensorList sensors;
|
||||
static IICSensorList sensors;
|
||||
static void addGroveItems(std::vector<IICSensorBase::Creator> &creators,GwApi *api, IICSensorList &sensors, const String &bus,const String &grove, int, int)
|
||||
{
|
||||
GwLog *logger=api->getLogger();
|
||||
for (auto &&init : iicGroveList)
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG, "trying grove item %s:%s:%s for grove %s, bus %s",
|
||||
init.base.c_str(),init.grove.c_str(),
|
||||
init.suffix.c_str(),grove.c_str(),bus.c_str()
|
||||
);
|
||||
String prfx = init.item(grove, bus);
|
||||
if (!prfx.isEmpty())
|
||||
{
|
||||
bool found=false;
|
||||
for (auto &&creator : creators)
|
||||
{
|
||||
if (! creator) continue;
|
||||
auto *scfg = creator(api, prfx);
|
||||
scfg->readConfig(api->getConfig());
|
||||
if (scfg->ok)
|
||||
{
|
||||
LOG_DEBUG(GwLog::LOG, "adding %s from grove config", prfx.c_str());
|
||||
sensors.add(api, scfg);
|
||||
found=true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG, "unmatched grove sensor config %s for %s", prfx.c_str(), scfg->type.c_str());
|
||||
delete scfg;
|
||||
}
|
||||
}
|
||||
if (! found){
|
||||
LOG_DEBUG(GwLog::ERROR,"no iic sensor found for %s",prfx.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void initIicTask(GwApi *api){
|
||||
GwLog *logger=api->getLogger();
|
||||
@@ -35,14 +88,21 @@ void initIicTask(GwApi *api){
|
||||
#else
|
||||
bool addTask=false;
|
||||
GwConfigHandler *config=api->getConfig();
|
||||
registerSHT3X(api,sensors);
|
||||
registerQMP6988(api,sensors);
|
||||
registerBME280(api,sensors);
|
||||
std::vector<IICSensorBase::Creator> creators;
|
||||
creators.push_back(registerSHT3X(api,sensors));
|
||||
creators.push_back(registerQMP6988(api,sensors));
|
||||
creators.push_back(registerBME280(api,sensors));
|
||||
#ifdef _GWI_IIC1
|
||||
addGroveItems(creators,api,sensors,"1",_GWI_IIC1);
|
||||
#endif
|
||||
#ifdef _GWI_IIC2
|
||||
addGroveItems(creators,api,sensors,"2",_GWI_IIC2);
|
||||
#endif
|
||||
for (auto it=sensors.begin();it != sensors.end();it++){
|
||||
if ((*it)->preinit(api)) addTask=true;
|
||||
}
|
||||
if (addTask){
|
||||
api->addUserTask(runIicTask,"iicTask",3000);
|
||||
api->addUserTask(runIicTask,"iicTask",4000);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -54,6 +114,40 @@ void runIicTask(GwApi *api){
|
||||
return;
|
||||
}
|
||||
#else
|
||||
bool initWireDo(GwLog *logger, TwoWire &wire, int num, const String &dummy, int scl, int sda)
|
||||
{
|
||||
if (sda < 0 || scl < 0)
|
||||
{
|
||||
LOG_DEBUG(GwLog::ERROR, "IIC %d invalid config sda=%d,scl=%d",
|
||||
num, sda, scl);
|
||||
return false;
|
||||
}
|
||||
bool rt = Wire.begin(sda, scl);
|
||||
if (!rt)
|
||||
{
|
||||
LOG_DEBUG(GwLog::ERROR, "unable to initialize IIC %d at sad=%d,scl=%d",
|
||||
num, sda, scl);
|
||||
return rt;
|
||||
}
|
||||
LOG_DEBUG(GwLog::ERROR, "initialized IIC %d at sda=%d,scl=%d",
|
||||
num,sda,scl);
|
||||
return true;
|
||||
}
|
||||
bool initWire(GwLog *logger, TwoWire &wire, int num){
|
||||
if (num == 1){
|
||||
#ifdef _GWI_IIC1
|
||||
return initWireDo(logger,wire,num,_GWI_IIC1);
|
||||
#endif
|
||||
return initWireDo(logger,wire,num,"",GWIIC_SDA,GWIIC_SCL);
|
||||
}
|
||||
if (num == 2){
|
||||
#ifdef _GWI_IIC2
|
||||
return initWireDo(logger,wire,num,_GWI_IIC2);
|
||||
#endif
|
||||
return initWireDo(logger,wire,num,"",GWIIC_SDA2,GWIIC_SCL2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void runIicTask(GwApi *api){
|
||||
GwLog *logger=api->getLogger();
|
||||
std::map<int,TwoWire *> buses;
|
||||
@@ -66,50 +160,15 @@ void runIicTask(GwApi *api){
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if (GWIIC_SDA < 0 || GWIIC_SCL < 0)
|
||||
{
|
||||
LOG_DEBUG(GwLog::ERROR, "IIC 1 invalid config sda=%d,scl=%d",
|
||||
(int)GWIIC_SDA, (int)GWIIC_SCL);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool rt = Wire.begin(GWIIC_SDA, GWIIC_SCL);
|
||||
if (!rt)
|
||||
{
|
||||
LOG_DEBUG(GwLog::ERROR, "unable to initialize IIC 1 at sad=%d,scl=%d",
|
||||
(int)GWIIC_SDA, (int)GWIIC_SCL);
|
||||
}
|
||||
else
|
||||
{
|
||||
buses[busId] = &Wire;
|
||||
LOG_DEBUG(GwLog::ERROR, "initialized IIC 1 at sda=%d,scl=%d",
|
||||
(int)GWIIC_SDA, (int)GWIIC_SCL);
|
||||
}
|
||||
if (initWire(logger,Wire,1)){
|
||||
buses[busId] = &Wire;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
if (GWIIC_SDA2 < 0 || GWIIC_SCL2 < 0)
|
||||
{
|
||||
LOG_DEBUG(GwLog::ERROR, "IIC 2 invalid config sda=%d,scl=%d",
|
||||
(int)GWIIC_SDA2, (int)GWIIC_SCL2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
bool rt = Wire1.begin(GWIIC_SDA2, GWIIC_SCL2);
|
||||
if (!rt)
|
||||
{
|
||||
LOG_DEBUG(GwLog::ERROR, "unable to initialize IIC 2 at sda=%d,scl=%d",
|
||||
(int)GWIIC_SDA2, (int)GWIIC_SCL2);
|
||||
}
|
||||
else
|
||||
{
|
||||
buses[busId] = &Wire1;
|
||||
LOG_DEBUG(GwLog::LOG, "initialized IIC 2 at sda=%d,scl=%d",
|
||||
(int)GWIIC_SDA2, (int)GWIIC_SCL2);
|
||||
}
|
||||
if (initWire(logger,Wire1,2)){
|
||||
buses[busId] = &Wire1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -124,7 +183,7 @@ void runIicTask(GwApi *api){
|
||||
GwIntervalRunner timers;
|
||||
int counterId=api->addCounter("iicsensors");
|
||||
for (auto it=sensors.begin();it != sensors.end();it++){
|
||||
SensorBase *cfg=*it;
|
||||
IICSensorBase *cfg=*it;
|
||||
auto bus=buses.find(cfg->busId);
|
||||
if (! cfg->isActive()) continue;
|
||||
if (bus == buses.end()){
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
#define _IIC_GROOVE_LIST
|
||||
#include "GwQMP6988.h"
|
||||
#ifdef _GWQMP6988
|
||||
#define PRFX1 "QMP698811"
|
||||
#define PRFX2 "QMP698812"
|
||||
#define PRFX3 "QMP698821"
|
||||
#define PRFX4 "QMP698822"
|
||||
class QMP6988Config : public SensorBase{
|
||||
#define TYPE "QMP6988"
|
||||
#define PRFX1 TYPE "11"
|
||||
#define PRFX2 TYPE "12"
|
||||
#define PRFX3 TYPE "21"
|
||||
#define PRFX4 TYPE "22"
|
||||
class QMP6988Config : public IICSensorBase{
|
||||
public:
|
||||
String prNam="Pressure";
|
||||
bool prAct=true;
|
||||
tN2kPressureSource prSrc=tN2kPressureSource::N2kps_Atmospheric;
|
||||
float prOff=0;
|
||||
QMP6988 *device=nullptr;
|
||||
QMP6988Config(GwApi* api,const String &prefix):SensorBase(api,prefix){}
|
||||
QMP6988Config(GwApi* api,const String &prefix):SensorBase(TYPE,api,prefix){}
|
||||
virtual bool isActive(){return prAct;};
|
||||
virtual bool initDevice(GwApi *api,TwoWire *wire){
|
||||
if (!isActive()) return false;
|
||||
@@ -48,6 +50,7 @@ class QMP6988Config : public SensorBase{
|
||||
CFG_GET(prOff,prefix);
|
||||
|
||||
virtual void readConfig(GwConfigHandler *cfg){
|
||||
if (ok) return;
|
||||
if (prefix == PRFX1){
|
||||
busId=1;
|
||||
addr=86;
|
||||
@@ -76,7 +79,10 @@ class QMP6988Config : public SensorBase{
|
||||
|
||||
}
|
||||
};
|
||||
void registerQMP6988(GwApi *api,SensorList &sensors){
|
||||
static IICSensorBase::Creator creator=[](GwApi *api,const String &prfx){
|
||||
return new QMP6988Config(api,prfx);
|
||||
};
|
||||
IICSensorBase::Creator registerQMP6988(GwApi *api,IICSensorList &sensors){
|
||||
GwLog *logger=api->getLogger();
|
||||
#if defined(GWQMP6988) || defined(GWQMP698811)
|
||||
{
|
||||
@@ -110,8 +116,11 @@ void registerQMP6988(GwApi *api,SensorList &sensors){
|
||||
#pragma message "GWQMP698822 defined"
|
||||
}
|
||||
#endif
|
||||
return creator;
|
||||
}
|
||||
|
||||
#else
|
||||
void registerQMP6988(GwApi *api,SensorList &sensors){}
|
||||
IICSensorBase::Creator registerQMP6988(GwApi *api,IICSensorList &sensors){
|
||||
return IICSensorBase::Creator();
|
||||
}
|
||||
#endif
|
||||
@@ -4,8 +4,6 @@
|
||||
#ifdef _GWIIC
|
||||
#if defined(GWQMP6988) || defined(GWQMP698811) || defined(GWQMP698812) || defined(GWQMP698821) || defined(GWQMP698822)
|
||||
#define _GWQMP6988
|
||||
#else
|
||||
#undef _GWQMP6988
|
||||
#endif
|
||||
#else
|
||||
#undef _GWQMP6988
|
||||
@@ -18,5 +16,5 @@
|
||||
#ifdef _GWQMP6988
|
||||
#include "QMP6988.h"
|
||||
#endif
|
||||
void registerQMP6988(GwApi *api,SensorList &sensors);
|
||||
IICSensorBase::Creator registerQMP6988(GwApi *api,IICSensorList &sensors);
|
||||
#endif
|
||||
@@ -1,11 +1,12 @@
|
||||
#include "GwSHT3X.h"
|
||||
|
||||
#ifdef _GWSHT3X
|
||||
#define PRFX1 "SHT3X11"
|
||||
#define PRFX2 "SHT3X12"
|
||||
#define PRFX3 "SHT3X21"
|
||||
#define PRFX4 "SHT3X22"
|
||||
class SHT3XConfig : public SensorBase{
|
||||
#define TYPE "SHT3X"
|
||||
#define PRFX1 TYPE "11"
|
||||
#define PRFX2 TYPE "12"
|
||||
#define PRFX3 TYPE "21"
|
||||
#define PRFX4 TYPE "22"
|
||||
|
||||
class SHT3XConfig : public IICSensorBase{
|
||||
public:
|
||||
String tmNam;
|
||||
String huNam;
|
||||
@@ -15,7 +16,7 @@ class SHT3XConfig : public SensorBase{
|
||||
tN2kTempSource tmSrc;
|
||||
SHT3X *device=nullptr;
|
||||
SHT3XConfig(GwApi *api,const String &prefix):
|
||||
SensorBase(api,prefix){}
|
||||
SensorBase(TYPE,api,prefix){}
|
||||
virtual bool isActive(){
|
||||
return tmAct || huAct;
|
||||
}
|
||||
@@ -77,6 +78,7 @@ class SHT3XConfig : public SensorBase{
|
||||
CFG_GET(tmSrc,prefix);
|
||||
|
||||
virtual void readConfig(GwConfigHandler *cfg){
|
||||
if (ok) return;
|
||||
if (prefix == PRFX1){
|
||||
busId=1;
|
||||
addr=0x44;
|
||||
@@ -104,11 +106,14 @@ class SHT3XConfig : public SensorBase{
|
||||
intv*=1000;
|
||||
}
|
||||
};
|
||||
void registerSHT3X(GwApi *api,SensorList &sensors){
|
||||
IICSensorBase::Creator creator=[](GwApi *api,const String &prfx){
|
||||
return new SHT3XConfig(api,prfx);
|
||||
};
|
||||
IICSensorBase::Creator registerSHT3X(GwApi *api,IICSensorList &sensors){
|
||||
GwLog *logger=api->getLogger();
|
||||
#if defined(GWSHT3X) || defined (GWSHT3X11)
|
||||
{
|
||||
SHT3XConfig *scfg=new SHT3XConfig(api,PRFX1);
|
||||
auto *scfg=creator(api,PRFX1);
|
||||
sensors.add(api,scfg);
|
||||
CHECK_IIC1();
|
||||
#pragma message "GWSHT3X11 defined"
|
||||
@@ -116,7 +121,7 @@ void registerSHT3X(GwApi *api,SensorList &sensors){
|
||||
#endif
|
||||
#if defined(GWSHT3X12)
|
||||
{
|
||||
SHT3XConfig *scfg=new SHT3XConfig(api,PRFX2);
|
||||
auto *scfg=creator(api,PRFX2);
|
||||
sensors.add(api,scfg);
|
||||
CHECK_IIC1();
|
||||
#pragma message "GWSHT3X12 defined"
|
||||
@@ -124,7 +129,7 @@ void registerSHT3X(GwApi *api,SensorList &sensors){
|
||||
#endif
|
||||
#if defined(GWSHT3X21)
|
||||
{
|
||||
SHT3XConfig *scfg=new SHT3XConfig(api,PRFX3);
|
||||
auto *scfg=creator(api,PRFX3);
|
||||
sensors.add(api,scfg);
|
||||
CHECK_IIC2();
|
||||
#pragma message "GWSHT3X21 defined"
|
||||
@@ -132,16 +137,18 @@ void registerSHT3X(GwApi *api,SensorList &sensors){
|
||||
#endif
|
||||
#if defined(GWSHT3X22)
|
||||
{
|
||||
SHT3XConfig *scfg=new SHT3XConfig(api,PRFX4);
|
||||
auto *scfg=creator(api,PRFX4);
|
||||
sensors.add(api,scfg);
|
||||
CHECK_IIC2();
|
||||
#pragma message "GWSHT3X22 defined"
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
void registerSHT3X(GwApi *api,SensorList &sensors){
|
||||
return creator;
|
||||
};
|
||||
|
||||
#else
|
||||
IICSensorBase::Creator registerSHT3X(GwApi *api,IICSensorList &sensors){
|
||||
return IICSensorBase::Creator();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
#ifdef _GWIIC
|
||||
#if defined(GWSHT3X) || defined(GWSHT3X11) || defined(GWSHT3X12) || defined(GWSHT3X21) || defined(GWSHT3X22)
|
||||
#define _GWSHT3X
|
||||
#else
|
||||
#undef _GWSHT3X
|
||||
#endif
|
||||
#else
|
||||
#undef _GWSHT3X
|
||||
@@ -18,5 +16,5 @@
|
||||
#ifdef _GWSHT3X
|
||||
#include "SHT3X.h"
|
||||
#endif
|
||||
void registerSHT3X(GwApi *api,SensorList &sensors);
|
||||
IICSensorBase::Creator registerSHT3X(GwApi *api,IICSensorList &sensors);
|
||||
#endif
|
||||
@@ -29,7 +29,6 @@ private:
|
||||
MyAisDecoder *aisDecoder=NULL;
|
||||
ConverterList<NMEA0183DataToN2KFunctions, SNMEA0183Msg> converters;
|
||||
std::map<String,unsigned long> lastSends;
|
||||
unsigned long minSendInterval=50;
|
||||
GwXDRMappings *xdrMappings;
|
||||
class WaypointNumber{
|
||||
public:
|
||||
@@ -92,7 +91,7 @@ private:
|
||||
return false;
|
||||
}
|
||||
bool send(tN2kMsg &msg, int sourceId,String key=""){
|
||||
return send(msg,key,minSendInterval,sourceId);
|
||||
return send(msg,key,config.min2KInterval,sourceId);
|
||||
}
|
||||
bool updateDouble(GwBoatItem<double> *target,double v, int sourceId){
|
||||
if (v != NMEA0183DoubleNA){
|
||||
@@ -304,7 +303,7 @@ private:
|
||||
LOG_DEBUG(GwLog::DEBUG + 1, "convert RMB");
|
||||
tRMB rmb;
|
||||
if (! NMEA0183ParseRMB_nc(msg,rmb)){
|
||||
LOG_DEBUG(GwLog::DEBUG, "failed to parse RMC %s", msg.line);
|
||||
LOG_DEBUG(GwLog::DEBUG, "failed to parse RMB %s", msg.line);
|
||||
return;
|
||||
}
|
||||
tN2kMsg n2kMsg;
|
||||
@@ -359,6 +358,7 @@ private:
|
||||
LOG_DEBUG(GwLog::DEBUG, "invalid status %c for RMC %s",status, msg.line);
|
||||
return;
|
||||
}
|
||||
lastRmc=millis(); //we received an RMC that is not from us
|
||||
tN2kMsg n2kMsg;
|
||||
if (
|
||||
UD(GPST) &&
|
||||
@@ -666,21 +666,33 @@ private:
|
||||
void convertDBT(const SNMEA0183Msg &msg){
|
||||
return convertDBKx(msg,DBT);
|
||||
}
|
||||
|
||||
#define validInstance(name) (name >= 0 && name <= 253)
|
||||
void convertRSA(const SNMEA0183Msg &msg){
|
||||
double RPOS=NMEA0183DoubleNA;
|
||||
double PRPOS=NMEA0183DoubleNA;
|
||||
if (msg.FieldCount() < 4)
|
||||
{
|
||||
LOG_DEBUG(GwLog::DEBUG, "failed to parse RSA %s", msg.line);
|
||||
return;
|
||||
}
|
||||
tN2kMsg n2kMsg;
|
||||
if (msg.FieldLen(0)>0){
|
||||
if (msg.Field(1)[0] != 'A') return;
|
||||
RPOS=degToRad*atof(msg.Field(0));
|
||||
tN2kMsg n2kMsg;
|
||||
if (! UD(RPOS)) return;
|
||||
SetN2kRudder(n2kMsg,RPOS);
|
||||
send(n2kMsg,msg.sourceId);
|
||||
if (msg.Field(1)[0] == 'A'){
|
||||
RPOS=degToRad*atof(msg.Field(0));
|
||||
if (UD(RPOS) && validInstance(config.starboardRudderInstance)) {
|
||||
SetN2kRudder(n2kMsg,RPOS,config.starboardRudderInstance);
|
||||
send(n2kMsg,msg.sourceId,"127245S");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (msg.FieldLen(2)>0){
|
||||
if (msg.Field(3)[0] == 'A'){
|
||||
PRPOS=degToRad*atof(msg.Field(2));
|
||||
if (UD(PRPOS) && validInstance(config.portRudderInstance)){
|
||||
SetN2kRudder(n2kMsg,PRPOS,config.portRudderInstance);
|
||||
send(n2kMsg,msg.sourceId,"127245P");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1061,10 +1073,10 @@ public:
|
||||
|
||||
NMEA0183DataToN2KFunctions(GwLog *logger, GwBoatData *boatData, N2kSender callback,
|
||||
GwXDRMappings *xdrMappings,
|
||||
unsigned long minSendInterval)
|
||||
const GwConverterConfig &cfg)
|
||||
: NMEA0183DataToN2K(logger, boatData, callback)
|
||||
{
|
||||
this->minSendInterval=minSendInterval;
|
||||
this->config=cfg;
|
||||
this->xdrMappings=xdrMappings;
|
||||
aisDecoder= new MyAisDecoder(logger,this->sender);
|
||||
registerConverters();
|
||||
@@ -1074,7 +1086,7 @@ public:
|
||||
|
||||
NMEA0183DataToN2K* NMEA0183DataToN2K::create(GwLog *logger,GwBoatData *boatData,N2kSender callback,
|
||||
GwXDRMappings *xdrMappings,
|
||||
unsigned long minSendInterval){
|
||||
return new NMEA0183DataToN2KFunctions(logger, boatData,callback,xdrMappings,minSendInterval);
|
||||
const GwConverterConfig &config){
|
||||
return new NMEA0183DataToN2KFunctions(logger, boatData,callback,xdrMappings,config);
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "GwBoatData.h"
|
||||
#include "N2kMessages.h"
|
||||
#include "GwXDRMappings.h"
|
||||
#include "GwConverterConfig.h"
|
||||
|
||||
class NMEA0183DataToN2K{
|
||||
public:
|
||||
@@ -12,14 +13,17 @@ class NMEA0183DataToN2K{
|
||||
GwLog * logger;
|
||||
GwBoatData *boatData;
|
||||
N2kSender sender;
|
||||
GwConverterConfig config;
|
||||
unsigned long lastRmc=millis();
|
||||
public:
|
||||
NMEA0183DataToN2K(GwLog *logger,GwBoatData *boatData,N2kSender callback);
|
||||
virtual bool parseAndSend(const char *buffer, int sourceId)=0;
|
||||
virtual unsigned long *handledPgns()=0;
|
||||
virtual int numConverters()=0;
|
||||
virtual String handledKeys()=0;
|
||||
unsigned long getLastRmc()const {return lastRmc; }
|
||||
static NMEA0183DataToN2K* create(GwLog *logger,GwBoatData *boatData,N2kSender callback,
|
||||
GwXDRMappings *xdrMappings,
|
||||
unsigned long minSendInterval);
|
||||
const GwConverterConfig &config);
|
||||
};
|
||||
#endif
|
||||
@@ -43,7 +43,7 @@ N2kDataToNMEA0183::N2kDataToNMEA0183(GwLog * logger, GwBoatData *boatData,
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
void N2kDataToNMEA0183::loop() {
|
||||
void N2kDataToNMEA0183::loop(unsigned long) {
|
||||
}
|
||||
|
||||
//*****************************************************************************
|
||||
@@ -62,20 +62,19 @@ class N2kToNMEA0183Functions : public N2kDataToNMEA0183
|
||||
{
|
||||
|
||||
private:
|
||||
int minXdrInterval=100; //minimal interval between 2 sends of the same transducer
|
||||
GwXDRMappings *xdrMappings;
|
||||
ConverterList<N2kToNMEA0183Functions,tN2kMsg> converters;
|
||||
std::map<String,unsigned long> lastSendTransducers;
|
||||
static const unsigned long RMCPeriod = 500;
|
||||
tNMEA0183Msg xdrMessage;
|
||||
bool xdrOpened=false;
|
||||
int xdrCount=0;
|
||||
unsigned long lastRmcSent=0;
|
||||
|
||||
bool addToXdr(GwXDRFoundMapping::XdrEntry entry){
|
||||
auto it=lastSendTransducers.find(entry.transducer);
|
||||
unsigned long now=millis();
|
||||
if (it != lastSendTransducers.end()){
|
||||
if ((it->second + minXdrInterval) > now) return false;
|
||||
if ((it->second + config.minXdrInterval) > now) return false;
|
||||
}
|
||||
lastSendTransducers[entry.transducer]=now;
|
||||
if (! xdrOpened){
|
||||
@@ -134,9 +133,6 @@ private:
|
||||
return boatData->update((double)value,sourceId,mapping);
|
||||
}
|
||||
|
||||
unsigned long LastPosSend;
|
||||
unsigned long NextRMCSend;
|
||||
unsigned long lastLoopTime;
|
||||
|
||||
virtual unsigned long *handledPgns()
|
||||
{
|
||||
@@ -166,7 +162,6 @@ private:
|
||||
{
|
||||
return converters.numConverters();
|
||||
}
|
||||
void SetNextRMCSend() { NextRMCSend = millis() + RMCPeriod; }
|
||||
|
||||
//*************** the converters ***********************
|
||||
void HandleHeading(const tN2kMsg &N2kMsg)
|
||||
@@ -546,11 +541,9 @@ private:
|
||||
void SendRMC()
|
||||
{
|
||||
long now = millis();
|
||||
if (NextRMCSend <= millis() &&
|
||||
boatData->LAT->isValid(now) &&
|
||||
boatData->LAT->getLastSource() == sourceId
|
||||
)
|
||||
if (boatData->LAT->isValid(now) && boatData->LON->isValid(now))
|
||||
{
|
||||
lastRmcSent=now;
|
||||
tNMEA0183Msg NMEA0183Msg;
|
||||
if (NMEA0183SetRMC(NMEA0183Msg,
|
||||
|
||||
@@ -565,7 +558,6 @@ private:
|
||||
{
|
||||
SendMessage(NMEA0183Msg);
|
||||
}
|
||||
SetNextRMCSend();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,24 +603,38 @@ private:
|
||||
|
||||
if (ParseN2kRudder(N2kMsg, RudderPosition, Instance, RudderDirectionOrder, AngleOrder))
|
||||
{
|
||||
|
||||
updateDouble(boatData->RPOS, RudderPosition);
|
||||
if (Instance != 0)
|
||||
if (Instance == config.starboardRudderInstance){
|
||||
updateDouble(boatData->RPOS, RudderPosition);
|
||||
}
|
||||
else if (Instance == config.portRudderInstance){
|
||||
updateDouble(boatData->PRPOS, RudderPosition);
|
||||
}
|
||||
else{
|
||||
return;
|
||||
}
|
||||
|
||||
tNMEA0183Msg NMEA0183Msg;
|
||||
|
||||
if (!NMEA0183Msg.Init("RSA", talkerId))
|
||||
return;
|
||||
if (!NMEA0183Msg.AddDoubleField(formatCourse(RudderPosition)))
|
||||
return;
|
||||
if (!NMEA0183Msg.AddStrField("A"))
|
||||
return;
|
||||
if (!NMEA0183Msg.AddDoubleField(0.0))
|
||||
return;
|
||||
if (!NMEA0183Msg.AddStrField("A"))
|
||||
return;
|
||||
|
||||
auto rpos=boatData->RPOS;
|
||||
if (rpos->isValid()){
|
||||
if (!NMEA0183Msg.AddDoubleField(formatWind(rpos->getData())))return;
|
||||
if (!NMEA0183Msg.AddStrField("A"))return;
|
||||
}
|
||||
else{
|
||||
if (!NMEA0183Msg.AddDoubleField(0.0))return;
|
||||
if (!NMEA0183Msg.AddStrField("V"))return;
|
||||
}
|
||||
auto prpos=boatData->PRPOS;
|
||||
if (prpos->isValid()){
|
||||
if (!NMEA0183Msg.AddDoubleField(formatWind(prpos->getData())))return;
|
||||
if (!NMEA0183Msg.AddStrField("A"))return;
|
||||
}
|
||||
else{
|
||||
if (!NMEA0183Msg.AddDoubleField(0.0))return;
|
||||
if (!NMEA0183Msg.AddStrField("V"))return;
|
||||
}
|
||||
SendMessage(NMEA0183Msg);
|
||||
}
|
||||
}
|
||||
@@ -1508,35 +1514,30 @@ private:
|
||||
public:
|
||||
N2kToNMEA0183Functions(GwLog *logger, GwBoatData *boatData,
|
||||
SendNMEA0183MessageCallback callback,
|
||||
String talkerId, GwXDRMappings *xdrMappings, int minXdrInterval)
|
||||
String talkerId, GwXDRMappings *xdrMappings, const GwConverterConfig &cfg)
|
||||
: N2kDataToNMEA0183(logger, boatData, callback,talkerId)
|
||||
{
|
||||
LastPosSend = 0;
|
||||
lastLoopTime = 0;
|
||||
NextRMCSend = millis() + RMCPeriod;
|
||||
|
||||
this->logger = logger;
|
||||
this->boatData = boatData;
|
||||
this->xdrMappings=xdrMappings;
|
||||
this->minXdrInterval=minXdrInterval;
|
||||
this->config=cfg;
|
||||
registerConverters();
|
||||
}
|
||||
virtual void loop()
|
||||
virtual void loop(unsigned long lastExtRmc) override
|
||||
{
|
||||
N2kDataToNMEA0183::loop();
|
||||
N2kDataToNMEA0183::loop(lastExtRmc);
|
||||
unsigned long now = millis();
|
||||
if (now < (lastLoopTime + 100))
|
||||
return;
|
||||
lastLoopTime = now;
|
||||
SendRMC();
|
||||
if (config.rmcInterval > 0 && (lastExtRmc + config.rmcCheckTime) <= now && (lastRmcSent + config.rmcInterval) <= now){
|
||||
SendRMC();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
N2kDataToNMEA0183* N2kDataToNMEA0183::create(GwLog *logger, GwBoatData *boatData,
|
||||
SendNMEA0183MessageCallback callback, String talkerId, GwXDRMappings *xdrMappings,
|
||||
int minXdrInterval){
|
||||
const GwConverterConfig &cfg){
|
||||
LOG_DEBUG(GwLog::LOG,"creating N2kToNMEA0183");
|
||||
return new N2kToNMEA0183Functions(logger,boatData,callback, talkerId,xdrMappings,minXdrInterval);
|
||||
return new N2kToNMEA0183Functions(logger,boatData,callback, talkerId,xdrMappings,cfg);
|
||||
}
|
||||
//*****************************************************************************
|
||||
|
||||
@@ -26,9 +26,10 @@ OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#include <NMEA0183.h>
|
||||
#include <NMEA2000.h>
|
||||
|
||||
#include <GwLog.h>
|
||||
#include <GwBoatData.h>
|
||||
#include <GwXDRMappings.h>
|
||||
#include "GwLog.h"
|
||||
#include "GwBoatData.h"
|
||||
#include "GwXDRMappings.h"
|
||||
#include "GwConverterConfig.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
class GwJsonDocument;
|
||||
@@ -36,8 +37,8 @@ class N2kDataToNMEA0183
|
||||
{
|
||||
public:
|
||||
typedef std::function<void(const tNMEA0183Msg &NMEA0183Msg,int id)> SendNMEA0183MessageCallback;
|
||||
|
||||
protected:
|
||||
GwConverterConfig config;
|
||||
GwLog *logger;
|
||||
GwBoatData *boatData;
|
||||
int sourceId=0;
|
||||
@@ -49,9 +50,9 @@ protected:
|
||||
|
||||
public:
|
||||
static N2kDataToNMEA0183* create(GwLog *logger, GwBoatData *boatData, SendNMEA0183MessageCallback callback,
|
||||
String talkerId, GwXDRMappings *xdrMappings,int minXdrInterval=100);
|
||||
String talkerId, GwXDRMappings *xdrMappings,const GwConverterConfig &cfg);
|
||||
virtual void HandleMsg(const tN2kMsg &N2kMsg, int sourceId) = 0;
|
||||
virtual void loop();
|
||||
virtual void loop(unsigned long lastRmc);
|
||||
virtual ~N2kDataToNMEA0183(){}
|
||||
virtual unsigned long* handledPgns()=0;
|
||||
virtual int numPgns()=0;
|
||||
|
||||
55
lib/sensors/GwSensor.h
Normal file
55
lib/sensors/GwSensor.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
(C) Andreas Vogel andreas@wellenvogel.de
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _GWSENSORS_H
|
||||
#define _GWSENSORS_H
|
||||
#include "GwApi.h"
|
||||
#include "GwLog.h"
|
||||
template<typename BUS>
|
||||
class SensorBase{
|
||||
public:
|
||||
int busId=0;
|
||||
int iid=99; //N2K instanceId
|
||||
int addr=-1;
|
||||
const String prefix;
|
||||
const String type;
|
||||
long intv=0;
|
||||
bool ok=false;
|
||||
virtual void readConfig(GwConfigHandler *cfg)=0;
|
||||
SensorBase(const String &tn,GwApi *api,const String &prfx):type(tn),prefix(prfx){
|
||||
}
|
||||
using Creator=std::function<SensorBase<BUS> *(GwApi *api,const String &prfx)>;
|
||||
virtual bool isActive(){return false;};
|
||||
virtual bool initDevice(GwApi *api,BUS *wire){return false;};
|
||||
virtual bool preinit(GwApi * api){return false;}
|
||||
virtual void measure(GwApi * api,BUS *wire, int counterId){};
|
||||
virtual ~SensorBase(){}
|
||||
};
|
||||
|
||||
template<typename BUS>
|
||||
class SensorList : public std::vector<SensorBase<BUS>*>{
|
||||
public:
|
||||
void add(GwApi *api, SensorBase<BUS> *sensor){
|
||||
sensor->readConfig(api->getConfig());
|
||||
api->getLogger()->logDebug(GwLog::LOG,"configured sensor %s, status %d",sensor->prefix.c_str(),(int)sensor->ok);
|
||||
this->push_back(sensor);
|
||||
}
|
||||
using std::vector<SensorBase<BUS>*>::vector;
|
||||
};
|
||||
|
||||
|
||||
#define CFG_GET(name,prefix) \
|
||||
cfg->getValue(name, GwConfigDefinitions::prefix ## name)
|
||||
|
||||
#endif
|
||||
@@ -115,11 +115,21 @@ void GwSerial::readMessages(GwMessageFetcher *writer){
|
||||
writer->handleBuffer(readBuffer);
|
||||
}
|
||||
|
||||
void GwSerial::flush(){
|
||||
if (! isInitialized()) return;
|
||||
while (write() == GwBuffer::AGAIN){
|
||||
vTaskDelay(1);
|
||||
bool GwSerial::flush(long max){
|
||||
if (! isInitialized()) return false;
|
||||
if (! availableWrite) {
|
||||
if ( serial->availableForWrite() < 1){
|
||||
return false;
|
||||
}
|
||||
availableWrite=true;
|
||||
}
|
||||
auto start=millis();
|
||||
while (millis() < (start+max)){
|
||||
if (write() != GwBuffer::AGAIN) return true;
|
||||
vTaskDelay(1);
|
||||
}
|
||||
availableWrite=(serial->availableForWrite() > 0);
|
||||
return false;
|
||||
}
|
||||
Stream * GwSerial::getStream(bool partialWrite){
|
||||
return new GwSerialStream(this,partialWrite);
|
||||
|
||||
@@ -17,6 +17,7 @@ class GwSerial : public GwChannelInterface{
|
||||
int overflows=0;
|
||||
size_t enqueue(const uint8_t *data, size_t len,bool partial=false);
|
||||
Stream *serial;
|
||||
bool availableWrite=false; //if this is false we will wait for availabkleWrite until we flush again
|
||||
public:
|
||||
static const int bufferSize=200;
|
||||
GwSerial(GwLog *logger,Stream *stream,int id,bool allowRead=true);
|
||||
@@ -25,8 +26,9 @@ class GwSerial : public GwChannelInterface{
|
||||
virtual size_t sendToClients(const char *buf,int sourceId,bool partial=false);
|
||||
virtual void loop(bool handleRead=true,bool handleWrite=true);
|
||||
virtual void readMessages(GwMessageFetcher *writer);
|
||||
void flush();
|
||||
bool flush(long millis=200);
|
||||
virtual Stream *getStream(bool partialWrites);
|
||||
bool getAvailableWrite(){return availableWrite;}
|
||||
friend GwSerialStream;
|
||||
};
|
||||
#endif
|
||||
139
lib/spitask/GWDMS22B.cpp
Normal file
139
lib/spitask/GWDMS22B.cpp
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
(C) Andreas Vogel andreas@wellenvogel.de
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "GWDMS22B.h"
|
||||
#include "GwApi.h"
|
||||
#include "N2kMessages.h"
|
||||
#include "GwHardware.h"
|
||||
|
||||
|
||||
#define CHECK_BUS(BUS) \
|
||||
checkDef("missing config for " #BUS,GW ## BUS ## _CLK ,GW ## BUS ## _MISO);
|
||||
|
||||
#define ADD22B(PRFX,BUS) \
|
||||
{\
|
||||
CHECK_BUS(BUS); \
|
||||
GWDMS22B *dms=new GWDMS22B(api,#PRFX,GW ## BUS ## _HOST);\
|
||||
sensors.add(api,dms); \
|
||||
}
|
||||
|
||||
#ifdef GWDMS22B11
|
||||
#define ADD22B11 ADD22B(DMS22B11,SPI1)
|
||||
#ifndef GWDMS22B11_CS
|
||||
#define GWDMS22B11_CS -1
|
||||
#endif
|
||||
#else
|
||||
#define GWDMS22B11_CS -1
|
||||
#define ADD22B11
|
||||
#endif
|
||||
|
||||
#ifdef GWDMS22B12
|
||||
#define ADD22B12 ADD22B(DMS22B12,SPI1)
|
||||
#ifndef GWDMS22B12_CS
|
||||
#error "you need to define GWDMS22B12_CS"
|
||||
#endif
|
||||
#if GWDMS22B11_CS == -1
|
||||
#error "multiple devices on one SPI bus need chip select defines - GWDMS22B11_CS is unset"
|
||||
#endif
|
||||
#else
|
||||
#define GWDMS22B12_CS -1
|
||||
#define ADD22B12
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef GWDMS22B21
|
||||
#define ADD22B21 ADD22B(DMS22B21,SPI2)
|
||||
#ifndef GWDMS22B21_CS
|
||||
#define GWDMS22B21_CS -1
|
||||
#endif
|
||||
#else
|
||||
#define GWDMS22B21_CS -1
|
||||
#define ADD22B21
|
||||
#endif
|
||||
|
||||
#ifdef GWDMS22B22
|
||||
#define ADD22B22 ADD22B(DMS22B22,SPI2)
|
||||
#ifndef GWDMS22B22_CS
|
||||
#error "you need to define GWDMS22B22_CS"
|
||||
#endif
|
||||
#if GWDMS22B21_CS == -1
|
||||
#error "multiple devices on one SPI bus need chip select defines - GWDMS22B21_CS is unset"
|
||||
#endif
|
||||
#else
|
||||
#define GWDMS22B22_CS -1
|
||||
#define ADD22B22
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
class GWDMS22B : public SSISensor{
|
||||
int zero=2047;
|
||||
bool invt=false;
|
||||
String zeroConfigName;
|
||||
public:
|
||||
GWDMS22B(GwApi *api,const String &prfx, int host):SSISensor("DMS22B",api,prfx,host){}
|
||||
virtual bool preinit(GwApi * api){
|
||||
GwLog *logger=api->getLogger();
|
||||
LOG_DEBUG(GwLog::LOG,"DMS22B configured, prefix=%s, intv=%f, active=%d",prefix.c_str(),fintv,(int)act);
|
||||
api->addCapability(prefix,"true");
|
||||
return act;
|
||||
}
|
||||
virtual void measure(GwApi * api,BusType *bus, int counterId){
|
||||
GwLog *logger=api->getLogger();
|
||||
uint32_t value=0;
|
||||
esp_err_t res=readData(value);
|
||||
if (res != ESP_OK){
|
||||
LOG_DEBUG(GwLog::ERROR,"unable to measure %s: %d",prefix.c_str(),(int)res);
|
||||
}
|
||||
double resolved=(((int)value-zero)*360.0/mask);
|
||||
if (invt) resolved=-resolved;
|
||||
LOG_DEBUG(GwLog::DEBUG,"measure %s : %d, resolved: %f",prefix.c_str(),value,(float)resolved);
|
||||
tN2kMsg msg;
|
||||
SetN2kRudder(msg,DegToRad(resolved),iid);
|
||||
api->sendN2kMessage(msg);
|
||||
api->increment(counterId,prefix);
|
||||
api->setCalibrationValue(zeroConfigName,(double)value);
|
||||
}
|
||||
#define DMS22B(PRFX,...) \
|
||||
if (prefix == #PRFX) {\
|
||||
CFG_GET(act,PRFX); \
|
||||
CFG_GET(iid,PRFX); \
|
||||
CFG_GET(fintv,PRFX); \
|
||||
CFG_GET(zero,PRFX); \
|
||||
zeroConfigName=GwConfigDefinitions::PRFX ## zero;\
|
||||
CFG_GET(invt,PRFX); \
|
||||
bits=12; \
|
||||
clock=500000; \
|
||||
cs=GW ## PRFX ## _CS; \
|
||||
__VA_ARGS__ \
|
||||
}
|
||||
|
||||
|
||||
virtual void readConfig(GwConfigHandler *cfg){
|
||||
DMS22B(DMS22B11);
|
||||
DMS22B(DMS22B12);
|
||||
DMS22B(DMS22B21);
|
||||
DMS22B(DMS22B22);
|
||||
intv=1000*fintv;
|
||||
}
|
||||
};
|
||||
|
||||
void registerDMS22B(GwApi *api,SpiSensorList &sensors){
|
||||
ADD22B11
|
||||
ADD22B12
|
||||
ADD22B21
|
||||
ADD22B22
|
||||
|
||||
}
|
||||
22
lib/spitask/GWDMS22B.h
Normal file
22
lib/spitask/GWDMS22B.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
(C) Andreas Vogel andreas@wellenvogel.de
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
SSI sensor DMS22B - https://www.mouser.de/datasheet/2/54/bour_s_a0011704065_1-2262614.pdf
|
||||
*/
|
||||
#ifndef _GWDMS22B_H
|
||||
#define _GWDMS22B_H
|
||||
#include "GwSpiSensor.h"
|
||||
void registerDMS22B(GwApi *api,SpiSensorList &sensors);
|
||||
#endif
|
||||
141
lib/spitask/GwSpiSensor.h
Normal file
141
lib/spitask/GwSpiSensor.h
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
(C) Andreas Vogel andreas@wellenvogel.de
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
//for SSI refer to https://www.posital.com/media/posital_media/documents/AbsoluteEncoders_Context_Technology_SSI_AppNote.pdf
|
||||
#ifndef _GWSPISENSOR_H
|
||||
#define _GWSPISENSOR_H
|
||||
#include <driver/spi_master.h>
|
||||
#include "GwSensor.h"
|
||||
#include <memory>
|
||||
|
||||
class SPIBus{
|
||||
spi_host_device_t hd;
|
||||
bool initialized=false;
|
||||
public:
|
||||
SPIBus(spi_host_device_t h):hd(h){}
|
||||
bool init(GwLog*logger,int mosi=-1,int miso=-1,int clck=-1){
|
||||
spi_bus_config_t buscfg = {
|
||||
.mosi_io_num = mosi,
|
||||
.miso_io_num = miso,
|
||||
.sclk_io_num = clck,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = 0
|
||||
};
|
||||
esp_err_t res=spi_bus_initialize(hd,&buscfg,0);
|
||||
if (res == ESP_OK){
|
||||
LOG_DEBUG(GwLog::LOG,"initialzed SPI bus %d,mosi=%d,miso=%d,clock=%d",
|
||||
(int)hd,mosi,miso,clck);
|
||||
initialized=true;
|
||||
}
|
||||
else{
|
||||
LOG_DEBUG(GwLog::ERROR,"unable to initialize SPI bus %d,mosi=%d,miso=%d,clock=%d, error=%d",
|
||||
(int)hd,mosi,miso,clck,(int)res);
|
||||
}
|
||||
return initialized;
|
||||
}
|
||||
spi_host_device_t host() const { return hd;}
|
||||
};
|
||||
|
||||
using BusType=SPIBus;
|
||||
|
||||
class SSIDevice{
|
||||
spi_device_handle_t spi;
|
||||
spi_host_device_t host;
|
||||
bool initialized=false;
|
||||
int bits=12;
|
||||
public:
|
||||
SSIDevice(const SPIBus *bus):host(bus->host()){}
|
||||
bool init(GwLog*logger,int clock,int cs=-1,int bits=12){
|
||||
this->bits=bits;
|
||||
spi_device_interface_config_t devcfg = {
|
||||
.command_bits = 0,
|
||||
.address_bits = 0,
|
||||
.dummy_bits = 0,
|
||||
.mode = 2,
|
||||
.duty_cycle_pos = 128,
|
||||
.cs_ena_pretrans = 0,
|
||||
.cs_ena_posttrans =0,
|
||||
.clock_speed_hz = clock,
|
||||
.input_delay_ns =0,
|
||||
.spics_io_num = cs, //CS pin
|
||||
.queue_size = 1 //see https://github.com/espressif/esp-idf/issues/9450
|
||||
};
|
||||
esp_err_t res=spi_bus_add_device(host,&devcfg,&spi);
|
||||
if (res == ESP_OK){
|
||||
LOG_DEBUG(GwLog::LOG,"added SSI device to bus %d, cs=%d, clock=%d",
|
||||
(int)host,cs,clock);
|
||||
initialized=true;
|
||||
}
|
||||
else{
|
||||
LOG_DEBUG(GwLog::ERROR,"unable to add SSI device to bus %d, cs=%d, clock=%d, error=%d",
|
||||
(int)host,cs,clock,(int) res);
|
||||
}
|
||||
return initialized;
|
||||
}
|
||||
bool isInitialized() const { return initialized;}
|
||||
spi_device_handle_t & device(){return spi;}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class SSISensor : public SensorBase<BusType>{
|
||||
std::unique_ptr<SSIDevice> device;
|
||||
protected:
|
||||
int bits=12;
|
||||
int mask=0xffff;
|
||||
int cs=-1;
|
||||
int clock=0;
|
||||
bool act=false;
|
||||
float fintv=0;
|
||||
virtual bool initSSI(GwLog*logger,const SPIBus *bus,
|
||||
int clock,int cs, int bits){
|
||||
mask= (1 << bits)-1;
|
||||
device.reset(new SSIDevice(bus));
|
||||
return device->init(logger,clock,cs,bits);
|
||||
}
|
||||
esp_err_t readData(uint32_t &res)
|
||||
{
|
||||
struct spi_transaction_t ta = {
|
||||
.flags = SPI_TRANS_USE_RXDATA,
|
||||
.cmd = 0,
|
||||
.addr = 0,
|
||||
.length = bits+1,
|
||||
.rxlength = 0};
|
||||
esp_err_t ret = spi_device_queue_trans(device->device(), &ta, portMAX_DELAY);
|
||||
if (ret != ESP_OK) return ret;
|
||||
struct spi_transaction_t *rs = NULL;
|
||||
ret = spi_device_get_trans_result(device->device(), &rs, portMAX_DELAY);
|
||||
if (ret != ESP_OK) return ret;
|
||||
if (rs == NULL) return ESP_ERR_INVALID_RESPONSE;
|
||||
res=SPI_SWAP_DATA_RX(*(uint32_t*)rs->rx_data,bits+1);
|
||||
res&=mask;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
public:
|
||||
SSISensor(const String &type,GwApi *api,const String &prfx, int host):SensorBase(type,api,prfx)
|
||||
{
|
||||
busId=host;
|
||||
}
|
||||
virtual bool isActive(){return act;};
|
||||
virtual bool initDevice(GwApi *api,BusType *bus){
|
||||
return initSSI(api->getLogger(),bus, clock,cs,bits);
|
||||
};
|
||||
|
||||
};
|
||||
using SpiSensorList=SensorList<BusType>;
|
||||
#define GWSPI1_HOST SPI2_HOST
|
||||
#define GWSPI2_HOST SPI3_HOST
|
||||
#endif
|
||||
136
lib/spitask/GwSpiTask.cpp
Normal file
136
lib/spitask/GwSpiTask.cpp
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
(C) Andreas Vogel andreas@wellenvogel.de
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "GwSpiTask.h"
|
||||
#include "GwSpiSensor.h"
|
||||
#include "GWDMS22B.h"
|
||||
#include "GwTimer.h"
|
||||
#include "GwHardware.h"
|
||||
|
||||
static SPIBus bus1(GWSPI1_HOST);
|
||||
static SPIBus bus2(GWSPI2_HOST);
|
||||
|
||||
static SpiSensorList sensors;
|
||||
|
||||
#ifdef GWSPI1_CLK
|
||||
static const int spi1clk=GWSPI1_CLK;
|
||||
#else
|
||||
static const int spi1clk=-1;
|
||||
#endif
|
||||
#ifdef GWSPI1_MISO
|
||||
static const int spi1miso=GWSPI1_MISO;
|
||||
#else
|
||||
static const int spi1miso=-1;
|
||||
#endif
|
||||
#ifdef GWSPI1_MOSI
|
||||
static const int spi1mosi=GWSPI1_MOSI;
|
||||
#else
|
||||
static const int spi1mosi=-1;
|
||||
#endif
|
||||
|
||||
#ifdef GWSPI2_CLK
|
||||
static const int spi2clk=GWSPI2_CLK;
|
||||
#else
|
||||
static const int spi2clk=-1;
|
||||
#endif
|
||||
#ifdef GWSPI2_MISO
|
||||
static const int spi2miso=GWSPI2_MISO;
|
||||
#else
|
||||
static const int spi2miso=-1;
|
||||
#endif
|
||||
#ifdef GWSPI2_MOSI
|
||||
static const int spi2mosi=GWSPI2_MOSI;
|
||||
#else
|
||||
static const int spi2mosi=-1;
|
||||
#endif
|
||||
|
||||
void runSpiTask(GwApi *api){
|
||||
GwLog *logger=api->getLogger();
|
||||
std::map<int,SPIBus *> buses;
|
||||
for (auto && sensor:sensors){
|
||||
int busId=sensor->busId;
|
||||
auto bus=buses.find(busId);
|
||||
if (bus == buses.end()){
|
||||
switch (busId)
|
||||
{
|
||||
case GWSPI1_HOST:
|
||||
if (spi1clk < 0){
|
||||
LOG_DEBUG(GwLog::ERROR,"SPI bus 1 not configured, cannot create %s",sensor->prefix.c_str());
|
||||
}
|
||||
else{
|
||||
if (bus1.init(logger,spi1mosi,spi1miso,spi1clk)){
|
||||
buses[busId]=&bus1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GWSPI2_HOST:
|
||||
if (spi2clk < 0){
|
||||
LOG_DEBUG(GwLog::ERROR,"SPI bus 2 not configured, cannot create %s",sensor->prefix.c_str());
|
||||
}
|
||||
else{
|
||||
if (bus2.init(logger,spi2mosi,spi2miso,spi2clk)){
|
||||
buses[busId]=&bus2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_DEBUG(GwLog::ERROR,"invalid busid %d for %s",busId,sensor->prefix.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
GwConfigHandler *config=api->getConfig();
|
||||
bool runLoop=false;
|
||||
GwIntervalRunner timers;
|
||||
int counterId=api->addCounter("spisensors");
|
||||
for (auto && sensor:sensors){
|
||||
if (!sensor->isActive()) continue;
|
||||
auto bus=buses.find(sensor->busId);
|
||||
if (bus == buses.end()){
|
||||
continue;
|
||||
}
|
||||
bool rt=sensor->initDevice(api,bus->second);
|
||||
if (rt){
|
||||
runLoop=true;
|
||||
timers.addAction(sensor->intv,[bus,api,sensor,counterId](){
|
||||
sensor->measure(api,bus->second,counterId);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (! runLoop){
|
||||
LOG_DEBUG(GwLog::LOG,"nothing to do for SPI task, finish");
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
while(true){
|
||||
delay(100);
|
||||
timers.loop();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
|
||||
void initSpiTask(GwApi *api){
|
||||
GwLog *logger=api->getLogger();
|
||||
registerDMS22B(api,sensors);
|
||||
bool addTask=false;
|
||||
for (auto && sensor:sensors){
|
||||
if (sensor->preinit(api)) addTask=true;
|
||||
}
|
||||
if (addTask){
|
||||
api->addUserTask(runSpiTask,"spiTask",3000);
|
||||
}
|
||||
else{
|
||||
LOG_DEBUG(GwLog::LOG,"no SPI sensors defined/active");
|
||||
}
|
||||
}
|
||||
20
lib/spitask/GwSpiTask.h
Normal file
20
lib/spitask/GwSpiTask.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
(C) Andreas Vogel andreas@wellenvogel.de
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#ifndef _GWSPITASK_H
|
||||
#define _GWSPITASK_H
|
||||
#include "GwApi.h"
|
||||
void initSpiTask(GwApi *api);
|
||||
DECLARE_INITFUNCTION(initSpiTask);
|
||||
#endif
|
||||
91
lib/spitask/config.json
Normal file
91
lib/spitask/config.json
Normal file
@@ -0,0 +1,91 @@
|
||||
[
|
||||
{
|
||||
"type": "array",
|
||||
"name": "DMS22B",
|
||||
"replace": [
|
||||
{
|
||||
"b": "1",
|
||||
"i": "11",
|
||||
"n": "0"
|
||||
},
|
||||
{
|
||||
"b": "1",
|
||||
"i": "12",
|
||||
"n": "1"
|
||||
},
|
||||
{
|
||||
"b": "2",
|
||||
"i": "21",
|
||||
"n": "1"
|
||||
},
|
||||
{
|
||||
"b": "2",
|
||||
"i": "22",
|
||||
"n": "22"
|
||||
}
|
||||
],
|
||||
"children": [
|
||||
{
|
||||
"name": "DMS22B$iact",
|
||||
"label": "DMS22BX$i enable",
|
||||
"type": "boolean",
|
||||
"default": "true",
|
||||
"description": "Enable the $i. SSI DMS22B rotary encoder (bus $b)",
|
||||
"category": "spisensors$b",
|
||||
"capabilities": {
|
||||
"DMS22B$i": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "DMS22B$iiid",
|
||||
"label": "DMS22B$i N2K iid",
|
||||
"type": "number",
|
||||
"default": "$n",
|
||||
"description": "the N2K instance id for the $i. DMS22B Rotary Encoder ",
|
||||
"category": "spisensors$b",
|
||||
"min": 0,
|
||||
"max": 253,
|
||||
"check": "checkMinMax",
|
||||
"capabilities": {
|
||||
"DMS22B$i": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "DMS22B$ifintv",
|
||||
"label": "DMS22B$i Interval",
|
||||
"type": "number",
|
||||
"default": 2,
|
||||
"description": "Interval(s) to query DMS22B rotation (0.5...10)",
|
||||
"category": "spisensors$b",
|
||||
"min": 0.5,
|
||||
"max": 10,
|
||||
"check": "checkMinMax",
|
||||
"capabilities": {
|
||||
"DMS22B$i": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "DMS22B$izero",
|
||||
"label": "DMS22B$i Zero",
|
||||
"type": "calset",
|
||||
"default": 2048,
|
||||
"description": "Zero position (0...2^bits-1)\nuse the \"C\" button to open a calibrate dialog",
|
||||
"category": "spisensors$b",
|
||||
"capabilities": {
|
||||
"DMS22B$i": "true"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "DMS22B$iinvt",
|
||||
"label": "DMS22BX$i invert",
|
||||
"type": "boolean",
|
||||
"default": "false",
|
||||
"description": "Invert the direction of the $i. SSI DMS22B rotary encoder (bus $b)",
|
||||
"category": "spisensors$b",
|
||||
"capabilities": {
|
||||
"DMS22B$i": "true"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
14
lib/spitask/platformio.ini
Normal file
14
lib/spitask/platformio.ini
Normal file
@@ -0,0 +1,14 @@
|
||||
[platformio]
|
||||
#basically for testing purposes
|
||||
[env:m5stack-atom-spidms22b]
|
||||
extends = sensors
|
||||
board = m5stack-atom
|
||||
lib_deps =
|
||||
${env.lib_deps}
|
||||
${sensors.lib_deps}
|
||||
build_flags=
|
||||
-D GWSPI1_CLK=21
|
||||
-D GWSPI1_MISO=25
|
||||
-D GWDMS22B11
|
||||
-D GWDMS22B11_CS=22
|
||||
${env.build_flags}
|
||||
@@ -332,6 +332,9 @@ public:
|
||||
api->getLogger()->logDebug(GwLog::LOG,"adding user task %s",tname.c_str());
|
||||
return true;
|
||||
}
|
||||
virtual void setCalibrationValue(const String &name, double value){
|
||||
api->setCalibrationValue(name,value);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user