added tone request gateway before actually swithcing the pin

This commit is contained in:
Flo
2025-12-08 19:24:47 +01:00
commit f0e8b49854
68 changed files with 11057 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
+10
View File
@@ -0,0 +1,10 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}
+37
View File
@@ -0,0 +1,37 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the convention is to give header files names that end with `.h'.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
+46
View File
@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into the executable file.
The source code of each library should be placed in a separate directory
("lib/your_library_name/[Code]").
For example, see the structure of the following example libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
Example contents of `src/main.c` using Foo and Bar:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
The PlatformIO Library Dependency Finder will find automatically dependent
libraries by scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
+24
View File
@@ -0,0 +1,24 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:nodemcu-32s]
platform = espressif32
board = nodemcu-32s
framework = arduino
upload_port = COM9
upload_speed = 921600
monitor_speed = 115200
build_flags =
-I ./src/xcp
-I ./src/Receivers433
-I ./src/Receivers433/Receivers3ByteKeys
lib_deps =
adafruit/Adafruit GFX Library@^1.12.4
thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays@^4.6.1
+126
View File
@@ -0,0 +1,126 @@
/*
Base32.cpp - Library for encoding to/decoding from Base32.
Compatible with RFC 4648 ( http://tools.ietf.org/html/rfc4648 )
Created by Vladimir Tarasow, December 18, 2012.
Released into the public domain.
*/
#include "Arduino.h"
#include "Base32.h"
#include "stdint.h"
Base32::Base32()
{
}
/* appends 0 to the base32 string */
int Base32::toBase32(byte* in, long length, char * out, boolean usePadding)
{
char base32StandardAlphabet[] = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"};
char standardPaddingChar = '=';
int result = 0;
int count = 0;
int bufSize = 8;
int index = 0;
if (length < 0 || length > 268435456LL)
{
return 0;
}
if (length > 0)
{
int buffer = in[0];
int next = 1;
int bitsLeft = 8;
while (count < bufSize && (bitsLeft > 0 || next < length))
{
if (bitsLeft < 5)
{
if (next < length)
{
buffer <<= 8;
buffer |= in[next] & 0xFF;
next++;
bitsLeft += 8;
}
else
{
int pad = 5 - bitsLeft;
buffer <<= pad;
bitsLeft += pad;
}
}
index = 0x1F & (buffer >> (bitsLeft -5));
bitsLeft -= 5;
out[result] = (byte)base32StandardAlphabet[index];
result++;
}
}
if (usePadding)
{
int pads = (result % 8);
if (pads > 0)
{
pads = (8 - pads);
for (int i = 0; i < pads; i++)
{
out[result] = standardPaddingChar;
result++;
}
}
}
out[result] = '\0';
return result;
}
int Base32::fromBase32(byte* in, long length, byte*& out)
{
int result = 0; // Length of the array of decoded values.
int buffer = 0;
int bitsLeft = 0;
byte* temp = NULL;
temp = (byte*)malloc(length); // Allocating temporary array.
for (int i = 0; i < length; i++)
{
byte ch = in[i];
// ignoring some characters: ' ', '\t', '\r', '\n', '='
if (ch == 0xA0 || ch == 0x09 || ch == 0x0A || ch == 0x0D || ch == 0x3D) continue;
// recovering mistyped: '0' -> 'O', '1' -> 'L', '8' -> 'B'
if (ch == 0x30) { ch = 0x4F; } else if (ch == 0x31) { ch = 0x4C; } else if (ch == 0x38) { ch = 0x42; }
// look up one base32 symbols: from 'A' to 'Z' or from 'a' to 'z' or from '2' to '7'
if ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0x61 && ch <= 0x7A)) { ch = ((ch & 0x1F) - 1); }
else if (ch >= 0x32 && ch <= 0x37) { ch -= (0x32 - 26); }
else { free(temp); return 0; }
buffer <<= 5;
buffer |= ch;
bitsLeft += 5;
if (bitsLeft >= 8)
{
temp[result] = (unsigned char)((unsigned int)(buffer >> (bitsLeft - 8)) & 0xFF);
result++;
bitsLeft -= 8;
}
}
out = (byte*)malloc(result);
memcpy(out, temp, result);
free(temp);
return result;
}
+22
View File
@@ -0,0 +1,22 @@
/*
Base32.h - Library for encoding to/decoding from Base32.
Compatible with RFC 4648 ( http://tools.ietf.org/html/rfc4648 )
Created by Vladimir Tarasow, December 18, 2012.
Released into the public domain.
*/
#ifndef Base32_h
#define Base32_h
#include "Arduino.h"
#include "stdint.h"
class Base32
{
public:
Base32();
int toBase32(byte*, long, char*, boolean);
int fromBase32(byte*, long, byte*&);
};
#endif
+83
View File
@@ -0,0 +1,83 @@
/*
* DataSender.cpp
*
* Created on: 08.10.2022
* Author: flori
*/
#include "main.h"
#include "MyWifiClient.h"
#include "Seconds.h"
#include "DataSender.h"
DataSender dataSender;
#define SEND_INTERVAL_SECONDS 120
#define DATA_SIZE_PER_FENSTER 11
static uint8_t buf[DATA_SIZE_PER_FENSTER * NUM_FENSTER];
DataSender::DataSender()
{
bRequestSendWifi = true;
tNextSend = SEND_INTERVAL_SECONDS;
}
DataSender::~DataSender()
{
// TODO Auto-generated destructor stub
}
/**
*
*/
void DataSender::onSetup(void)
{
myWifiClient.onSetup();
}
/**
*
*/
void DataSender::onLoop(void)
{
if (Seconds::Get() >= tNextSend )
{
bRequestSendWifi = true;
}
if (bRequestSendWifi && myWifiClient.canSend())
{
bRequestSendWifi = false;
for (uint8_t i = 0; i < NUM_FENSTER; i++)
{
uint8_t offset = DATA_SIZE_PER_FENSTER * i;
memcpy( &buf[offset], alleFenster[i]->name, 8 );
uint16_t remainingTime = (uint16_t) alleFenster[i]->GetRemainingTime();
memcpy( &buf[offset+8], &remainingTime , 2);
uint8_t state = alleFenster[i]->IsOpen() ? 1 : 0;
state |= alleFenster[i]->ShallPiep() ? 2 : 0;
memcpy( &buf[offset+10], &state , 1);
}
myWifiClient.send(buf, sizeof(buf));
tNextSend = Seconds::Get() + SEND_INTERVAL_SECONDS;
}
myWifiClient.onLoop();
}
/**
*
*/
void DataSender::requestSend(void)
{
bRequestSendWifi = true;
}
+27
View File
@@ -0,0 +1,27 @@
/*
* DataSender.h
*
* Created on: 08.10.2022
* Author: flori
*/
#ifndef DATASENDER_H_
#define DATASENDER_H_
class DataSender
{
public:
DataSender();
virtual ~DataSender();
void onSetup(void);
void onLoop(void);
void requestSend(void);
private:
bool bRequestSendWifi;
uint32_t tNextSend;
};
extern DataSender dataSender;
#endif /* DATASENDER_H_ */
+178
View File
@@ -0,0 +1,178 @@
#include "main.h"
#if VERSION_BIG_DISPLAY
/*
* Display.cpp
*
* Created on: 15.05.2020
* Author: flori
*/
#include "Arduino.h"
#include <SPI.h>
#include <Adafruit_GFX.h> // needs Adafruit_GFX_Library + Adafruit_BusIO
#include <Adafruit_ST7735.h> // needs Adafruit_ST7735_and_ST7789_Library
#include <Fonts/FreeSans9pt7b.h>
#include "Display.h"
Adafruit_ST7735 tft = Adafruit_ST7735(TFT_PIN_CS, TFT_PIN_DC, TFT_PIN_MOSI, TFT_PIN_CLK, TFT_PIN_RST); // ST7735-Bibliothek Setup
Display display;
static int wWindow = 38;
static int hWindow = 18;
/**
*
*/
void Display::Init(void)
{
tft.initR(INITR_BLACKTAB);
tft.setRotation(1);
tft.fillScreen(ST7735_BLACK);
}
void drawWindow(int x, int y, Fenster *fenster)
{
uint16_t col = fenster->ShallPiep() ? ST7735_ORANGE : fenster->IsOpen() ? ST77XX_WHITE : 0x0010;
if (col != fenster->color)
{
tft.fillRect(x,y,wWindow, hWindow, ST7735_BLACK);
tft.drawRect(x,y,wWindow, hWindow, col);
tft.setCursor( x+2, y + hWindow/2 - 3);
tft.setTextSize(1);
tft.setTextColor(col);
tft.print(fenster->name);
fenster->color = col;
}
}
DeciSeconds_t calcRemainingTime()
{
DeciSeconds_t remainingTime = 99999;
for (uint8_t i = 0; i < NUM_FENSTER; i++)
{
if (alleFenster[i]->IsOpen()) remainingTime = min(remainingTime, alleFenster[i]->GetRemainingTime());
}
return remainingTime;
}
/**
*
*/
void Display::Update(void)
{
// drawRect(pos_links,pos_oben,breite,hoehe,farbe);
// setTextSize(groesse);
//tft.fillScreen(ST7735_BLACK);
tft.drawRect(0, 0, 160, 128, ST7735_BLUE);
tft.setFont(NULL);
int x = 0;
int xs = 1;
int y = 1;
#if 0
drawWindow(xs + 0 * (wWindow + 2), y, &fensterBadOben);
drawWindow(xs + 1 * (wWindow + 2), y, &fensterFlo);
drawWindow(xs + 2 * (wWindow + 2), y, &fensterHanna);
drawWindow(xs + 3 * (wWindow + 2), y, &fensterFloBuero);
y += hWindow + 2;
#endif
drawWindow(xs , y, &fensterBadUnten);
drawWindow(xs + 1 * (wWindow + 2), y, &fensterKueche);
drawWindow(xs + 2 * (wWindow + 2), y, &fensterWz);
drawWindow(xs + 3 * (wWindow + 2), y, &fensterWz2);
//drawWindow(xs+3*(wWindow+2), y, "Bad", true);
y += hWindow + 2;
drawWindow(xs + 0 * (wWindow + 2), y, &fensterToniNeu);
drawWindow(xs + 1 * (wWindow + 2), y, &fensterGefrier);
y += hWindow + 2;
drawWindow(xs + 0 * (wWindow + 2), y, &fensterKeller);
drawWindow(xs + 1 * (wWindow + 2), y, &fensterGaeste);
// drawWindow(xs+1*(wWindow+2), y, "Vorrat", getRandBool(), getRandBool());
//drawWindow(xs+2*(wWindow+2), y, "Wohnz", true);
//drawWindow(xs+3*(wWindow+2), y, "Bad", true);
//tft.setFont(&FreeSans9pt7b);
tft.setTextSize(2);
tft.setTextColor( ST77XX_CYAN);
x = 90;
y = 70;
tft.setCursor(x, y);
tft.fillRect(x, y-1, 159-90, 20, ST7735_BLACK );
//thermoData.rh = 50; thermoData.temp =7.3;
if (thermoData.rhPercent > 0)
{
sprintf(strBuf, "% 3d C", (int) thermoData.tempC );
}
else
{
sprintf(strBuf, " --");
}
tft.print(strBuf);
x = 10;
y = 97;
tft.setTextSize(3);
int yrect = 90;
int xrect = 1;
uint16_t wrect = 158;
uint16_t hrect = 127-yrect;
strcpy(strBuf, "");
for (uint8_t i = 0; i < NUM_FENSTER; i++)
{
if (alleFenster[i]->ShallPiep())
{
strcpy(strBuf, alleFenster[i]->name);
break;
}
}
if (strlen(strBuf)==0)
{
DeciSeconds_t remainingTime = calcRemainingTime();
uint8_t mins = (remainingTime / 10) / 60;
uint8_t secs = (remainingTime / 10) % 60;
if (mins < 60)
{
sprintf(strBuf, "%d:%02d", (int) (mins), (int) (secs));
}
}
if (strlen(strBuf)==0)
{
tft.fillRect(xrect, yrect, wrect, hrect, ST7735_BLACK);
}
else
{
tft.fillRect(xrect, yrect, wrect, hrect, ST7735_WHITE);
tft.setTextColor( ST77XX_BLACK);
uint16_t w, h;
int16_t x1, y1;
tft.getTextBounds(strBuf, x, y, &x1, &y1, &w, &h);
tft.setCursor(xrect + (wrect - w) / 2, yrect + (hrect - h) / 2);
tft.print(strBuf);
}
}
#endif
+29
View File
@@ -0,0 +1,29 @@
/*
* Display.h
*
* Created on: 15.05.2020
* Author: flori
*/
#include "main.h"
#if VERSION_BIG_DISPLAY
#ifndef DISPLAY_H_
#define DISPLAY_H_
class Display
{
public:
void Init(void);
void Update(void);
private:
char strBuf[50];
};
extern Display display;
#endif /* DISPLAY_H_ */
#endif /* #if VERSION_EG_ONLY */
+153
View File
@@ -0,0 +1,153 @@
#include "main.h"
#if VERSION_SMALL_DISPLAY
/*
* Display.cpp
*
* Created on: 15.05.2020
* Author: flori
*/
#include "Arduino.h"
#include "Display_SSD1306.h"
#include "SSD1306Wire.h" /* LIBRARY : ESP8266_and_ESP32_OLED_driver_for_SSD1306_displays */
// for 128x64 displays:
SSD1306Wire ssd1306(0x3c, SDA, SCL); // ADDRESS, SDA, SCL
Display display;
/**
*
*/
void Display::Init(void)
{
ssd1306.init();
}
DeciSeconds_t calcRemainingTime()
{
DeciSeconds_t remainingTime = 99999;
for (uint8_t i = 0; i < NUM_FENSTER; i++)
{
if (alleFenster[i]->IsOpen()) remainingTime = min(remainingTime, alleFenster[i]->GetRemainingTime());
}
return remainingTime;
}
/**
*
*/
void Display::Update(void)
{
ssd1306.clear();
ssd1306.setFont(ArialMT_Plain_16); /* https://github.com/ThingPulse/esp8266-oled-ssd1306/blob/master/README.md */
ssd1306.setBrightness(100u);
int x = 2;
int y = 0;
int yrect = 0;
int xrect = 0;
uint16_t wrect = 64;
uint16_t hrect = 18;
/* print Windows */
uint8_t i;
for (i=0; i<NUM_FENSTER; i++)
{
if (alleFenster[i]->IsOpen())
{
ssd1306.setColor(WHITE);
ssd1306.fillRect(xrect, yrect, wrect, hrect);
ssd1306.setColor(BLACK);
ssd1306.drawString(x, y, alleFenster[i]->name);
ssd1306.drawString(x+1, y, alleFenster[i]->name);
ssd1306.drawString(x+1, y+1, alleFenster[i]->name);
ssd1306.drawString(x, y+1, alleFenster[i]->name);
}
else
{
ssd1306.setColor(WHITE);
ssd1306.drawString(x, y, alleFenster[i]->name);
}
if (i&1)
{
xrect = 0u;
x = 2u;
yrect += 20;
y+= 20;
}
else
{
xrect = 64;
x = 66;
}
}
/* print Temperature */
x=0;
y=64-16;
if (thermoData.rhPercent > 0)
{
sprintf(strBuf, "% 3d C", (int) thermoData.tempC);
}
else
{
sprintf(strBuf, " --");
}
//tft.print(strBuf);
ssd1306.setColor(WHITE);
ssd1306.drawString(x, y, strBuf);
/* print Remaining time */
yrect = 64-16;
xrect = 64;
wrect = 32;
hrect = 16;
strcpy(strBuf, "");
for (uint8_t i = 0; i < NUM_FENSTER; i++)
{
if (alleFenster[i]->ShallPiep())
{
strcpy(strBuf, alleFenster[i]->name);
break;
}
}
if (strlen(strBuf)==0)
{
DeciSeconds_t remainingTime = calcRemainingTime();
uint8_t mins = (remainingTime / 10) / 60;
uint8_t secs = (remainingTime / 10) % 60;
if (mins < 60)
{
sprintf(strBuf, "%d:%02d", (int) (mins), (int) (secs));
}
}
if (strlen(strBuf)==0)
{
//ssd1306.setColor(BLACK);
//ssd1306.fillRect(xrect, yrect, wrect, hrect);
}
else
{
ssd1306.setColor(WHITE);
//ssd1306.fillRect(xrect, yrect, wrect, hrect);
//ssd1306.setColor(BLACK);
ssd1306.drawString(xrect,yrect, strBuf);
ssd1306.drawString(xrect+1,yrect, strBuf);
}
ssd1306.display();
}
#endif // #if VERSION_DG_ONLY
+30
View File
@@ -0,0 +1,30 @@
/*
* Display.h
*
* Created on: 15.05.2020
* Author: flori
*/
#include "main.h"
#if VERSION_SMALL_DISPLAY
#ifndef DISPLAY_SSD1306_H_
#define DISPLAY_SSD1306_H_
class Display
{
public:
void Init(void);
void Update(void);
private:
char strBuf[50];
};
extern Display display;
#endif /* DISPLAY_SSD1306_H_ */
#endif
+107
View File
@@ -0,0 +1,107 @@
/*
* Fenster.cpp
*
* Created on: 29.02.2020
* Author: flori
*/
#include "main.h"
#include "Fenster.h"
#include "ReceiverFunkThermometer.h"
#define SERIAL_PRINT(x) //Serial.print(" "); Serial.print(x)
/**
*
*/
Fenster::Fenster(const char *_name, uint8_t myKeyNumber)
{
strcpy(this->name , _name);
this->myKeyNumber = myKeyNumber;
openingTime = 0;
shallPiep = false;
color = 0;
}
/**
* keyNum : key number with offset
*/
bool Fenster::HandleKey(int8_t keyNum, bool direction)
{
bool bThisWindowChanged = false;
if (keyNum == myKeyNumber)
{
if (direction == DIRECTION_OPEN)
{
if (openingTime == 0u)
{
bThisWindowChanged = true;
openingTime = tDecis;
SERIAL_PRINT("open ");
SERIAL_PRINT(myKeyNumber);
SERIAL_PRINT(waitTimeDs);
}
}
else
{
if (openingTime != 0u)
{
bThisWindowChanged = true;
shallPiep = false;
openingTime = 0;
SERIAL_PRINT("close ");
SERIAL_PRINT(myKeyNumber);
}
}
}
return bThisWindowChanged;
}
/**
*
*/
bool Fenster::ShallPiep()
{
DeciSeconds_t tWaitDs = waitTimeDs;
if (this == &fensterGefrier)
{
tWaitDs = 300u;
}
if ((tDecis > openingTime + tWaitDs) && (openingTime > 0))
{
shallPiep = true;
}
return shallPiep;
}
/**
*
*/
DeciSeconds_t Fenster::GetRemainingTime()
{
DeciSeconds_t tWaitDs = waitTimeDs;
if (this == &fensterGefrier)
{
tWaitDs = 300u;
}
if (openingTime > 0)
{
DeciSeconds_t remainingTime = openingTime + tWaitDs - tDecis;
return remainingTime;
}
else
{
return 0;
}
}
bool Fenster::IsOpen()
{
return (openingTime > 0);
}
+32
View File
@@ -0,0 +1,32 @@
/*
* Fenster.h
*
* Created on: 29.02.2020
* Author: flori
*/
#ifndef FENSTER_H_
#define FENSTER_H_
#include "typedefs.h"
class Fenster
{
public:
char name[8];
uint16_t color;
Fenster(const char *_name, uint8_t myKeyNumber);
bool HandleKey(int8_t keyNum, bool direction);
bool ShallPiep();
DeciSeconds_t GetRemainingTime();
bool IsOpen();
private:
uint8_t myKeyNumber;
DeciSeconds_t openingTime;
bool shallPiep;
};
#endif /* FENSTER_H_ */
+20
View File
@@ -0,0 +1,20 @@
/*
* Hamming.cpp
*
* Created on: 10.10.2022
* Author: flori
*/
#include "Hamming.h"
Hamming::Hamming()
{
// TODO Auto-generated constructor stub
}
Hamming::~Hamming()
{
// TODO Auto-generated destructor stub
}
+18
View File
@@ -0,0 +1,18 @@
/*
* Hamming.h
*
* Created on: 10.10.2022
* Author: flori
*/
#ifndef HAMMING_H_
#define HAMMING_H_
class Hamming
{
public:
Hamming();
virtual ~Hamming();
};
#endif /* HAMMING_H_ */
+149
View File
@@ -0,0 +1,149 @@
#include "main.h"
#include "PiepPattern.h"
#include "ReceiverSmartWares.h"
#include "ReceiverAiggend.h"
#include "ReceiverOval.h"
#include "ReceiverKerui.h"
#include "ReceiverFunkThermometer.h"
#include "InterruptHandler.h"
#define LOOP_COUNTS_FOR_PAUSE (2u)
/*****************************************************/
IRAM_ATTR void timerIsr();
IRAM_ATTR void pinLevelChangeIsr(void);
/*****************************************************/
/**
*
*/
void InterruptHandler_Init(void)
{
/* setup interrupt */
attachInterrupt(digitalPinToInterrupt(DIN_FUNK), pinLevelChangeIsr, CHANGE);
#if 1
hw_timer_t * timer = timerBegin(0, 80, true); /* 80 -> 1 Mhz */
timerAttachInterrupt(timer, &timerIsr, true);
timerAlarmWrite(timer, ISR_TIME_US, true);
timerAlarmEnable(timer);
#endif
}
/**
* called every 10 ms
*
* used to update tDecis, and for beeping
*/
IRAM_ATTR void timerIsr()
{
static uint32_t tshortPiepStartedMs = 0;
static uint8_t count = 0;
static boolean toneOn = false;
uint32_t tMillis = millis();
#if 0
static bool on = true;
if (on) digitalWrite(DOUT_TEST_TIMER, HIGH);
else digitalWrite(DOUT_TEST_TIMER, LOW);
on = !on;
#endif
if (++count == MS_TO_ISR_COUNT(100uL) )
{
/* increment tDecis every 100ms */
count = 0;
tDecis++;
}
if (bRequestShortBeep)
{
bRequestShortBeep = false;
tshortPiepStartedMs = tMillis;
}
if (tshortPiepStartedMs > 0u)
{
if (tMillis < (tshortPiepStartedMs + 30uL))
{
if (false == toneOn)
{
TONE_REQUEST_ON(TONE_REQUEST_SOURCE_SHORTPIEP);
toneOn = true;
}
}
else
{
TONE_REQUEST_OFF(TONE_REQUEST_SOURCE_SHORTPIEP);
tshortPiepStartedMs = 0;
toneOn = false;
}
}
else
{
piepPattern->TaskCyclic();
}
if (toneRequest != 0u)
{
digitalWrite(DOUT_PIEP_VCC, HIGH);
}
else
{
digitalWrite(DOUT_PIEP_VCC, LOW);
}
}
IRAM_ATTR void InterruptHandler_PauseReceive()
{
loopCountSincePause = 0u;
}
/**
*
*/
IRAM_ATTR void pinLevelChangeIsr(void)
{
static bool lastVal = LOW;
static uint32_t lastMics = 0;
static uint32_t MINIMAL_DT_MICROS_FOR_RECEIVERS = 100u;
uint32_t dtMicros = micros() - lastMics;
bool pinFunkVal = digitalRead(DIN_FUNK);
if (lastVal == pinFunkVal)
{
return;
}
else
{
lastMics = micros();
lastVal = pinFunkVal;
if (loopCountSincePause < LOOP_COUNTS_FOR_PAUSE)
{
/* after receiving a key, wait for the main loop to run x times before activating receiving again */
return;
}
else if (dtMicros > MINIMAL_DT_MICROS_FOR_RECEIVERS)
{
receiverSw.Isr(dtMicros, pinFunkVal);
receiverAiggend.Isr(dtMicros, pinFunkVal);
receiverOval.Isr(dtMicros, pinFunkVal);
receiverKerui.Isr(dtMicros, pinFunkVal);
receiverThermo.Isr(dtMicros, pinFunkVal);
//digitalWrite(LED_BUILTIN, pinFunkVal);
}
}
}
+25
View File
@@ -0,0 +1,25 @@
/*
* interruptHandler.h
*
* Created on: 11.10.2022
* Author: flori
*/
#ifndef INTERRUPTHANDLER_H_
#define INTERRUPTHANDLER_H_
#include "Arduino.h"
#define ISR_TIME_US (10000uL)
#define MS_TO_ISR_COUNT(ms) ( ((ms)*1000uL) / ISR_TIME_US )
void InterruptHandler_Init(void);
void InterruptHandler_PauseReceive();
#endif /* INTERRUPTHANDLER_H_ */
+54
View File
@@ -0,0 +1,54 @@
/*
* LedBlinker.cpp
*
* Created on: 29.02.2020
* Author: flori
*/
#include "main.h"
#include "LedBlinker.h"
#include "ReceiverFunkThermometer.h"
#define BLINK_TIME ((DeciSeconds_t)2)
LedBlinker ledBlinker;
/**
*
*/
void LedBlinker::OnLoop()
{
static DeciSeconds_t tOn;
static DeciSeconds_t tOff;
static uint32_t numBlinkFast = 0;
if (numberWindowsOpen > 0)
{
if (tDecis > tOn)
{
digitalWrite(LED_BUILTIN, HIGH);
tOff = tDecis + BLINK_TIME;
tOn = tOff + BLINK_TIME;
}
if (tDecis > tOff)
{
digitalWrite(LED_BUILTIN, LOW);
tOn = tDecis + BLINK_TIME;
tOff = tOn + BLINK_TIME;
if (numBlinkFast>0)
{
numBlinkFast--;
}
else
{
numBlinkFast = numberWindowsOpen-1;
tOn += BLINK_TIME*3;
tOff += BLINK_TIME*3;
}
}
}
}
+19
View File
@@ -0,0 +1,19 @@
/*
* LedBlinker.h
*
* Created on: 29.02.2020
* Author: flori
*/
#ifndef LEDBLINKER_H_
#define LEDBLINKER_H_
class LedBlinker
{
public:
void OnLoop();
};
extern LedBlinker ledBlinker;
#endif /* LEDBLINKER_H_ */
+194
View File
@@ -0,0 +1,194 @@
/*
* MyWifiClient.cpp
*
* Created on: 24.09.2020
* Author: flori
*/
#include "main.h"
#include "Base32.h"
#include "Seconds.h"
#include "Version.h"
#include "MyWifiClient.h"
Base32 base32;
#if 1
#define MonitorPrint(...) Serial.print(__VA_ARGS__)
#define MonitorPrintln(...) Serial.println(__VA_ARGS__)
#else
#define MonitorPrint(...)
#define MonitorPrintln(...)
#endif
MyWifiClient myWifiClient;
/**
*
*/
MyWifiClient::MyWifiClient()
{
state = IDLE;
bSend = false;
}
/**
*
*/
MyWifiClient::~MyWifiClient()
{
}
/**
*
*/
bool MyWifiClient::canSend(void)
{
return state == IDLE && bSend == false;
}
/* converts dat to base32 and triggers GET request */
void MyWifiClient::send(uint8_t *dat, uint16_t len)
{
strcpy( wifibufMsg , "GET /genericData.php?project=fensterpiepser&dataname=fenster&data=");
size_t pos = strlen(wifibufMsg);
(void) base32.toBase32(dat, len, &wifibufMsg[pos], true);
strcat( wifibufMsg, " HTTP/1.1\r\nHost: fly-with-cats.com\r\nAccept: */*\r\n\r\n");
bSend = true;
}
/**
*
*/
void MyWifiClient::onSetup(void)
{
}
/**
*
*/
void MyWifiClient::onLoop(void)
{
static substate_t substate = ENTRY;
static state_t prevState = IDLE;
if (prevState != state)
{
substate = ENTRY;
prevState = state;
switch(state)
{
case IDLE:
MonitorPrintln("IDLE");
break;
case WAIT_CONNECT:
MonitorPrintln("WAIT_CONNECT");
break;
case WAIT_RECEIVE:
MonitorPrintln("WAIT_RECEIVE");
break;
}
}
switch (state)
{
case IDLE:
switch (substate)
{
static uint32_t tConnectWifiEndSeconds;
case ENTRY:
tConnectWifiEndSeconds = Seconds::Get() + 60;
substate = CYCLIC;
break;
case CYCLIC:
if (WiFi.isConnected())
{
tConnectWifiEndSeconds = Seconds::Get() + 60;
if (bSend)
{
bSend = false;
state = WAIT_CONNECT;
}
}
else
{
if (Seconds::Get() > tConnectWifiEndSeconds)
{
Serial.println("RESET (Wifi)");
ESP.restart();
}
}
break;
}
break;
case WAIT_CONNECT:
switch (substate)
{
static uint32_t tConnectEndSeconds;
case ENTRY:
/* Connect to Server */
this->connect("fly-with-cats.com", 8887, 100);
tConnectEndSeconds = Seconds::Get() + 5;
substate = CYCLIC;
break;
case CYCLIC:
if (this->connected())
{
/* send HTTP request */
this->print(wifibufMsg);
MonitorPrint(wifibufMsg);
state = WAIT_RECEIVE;
}
else if (Seconds::Get() > tConnectEndSeconds)
{
state = IDLE;
}
break;
}
break;
case WAIT_RECEIVE:
switch (substate)
{
static uint32_t tReceiveEndSeconds;
case ENTRY:
tReceiveEndSeconds = Seconds::Get() + 5;
substate = CYCLIC;
break;
case CYCLIC:
if (this->available())
{
int sizeRec = this->read(wifibufRx, WIFI_BUF_SIZE_RX);
wifibufRx[sizeRec] = 0;
//MonitorPrintln((char*)wifibufRx);
state = IDLE;
}
else if (Seconds::Get() >= tReceiveEndSeconds)
{
this->stop();
state = IDLE;
}
break;
}
}
}
+41
View File
@@ -0,0 +1,41 @@
/*
* MyWifiClient.h
*
* Created on: 24.09.2020
* Author: flori
*/
#ifndef MYWIFICLIENT_H_
#define MYWIFICLIENT_H_
#include <WiFi.h>
#include "Base32.h"
#include <WiFiClient.h>
#define WIFI_BUF_SIZE_RX 1024
typedef enum { IDLE, WAIT_CONNECT, WAIT_RECEIVE } state_t;
typedef enum { ENTRY, CYCLIC } substate_t;
class MyWifiClient: public WiFiClient
{
public:
MyWifiClient();
virtual ~MyWifiClient();
void send(uint8_t *dat, uint16_t len);
void onSetup(void);
void onLoop(void);
bool canSend(void);
private:
bool bSend;
state_t state;
char wifibufMsg[WIFI_BUF_SIZE_RX];
uint8_t wifibufRx[WIFI_BUF_SIZE_RX];
};
extern MyWifiClient myWifiClient;
extern Base32 base32;
#endif /* MYWIFICLIENT_H_ */
+146
View File
@@ -0,0 +1,146 @@
/*
* PiepMode.cpp
*
* Created on: 25.02.2020
* Author: flori
*/
#include "main.h"
#include "PiepMode.h"
#define SERIAL_PRINT(x) //Serial.print(" "); Serial.print(x)
#define STANDBY 0
#define ON 1
#define OFF 2
/**
*
*/
PiepMode::PiepMode()
{
// TODO Auto-generated constructor stub
state = STANDBY;
startRequest = false;
stopRequest = false;
requestCount = 255;
timer = 0;
onTime = 100;
offTime = 100;
counter = 0;
outPin = 13;
}
/**
*
*/
IRAM_ATTR void PiepMode::Start(uint8_t outPin)
{
startRequest = true;
this->outPin = outPin;
//pinMode(outPin, OUTPUT);
state = STANDBY;
}
/**
*
*/
IRAM_ATTR void PiepMode::Stop()
{
stopRequest = true;
TONE_REQUEST_OFF(TONE_REQUEST_SOURCE_MODE);
}
/**
*
*/
IRAM_ATTR bool PiepMode::HasCompleted(void)
{
return (state == STANDBY);
}
/**
*
*/
IRAM_ATTR void PiepMode::TaskCyclic()
{
switch (state)
{
case STANDBY:
SERIAL_PRINT("S");
stopRequest = false;
if (startRequest)
{
startRequest = false;
state = ON;
counter = 0;
timer = onTime;
}
break;
case ON:
SERIAL_PRINT(timer);
SERIAL_PRINT(onTime);
/* switch on */
startRequest = false;
if (stopRequest)
{
state = STANDBY;
}
else if (timer > 0)
{
TONE_REQUEST_ON(TONE_REQUEST_SOURCE_MODE);
timer--;
}
else
{
timer = offTime;
state = OFF;
}
break;
case OFF:
SERIAL_PRINT("F");
/* switch off */
startRequest = false;
if (stopRequest)
{
state = STANDBY;
}
else if (timer > 0)
{
TONE_REQUEST_OFF(TONE_REQUEST_SOURCE_MODE);
timer--;
}
else if (requestCount == 0)
{
timer = onTime;
state = ON;
}
else if (++counter < requestCount)
{
timer = onTime;
state = ON;
}
else
{
state = STANDBY;
}
break;
default:
Serial.print(state);
break;
}
}
+30
View File
@@ -0,0 +1,30 @@
/*
* PiepMode.h
*
* Created on: 25.02.2020
* Author: flori
*/
#ifndef PIEPMODE_H_
#define PIEPMODE_H_
class PiepMode
{
public:
PiepMode();
void TaskCyclic();
void Start(uint8_t outPin);
void Stop();
bool HasCompleted(void);
uint32_t onTime, offTime;
uint32_t requestCount;
private :
uint32_t counter, timer, outPin;
uint8_t state;
uint8_t startRequest, stopRequest;
};
#endif /* PIEPMODE_H_ */
+115
View File
@@ -0,0 +1,115 @@
/*
* PiepPattern.cpp
*
* Created on: 25.02.2020
* Author: flori
*/
#include "main.h"
#include "PiepPattern.h"
#include "PiepMode.h"
#define SERIAL_PRINT(x) // Serial.print(" "); Serial.print(x)
#define STANDBY 0
#define ON 1
/**
*
*/
PiepPattern::PiepPattern()
{
requestCount = 0;
numberModes = 0;
counter = 0;
modeIndex = 0;
startRequest = false;
stopRequest = false;
state = STANDBY;
outPin = 13;
piepModes = NULL;
}
/**
*
*/
IRAM_ATTR void PiepPattern::Start(uint8_t outPin)
{
startRequest = true;
this->outPin = outPin;
state = STANDBY;
}
/**
*
*/
IRAM_ATTR void PiepPattern::Stop()
{
stopRequest = true;
}
/**
*
*/
IRAM_ATTR void PiepPattern::TaskCyclic()
{
switch (state)
{
case STANDBY:
SERIAL_PRINT("STDBY");
stopRequest = false;
if (startRequest)
{
startRequest = false;
counter = 0;
modeIndex = 0;
if (numberModes > 0)
{
state = ON;
piepModes[modeIndex]->Start(outPin);
piepModes[modeIndex]->TaskCyclic();
}
}
break;
case ON:
SERIAL_PRINT(modeIndex);
SERIAL_PRINT(piepModes[modeIndex]->onTime);
startRequest = false;
piepModes[modeIndex]->TaskCyclic();
if (stopRequest)
{
piepModes[modeIndex]->Stop();
state = STANDBY;
}
else
{
if (piepModes[modeIndex]->HasCompleted())
{
if (++modeIndex < numberModes)
{
piepModes[modeIndex]->Start(outPin);
}
else if ( requestCount == 0)
{
modeIndex = 0;
piepModes[modeIndex]->Start(outPin);
}
else if ( ++counter < requestCount )
{
modeIndex = 0;
piepModes[modeIndex]->Start(outPin);
}
}
}
break;
default:
Serial.print(state);
break;
}
}
+36
View File
@@ -0,0 +1,36 @@
/*
* PiepPattern.h
*
* Created on: 25.02.2020
* Author: flori
*/
#ifndef PIEPPATTERN_H_
#define PIEPPATTERN_H_
#include "PiepMode.h"
class PiepPattern
{
public:
PiepPattern();
void TaskCyclic();
void Start(uint8_t outPin);
void Stop(void);
uint8_t requestCount;
uint8_t numberModes;
class PiepMode **piepModes;
private :
uint8_t counter;
uint8_t modeIndex;
uint8_t outPin;
uint8_t startRequest, stopRequest;
uint8_t state;
};
#endif /* PIEPPATTERN_H_ */
@@ -0,0 +1,326 @@
/*
* ReceiverFunkThermometer.cpp
*
* Created on: 10.05.2020
* Author: flori
*/
#include "main.h"
#include "DataSender.h"
#include "ReceiverFunkThermometer.h"
#define DEBUG_LEVEL 0
#define MonitorPrint(x) // Serial.print(x)
ReceiverFunkThermometer receiverThermo;
/* ca. alle 50s wird temp + rh gesendet */
/**
*
*/
ReceiverFunkThermometer::ReceiverFunkThermometer()
{
ResetBuffer();
data.tempC = 10;
data.rhPercent = 50;
bNewData = false;
dataLast.tempC = 99;
dataLast.rhPercent = 0u;
rBitNumber = 0u;
}
/**
*
*/
bool ReceiverFunkThermometer::HasNewData(void)
{
return bNewData;
}
/**
*
*/
ReceiverFunkThermometerData_t ReceiverFunkThermometer::GetData(void)
{
ReceiverFunkThermometerData_t datTemp = data;
return datTemp;
}
/**
*
*/
IRAM_ATTR void ReceiverFunkThermometer::Isr(uint32_t dtMicros, bool pinValue)
{
static SignalDurationThermometer_t lastDuration = FUNK_THERMO_INVALID;
SignalDurationThermometer_t thisDuration = FUNK_THERMO_INVALID;
if (dtMicros > 350 && dtMicros < 600)
{
thisDuration = MS_0_5;
}
else if (dtMicros > 800 && dtMicros < 1200)
{
thisDuration = MS_1_0;
}
else if (dtMicros > 1800 && dtMicros < 2200)
{
thisDuration = MS_2_0;
}
else
{
thisDuration = FUNK_THERMO_INVALID;
}
if (thisDuration == FUNK_THERMO_INVALID )
{
ResetBuffer();
}
else
{
if (lastDuration == FUNK_THERMO_INVALID)
{
}
else if (pinValue == HIGH )
{
#if DEBUG_LEVEL > 1
bool bprint = (rByteIndex > 0 || rBitIndex<7);
#else
bool bprint = false;
#endif
if (bprint)
{
sprintf(textBuf, "\n%d %d : ", rByteIndex, rBitIndex );
MonitorPrint(textBuf);
}
if (thisDuration==MS_2_0 && lastDuration == MS_0_5)
{
if (bprint)
{
MonitorPrint(F("1"));
}
/* bit 1 received */
rBytes[rByteIndex] |= (1 << rBitIndex);
if (rBitIndex == 0)
{
NextByte();
}
else
{
rBitIndex--;
}
rBitNumber++;
if (THERMO_NUM_BITS_IGNORED == rBitNumber)
{
rByteIndex = 0;
rBitIndex = 7;
rBytes[0] = 0;
}
}
else if (thisDuration==MS_1_0 &&lastDuration == MS_0_5)
{
if (bprint)
{
MonitorPrint(F("0"));
}
/* bit 0 received */
if (rBitIndex == 0)
{
NextByte();
}
else
{
rBitIndex--;
}
rBitNumber++;
if (THERMO_NUM_BITS_IGNORED == rBitNumber)
{
rByteIndex = 0;
rBitIndex = 7;
rBytes[0] = 0;
}
}
}
}
lastDuration = thisDuration;
}
/**
*
*/
IRAM_ATTR void ReceiverFunkThermometer::ResetBuffer(void)
{
rByteIndex = 0;
rBitIndex = 7;
rBytes[0] = 0;
rBitNumber = 0u;
}
/**
*
*/
IRAM_ATTR void ReceiverFunkThermometer::NextByte(void)
{
rByteIndex++;
rBitIndex = 7;
if (rByteIndex == THERMO_KEY_NUMBYTES_PER_KEY)
{
OnTempReceived();
ResetBuffer();
}
else
{
/* init the next byte */
rBytes[rByteIndex] = 0;
}
}
/*
*
bytes received from woolworth temp
-0,9C 89%
112
255
127
89
------------
-0,8 89
112
255
143
89
------------
-0,7 89
112
255
159
89
------------
-0,6 89
112
255
175
89
------------
-0,5 89
112
255
191
89
------------
0,0 90
112
0
15
90 rh
------------
0.1 90
112
0
31
90
112
0
95
90
6.4
112
4
15
69
*
*/
IRAM_ATTR void ReceiverFunkThermometer::OnTempReceived(void)
{
/* first 4 bits of 36 bits are thrown away.. Rest :
bytes 0 1 2 3
nibbles : 0 1 2 3 4 5 6 7
value : id id t t t 0xf h h
*/
#define PRINT_ON_TEMP_RECEIVED 0
#if 0
/* testdaten */
rBytes[0] = 112u;
rBytes[1] = 255u;
rBytes[2] = 191u;
rBytes[3] = 89u;
#endif
#if PRINT_ON_TEMP_RECEIVED
Serial.println(rBytes[0]);
Serial.println(rBytes[1]);
Serial.println(rBytes[2]);
Serial.println(rBytes[3]);
#endif
if ((rBytes[2]&0xF) == 0xF) /* these 4 bits must be 1 */
{
int16_t tempInt = 0;
int16_t tempNow = 0;
uint8_t rhNow = rBytes[3];
bool isNegative;
tempInt = rBytes[1] << 4;
tempInt |= (int16_t)(rBytes[2] >> 4);
isNegative = (rBytes[1]&0x80) != 0u;
if ( isNegative) // the first bit of nibble 1 shows if the value is negative
{
/* 2's complement */
tempInt = (~tempInt) & 0xFFFu;
tempInt += 1;
}
#if PRINT_ON_TEMP_RECEIVED
Serial.println(tempInt);
#endif
/* do the rounding with positive number */
tempNow = (tempInt + 5) / 10;
if (isNegative)
{
/* set to negative */
tempNow = -tempNow;
}
#if PRINT_ON_TEMP_RECEIVED
Serial.println(tempNow);
#endif
int16_t dTempAbs = (tempNow >= dataLast.tempC) ? (tempNow - dataLast.tempC) : (dataLast.tempC - tempNow);
uint8_t dRHAbs = (rhNow >= dataLast.rhPercent) ? (rhNow - dataLast.rhPercent) : (dataLast.rhPercent - rhNow);
dataLast.tempC = tempNow;
dataLast.rhPercent = rhNow;
#if 1
/* plausibility check: Temp and RH cannot have changed more than 2 units , if a similar value was received two times, it should be ok*/
if ( (dTempAbs <= 2) &&
(dRHAbs <= 2u) )
#endif
{
bNewData = true;
data = dataLast;
}
}
}
@@ -0,0 +1,63 @@
/*
* ReceiverFunkThermometer.h
*
* Created on: 10.05.2020
* Author: flori
*/
#ifndef RECEIVERFUNKTHERMOMETER_H_
#define RECEIVERFUNKTHERMOMETER_H_
#define THERMO_NUM_BITS_IGNORED 4
#define THERMO_NUM_BITS_PER_KEY 36
#define THERMO_KEY_NUMBYTES_PER_KEY 4/* 36 bits, but first 4 bits are ignored -> 32 bits */
typedef enum
{
FUNK_THERMO_INVALID,
MS_0_5,
MS_1_0,
MS_2_0
} SignalDurationThermometer_t;
typedef struct
{
int16_t tempC;
uint8_t rhPercent;
} ReceiverFunkThermometerData_t;
class ReceiverFunkThermometer
{
public:
ReceiverFunkThermometer();
void Isr(uint32_t dtMicros, bool pinValue);
bool HasNewData(void);
ReceiverFunkThermometerData_t GetData(void);
void ResetNewData(void){ bNewData = false; }
private:
void OnTempReceived(void);
void ResetBuffer(void);
void NextByte(void);
uint8_t rBytes[THERMO_KEY_NUMBYTES_PER_KEY];
uint8_t rByteIndex = 0;
uint8_t rBitIndex = 7;
uint8_t rBitNumber = 0;
ReceiverFunkThermometerData_t data;
ReceiverFunkThermometerData_t dataLast;
bool bNewData = false;
};
extern ReceiverFunkThermometer receiverThermo;
#endif /* RECEIVERFUNKTHERMOMETER_H_ */
+219
View File
@@ -0,0 +1,219 @@
/*
* ReceiverSmartWares.cpp
*
* Created on: 22.02.2020
* Author: flori
*/
#include "main.h"
#include "ReceiverSmartWares.h"
#define MonitorPrint(x) //Serial.print(x)
#define MonitorPrintln(x) //Serial.println(x)
#define KEY_BYTE_OPEN 0x56
#define KEY_BYTE_CLOSE 0x55
ReceiverSmartWares receiverSw;
#if 0
static const char* keyNames[] = {
"DAEMM","FB1","FB2","FB3","FB4",
"HAUSTUERE","KLO EG","BAD","WIN 4","KELLERTREPPE",
"GEFRIER","ABSTELL","WIN TONI","Doppel_L","DOPPEL_R",
"LICHT S","LICHT W","LICHT O","LICHT GARAGE","BEW GARAGE",
"STECK 1","STECK 2"};
#endif
/* bytes 4 + 5 sind immer 0x55, byte 6 sagt ON oder oFF, daher hier nur als 0 aufgefuehrt */
const uint8_t ReceiverSmartWares::keys[SMW_KEY_NUMKEYS][SMW_KEY_NUMBYTES_PER_KEY] =
{
/* ausgelesene Keys */
{ 0b01010101, 0b01100101, 0b10010110, 0b10011001, 0, 0, 0, 0b01010110 }, //0 DAEMMERUNG
{ 0b01011010, 0b01100101, 0b10101001, 0b10010101, 0, 0, 0, 0b01010110 }, //1 FB1
{ 0b01011010, 0b01100101, 0b10101001, 0b10010101, 0, 0, 0, 0b01011001 }, //2 FB2
{ 0b01011010, 0b01100101, 0b10101001, 0b10010101, 0, 0, 0, 0b01011010 }, //3 FB3
{ 0b01011010, 0b01100101, 0b10101001, 0b10010101, 0, 0, 0, 0b01100101 }, //4 FB4
{ 0b01010110, 0b01010101, 0b10101001, 0b01100110, 0, 0, 0, 0b01010110 }, //5 BEW HAUSTUERE
{ 0b01010101, 0b01101001, 0b10010110, 0b10010101, 0, 0, 0, 0b01010110 }, //6 WINDOW KLO unten
{ 0b01010101, 0b10011010, 0b10010110, 0b10100110, 0, 0, 0, 0b01010110 }, //7 WINDOW BAD oben
{ 0b01010101, 0b10100110, 0b01011010, 0b01011010, 0, 0, 0, 0b01010110 }, //8 WINDOW FLO
{ 0b01010101, 0b01011001, 0b01010101, 0b01100110, 0, 0, 0, 0b01010110 }, //9 BEW KELLERTREPPE
{ 0b01010101, 0b10011010, 0b01101001, 0b01100110, 0, 0, 0, 0b01010110 }, //10 GEFRIER
{ 0b01010101, 0b10100110, 0b01011010, 0b01011010, 0, 0, 0, 0b01010110 }, //11 ABSTELLRAUM
{ 0b01010101, 0b10101001, 0b01100110, 0b01011010, 0, 0, 0, 0b01010110 }, //12 WINDOW TONI
{ 0b01011001, 0b01101001, 0b01100101, 0b01011001, 0, 0, 0, 0b01010110 }, //13 DOPPELSCHALTER_L
{ 0b01011001, 0b01101001, 0b01100101, 0b01011001, 0, 0, 0, 0b01011001 }, //14 DOPPELSCHALTER_R
/* selbst erfundene Keys */
/* nur 5,6,9,a : immer genausoviele 1en wie 0en -> immer gleich lange sendedauer */
{ 0x56, 0x55, 0x56, 0x55, 0, 0, 0, 0x55}, //15 LICHT TERASSE_SUED
{ 0x56, 0x55, 0x56, 0x55, 0, 0, 0, 0x56}, //16 LICHT TERASSE_WEST
{ 0x56, 0x55, 0x56, 0x55, 0, 0, 0, 0x59}, //17 LICHT HAUSTÜRE_OST
{ 0x56, 0x55, 0x56, 0x55, 0, 0, 0, 0x5a}, //18 LICHT GARAGE
{ 0x56, 0x55, 0x56, 0x55, 0, 0, 0, 0x65}, //19 BEW GARAGE (weitergeleitet von ReceiverBew)
{ 0x6A, 0x95, 0x55, 0x99, 0, 0, 0, 0x56} , // Smartwares Ferbedienung Steckdose Auen A
{ 0x6A, 0x95, 0x55, 0x99, 0, 0, 0, 0x59} , // Smartwares Ferbedienung Steckdose Auen B
};
#define NUM_SW_WINDOW_KEYS 5u
const uint8_t smWindowKeys[NUM_SW_WINDOW_KEYS] = {6u, 7u, 8u, 10u, 12u };
/* NUR FENSTER KEYS WERDEN WEITERGELEITET , SIEHE UNTEN*/
/**
*
*/
ReceiverSmartWares::ReceiverSmartWares()
{
lastReceivedKeyNum = -1;
lastKeyOpenDirection = 0;
ResetBuffer();
}
/**
*
*/
IRAM_ATTR void ReceiverSmartWares::Isr(uint32_t dtMicros, bool pinValue)
{
static SignalDuration_t lastDuration = INVALID;
SignalDuration_t thisDuration = INVALID;
if (dtMicros > 150 && dtMicros < 350)
{
thisDuration = SHORT;
}
else if (dtMicros > 1000 && dtMicros < 1350)
{
thisDuration = LONG;
}
else
{
thisDuration = INVALID;
}
if (thisDuration == INVALID)
{
if (numBits == 64)
{
compareKeys();
}
ResetBuffer();
}
else
{
if (lastDuration == INVALID)
{
}
else if (pinValue == HIGH)
{
numBits++;
if (thisDuration == LONG && lastDuration == SHORT)
{
rBytes[rByteIndex] |= (1 << rBitIndex); /* set a 1 */
if (rBitIndex == 0)
{
NextByte();
}
else
{
rBitIndex--;
}
}
else if (thisDuration == SHORT && lastDuration == SHORT)
{
/* leave the 0 that was the init value of every bit */
if (rBitIndex == 0)
{
NextByte();
}
else
{
rBitIndex--;
}
}
}
}
lastDuration = thisDuration;
}
/**
*
*/
IRAM_ATTR void ReceiverSmartWares::ResetBuffer()
{
rByteIndex = 0;
rBitIndex = 7;
numBits = 0;
rBytes[0] = 0;
}
/**
*
*/
IRAM_ATTR void ReceiverSmartWares::NextByte()
{
rByteIndex++;
rBitIndex = 7;
if (rByteIndex == SMW_KEY_NUMBYTES_PER_KEY)
{
compareKeys();
ResetBuffer();
}
else
{
rBytes[rByteIndex] = 0;
}
}
/**
*
*/
IRAM_ATTR void ReceiverSmartWares::compareKeys()
{
int8_t keyFound = -1;
uint8_t i,j;
for (i=0; i<NUM_SW_WINDOW_KEYS; i++)
{
keyFound = smWindowKeys[i];
if (rBytes[0] != keys[keyFound][0] ) { keyFound = -1; }
else if (rBytes[1] != keys[keyFound][1] ) { keyFound = -1; }
else if (rBytes[2] != keys[keyFound][2] ) { keyFound = -1; }
else if (rBytes[3] != keys[keyFound][3] ) { keyFound = -1; }
else if (rBytes[4] != 0x55 ) { keyFound = -1; }
else if (rBytes[5] != 0x55 ) { keyFound = -1; }
else if ((rBytes[6] != KEY_BYTE_OPEN) && (rBytes[6] != KEY_BYTE_CLOSE)) { keyFound = -1; }
else if (rBytes[7] != keys[keyFound][7] ) { keyFound = -1; }
else
{
MonitorPrint("\nSM ");
MonitorPrint(keyFound);
break;
}
}
bool direction = (rBytes[6] == KEY_BYTE_OPEN);
if ((keyFound>=6 && keyFound<=8) || keyFound==12 || keyFound==10) /* NUR FENSTER KEYS WERDEN WEITERGELEITET */
{
if ((keyFound != lastReceivedKeyNum) || (direction != lastKeyOpenDirection))
{
newKeyReceived = true;
lastReceivedKeyNum = keyFound;
lastKeyOpenDirection = direction;
}
}
else
{
sprintf(textBuf, "SM %x %x %x %X %x %x %x %x", rBytes[0], rBytes[1],
rBytes[2], rBytes[3], rBytes[4], rBytes[5], rBytes[6],
rBytes[7]);
MonitorPrintln(textBuf);
}
}
+46
View File
@@ -0,0 +1,46 @@
/*
* ReceiverSmartWares.h
*
* Created on: 22.02.2020
* Author: flori
*/
#ifndef RECEIVERSMARTWARES_H_
#define RECEIVERSMARTWARES_H_
#include "ReceiverWinSensor433.h"
#define SMW_KEY_NUMKEYS 22
#define SMW_KEY_NUMBYTES_PER_KEY 8
class ReceiverSmartWares : public Receiver433
{
public:
ReceiverSmartWares();
virtual void Isr(uint32_t dtMicros, bool pinValue);
private:
static const uint8_t keys[SMW_KEY_NUMKEYS][SMW_KEY_NUMBYTES_PER_KEY];
uint8_t rBytes[SMW_KEY_NUMBYTES_PER_KEY];
uint8_t rByteIndex = 0;
uint8_t rBitIndex = 7;
uint8_t numBits = 0;
char textBuf[32];
//void printByteBits(byte by);
//void printBuffer();
void compareKeys();
//uint8_t correlationFunction(uint8_t buf1[], uint8_t buf2[], uint8_t sizeBufs, int8_t shift);
void ResetBuffer();
void NextByte();
};
extern ReceiverSmartWares receiverSw;
#endif /* RECEIVERSMARTWARES_H_ */
+37
View File
@@ -0,0 +1,37 @@
/*
* Receiver433.cpp
*
* Created on: 17.10.2021
* Author: flori
*/
#include "ReceiverWinSensor433.h"
Receiver433::Receiver433()
{
doBuffer = true;
newKeyReceived = false;
lastReceivedKeyNum = -1;
lastKeyOpenDirection = false;
}
Receiver433::~Receiver433()
{
// TODO Auto-generated destructor stub
}
int8_t Receiver433::GetLastReceivedKeyNum()
{
if (newKeyReceived) return lastReceivedKeyNum;
else return -1;
}
void Receiver433::ResetReceivedKeyNum()
{
newKeyReceived = false;
}
bool Receiver433::GetLastReceivedDirection()
{
return lastKeyOpenDirection;
}
+47
View File
@@ -0,0 +1,47 @@
/*
* Receiver433.h
*
* Created on: 17.10.2021
* Author: flori
*/
#ifndef RECEIVERWINSENSOR433_H_
#define RECEIVERWINSENSOR433_H_
#include "Arduino.h"
typedef enum
{
INVALID,
SHORT,
LONG
} SignalDuration_t;
/* VIRTUAL BASE CLASS FOR RECEIVERS */
class Receiver433
{
public:
Receiver433();
virtual ~Receiver433();
virtual void Isr(uint32_t dtMicros, bool pinValue) = 0;
virtual int8_t GetLastReceivedKeyNum();
virtual void ResetReceivedKeyNum();
virtual bool GetLastReceivedDirection();
protected:
bool lastKeyOpenDirection; // TRUE -> OPEN, FALSE -> CLOSE
bool doBuffer;
bool newKeyReceived;
int8_t lastReceivedKeyNum;
};
#endif /* RECEIVERWINSENSOR433_H_ */
@@ -0,0 +1,194 @@
/*
* Receiver3ByteKey.cpp
*
* Created on: 12.10.2022
* Author: flori
*/
#include "Receiver3ByteKey.h"
#include "InterruptHandler.h"
/*******************************************************************/
#define DEBUG_LEVEL_NO_PRINT 0
#define DEBUG_LEVEL_PRINT_NEW_KEYS_ONLY 1
#define DEBUG_LEVEL_PRINT_ALL_RECEIVED_KEYS 2
#define DEBUG_LEVEL DEBUG_LEVEL_NO_PRINT
#define SERIAL_PRINT(x) Serial.print(x)
/*******************************************************************/
/**
*
*/
Receiver3ByteKey::Receiver3ByteKey()
{
lastDuration = INVALID;
lastReceivedKeyNum = -1;
lastKeyOpenDirection = 0;
ResetBuffer();
}
/**
*
*/
IRAM_ATTR void Receiver3ByteKey::Isr(uint32_t dtMicros, bool pinValue)
{
SignalDuration_t thisDuration = INVALID;
if (dtMicros > config.tShortMin && dtMicros < config.tShortMax)
{
thisDuration = SHORT;
//if (doBuffer) buft[ibuf++] = dtMicros;
}
else if (dtMicros > config.tLongMin && dtMicros < config.tLongMax)
{
thisDuration = LONG;
//if (doBuffer) buft[ibuf++] = dtMicros;
}
else
{
thisDuration = INVALID;
}
if (thisDuration == INVALID)
{
ResetBuffer();
}
else
{
if (lastDuration == INVALID)
{
/* ResetBuffer was already called last time */
}
else if (pinValue == HIGH)
{
// a valid bit is always terminated with a rising edge (the last bit is always 0 so this is the termination for the last bit to read )
if (thisDuration == LONG && lastDuration == SHORT) // short high, long low -> bit 0
{
/* bytes are initialized as 0, so for bit 0, nothing to change */
NextBit();
}
else if (thisDuration == SHORT && lastDuration == LONG) // long high, short low -> bit 1
{
rBytes[rByteIndex] |= (1 << rBitIndex); // bit 1
NextBit();
}
else
{
// long -> long or short->short is invalid
ResetBuffer();
}
}
else
{
/* falling edge -> wait for next rising edge */
}
}
lastDuration = thisDuration;
}
/**
*
*/
IRAM_ATTR void Receiver3ByteKey::ResetBuffer()
{
rByteIndex = 0;
rBitIndex = 7;
rBytes[0] = 0; /* all other bytes are set to 0 in NextByte() */
ibuf = 0;
}
/**
*
*/
IRAM_ATTR void Receiver3ByteKey::NextBit()
{
if (rBitIndex == 0)
{
NextByte();
}
else
{
rBitIndex--;
}
}
/**
*
*/
IRAM_ATTR void Receiver3ByteKey::NextByte()
{
rByteIndex++;
rBitIndex = 7;
if (rByteIndex == NUM_BYTES_PER_KEY)
{
compareKeys();
ResetBuffer();
}
else
{
rBytes[rByteIndex] = 0;
}
}
/**
*
*/
IRAM_ATTR void Receiver3ByteKey::compareKeys()
{
int8_t keyFound = -1;
bool direction = false;
uint8_t i;
for (i=0; i<config.numberKeys; i++)
{
keyFound = i;
uint8_t iBase = i*(NUM_BYTES_PER_KEY+1u); /* there is always one more byte indicating closing */
if (rBytes[0] != config.keys[iBase+0]) { keyFound = -1; } /* byte 0 does not match */
else if (rBytes[1] != config.keys[iBase+1]) { keyFound = -1; } /* byte 1 does not match */
else if ((rBytes[2] != config.keys[iBase+2]) &&
(rBytes[2] != config.keys[iBase+3]) ) { keyFound = -1; } /* neither open , nor close byte match */
if (keyFound==i)
{
break;
}
}
if (keyFound>=0)
{
uint8_t iBase = keyFound*(NUM_BYTES_PER_KEY+1u);
direction = rBytes[2] == config.keys[ iBase + 2 ];
if ( (keyFound != lastReceivedKeyNum ) || (lastKeyOpenDirection != direction) )
{
doBuffer = false;
newKeyReceived = true;
lastReceivedKeyNum = keyFound;
lastKeyOpenDirection = direction;
InterruptHandler_PauseReceive();
#if DEBUG_LEVEL>=DEBUG_LEVEL_PRINT_ALL_RECEIVED_KEYS
sprintf(textBuf, "\n%s %d %d", config.name, keyFound, lastKeyOpenDirection);
SERIAL_PRINT(textBuf);
#endif
}
}
else
{
#if DEBUG_LEVEL>=DEBUG_LEVEL_PRINT_NEW_KEYS_ONLY
sprintf(textBuf, "\nnew %s %x %x %x", config.name, rBytes[0], rBytes[1], rBytes[2]);
SERIAL_PRINT(textBuf);
#endif
}
}
@@ -0,0 +1,60 @@
/*
* Receiver3ByteKey.h
*
* Created on: 12.10.2022
* Author: flori
*/
#ifndef RECEIVER3BYTEKEY_H_
#define RECEIVER3BYTEKEY_H_
#include "ReceiverWinSensor433.h"
#define NUM_BYTES_PER_KEY 3u
class Receiver3ByteKey : public Receiver433
{
public:
Receiver3ByteKey();
void Isr(uint32_t dtMicros, bool pinValue);
void startBuffering(){ doBuffer = true; }
uint32_t buft[10*8];
protected:
class Config
{
public:
const char *name;
uint16_t tShortMin;
uint16_t tShortMax;
uint16_t tLongMin;
uint16_t tLongMax;
uint8_t numberKeys;
const uint8_t *keys;
};
class Config config;
private:
SignalDuration_t lastDuration;
uint8_t rBytes[NUM_BYTES_PER_KEY];
uint8_t rByteIndex = 0;
uint8_t rBitIndex = 7;
uint32_t ibuf;
//void printByteBits(byte by);
//void printBuffer();
void compareKeys();
//uint8_t correlationFunction(uint8_t buf1[], uint8_t buf2[], uint8_t sizeBufs, int8_t shift);
void ResetBuffer();
void NextBit();
void NextByte();
char textBuf[32];
};
#endif /* RECEIVER3BYTEKEY_H_ */
@@ -0,0 +1,49 @@
/*
* ReceiverAiggend.cpp
*
* Created on: 21.10.2020
* Author: flori
*/
#include "main.h"
#include "Receiver3ByteKey.h"
#include "ReceiverAiggend.h"
/*******************************************************************/
#define KEY_NIBBLE_OPEN 0x0A
#define KEY_NIBBLE_CLOSE 0x0E
#define NUM_KEYS_AIGGEND 4u
/*******************************************************************/
static const char* nameAiggend = "Aiggend";
static const uint8_t keysAiggend[NUM_KEYS_AIGGEND * (NUM_BYTES_PER_KEY+1u) ] =
{
//0b10101110, 0b10110010, 0b00001010 , // 10101110 10110010 0000 1010 0 AUF, 10101110 10110010 0000 1110 0 ZU
0xae, 0xb2, 0x0a , 0x0e,
0xa4, 0x30, 0x0a , 0x0e, // 0xa auf, zu: 0xe
0xa1, 0x4a, 0x0a , 0x0e, // 0xa auf, zu: 0xe
0xe6, 0x80, 0x46 , 0x49 // 0x49 auf, zu 0x46
};
/*******************************************************************/
ReceiverAiggend receiverAiggend;
/*******************************************************************/
ReceiverAiggend::ReceiverAiggend() : Receiver3ByteKey()
{
config.name = nameAiggend;
config.tShortMin = 370u;
config.tShortMax = 680u;
config.tLongMin = 1100u;
config.tLongMax = 1540u;
config.numberKeys = NUM_KEYS_AIGGEND;
config.keys = keysAiggend;
}
@@ -0,0 +1,23 @@
/*
* ReceiverAiggend.h
*
* Created on: 21.10.2020
* Author: flori
*/
#ifndef RECEIVERAIGGEND_H_
#define RECEIVERAIGGEND_H_
#include "Receiver3ByteKey.h"
class ReceiverAiggend : public Receiver3ByteKey
{
public:
ReceiverAiggend();
};
extern ReceiverAiggend receiverAiggend;
#endif /* RECEIVERAIGGEND_H_ */
@@ -0,0 +1,46 @@
/*
* ReceiverKerui.cpp
*
* Created on: 12.10.2022
* Author: flori
*/
#include "main.h"
#include "ReceiverKerui.h"
/*******************************************************************/
#define KEY_NIBBLE_OPEN 0x0E
#define KEY_NIBBLE_CLOSE 0x07
#define NUM_KEYS_KERUI 3u
/*******************************************************************/
static const char* nameKerui = "Kerui";
static const uint8_t keysKerui[NUM_KEYS_KERUI* (NUM_BYTES_PER_KEY+1u) ] =
{
0x3c, 0xf3, 0x0E, 0x07 , /* key, key, open, close */
0xea, 0x3a, 0x0E, 0x07 ,
0xbd, 0x14, 0x0E, 0x07
};
/*******************************************************************/
ReceiverKerui receiverKerui = ReceiverKerui();
/*******************************************************************/
ReceiverKerui::ReceiverKerui() : Receiver3ByteKey()
{
config.name = nameKerui;
config.tShortMin = 250u;
config.tShortMax = 450u;
config.tLongMin = 850u;
config.tLongMax = 1150u;
config.numberKeys = NUM_KEYS_KERUI;
config.keys = keysKerui;
}
@@ -0,0 +1,22 @@
/*
* ReceiverKerui.h
*
* Created on: 12.10.2022
* Author: flori
*/
#ifndef RECEIVERKERUI_H_
#define RECEIVERKERUI_H_
#include "Receiver3ByteKey.h"
class ReceiverKerui : public Receiver3ByteKey
{
public:
ReceiverKerui();
};
extern ReceiverKerui receiverKerui;
#endif /* RECEIVERKERUI_H_ */
@@ -0,0 +1,52 @@
/*
* ReceiverOval.cpp
*
* Created on: 12.10.2022
* Author: flori
*/
#include "main.h"
#include "ReceiverOval.h"
/*******************************************************************/
#define KEY_NIBBLE_OPEN 0x03
#define KEY_NIBBLE_CLOSE 0x09
#define NUM_KEYS_OVAL 6u
/*******************************************************************/
static const char* nameOval = "Oval";
static const uint8_t keysOval[NUM_KEYS_OVAL * (NUM_BYTES_PER_KEY+1u)] =
{
0xdc, 0x86, 0x03 , 0x09, // 0x3 auf 0x9 zu,
0x30, 0xa5, 0x03 , 0x09, // 0x3 auf 0x9 zu,
0x4c, 0xe6, 0x03 , 0x09, // 0x3 auf 0x9 zu,
0x74, 0xa5, 0x03 , 0x09, // 0x3 auf 0x9 zu,
0x29, 0x66, 0x03 , 0x09, // 0x3 auf 0x9 zu,
0xe4, 0x0f, 0x76 , 0x79 // 0x3 auf 0x9 zu,
};
/*******************************************************************/
ReceiverOval receiverOval;
/*******************************************************************/
ReceiverOval::ReceiverOval() : Receiver3ByteKey()
{
config.name = nameOval;
config.tShortMin = 320u;
config.tShortMax = 510u;
config.tLongMin = 1100u;
config.tLongMax = 1330u;
config.numberKeys = NUM_KEYS_OVAL;
config.keys = keysOval;
}
@@ -0,0 +1,23 @@
/*
* ReceiverOval.h
*
* Created on: 12.10.2022
* Author: flori
*/
#ifndef RECEIVEROVAL_H_
#define RECEIVEROVAL_H_
#include "Receiver3ByteKey.h"
class ReceiverOval : public Receiver3ByteKey
{
public:
ReceiverOval();
};
extern ReceiverOval receiverOval;
#endif /* RECEIVEROVAL_H_ */
+30
View File
@@ -0,0 +1,30 @@
/*
* Seconds.cpp
*
* Created on: 10.09.2020
* Author: flori
*/
#include "Seconds.h"
uint32_t Seconds::lastMillisShifted = 0;
uint32_t Seconds::seconds = 0;
uint32_t Seconds::secondsOverflow = 0;
boolean volatile Seconds::semaphore = false;
uint32_t Seconds::Get(void)
{
uint32_t secRet;
uint32_t secNow = millis() / 1000;
if (secNow < seconds)
{
secondsOverflow += seconds + 1;
}
seconds = secNow;
secRet = seconds + secondsOverflow;
return secRet;
}
+25
View File
@@ -0,0 +1,25 @@
/*
* Seconds.h
*
* Created on: 10.09.2020
* Author: flori
*/
#ifndef SECONDS_H_
#define SECONDS_H_
#include "Arduino.h"
class Seconds
{
public:
static uint32_t Get();
private:
static uint32_t lastMillisShifted;
static uint32_t seconds;
static uint32_t secondsOverflow;
static volatile boolean semaphore;
};
#endif /* SECONDS_H_ */
+119
View File
@@ -0,0 +1,119 @@
/*
* UpdateHandler.c
*
* Created on: 04.08.2023
* Author: flori
*/
#include "WebServer.h"
#include <Update.h>
#include "Version.h"
WebServer webServer;
const char* serverIndex =
"<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
"<br>" PROJECT_NAME " " VERSION_STR "<br><br>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
"<input type='file' name='update'>"
"<input type='submit' value='Update'>"
"</form>"
"<div id='prg'>progress: 0%</div>"
"<script>"
"$('form').submit(function(e){"
"e.preventDefault();"
"var form = $('#upload_form')[0];"
"var data = new FormData(form);"
" $.ajax({"
"url: '/update',"
"type: 'POST',"
"data: data,"
"contentType: false,"
"processData:false,"
"xhr: function() {"
"var xhr = new window.XMLHttpRequest();"
"xhr.upload.addEventListener('progress', function(evt) {"
"if (evt.lengthComputable) {"
"var per = evt.loaded / evt.total;"
"$('#prg').html('progress: ' + Math.round(per*100) + '%');"
"}"
"}, false);"
"return xhr;"
"},"
"success:function(d, s) {"
"$('#prg').html('success!');"
"},"
"error: function (a, b, c) {"
"}"
"});"
"});"
"</script>";
void UpdateHandler()
{
static bool initDone = false;
if (false == WiFi.isConnected())
{
initDone = false;
}
else
{
if (initDone == false)
{
initDone = true;
webServer.on("/", HTTP_GET, []()
{
Serial.printf("HTTP_GET");
webServer.sendHeader("Connection", "close");
webServer.send(200, "text/html", serverIndex);
});
/*handling uploading firmware file */
webServer.on("/update", HTTP_POST, []()
{
webServer.sendHeader("Connection", "close");
webServer.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []()
{
HTTPUpload& upload = webServer.upload();
if (upload.status == UPLOAD_FILE_START)
{
Serial.printf("Update: %s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN))
{ //start with max available size
Update.printError(Serial);
}
}
else if (upload.status == UPLOAD_FILE_WRITE)
{
/* flashing firmware to ESP*/
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize)
{
Update.printError(Serial);
}
}
else if (upload.status == UPLOAD_FILE_END)
{
if (Update.end(true))
{ //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
}
else
{
Update.printError(Serial);
}
}
});
webServer.begin(80u);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.printf("webServer init done");
}
webServer.handleClient();
}
}
+15
View File
@@ -0,0 +1,15 @@
/*
* UpdateHandler.h
*
* Created on: 04.08.2023
* Author: flori
*/
#ifndef UPDATEHANDLER_H_
#define UPDATEHANDLER_H_
void UpdateHandler(void);
#endif /* UPDATEHANDLER_H_ */
+21
View File
@@ -0,0 +1,21 @@
/*
* Version.h
*
* Created on: 04.08.2023
* Author: flori
*/
#ifndef VERSION_H_
#define VERSION_H_
#include "main.h"
#if VERSION_DG_ONLY
#define PROJECT_NAME "FENSTER_PIEPSER_NODEMCU_32_S_DG"
#else
#define PROJECT_NAME "FENSTER_PIEPSER_NODEMCU_32_S_EG"
#endif
#define VERSION_STR "v1.3.2"
#endif /* VERSION_H_ */
View File
+22
View File
@@ -0,0 +1,22 @@
// Only modify this file to include
// - function definitions (prototypes)
// - include files
// - extern variable definitions
// In the appropriate section
#ifndef _fensterPIEP_H_
#define _fensterPIEP_H_
#include "Arduino.h"
//add your includes for the project fensterPIEP here
//end of add your includes here
//add your function definitions for the project fensterPIEP here
//Do not add code below this line
#endif /* _fensterPIEP_H_ */
+635
View File
@@ -0,0 +1,635 @@
#include "ReceiverSmartWares.h"
#include "ReceiverAiggend.h"
#include "ReceiverOval.h"
#include "ReceiverKerui.h"
#include "ReceiverFunkThermometer.h"
#include "PiepMode.h"
#include "PiepPattern.h"
#include "LedBlinker.h"
#include "Fenster.h"
#include "Display.h"
#include "Display_SSD1306.h"
#include "Seconds.h"
#include "DataSender.h"
#include "InterruptHandler.h"
#include "xcp/XcpPort.h"
#include "UpdateHandler.h"
#include "main.h"
#include "Version.h"
#include "WiFi.h"
#include "time.h"
/*
* platform esp32/1.0.6
* NodeMCU-32S
* FlashFreq 80MHz
* Upload Speed 921600
*
*
* LIBRARIES :
* -----------
* Adafruit_BusIO
* Adafruit_GFX_Library
* Adafruit_ST7735_and_ST7789_Library
* ESP8266_and_ESP32_OLED_driver_for_SSD1306_displays
* FS
* SPI
* Update
* WebServer
* WiFi
* Wire
*
*/
/* COM PORT : Silicon Labs CP210x USB to UART Bridge */
/*---------------- DEFINES ------------- */
#define TEST_PIEPEN_BEI_START 0
#define SECONDS_TO_DECIS(x) ((DeciSeconds_t)10UL*x)
#define MINUTES_TO_DECIS(x) ((DeciSeconds_t)600UL*x)
#define MINUTES_TO_SECONDS(x) (60*x)
#define DAYS_TO_MILLIS(x) ((x)*24UL*3600UL*1000UL)
#define SERIAL_PRINT(x) Serial.print(x)
#define AIGGEND_KEY_INDEX_OFFSET 30u
#define OVAL_KEY_INDEX_OFFSET 40u
#define KERUI_KEY_INDEX_OFFSET 50u
#define TONE_FREQUENCY_HZ 2000
#define USE_XCP (1u)
#define USE_WIFI (1u) /* WARNING, no OTA update without wifi ! */
#define USE_DATASENDER (0u)
/*---------------- GLOBAL VARIABLES ------------- */
uint32_t gtMillis;
char textBuf[100];
DeciSeconds_t waitTimeDs = 0; /* in deciSeconds */
DeciSeconds_t tDecis = 0;
uint8_t numberWindowsOpen = 0;
ReceiverFunkThermometerData_t thermoData = {0, 0};
bool bRequestShortBeep = false;
bool bIsNightTime = false;
PiepPattern *piepPattern;
/*
* every sensor type has a list of keys, index starting at 0.
* the handleKeyReceived adds a offset for each sensor type.
* in the config here, the key must be configured with resulting sum.
*/
/* SMART WARES */
Fenster fensterGefrier("Gefrier" ,10);
/* Aiggend keys */
Fenster fensterWz("Wohnz", 2 + KERUI_KEY_INDEX_OFFSET); /* NICHT GENUTZT AKTUELL */
Fenster fensterFlo("Flo", 2 + AIGGEND_KEY_INDEX_OFFSET);
Fenster fensterBadUnten("Bad u", 3 + AIGGEND_KEY_INDEX_OFFSET);
/* OVAL keys */
Fenster fensterKeller("Keller", 0 + OVAL_KEY_INDEX_OFFSET);
Fenster fensterToniNeu("Toni", 1 + OVAL_KEY_INDEX_OFFSET);
Fenster fensterKueche("Kueche", 2 + OVAL_KEY_INDEX_OFFSET);
Fenster fensterWz2("Wohnz", 3 + OVAL_KEY_INDEX_OFFSET);
Fenster fensterFloBuero("Buero", 4 + OVAL_KEY_INDEX_OFFSET);
Fenster fensterHanna("Hanna", 5 + OVAL_KEY_INDEX_OFFSET);
/** */
Fenster fensterGaeste("Gaeste" , 1 + KERUI_KEY_INDEX_OFFSET);
Fenster fensterBadOben("Bad o", 1 + AIGGEND_KEY_INDEX_OFFSET);
#if VERSION_SMALL_DISPLAY
#if VERSION_DG_ONLY /* DACHGESCHOSS */
Fenster* alleFenster[NUM_FENSTER] =
{
&fensterBadOben, &fensterFlo, &fensterHanna, &fensterFloBuero , //OG
};
#else
Fenster* alleFenster[NUM_FENSTER] =
{
&fensterWz, &fensterBadUnten, &fensterKueche, &fensterToniNeu , //EG
};
#endif
#else
#ifdef VERSION_BIG_DISPLAY
Fenster* alleFenster[NUM_FENSTER] =
{
&fensterBadUnten, &fensterKueche, &fensterWz, &fensterWz2, &fensterToniNeu, &fensterGefrier,//EG
&fensterKeller, &fensterGaeste //KG
};
#else
Fenster* alleFenster[NUM_FENSTER] =
{
&fensterBadOben, &fensterFlo, &fensterHanna, &fensterFloBuero , //OG
&fensterBadUnten, &fensterKueche, &fensterWz, &fensterWz2, &fensterToniNeu, &fensterGefrier,//EG
&fensterKeller, &fensterGaeste //KG
};
#endif
#endif
uint32_t loopCountSincePause = 0u;
uint8_t toneRequest = 0u;
/*---------------- LOCAL VARIABLES ------------- */
static PiepMode *piepFast, *piepSlow, *piepPauseLong, *piepPauseShort;
static PiepMode *piepModes[3];
static int8_t manualKeyNo = -1;
static bool manualKeyDirection = false;
static bool bUpdateDisp = false;
static uint32_t tBeepingStartWithoutWindowClose = 0u;
/*---------------- LOCAL FUNCTIONS ------------- */
static void handleManualInputRequest();
static void updateWaittime(void);
static void xcpLoop(void);
#ifdef TEST_WAITTIME
static void testWaitTime(void);
#endif
static void handleDispUpdate(void);
static void handleKeyReceived(void);
static void updateIsNighttime();
static void updatePiepPattern(void);
/**
*
*/
void setup()
{
#if USE_XCP
XcpInit();
#endif
#if USE_WIFI
static const char* ssidElektro = "Elektrosmog";
static const char* password = "r4g8f-xz5av";
WiFi.setHostname(PROJECT_NAME);
WiFi.mode(WIFI_STA);
WiFi.begin(ssidElektro, password);
dataSender.onSetup();
const char* ntpServer = "ptbtime3.ptb.de";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
#endif
/* setup pins receiver */
pinMode(DOUT_TEST_TIMER, OUTPUT); digitalWrite(DOUT_TEST_TIMER, HIGH);
pinMode(DOUT_FUNK_VCC, OUTPUT); digitalWrite(DOUT_FUNK_VCC, HIGH);
pinMode(DOUT_FUNK_GND, OUTPUT); digitalWrite(DOUT_FUNK_GND, LOW);
pinMode(DOUT_PIEP_VCC, OUTPUT);
pinMode(DIN_FUNK, INPUT_PULLUP);
/* TONE SETUP */
ledcSetup(TONE_PWM_CHANNEL, TONE_FREQUENCY_HZ, 8);
ledcAttachPin(DOUT_PIEP_PWM, TONE_PWM_CHANNEL);
ledcWrite(TONE_PWM_CHANNEL, 127);
/* setup Serial */
Serial.begin(115200uL);
Serial.println(F("\n---\nOK\n"));
/* Piep times based on 33.3ms */
/* setup Piep mode fast*/
piepFast = new PiepMode();
piepFast->onTime = MS_TO_ISR_COUNT(20uL);
piepFast->offTime = MS_TO_ISR_COUNT(80uL);
piepFast->requestCount = 2u;
/* setup Piep mode slow*/
piepSlow = new PiepMode();
piepSlow->onTime = MS_TO_ISR_COUNT(500uL);
piepSlow->offTime = MS_TO_ISR_COUNT(100uL);
piepSlow->requestCount = 1u;
/* setup Piep mode pause*/
piepPauseLong = new PiepMode();
piepPauseLong->onTime = 0u;
piepPauseLong->offTime = MS_TO_ISR_COUNT(1000uL); /* 1s */
piepPauseLong->requestCount = 120u; /* 60s pause */
piepPauseShort = new PiepMode();
piepPauseShort->onTime = 0u;
piepPauseShort->offTime = MS_TO_ISR_COUNT(1000uL); /* 1s */
piepPauseShort->requestCount = 20u; /* 10s pause */
/* setup Piep pattern*/
piepPattern = new PiepPattern();
piepPattern->numberModes = 3u;
piepPattern->requestCount = 0u;
piepPattern->piepModes = piepModes;
piepPattern->piepModes[0] = piepFast;
piepPattern->piepModes[1] = piepSlow;
piepPattern->piepModes[2] = piepPauseLong;
#if TEST_PIEPEN_BEI_START
/* start piep pattern (just for debugging, uncomment stopping in loop for debugging)*/
piepPattern->Start(DOUT_PIEP_PWM);
#endif
InterruptHandler_Init();
display.Init();
updateWaittime();
#ifdef TEST_WAITTIME
testWaitTime();
#endif
}
/**
*
*/
void loop()
{
handleKeyReceived();
handleDispUpdate();
#if USE_WIFI
//updateIsNighttime();
#if USE_DATASENDER
dataSender.onLoop();
#endif
UpdateHandler();
#endif
updatePiepPattern();
#if USE_XCP
xcpLoop();
#endif
/* reset ECU every day */
if (millis() > DAYS_TO_MILLIS(1uL) && numberWindowsOpen == 0)
{
Serial.print("RESET");
ESP.restart();
}
loopCountSincePause++;
}
static void handleDispUpdate(void)
{
/* cyclically request display update */
static DeciSeconds_t nextDispUpdateDecis = 0;
if (tDecis > nextDispUpdateDecis || bUpdateDisp)
{
bUpdateDisp = true;
if (numberWindowsOpen > 0)
{
nextDispUpdateDecis = tDecis + SECONDS_TO_DECIS(1u);
}
else
{
nextDispUpdateDecis = tDecis + SECONDS_TO_DECIS(10u);
}
}
/* update display if requested*/
if (bUpdateDisp)
{
//noInterrupts();
bUpdateDisp = false;
display.Update();
//interrupts();
}
}
static void updateIsNighttime()
{
static DeciSeconds_t nextUpdateDecis = SECONDS_TO_DECIS(120u);
if (tDecis > nextUpdateDecis )
{
struct tm timeinfo;
if (!getLocalTime(&timeinfo, 100u))
{
Serial.println("Failed to obtain time");
nextUpdateDecis = tDecis + SECONDS_TO_DECIS(120u);
return;
}
else
{
nextUpdateDecis = tDecis + SECONDS_TO_DECIS(120u);
bIsNightTime = (timeinfo.tm_hour >= 22 || timeinfo.tm_hour < 6);
if (bIsNightTime)
{
Serial.print("\nNIGHT");
}
else
{
Serial.print("\nDAY");
}
}
}
}
/**
* reduce paus time after x minutes, when beep is active
*
*/
static void updatePiepPattern(void)
{
#if TEST_PIEPEN_BEI_START
piepPattern->piepModes[2] = piepPauseShort;
#else
if (tBeepingStartWithoutWindowClose == 0u)
{
piepPattern->piepModes[2] = piepPauseLong;
}
else if ((Seconds::Get() - tBeepingStartWithoutWindowClose) < MINUTES_TO_SECONDS(6u) ) /* reduce pause time after x mintues */
{
piepPattern->piepModes[2] = piepPauseLong;
}
else
{
piepPattern->piepModes[2] = piepPauseShort;
}
#endif
}
/**/
static void handleKeyReceived(void)
{
int8_t lastKey = - 1; /* lastKey gets an offset for each receiver type */
bool lastKeyDirection = DIRECTION_CLOSE;
//delay(10);
//handleManualInputRequest();
if (manualKeyNo >= 0)
{
lastKey = manualKeyNo;
lastKeyDirection = manualKeyDirection;
}
if (lastKey < 0)
{
/* first check if a SW key was received */
lastKey = receiverSw.GetLastReceivedKeyNum();
if (lastKey >= 0)
{
receiverSw.ResetReceivedKeyNum();
lastKeyDirection = receiverSw.GetLastReceivedDirection();
}
}
if (lastKey < 0) /* if no SW key was received, check if a aiggend key was received */
{
lastKey = receiverAiggend.GetLastReceivedKeyNum();
if (lastKey >= 0)
{
receiverAiggend.ResetReceivedKeyNum();
lastKey += AIGGEND_KEY_INDEX_OFFSET;
lastKeyDirection = receiverAiggend.GetLastReceivedDirection();
#if 0
Serial.println("--");
for (uint32_t i=0; i<24; i++)
{
Serial.println(receiverAiggend.buft[i]);
}
receiverAiggend.startBuffering();
#endif
}
}
if (lastKey < 0)
{
lastKey = receiverOval.GetLastReceivedKeyNum();
if (lastKey >= 0)
{
receiverOval.ResetReceivedKeyNum();
lastKey += OVAL_KEY_INDEX_OFFSET;
lastKeyDirection = receiverOval.GetLastReceivedDirection();
}
}
if (lastKey < 0)
{
lastKey = receiverKerui.GetLastReceivedKeyNum();
if (lastKey >= 0)
{
receiverKerui.ResetReceivedKeyNum();
lastKey += KERUI_KEY_INDEX_OFFSET;
lastKeyDirection = receiverKerui.GetLastReceivedDirection();
}
}
/* read the thermo data and update wait time */
if (receiverThermo.HasNewData())
{
thermoData = receiverThermo.GetData();
receiverThermo.ResetNewData();
bUpdateDisp = true;
/*
char buf[16];
sprintf(buf, "\n%d.%dC %d%%", (int)floor(thermoData.temp), (int) floor(thermoData.temp*10) -(int) floor(thermoData.temp)*10, (int)floor(thermoData.rh));
Serial.print(buf);
*/
/* update wait time according to temperature */
updateWaittime();
}
/* handle windows and possibly start/stop beep pattern */
{
static bool shallPiepPrevious = false;
bool shallPiepNew = false;
uint8_t numberWindowsOpenNew = 0;
for (uint8_t i = 0; i < NUM_FENSTER; i++)
{
bool bWindowChanged = alleFenster[i]->HandleKey(lastKey, lastKeyDirection);
numberWindowsOpenNew += alleFenster[i]->IsOpen() ? 1 : 0;
shallPiepNew |= alleFenster[i]->ShallPiep();
if (bWindowChanged)
{
bUpdateDisp = true;
dataSender.requestSend();
bRequestShortBeep = true;
if (lastKeyDirection == DIRECTION_CLOSE)
{
tBeepingStartWithoutWindowClose = 0u;
}
}
}
/* possibly stop or start beeping */
if (bIsNightTime)
{
#if (TEST_PIEPEN_BEI_START == 0)
piepPattern->Stop();
#endif
}
else if (false == shallPiepNew)
{
#if (TEST_PIEPEN_BEI_START == 0)
piepPattern->Stop();
#endif
}
else if ((true == shallPiepNew) && (false == shallPiepPrevious))
{
tBeepingStartWithoutWindowClose = Seconds::Get();
piepPattern->Start(DOUT_PIEP_PWM);
bUpdateDisp = true;
}
shallPiepPrevious = shallPiepNew;
numberWindowsOpen = numberWindowsOpenNew;
}
if (numberWindowsOpen == 0u)
{
tBeepingStartWithoutWindowClose = 0u;
}
}
#ifdef TEST_WAITTIME
static void testWaitTime()
{
thermoData.rhPercent = 5;
float tempC;
for (tempC = -10; tempC < 30; tempC += 0.5f)
{
thermoData.tempC = tempC;
updateWaittime();
Serial.print(tempC);
Serial.print(" ");
Serial.print(waitTimeDs);
Serial.print("\n");
}
}
#endif
/**
*
*/
static void updateWaittime(void)
{
/** < -5 : 5min
* -5 .. 19 : 5..30 min min = 5 + t- (-5) * (30-5) / (19- (-5) ) ;
* >19 : inf
* >25 : 30 min
*/
if (thermoData.rhPercent > 0.0f)
{
/* VALUE RECEIVED */
if (thermoData.tempC > 25.0f)
{
waitTimeDs = MINUTES_TO_DECIS(30);
}
else if (thermoData.tempC > 19.5f)
{
waitTimeDs = MINUTES_TO_DECIS(60*24*14); //zwei Wochen = unendlich
}
else if (thermoData.tempC < -5.0f)
{
waitTimeDs = MINUTES_TO_DECIS(5);
piepPauseLong->requestCount = 20;
}
else
{
const float dy = 30.0f-5.0f;
const float dx = 19.5f-(-5.0f);
float minutes = 5.0f + (thermoData.tempC-(-5.0f)) * dy / dx ;
waitTimeDs = (DeciSeconds_t)(600.0f * minutes);
}
}
else
{
/* DEFAULT IF NO VALUE WAS RECEIVED YET*/
#if 0
/* calculate the wait Time from the poti value */
waitTimeDs = ((DeciSeconds_t) analogRead(AIN_POTI)
* MINUTES_TO_DECIS(19UL)) / 1023UL; /* max 19 minutes */
waitTimeDs += MINUTES_TO_DECIS(1UL); /* minimum 1 Minute */
#endif
waitTimeDs = MINUTES_TO_DECIS(10);
}
}
/**
* im serial monitor zwei zahlen mit leerzeichen eingeben, um einen key zu senden :
* 1 1 sendet key 1 an,
* 2 0 sendet key 2 aus,..
*/
static void handleManualInputRequest()
{
if (Serial.available())
{
char buf[10];
size_t numBytesRead = Serial.readBytesUntil(' ', buf, 10);
if (numBytesRead > 0)
{
buf[numBytesRead] = '\0';
int n1;
sscanf(buf, "%d", &n1);
Serial.print(n1);
Serial.print(" n1 \n");
numBytesRead = Serial.readBytesUntil(' ', buf, 10);
if (numBytesRead > 0) /* send key */
{
buf[numBytesRead] = '\0';
int n2;
sscanf(buf, "%d", &n2);
Serial.print(n2);
Serial.print(" n2 \n");
if (n1 > 0 && n2 >= 0 && n2 <= 1)
{
manualKeyNo = n1;
manualKeyDirection = n2;
}
}
}
}
}
#if USE_XCP
static void xcpLoop(void)
{
static uint32_t tNext10ms = 0;
static uint32_t tNext100ms = 0;
static uint32_t tNext500ms = 0;
static uint32_t tNext1000ms = 0;
/* trigger events */
if (millis() >= tNext10ms)
{
tNext10ms += 10;
XcpEvent(0);
}
if (millis() >= tNext100ms)
{
tNext100ms += 100;
XcpEvent(1);
}
if (millis() >= tNext500ms)
{
tNext500ms += 500;
XcpEvent(2);
}
if (millis() >= tNext1000ms)
{
tNext1000ms += 1000;
XcpEvent(3);
}
XcpPoll();
XcpSendLoop();
}
#endif
+12
View File
@@ -0,0 +1,12 @@
// Only modify this file to include
// - function definitions (prototypes)
// - include files
// - extern variable definitions
// In the appropriate section
#ifndef _fenster_PIEPSER_NodeMCU32S_H_
#define _fenster_PIEPSER_NodeMCU32S_H_
/* USE main.h */
#endif /* _fenster_PIEPSER_NodeMCU32S_H_ */
+100
View File
@@ -0,0 +1,100 @@
/*
* main.h
*
* Created on: 22.02.2020
* Author: flori
*/
#ifndef MAIN_H_
#define MAIN_H_
/* -------------- INCLUDES --------------*/
#include "Arduino.h"
#include "typedefs.h"
#include "PiepPattern.h"
#include "ReceiverFunkThermometer.h"
#include "Fenster.h"
/* --------------- TYPEDEFS -------------*/
/* --------- SYMBOLIC CONSTANTS ---------*/
#define VERSION_DG_ONLY 0
#define VERSION_SMALL_DISPLAY 1
#define VERSION_BIG_DISPLAY (! VERSION_SMALL_DISPLAY)
/* singal pins */
#define TFT_PIN_CLK 14 /* SCK */
#define TFT_PIN_MOSI 13 /* SDA */
#define TFT_PIN_RST 22 // RES
#define TFT_PIN_DC 21 // RS (Data/Command = Register select)
#define TFT_PIN_CS 15 /* CS Chip select */
#define DOUT_TEST_TIMER 16
#define DOUT_FUNK_VCC 12
#define DOUT_FUNK_GND 32
#define DIN_FUNK 26
#define DOUT_PIEP_PWM 33
#define DOUT_PIEP_VCC 18
#define TONE_PWM_CHANNEL 12
#define TONE_REQUEST_ON(source) toneRequest |= (1u<<source) /* the pwm output is always active, only the supply gets switched */
#define TONE_REQUEST_OFF(source) toneRequest &= (~(1u<<source))
#define TONE_REQUEST_SOURCE_MODE 1u
#define TONE_REQUEST_SOURCE_SHORTPIEP 0u
#if VERSION_SMALL_DISPLAY
#define NUM_FENSTER 4
#elif VERSION_BIG_DISPLAY
#define NUM_FENSTER 8
#endif
#define DIRECTION_OPEN (1u)
#define DIRECTION_CLOSE (0u)
/* ------------- GLOBAL VARIABLES --------*/
extern uint8_t numberWindowsOpen;
extern uint32_t waitTimeDs;
extern char textBuf[100];
extern bool bRequestShortBeep;
extern bool bIsNightTime;
extern PiepPattern *piepPattern;
extern DeciSeconds_t tDecis;
extern ReceiverFunkThermometerData_t thermoData;
extern uint32_t loopCountSincePause;
extern uint8_t toneRequest;
extern Fenster fensterFloBuero;
extern Fenster fensterGefrier;
extern Fenster fensterBadOben;
extern Fenster fensterBadUnten;
extern Fenster fensterFlo;
extern Fenster fensterHanna;
extern Fenster fensterWz;
extern Fenster fensterWz2;
extern Fenster fensterX;
extern Fenster fensterToniNeu;
extern Fenster fensterKueche;
extern Fenster fensterKeller;
extern Fenster fensterGaeste;
extern Fenster* alleFenster[NUM_FENSTER];
/* ----------------------------------------*/
#endif /* MAIN_H_ */
+16
View File
@@ -0,0 +1,16 @@
/*
* typedefs.h
*
* Created on: 24.05.2020
* Author: flori
*/
#ifndef TYPEDEFS_H_
#define TYPEDEFS_H_
#include "Arduino.h"
typedef uint32_t DeciSeconds_t;
#endif /* TYPEDEFS_H_ */
+160
View File
@@ -0,0 +1,160 @@
#ifndef RINGBUFFER_H
#define RINGBUFFER_H
#include "Arduino.h"
/**
* the buffer always begins at iRead and ends at iBufEnd
* writing is allowed as long as iWrite != iBufEnd
* reading is possible as long as iRead != iWrite
* start (no data to read, 6 elements [0..5] free to write ):
* [ 0 1 2 3 4 5 6 ]
* iRead
* iWrite x x x x x iBufEnd
*
* 4 elements available to read:
* [ x x x iBufEnd iRead x x x iWrite x x x ]
* after reading 4 elements:
* [ x x x x x x x iBufEnd iWrite x x x ]
* iRead
*
* 1 more element can be written, 8 can be read
* [ x x x iWrite iBufEnd iRead x x x x ]
* after writing 1 element:
* buffer is full, 9 to be read
* [ x x x x iBufEnd iRead x x x x ]
* iWrite
*
*
* writing is split up into three calls :
* 1. canWrite -> check if the buffer has space left
* 2. getWritePointer returns the pointer to the element
* that can be written on (or NULL if writing is forbidden)
* 3. write moves the write index to the next position and thereby
* signals that the just written element can be read now
*
* reading is done by
* 1. canRead -> check if there are elements that have been written
* but not yet read
* 2. getReadPointer : returns pointer to the next available element
* and increments the read index. Reading from the pointer
* is safe (data will not be overwritten) until the next call of
* getReadPointer
*
*/
template<class T> class RingBuffer
{
public:
/**
* The RingBuffer does not create the underlying array itself, it must be
* created outside.
* \param : array : pointer to first element of the array
* arraySize : number of elements in the array
*/
RingBuffer<T>(T * array, uint32_t arraySize)
{
this->array = array; //constant
this->arraySize = arraySize; //constant
iBufEnd = arraySize-1;
iWrite = 0;
iRead = 0;
}
/**
* return if the buffer has at least one element left to write on
* without overwriting unread elements
*/
bool canWrite(void)
{
return iWrite != iBufEnd;
}
/**
* returns NULL if write is not permitted!
* (Check can be done with canWrite())
* When the writing to the pointer is finished call write()!
*/
T* getWritePointer(void)
{
T* pWrite = NULL;
if (canWrite())
{
pWrite = &array[iWrite];
}
return pWrite;
}
/**
* to be called as soon as the data has been written.
* Don't put this into getWritePointer to allow reading
* the element immediately
*/
void write(void)
{
if ( canWrite() )
{
/* should always be true, otherwise there was an error before */
if (++iWrite==arraySize){
iWrite = 0; //wrap
}
}
}
/**
* return true if there are elements that can be read
*/
bool canRead(void)
{
return iRead != iWrite;
}
/**
* return the number of received elements that haven't been read yet
*/
uint32_t getNumberUnread(void)
{
uint32_t numUnread;
if ( iRead == iWrite )
{
numUnread = 0;
}
else if ( iWrite > iRead )
{
numUnread = iWrite-iRead;
}
else
{
numUnread = arraySize + iWrite - iRead;
}
return numUnread;
}
/**
* get Pointer to next received frame that hasn't been read yet.
* the data will be safe to read until the next call of the function
* (because array[iBufEnd] will not be overwritten)
* The function increments the read index, so it may only be called once per element
*/
T* getReadPointer(void)
{
T* pEntry = &array[iRead];
iBufEnd = iRead;
if (++iRead==arraySize){
iRead = 0; //wrap
}
return pEntry;
}
private:
T* array;
uint32_t arraySize;
uint32_t iWrite;
uint32_t iRead;
uint32_t iBufEnd;
};
#endif
+19
View File
@@ -0,0 +1,19 @@
/*
* XcpApplInterface.h
*
* Created on: 30.07.2022
* Author: flori
*/
#ifndef XCP_XCPAPPINTERFACE_H_
#define XCP_XCPAPPINTERFACE_H_
#include "xcp_cfg.h"
extern const vuint8 kXcpEventDirection[kXcpMaxEvent]; //DAQ
extern const vuint8 kXcpEventCycle[kXcpMaxEvent];
extern const vuint8 kXcpEventUnit[kXcpMaxEvent];
extern const char kXcpEventName[kXcpMaxEvent][7];
extern const vuint8 kXcpEventNameLength[kXcpMaxEvent];
#endif /* XCP_XCPAPPINTERFACE_H_ */
+139
View File
@@ -0,0 +1,139 @@
/*
* XcpApplnterface.c
*
* Created on: 30.07.2022
* Author: flori
*/
/****************************************************************************/
#include "XcpBasic.h"
#include "XcpFrameReceiver.h"
#include "XcpDriverCom.h"
#include "XcpAppInterface.h"
/****************************************************************************/
#define XCPFRAME_BUFFERSIZE 5 /* x frames are sufficient */
/****************************************************************************/
const vuint8 kXcpEventDirection[kXcpMaxEvent] = { 4, 4, 4, 4 }; //DAQ
const vuint8 kXcpEventCycle[kXcpMaxEvent] = { 1, 1, 5, 1 };
const vuint8 kXcpEventUnit[kXcpMaxEvent] = { 7, 8, 8, 9 };
const char kXcpEventName[kXcpMaxEvent][7] = { {"10ms "}, {"100ms "}, {"500ms "}, {"1000ms"}};
const vuint8 kXcpEventNameLength[kXcpMaxEvent] = { 4, 5, 5, 6 };
/****************************************************************************/
static XcpFrame tlComXcpRxPackets[XCPFRAME_BUFFERSIZE];
static XcpFrameReceiver xcpFrameReceiver( tlComXcpRxPackets, XCPFRAME_BUFFERSIZE, false );
#define XCP_SEND_BUFFER_SIZE 10u
static XcpFrame sendBuffer[XCP_SEND_BUFFER_SIZE];
static vuint16 xcpSendBufWritePos = 0;
static vuint16 xcpSendBufReadPos = 0;
/****************************************************************************/
/**
*
*/
void XcpPoll()
{
/* receive message */
if (XCP_COM_AVAILABLE())
{
while (XCP_COM_AVAILABLE())
{
uint8_t serData = XCP_COM_READ();
if (xcpFrameReceiver.hasSpace())
{
xcpFrameReceiver.putData(1, &serData);
}
if (xcpFrameReceiver.hasFrames())
{
XcpFrame *pFrame = xcpFrameReceiver.getFrame();
XcpCommand(pFrame->data.u32);
break;
}
}
}
}
/**
*
*/
void ApplXcpSend( uint8_t len, MEMORY_ROM BYTEPTR msg )
{
uint8_t iBuf = 0;
sendBuffer[xcpSendBufWritePos].data.u8[iBuf++] = XcpFrameReceiver::ESCBYTE;
sendBuffer[xcpSendBufWritePos].data.u8[iBuf++] = len;
for (uint8_t iMsg = 0; iMsg<len; iMsg++ )
{
sendBuffer[xcpSendBufWritePos].data.u8[iBuf++] = msg[iMsg];
}
sendBuffer[xcpSendBufWritePos].len = iBuf;
if (++xcpSendBufWritePos >= XCP_SEND_BUFFER_SIZE)
{
xcpSendBufWritePos = 0u;
}
XcpSendCallBack();
}
/**
* send max one frame from buffer
*/
void XcpSendLoop()
{
#define SEND_MAX_FRAMES_PER_CALL 3u
for (uint8_t i=0; i<SEND_MAX_FRAMES_PER_CALL; i++)
{
if (xcpSendBufReadPos != xcpSendBufWritePos)
{
Serial.write(sendBuffer[xcpSendBufReadPos].data.u8, sendBuffer[xcpSendBufReadPos].len);
if (++xcpSendBufReadPos >= XCP_SEND_BUFFER_SIZE)
{
xcpSendBufReadPos = 0u;
}
}
}
}
/**
*
*/
MTABYTEPTR ApplXcpGetPointer( uint8_t addr_ext, uint32_t addr )
{
//return (MTABYTEPTR)&kXcpEventName;
return (MTABYTEPTR)(addr + 0*addr_ext);
}
/**
*
*/
void ApplXcpInterruptEnable()
{
//interrupts();
}
/**
*
*/
void ApplXcpInterruptDisable()
{
//noInterrupts();
}
/**
*
*/
uint16_t ApplXcpGetTimestamp(void)
{
return (uint16_t) millis();
}
+3742
View File
File diff suppressed because it is too large Load Diff
+2368
View File
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
/*
* XcpDriverCom.h
*
* Created on: 30.07.2022
* Author: flori
*/
#ifndef XCPDRIVERCOM_H_
#define XCPDRIVERCOM_H_
#define XCP_COM_AVAILABLE() Serial.available()
#define XCP_COM_READ() Serial.read()
#define XCP_COM_WRITE_BYTE(b) Serial.write(b)
#endif /* XCPDRIVERCOM_H_ */
+18
View File
@@ -0,0 +1,18 @@
#ifndef XCPFRAME_H
#define XCPFRAME_H
#include "Arduino.h"
#define DTOBUF_PACKETSIZE 16u /* packet size in bytes */
class XcpFrame
{
public:
uint16_t len;
union{
uint32_t u32[DTOBUF_PACKETSIZE/4u];
uint8_t u8[DTOBUF_PACKETSIZE];
} data; /* the xcp driver needs uint32 aligned data */
};
#endif
+146
View File
@@ -0,0 +1,146 @@
#include "XcpFrameReceiver.h"
template class RingBuffer<XcpFrame>;
/**
* XcpFrameReceiver : protocol class to decode frame data with SOF byte and
* byte stuffing (with preceding escape byte). A valid frame must be transmitted
* like this:
* SOF len(LSB) len(MSB) cs(LSB) cs(MSB) data0 data1 ..
*
* len: uint16 , number of data bytes
* cs : uint16 , checksum (sum over all data bytes)
*
* if there is any escape byte or SOF byte inside the len, cs, or data field
* it must be transmitted with a preceding escape byte (this does not affect the
* len or cs itself).
*
* Usage:
* 1. initialize with existing array
* 2. call hasSpace, putData to write and decode the received data and
* store it into the given array
* 3. call hasFrames, getFrame to get the decoded frames
*
*/
/*
* constructor: Init everything
* \param : frameArray : pointer to first element of frame array
* arraySize : number of elements inside the array
*
*/
XcpFrameReceiver::XcpFrameReceiver(XcpFrame *frameArray, uint32_t arraySize, bool useChecksum )
{
ringBuffer = new RingBuffer<XcpFrame>(frameArray, arraySize);
state = NONE_XCP_DATA;
frameLen = 0;
frameCount = 0;
iFrameData = 0;
pWriteFrame = NULL;
numProtocolErrors = 0;
}
/**
* return false if the underlying buffer has no space left
*/
bool XcpFrameReceiver::hasSpace(void)
{
return ringBuffer->canWrite();
}
/**
* return true if there are readable elements in the underlying buffer
*/
bool XcpFrameReceiver::hasFrames(void)
{
return ringBuffer->canRead();
}
/**
* get the available number of frames that have not been read yet
*/
uint32_t XcpFrameReceiver::getNumberFrames(void)
{
return ringBuffer->getNumberUnread();
}
/**
* return the frame that was received next and yet not read.
* -> call only once per receive frame (increments the index)
*/
XcpFrame *XcpFrameReceiver::getFrame(void)
{
return ringBuffer->getReadPointer();
}
/** check canWrite before putting new data ! */
void XcpFrameReceiver::putData(uint32_t lenData, uint8_t * data)
{
uint32_t i;
pWriteFrame = ringBuffer->getWritePointer();
i = 0;
while (i<lenData)
{
/* data must be processed byte by byte because SOF/ESC bytes need to be detected */
if ( NULL == pWriteFrame )
{
/* pWriteFrame might become NULL in processing function */
break; //while loop
}
else
{
processByte(data[i]);
}
i++;
} //while (i<lenData)
}
/**
*
*/
void XcpFrameReceiver::processByte(uint8_t byte)
{
switch ( state)
{
case NONE_XCP_DATA:
if (byte == ESCBYTE)
{
state = ESCAPED;
}
else
{
//std::cout << byte << std::flush;
}
break;
case ESCAPED:
if (byte == ESCBYTE)
{
//std::cout << byte << std::flush;
state = NONE_XCP_DATA;
}
else
{
frameLen = byte;
iFrameData = 0u;
state = XCP_DATA;
}
break;
case XCP_DATA:
pWriteFrame->data.u8[iFrameData++] = byte;
if (iFrameData == frameLen)
{
pWriteFrame->len = frameLen;
ringBuffer->write();
state = NONE_XCP_DATA;
}
break;
}
}
+61
View File
@@ -0,0 +1,61 @@
#ifndef XCPFRAMERECEIVER_H
#define XCPFRAMERECEIVER_H
#include "RingBuffer.h"
#include "XcpFrame.h"
class XcpFrameReceiver
{
public :
static const uint8_t ESCBYTE = 0xFF;
/*
* constructor: Init everything
*/
XcpFrameReceiver(XcpFrame *frameArray, uint32_t arraySize, bool useChecksum = true);
/**
* return false if the back buffer has no space left
*/
bool hasSpace(void);
/**
* return true if there are readable frames in the back buffer
*/
bool hasFrames(void);
/**
* get the available number of frames that have not been read yet
*/
uint32_t getNumberFrames(void);
/**
* return the frame that was received next and yet not read.
*/
XcpFrame *getFrame(void);
/** check canWrite before putting new data ! */
void putData(uint32_t lenData, uint8_t * data);
private :
uint32_t frameCount; /** counter for every XCP ethernet frame to be compared with received counter */
class RingBuffer<XcpFrame> *ringBuffer;
XcpFrame* pWriteFrame;
uint16_t iFrameData; /* temporary index for received Xcp Frame data */
uint8_t frameLen;
uint32_t numProtocolErrors;
enum receiveState { NONE_XCP_DATA, ESCAPED, XCP_DATA } state;
/**
* destuff escape bytes, detect start of frame, forward data bytes
*/
void processByte(uint8_t byte);
};
#endif
+18
View File
@@ -0,0 +1,18 @@
/*
* XcpPort.h
*
* Created on: 30.07.2022
* Author: flori
*/
#ifndef XCP_XCPPORT_H_
#define XCP_XCPPORT_H_
#include "xcp_typedefs.h"
vuint8 XcpEvent( vuint8 event );
extern void XcpInit( void );
extern void XcpPoll();
extern void XcpSendLoop();
#endif /* XCP_XCPPORT_H_ */
+140
View File
@@ -0,0 +1,140 @@
/* -----------------------------------------------------------------------------
C O P Y R I G H T
-------------------------------------------------------------------------------
Copyright (c) 2001-2006 by Vector Informatik GmbH. All rights reserved.
This software is copyright protected and proprietary to Vector Informatik
GmbH.
Vector Informatik GmbH grants to you only those rights as set out in the
license conditions.
All other rights remain with Vector Informatik GmbH.
-------------------------------------------------------------------------------
----------------------------------------------------------------------------- */
#if !defined(__XCP_CFG_H__)
#define __XCP_CFG_H__
#undef EXTERN
/* */
/* CPU */
#define C_CPUTYPE_LITTLEENDIAN
#define XCP_ENABLE_CANAPE_5_5_X_SUPPORT //nur fuer EVENT_TIME_UNIT bei GET_DAQ_EVENT_INFO
/* General settings */
#define XCP_ENABLE_PARAMETER_CHECK
#define XCP_ENABLE_SEND_EVENT
#define XCP_DISABLE_TESTMODE
#define XCP_DISABLE_BOOTLOADER_DOWNLOAD
#define XCP_DISABLE_WRITE_PROTECTION
#define XCP_DISABLE_READ_PROTECTION
#define XCP_ENABLE_CONTROL
#define XCP_DISABLE_GET_XCP_DATA_POINTER
#define XCP_DISABLE_OPENCMDIF
#define XCP_ENABLE_MEM_MAPPING
#define XCP_DISABLE_VERSION_INFO_API
/* */
/* EEPROM access */
#define XCP_DISABLE_READ_EEPROM
#define XCP_DISABLE_WRITE_EEPROM
/* */
/* Service request message */
#define XCP_DISABLE_SERV_TEXT
#define XCP_DISABLE_SERV_TEXT_PUTCHAR
#define XCP_DISABLE_SERV_TEXT_PRINTF
/* */
/* Standard commands */
#define XCP_ENABLE_COMM_MODE_INFO
#define XCP_DISABLE_SEED_KEY
#define XCP_ENABLE_MODIFY_BITS
#define XCP_ENABLE_SHORT_DOWNLOAD
#define XCP_DISABLE_USER_COMMAND
#define XCP_DISABLE_VECTOR_MAPNAMES
#define XCP_ENABLE_TL_COMMAND
/* */
/* Block transfer */
#define XCP_ENABLE_BLOCK_UPLOAD
#define XCP_ENABLE_BLOCK_DOWNLOAD
/* */
/* Checksum */
#define XCP_DISABLE_CHECKSUM
#define XCP_DISABLE_AUTOSAR_CRC_MODULE
#define kXcpChecksumMethod XCP_CHECKSUM_TYPE_ADD12
#define kXcpChecksumBlockSize 0
/* */
/* Synchronous Data Acquisition (DAQ) */
#define XCP_ENABLE_DAQ
#define kXcpDaqMemSize 256
#define XCP_DISABLE_STIM
#define XCP_DISABLE_UNALIGNED_MEM_ACCESS
#define XCP_ENABLE_SEND_DIRECT
#define XCP_DISABLE_SEND_QUEUE
#define kXcpStimOdtCount 0x04u
#define XCP_ENABLE_DAQ_PRESCALER
#define XCP_ENABLE_DAQ_OVERRUN_INDICATION
#define XCP_ENABLE_WRITE_DAQ_MULTIPLE
#undef XCP_ENABLE_DAQ_HDR_ODT_DAQ
#undef XCP_ALLIGN_WORD
#undef XCP_ENABLE_ODT_SIZE_WORD
#define XCP_ENABLE_DAQ_RESUME
#define XCP_ENABLE_DAQ_PROCESSOR_INFO
#define XCP_ENABLE_DAQ_RESOLUTION_INFO
/* */
// CALIBRATION
#define XCP_ENABLE_CALIBRATION
/* Events */
#define XCP_ENABLE_DAQ_EVENT_INFO
#define kXcpMaxEvent 4
/* */
/* DAQ Timestamp */
#define XCP_ENABLE_DAQ_TIMESTAMP
#define XCP_ENABLE_DAQ_TIMESTAMP_FIXED
#define kXcpDaqTimestampUnit DAQ_TIMESTAMP_UNIT_1MS
#define kXcpDaqTimestampTicksPerUnit 1
#define kXcpDaqTimestampSize DAQ_TIMESTAMP_WORD
/* */
/* Page switching */
#undef XCP_DISABLE_CALIBRATION_PAGE
#define kXcpMaxSegment 1
#undef XCP_ENABLE_PAGE_INFO
#define kXcpMaxPages 2
#define XCP_DISABLE_PAGE_COPY
#define XCP_DISABLE_PAGE_FREEZE
/* */
/* Programming */
#define XCP_DISABLE_PROGRAM
#define kXcpProgramMinStPgm 0
#define kXcpProgramMaxSector 1
#define XCP_DISABLE_PROGRAM_INFO
/* */
#define CP_XCPDLL_VERSION 0x0209u
#define CP_XCPDLL_RELEASE_VERSION 0x00u
#define XCP_SEND_QUEUE_SAMPLE_ODT
//#define XCP_TRANSPORT_LAYER_TYPE_FLEXRAY_ASR
//#define XCP_TRANSPORT_LAYER_TYPE_CAN
/* begin Fileversion check */
#ifndef SKIP_MAGIC_NUMBER
#ifdef MAGIC_NUMBER
#if MAGIC_NUMBER != 2124540520
#error "The magic number of the generated file <D:\USR\_PROJECTS\Audi\EE-82\D4_MJ09_FR\E50_Verification\XCPonFlexRay\zTsi_XcpOnFlexRay\V85x\GHS\StandardECU_TTXSWV01.12.02\_Demo\DemoXcp\schedule\xcp_cfg.h> is different. Please check time and date of generated files!"
#endif
#else
#define MAGIC_NUMBER 2124540520
#endif /* MAGIC_NUMBER */
#endif /* SKIP_MAGIC_NUMBER */
/* end Fileversion check */
#endif /* __XCP_CFG_H__ */
+172
View File
@@ -0,0 +1,172 @@
/*----------------------------------------------------------------------------
| File:
| XCP_DEF.H
|
| Project:
| XCP samples
|
| Description
| XCP default settings
| Don't change this file
|
----------------------------------------------------------------------------*/
#if defined ( __XCP_DEF_H__ )
#else
#define __XCP_DEF_H__
#ifdef VAR_DEF
#define EXTERN
#else
#define EXTERN extern
#endif
/*------------------------------------------------------------------------------------*/
/* Default settings */
/* XCP transport layer */
#if !defined(XCP_TRANSPORT_LAYER_VERSION)
#define XCP_TRANSPORT_LAYER_VERSION 0x0100
#endif
#undef EXTERN
#define GRANULARITY_ODT_ENTRY_SIZE_ODT 1
/* ROM memory qualifiers */
#if !defined(MEMORY_ROM)
#define MEMORY_ROM const
#endif
#if !defined(V_MEMROM0)
#define V_MEMROM0
#endif
#if !defined(MEMORY_CONST)
#define MEMORY_CONST
#endif
/* Alignment requirements */
/* Specify, whether the microcontroller allows unaligned memory access or not */
#if !defined(XCP_ENABLE_UNALIGNED_MEM_ACCESS) && !defined(XCP_DISABLE_UNALIGNED_MEM_ACCESS)
#define XCP_DISABLE_UNALIGNED_MEM_ACCESS
#endif
/* General settings */
#if !defined(XCP_ENABLE_PARAMETER_CHECK) && !defined(XCP_DISABLE_PARAMETER_CHECK)
#define XCP_DISABLE_PARAMETER_CHECK
#endif
#if !defined(XCP_ENABLE_COMM_MODE_INFO) && !defined(XCP_DISABLE_COMM_MODE_INFO)
#define XCP_ENABLE_COMM_MODE_INFO
#endif
#if !defined(XCP_ENABLE_USER_COMMAND) && !defined(XCP_DISABLE_USER_COMMAND)
#define XCP_DISABLE_USER_COMMAND
#endif
/* Block transfer */
#if !defined(XCP_ENABLE_BLOCK_UPLOAD) && !defined(XCP_DISABLE_BLOCK_UPLOAD)
#define XCP_DISABLE_BLOCK_UPLOAD
#endif
#if !defined(XCP_ENABLE_BLOCK_DOWNLOAD) && !defined(XCP_DISABLE_BLOCK_DOWNLOAD)
#define XCP_DISABLE_BLOCK_DOWNLOAD
#endif
/* Enable transmission of event messages */
#if !defined(XCP_ENABLE_SEND_EVENT) && !defined(XCP_DISABLE_SEND_EVENT)
#define XCP_DISABLE_SEND_EVENT
#endif
/* Service request message */
#if !defined(XCP_ENABLE_SERV_TEXT) && !defined(XCP_DISABLE_SERV_TEXT)
#define XCP_DISABLE_SERV_TEXT
#endif
#if !defined(XCP_ENABLE_SERV_TEXT_PUTCHAR) && !defined(XCP_DISABLE_SERV_TEXT_PUTCHAR)
#define XCP_DISABLE_SERV_TEXT_PUTCHAR
#endif
#if !defined(XCP_ENABLE_SERV_TEXT_PRINTF) && !defined(XCP_DISABLE_SERV_TEXT_PRINTF)
#define XCP_DISABLE_SERV_TEXT_PRINTF
#endif
/* Disable/Enable Interrupts */
/* Has to be defined only if xcpSendCallBack may interrupt xcpEvent */
#if !defined(XcpInterruptDisable)
#define XcpInterruptDisable()
#endif
#if !defined(XcpInterruptEnable)
#define XcpInterruptEnable()
#endif
/* Custom initialization not needed */
#if !defined(ApplXcpInit)
#define ApplXcpInit()
#endif
/* Custom background processing not needed */
#if !defined(ApplXcpBackground)
#define ApplXcpBackground()
#endif
/* Flush of transmit queue not needed */
#if !defined(ApplXcpSendFlush)
#define ApplXcpSendFlush()
#endif
/* XCP page switching */
#if !defined ( XCP_ENABLE_CALIBRATION_PAGE ) && !defined ( XCP_DISABLE_CALIBRATION_PAGE )
#define XCP_DISABLE_CALIBRATION_PAGE
#endif
/* XCP protocol data acquisition parameters (DAQ) */
#if defined(XCP_DISABLE_DAQ)
#define XCP_DISABLE_SEND_QUEUE
#define XCP_ENABLE_SEND_DIRECT
#else
#if !defined(XCP_ENABLE_DAQ) && !defined(XCP_DISABLE_DAQ)
#define XCP_ENABLE_DAQ
#endif
#if !defined(XCP_ENABLE_SEND_DIRECT) && !defined(XCP_ENABLE_SEND_QUEUE)
#define XCP_ENABLE_SEND_QUEUE
#define XCP_DISABLE_SEND_DIRECT
#endif
#if defined(XCP_ENABLE_SEND_QUEUE)
#define XCP_DISABLE_SEND_DIRECT
#endif
#if !defined(XCP_ENABLE_DAQ_HDR_ODT_DAQ) && !defined(XCP_DISABLE_DAQ_HDR_ODT_DAQ)
#define XCP_DISABLE_DAQ_HDR_ODT_DAQ
#endif
#if !defined(kXcpDaqMemSize)
#define kXcpDaqMemSize 256
#endif
#if !defined(kXcpStiOdtCount)
#define kXcpStiOdtCount 1
#endif
#if !defined(XCP_ENABLE_DAQ_PROCESSOR_INFO) && !defined(XCP_DISABLE_DAQ_PROCESSOR_INFO)
#define XCP_ENABLE_DAQ_PROCESSOR_INFO
#endif
#if !defined(XCP_ENABLE_DAQ_RESOLUTION_INFO) && !defined(XCP_DISABLE_DAQ_RESOLUTION_INFO)
#define XCP_ENABLE_DAQ_RESOLUTION_INFO
#endif
#if !defined(XCP_ENABLE_DAQ_PRESCALER) && !defined(XCP_DISABLE_DAQ_PRESCALER)
#define XCP_DISABLE_DAQ_PRESCALER
#endif
#if !defined(XCP_ENABLE_DAQ_OVERRUN_INDICATION) && !defined(XCP_DISABLE_DAQ_OVERRUN_INDICATION)
#define XCP_ENABLE_DAQ_OVERRUN_INDICATION
#endif
#if !defined(XCP_ENABLE_DAQ_RESUME) && !defined(XCP_DISABLE_DAQ_RESUME)
#define XCP_DISABLE_DAQ_RESUME
#endif
#if !defined(XCP_ENABLE_DAQ_TIMESTAMP) && !defined(XCP_DISABLE_DAQ_TIMESTAMP)
#define XCP_DISABLE_DAQ_TIMESTAMP
#endif
#if !defined(XCP_ENABLE_DAQ_EVENT_INFO) && !defined(XCP_DISABLE_DAQ_EVENT_INFO)
#define XCP_DISABLE_DAQ_EVENT_INFO
#endif
#endif
#if !defined(XCP_ENABLE_STIM) && !defined(XCP_DISABLE_STIM)
#define XCP_DISABLE_STIM
#endif
#endif
+37
View File
@@ -0,0 +1,37 @@
/*****************************************************************************
| Project Name: XCP Protocol Layer
| File Name: xcp_par.c
|
| Description: Implementation of the XCP Protocol Layer
| XCP V1.0 slave device driver
| Basic Version (see feature list below)
|
|
|
|-----------------------------------------------------------------------------
| C O P Y R I G H T
|-----------------------------------------------------------------------------
| Copyright (c) 2008 by Vector Informatik GmbH. All rights reserved.
|
| This software is copyright protected and
| proporietary to Vector Informatik GmbH.
| Vector Informatik GmbH grants to you only
| those rights as set out in the license conditions.
| All other rights remain with Vector Informatik GmbH.
|
| Diese Software ist urheberrechtlich geschuetzt.
| Vector Informatik GmbH raeumt Ihnen an dieser Software nur
| die in den Lizenzbedingungen ausdruecklich genannten Rechte ein.
| Alle anderen Rechte verbleiben bei Vector Informatik GmbH.
|
|***************************************************************************/
#include "XcpBasic.h"
// Slave device id
#if defined ( kXcpStationIdLength )
V_MEMROM0 MEMORY_ROM vuint8 kXcpStationId[kXcpStationIdLength] = kXcpStationIdString;
#endif
+41
View File
@@ -0,0 +1,41 @@
/*****************************************************************************
| Project Name: XCP Protocol Layer
| File Name: xcp_par.h
|
| Description: Header of XCP Protocol Layer
| XCP V1.0 slave device driver
| Basic Version
|
||
|-----------------------------------------------------------------------------
| C O P Y R I G H T
|-----------------------------------------------------------------------------
| Copyright (c) 2008 by Vector Informatik GmbH. All rights reserved.
|
| This software is copyright protected and
| proporietary to Vector Informatik GmbH.
| Vector Informatik GmbH grants to you only
| those rights as set out in the license conditions.
| All other rights remain with Vector Informatik GmbH.
|
| Diese Software ist urheberrechtlich geschuetzt.
| Vector Informatik GmbH raeumt Ihnen an dieser Software nur
| die in den Lizenzbedingungen ausdruecklich genannten Rechte ein.
| Alle anderen Rechte verbleiben bei Vector Informatik GmbH.
|
|
|***************************************************************************/
#if defined ( __XCP_PAR_H__ )
#else
#define __XCP_PAR_H__
/* XCP default settings */
#include "xcp_def.h"
V_MEMROM0 extern vuint8 MEMORY_ROM kXcpStationId[];
#endif
+10
View File
@@ -0,0 +1,10 @@
#ifndef XCP_TYPEDEFS_H
#define XCP_TYPEDEFS_H
#include "Arduino.h"
typedef uint32_t vuint32;
typedef uint16_t vuint16;
typedef uint8_t vuint8;
#endif
+11
View File
@@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html