From e7034a81694b8b3784478855b25cb5dfd1a906f4 Mon Sep 17 00:00:00 2001 From: Adminius Date: Tue, 15 Mar 2022 21:20:11 +0100 Subject: [PATCH] version 0.4.0 --- ALEDD1.ino | 54 +- KONNEKTING_ALEDD1.kdevice.xml | 16 +- aledd1.h | 19 +- button.h | 9 +- fakeEEPROM.h | 208 --- hsvrgb.h | 3 + led_functions.h | 8 +- readme.md | 2 - src/KonnektingDeviceLibrary/ArrayList.h | 141 -- src/KonnektingDeviceLibrary/DebugUtil.cpp | 112 -- src/KonnektingDeviceLibrary/DebugUtil.h | 84 - src/KonnektingDeviceLibrary/KnxComObject.cpp | 176 -- src/KonnektingDeviceLibrary/KnxComObject.h | 249 --- .../KnxDataPointTypes.h | 450 ------ src/KonnektingDeviceLibrary/KnxDevice.cpp | 619 ------- src/KonnektingDeviceLibrary/KnxDevice.h | 259 --- src/KonnektingDeviceLibrary/KnxDptConstants.h | 36 - src/KonnektingDeviceLibrary/KnxTelegram.cpp | 185 --- src/KonnektingDeviceLibrary/KnxTelegram.h | 301 ---- src/KonnektingDeviceLibrary/KnxTpUart.cpp | 637 -------- src/KonnektingDeviceLibrary/KnxTpUart.h | 369 ----- .../KonnektingDevice.cpp | 1193 -------------- .../KonnektingDevice.h | 239 --- src/KonnektingDeviceLibrary/RingBuff.h | 96 -- virtualEEPROM.h | 1440 +++++++++++++++++ 25 files changed, 1508 insertions(+), 5397 deletions(-) delete mode 100644 fakeEEPROM.h delete mode 100644 src/KonnektingDeviceLibrary/ArrayList.h delete mode 100644 src/KonnektingDeviceLibrary/DebugUtil.cpp delete mode 100644 src/KonnektingDeviceLibrary/DebugUtil.h delete mode 100644 src/KonnektingDeviceLibrary/KnxComObject.cpp delete mode 100644 src/KonnektingDeviceLibrary/KnxComObject.h delete mode 100644 src/KonnektingDeviceLibrary/KnxDataPointTypes.h delete mode 100644 src/KonnektingDeviceLibrary/KnxDevice.cpp delete mode 100644 src/KonnektingDeviceLibrary/KnxDevice.h delete mode 100644 src/KonnektingDeviceLibrary/KnxDptConstants.h delete mode 100644 src/KonnektingDeviceLibrary/KnxTelegram.cpp delete mode 100644 src/KonnektingDeviceLibrary/KnxTelegram.h delete mode 100644 src/KonnektingDeviceLibrary/KnxTpUart.cpp delete mode 100644 src/KonnektingDeviceLibrary/KnxTpUart.h delete mode 100644 src/KonnektingDeviceLibrary/KonnektingDevice.cpp delete mode 100644 src/KonnektingDeviceLibrary/KonnektingDevice.h delete mode 100644 src/KonnektingDeviceLibrary/RingBuff.h create mode 100644 virtualEEPROM.h diff --git a/ALEDD1.ino b/ALEDD1.ino index 2b75f59..c53122f 100644 --- a/ALEDD1.ino +++ b/ALEDD1.ino @@ -1,42 +1,48 @@ /* --------------------------------------------------------------------------------------------- ALEDD 0.4.0 beta (work in progress) Hardware/Firmware/Sketch/kdevice.xml by E.Burkowski / e.burkowski@konnekting.de, GPL Licensed -Compatible with: KONNEKTING Device Library 1.0.0 beta 4b +Compatible with: KONNEKTING Device Library 1.0.0 RC1 */ +//Board: Arduino Zero (Native USB Port) (Core Version 1.8.11) + /* this libraries are required (click on link and download with library manager): -FlashStorage: http://librarymanager/All#FlashStorage -DimmerControl: http://librarymanager/All#DimmerControl -Adafruit Neopixel: http://librarymanager/All#Adafruit_Neopixel -Adafruit_ZeroDMA: http://librarymanager/All#Zero_DMA -Adafruit Neopixel ZeroDMA 1.0.8: http://librarymanager/All#Adafruit_DMA_neopixel_library -NeoPixel Painter: http://librarymanager/All#NeoPixel_Painter -KONNEKTING Device Library: http://librarymanager/All#Konnekting +KonnektingFlashStorage 1.0.1: http://librarymanager/All#KonnektingFlashStorage //do not install other FlashStorage library! +DimmerControl 1.2.0: http://librarymanager/All#DimmerControl +Adafruit Neopixel 1.10.0: http://librarymanager/All#Adafruit_Neopixel +Adafruit Zero DMA Library 1.1.0: http://librarymanager/All#Zero_DMA +Adafruit DMA neopixel library 1.2.3: http://librarymanager/All#Adafruit_DMA_neopixel_library +NeoPixel Painter 1.0.0: http://librarymanager/All#NeoPixel_Painter +KONNEKTING Device Library 1.0.0-RC1: http://librarymanager/All#Konnekting_device */ //developer settings //#define DEVELOPMENT -//#define FAKE_EEPROM //don't use this ;) -//#define KDEBUG // comment this line to disable DEBUG mode + + + +//#define VIRTUAL_EEPROM //don't use this ;) +#define KDEBUG // comment this line to disable DEBUG mode #include #include #include #include - -#include "src/KonnektingDeviceLibrary/KonnektingDevice.h" +#include #include "aledd1.h" #include "kdevice_ALEDD1.h" #include "defines.h" #ifdef KDEBUG -#include "src/KonnektingDeviceLibrary/DebugUtil.h" +#include #endif -#ifdef FAKE_EEPROM -#include "fakeEEPROM.h" +#ifdef VIRTUAL_EEPROM +#include "virtualEEPROM.h" +#else +Flash(my_eeprom_storage, 2048); #endif //global variables @@ -156,7 +162,7 @@ HSV brushcolor; DimmerControl dimmer; //make functions known -void showPixels (); +void showPixels(); #include "hsvrgb.h" #include "animations.h" @@ -166,6 +172,7 @@ void showPixels (); #include "button.h" #include "knx_events.h" + void setup() { pinMode(PROG_LED_PIN, OUTPUT); pinMode(PROG_BUTTON_PIN, INPUT_PULLUP); @@ -174,21 +181,26 @@ void setup() { #ifdef KDEBUG SerialUSB.begin(115200); - while (!SerialUSB); + while (!SerialUSB); Debug.setPrintStream(&SerialUSB); #endif -#ifdef FAKE_EEPROM - initFakeEeprom(); +#ifdef VIRTUAL_EEPROM + initVirtualEeprom(); +#else + EEPROM.setStorage(&my_eeprom_storage); #endif Konnekting.setMemoryReadFunc(&readMemory); Konnekting.setMemoryWriteFunc(&writeMemory); Konnekting.setMemoryUpdateFunc(&updateMemory); Konnekting.setMemoryCommitFunc(&commitMemory); +#ifndef DEVELOPMENT + Konnekting.setPrepareSerialFunc(&prepareSerial); +#endif Konnekting.init(SerialKNX, &progLed, MANUFACTURER_ID, DEVICE_ID, REVISION); -#ifndef FAKE_EEPROM - for (int i = 0; i < Konnekting.getFreeEepromOffset(); i++) { +#ifndef VIRTUAL_EEPROM + for (int i = 0; i < Konnekting.getMemoryUserSpaceStart(); i++) { Debug.println(F("\t\twriteMemory(%d,0x%02X);"), i, EEPROM.read(i)); } #endif diff --git a/KONNEKTING_ALEDD1.kdevice.xml b/KONNEKTING_ALEDD1.kdevice.xml index bdf7cb4..48078c4 100644 --- a/KONNEKTING_ALEDD1.kdevice.xml +++ b/KONNEKTING_ALEDD1.kdevice.xml @@ -1,6 +1,6 @@ - + KONNEKTING ALEDD1 @@ -493,12 +493,12 @@ 43 - - + + @@ -509,17 +509,17 @@ - + - + - + - + --> diff --git a/aledd1.h b/aledd1.h index 19fdffc..5235d4b 100644 --- a/aledd1.h +++ b/aledd1.h @@ -1,10 +1,13 @@ #ifndef DEVELOPMENT //ALEDD + +#include "wiring_private.h" //for pinPeripheral + //create a new Serial on Pins 1=TX and 3=RX Uart SerialKNX (&sercom2, 3, 1, SERCOM_RX_PAD_1, UART_TX_PAD_2); //+pinPeripheral //Interrupt handler for SerialKNX void SERCOM2_Handler() { - SerialKNX.IrqHandler(); + SerialKNX.IrqHandler(); } //Hardware settings @@ -14,6 +17,16 @@ void SERCOM2_Handler() #define POWER_SUPPLY_PIN 38 //active low #define EEPROM_EMULATION_SIZE 2048 +// custom serial port preparation function +void prepareSerial(){ + Debug.println(F("Prepare serial")); + SerialKNX.begin(19200, SERIAL_8E1); + pinPeripheral(3, PIO_SERCOM_ALT); + pinPeripheral(1, PIO_SERCOM_ALT); + Debug.println(F("Prepare serial *DONE*")); +} + + #else //test board //Hardware settings #define PROG_BUTTON_PIN 7 //active low @@ -21,12 +34,12 @@ void SERCOM2_Handler() #define LED_STRIP_PIN 6 //LED shield #define POWER_SUPPLY_PIN 8 //active low #define EEPROM_EMULATION_SIZE 2048 -#define SerialKNX Serial +#define SerialKNX Serial1 #endif -#ifndef FAKE_EEPROM +#ifndef VIRTUAL_EEPROM byte readMemory(int index) { Debug.println(F("FLASH read on index %d"),index); return EEPROM.read(index); diff --git a/button.h b/button.h index 2926ce1..7c3f20c 100644 --- a/button.h +++ b/button.h @@ -4,11 +4,10 @@ void taskOnShortClick(){ //if already programmed, show LED settings if(!Konnekting.isFactorySetting() && !ledTestMode){ - if(Konnekting.isProgState()) - showProgrammedLeds(); - else - neopixels->clear(); - neopixels->show(); + neopixels->clear(); + neopixels->show(); + if(Konnekting.isProgState()) showProgrammedLeds(); + } Debug.println(F("free ram: %d bytes"), Debug.freeRam()); } diff --git a/fakeEEPROM.h b/fakeEEPROM.h deleted file mode 100644 index e8e5979..0000000 --- a/fakeEEPROM.h +++ /dev/null @@ -1,208 +0,0 @@ -#ifdef FAKE_EEPROM -byte virtualEEPROM[256]; - -byte readMemory(int index){ - return virtualEEPROM[index]; -} - -void writeMemory(int index, byte val) { - virtualEEPROM[index] = val; -} - -void updateMemory(int index, byte val) { - if (readMemory(index) != val) { - writeMemory(index, val); - } -} - -void commitMemory() { - -} - -void initFakeEeprom(){ - writeMemory(0,0xFF); - writeMemory(1,0xFF); - writeMemory(2,0xFF); - writeMemory(3,0xFF); - writeMemory(4,0xFF); - writeMemory(5,0xFF); - writeMemory(6,0xFF); - writeMemory(7,0xFF); - writeMemory(8,0xFF); - writeMemory(9,0xFF); - writeMemory(10,0xFF); - writeMemory(11,0xFF); - writeMemory(12,0xFF); - writeMemory(13,0xFF); - writeMemory(14,0xFF); - writeMemory(15,0xFF); - writeMemory(16,0xFF); - writeMemory(17,0xFF); - writeMemory(18,0xFF); - writeMemory(19,0xFF); - writeMemory(20,0xFF); - writeMemory(21,0xFF); - writeMemory(22,0xFF); - writeMemory(23,0xFF); - writeMemory(24,0xFF); - writeMemory(25,0xFF); - writeMemory(26,0xFF); - writeMemory(27,0xFF); - writeMemory(28,0xFF); - writeMemory(29,0xFF); - writeMemory(30,0xFF); - writeMemory(31,0xFF); - writeMemory(32,0xFF); - writeMemory(33,0xFF); - writeMemory(34,0xFF); - writeMemory(35,0xFF); - writeMemory(36,0xFF); - writeMemory(37,0xFF); - writeMemory(38,0xFF); - writeMemory(39,0xFF); - writeMemory(40,0xFF); - writeMemory(41,0xFF); - writeMemory(42,0xFF); - writeMemory(43,0xFF); - writeMemory(44,0xFF); - writeMemory(45,0xFF); - writeMemory(46,0xFF); - writeMemory(47,0xFF); - writeMemory(48,0xFF); - writeMemory(49,0xFF); - writeMemory(50,0xFF); - writeMemory(51,0xFF); - writeMemory(52,0xFF); - writeMemory(53,0xFF); - writeMemory(54,0xFF); - writeMemory(55,0xFF); - writeMemory(56,0xFF); - writeMemory(57,0xFF); - writeMemory(58,0xFF); - writeMemory(59,0xFF); - writeMemory(60,0xFF); - writeMemory(61,0xFF); - writeMemory(62,0xFF); - writeMemory(63,0xFF); - writeMemory(64,0xFF); - writeMemory(65,0xFF); - writeMemory(66,0xFF); - writeMemory(67,0xFF); - writeMemory(68,0xFF); - writeMemory(69,0xFF); - writeMemory(70,0xFF); - writeMemory(71,0xFF); - writeMemory(72,0xFF); - writeMemory(73,0xFF); - writeMemory(74,0xFF); - writeMemory(75,0xFF); - writeMemory(76,0xFF); - writeMemory(77,0xFF); - writeMemory(78,0xFF); - writeMemory(79,0xFF); - writeMemory(80,0xFF); - writeMemory(81,0xFF); - writeMemory(82,0xFF); - writeMemory(83,0xFF); - writeMemory(84,0xFF); - writeMemory(85,0xFF); - writeMemory(86,0xFF); - writeMemory(87,0xFF); - writeMemory(88,0xFF); - writeMemory(89,0xFF); - writeMemory(90,0xFF); - writeMemory(91,0xFF); - writeMemory(92,0xFF); - writeMemory(93,0xFF); - writeMemory(94,0xFF); - writeMemory(95,0xFF); - writeMemory(96,0xFF); - writeMemory(97,0xFF); - writeMemory(98,0xFF); - writeMemory(99,0xFF); - writeMemory(100,0xFF); - writeMemory(101,0xFF); - writeMemory(102,0xFF); - writeMemory(103,0xFF); - writeMemory(104,0xFF); - writeMemory(105,0xFF); - writeMemory(106,0xFF); - writeMemory(107,0xFF); - writeMemory(108,0xFF); - writeMemory(109,0xFF); - writeMemory(110,0xFF); - writeMemory(111,0xFF); - writeMemory(112,0xFF); - writeMemory(113,0xFF); - writeMemory(114,0xFF); - writeMemory(115,0xFF); - writeMemory(116,0xFF); - writeMemory(117,0xFF); - writeMemory(118,0xFF); - writeMemory(119,0xFF); - writeMemory(120,0xFF); - writeMemory(121,0xFF); - writeMemory(122,0xFF); - writeMemory(123,0xFF); - writeMemory(124,0xFF); - writeMemory(125,0xFF); - writeMemory(126,0xFF); - writeMemory(127,0xFF); - writeMemory(128,0xFF); - writeMemory(129,0xFF); - writeMemory(130,0xFF); - writeMemory(131,0xFF); - writeMemory(132,0xFF); - writeMemory(133,0xFF); - writeMemory(134,0xFF); - writeMemory(135,0xFF); - writeMemory(136,0xFF); - writeMemory(137,0xFF); - writeMemory(138,0xFF); - writeMemory(139,0xFF); - writeMemory(140,0xFF); - writeMemory(141,0xFF); - writeMemory(142,0xFF); - writeMemory(143,0xFF); - writeMemory(144,0xFF); - writeMemory(145,0xFF); - writeMemory(146,0xFF); - writeMemory(147,0xFF); - writeMemory(148,0xFF); - writeMemory(149,0xFF); - writeMemory(150,0xFF); - writeMemory(151,0xFF); - writeMemory(152,0xFF); - writeMemory(153,0xFF); - writeMemory(154,0xFF); - writeMemory(155,0xFF); - writeMemory(156,0xFF); - writeMemory(157,0xFF); - writeMemory(158,0xFF); - writeMemory(159,0xFF); - writeMemory(160,0xFF); - writeMemory(161,0xFF); - writeMemory(162,0xFF); - writeMemory(163,0xFF); - writeMemory(164,0xFF); - writeMemory(165,0xFF); - writeMemory(166,0xFF); - writeMemory(167,0xFF); - writeMemory(168,0xFF); - writeMemory(169,0xFF); - writeMemory(170,0xFF); - writeMemory(171,0xFF); - writeMemory(172,0xFF); - writeMemory(173,0xFF); - writeMemory(174,0xFF); - writeMemory(175,0xFF); - writeMemory(176,0xFF); - writeMemory(177,0xFF); - writeMemory(178,0xFF); - writeMemory(179,0xFF); - writeMemory(180,0xFF); - writeMemory(181,0xFF); - writeMemory(182,0xFF); - writeMemory(183,0xFF); -} -#endif diff --git a/hsvrgb.h b/hsvrgb.h index 1aa6b40..f988c12 100644 --- a/hsvrgb.h +++ b/hsvrgb.h @@ -1,3 +1,6 @@ +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) + void hsvToRgb(byte h, byte s, byte v, byte rgbColor[]){ if(s){ byte i = h / 43; diff --git a/led_functions.h b/led_functions.h index 7501951..f34c5ae 100644 --- a/led_functions.h +++ b/led_functions.h @@ -45,9 +45,9 @@ void testStrip(){ if(neopixels) delete neopixels; neopixels = new Adafruit_NeoPixel_ZeroDMA(600, LED_STRIP_PIN, NEO_RGBW); #ifdef DEVELPMENT - neopixels->begin(&sercom5, SERCOM5, SERCOM5_DMAC_ID_TX, 6, 7, A5, SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0, PIO_SERCOM); + neopixels->begin(&sercom5, SERCOM5, SERCOM5_DMAC_ID_TX, 6, SPI_PAD_2_SCK_3, PIO_SERCOM); #else - neopixels->begin(&sercom4, SERCOM4, SERCOM4_DMAC_ID_TX, 22, 23, 24, SPI_PAD_0_SCK_3, SERCOM_RX_PAD_2, PIO_SERCOM_ALT); + neopixels->begin(&sercom4, SERCOM4, SERCOM4_DMAC_ID_TX, 22, SPI_PAD_0_SCK_3, PIO_SERCOM_ALT); #endif neopixels->setPixelColor(0, 255 , 0, 0, 0); neopixels->setPixelColor(1, 0, 255, 0, 0); @@ -87,9 +87,9 @@ void initStrip(word pixel, byte type){ pixelbrush3 = new NeoPixelPainterBrush(pixelcanvas); pixelbrush4on2 = new NeoPixelPainterBrush(pixelcanvas2); #ifdef DEVELPMENT - neopixels->begin(&sercom5, SERCOM5, SERCOM5_DMAC_ID_TX, 6, 7, A5, SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0, PIO_SERCOM); + neopixels->begin(&sercom5, SERCOM5, SERCOM5_DMAC_ID_TX, 6, SPI_PAD_2_SCK_3, PIO_SERCOM); #else - neopixels->begin(&sercom4, SERCOM4, SERCOM4_DMAC_ID_TX, 22, 23, 24, SPI_PAD_0_SCK_3, SERCOM_RX_PAD_2, PIO_SERCOM_ALT); + neopixels->begin(&sercom4, SERCOM4, SERCOM4_DMAC_ID_TX, 22, SPI_PAD_0_SCK_3, PIO_SERCOM_ALT); #endif neopixels->show(); Debug.println(F("initPixel")); diff --git a/readme.md b/readme.md index 5a9fc18..306527a 100644 --- a/readme.md +++ b/readme.md @@ -5,8 +5,6 @@ Use releases only: [https://github.com/KONNEKTING/ALEDD1/releases](https://githu This firmware requires external libraries, all of them can be installed via Arduino IDE library manager. Please check comment in [ALEDD1.ino](https://github.com/KONNEKTING/ALEDD1/blob/master/ALEDD1.ino#L7-L15) -at the moment a special version of KONNEKTING Device Library is required (but it is included). - not all features are implemented. Pull-requests are welcome :) diff --git a/src/KonnektingDeviceLibrary/ArrayList.h b/src/KonnektingDeviceLibrary/ArrayList.h deleted file mode 100644 index 8373547..0000000 --- a/src/KonnektingDeviceLibrary/ArrayList.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// File : ArrayList.h -// Initial Author : Alexander Christian -// Description : Generic array list for simple numeric types like word, int, ... -// Module dependencies : none -#ifndef ArrayList_h -#define ArrayList_h - -#include "Arduino.h" - -// https://de.wikibooks.org/wiki/C%2B%2B-Programmierung/_Templates/_Klassentemplates -// https://stackoverflow.com/questions/8752837/undefined-reference-to-template-class-constructor -template class ArrayList { - public: - - ArrayList(void) { - this->size = 0; - } - - ~ArrayList(void) { - free(list); - } - - void addItem(T* item) { - T **newlist = (T**)malloc((size + 1) * sizeof(T*)); - - if (size > 0) { - // umkopieren - for (int i = 0; i < size; i++) { - newlist[i] = list[i]; - } - } - - // insert new value - newlist[size] = item; - if (list != NULL) { - free(list); // free memory of old list - } - list = newlist; // replace free'd list with newlist - size = size + 1; - } - - bool removeItem(int index) { - // if there is nothing to remove, just return - if (size == 0 || index > size) { - return false; - } - - // check if we are about to clear the list --> reach size=0 after this removal - if (size == 1) { - clearList(); - return true; - } - - // we did not yet reach size=0, so we need to shring the array by creatingnew array - T **newlist = (T**)malloc((size - 1) * sizeof(T*)); - - //From Begining - for (int i = 0; i < index; i++) { - newlist[i] = list[i]; - } - //From next Index - for (int i = index; i <= size - 1; i++) { - newlist[i] = list[i + 1]; - } - - - free(list); // free memory of old list - list = newlist; // replace free'd list with newlist - - size = size - 1; - return true; - } - - bool setItem(int index, T* item) { - if (size == 0 || index > size) { - return false; - } - list[index] = item; - return true; - } - - bool getItem(int index, T* item) { - if (size == 0 || index > size) { - return false; - } - item = this->list[index]; - return true; - } - - void clearList() { - size = 0; - free(list); // free memory of old list - list = NULL; - } - - void setList(T** list) { - free(this->list); - this->list = list; - } - - T** getList() { - return list; - } - - int getSize() { - return size; - } - - void logList() { - char charVal[20]; - for (int i = 0; i < size; i++) { - sprintf(charVal, fmt, i, list[i]); - Serial.println(charVal); - } - } - - private: - const char* fmt = "[%i] 0x%08X"; - T** list; - int size; -}; - -#endif diff --git a/src/KonnektingDeviceLibrary/DebugUtil.cpp b/src/KonnektingDeviceLibrary/DebugUtil.cpp deleted file mode 100644 index 15c4bec..0000000 --- a/src/KonnektingDeviceLibrary/DebugUtil.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include "DebugUtil.h" -#include "wiring_private.h" - -#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_STM32) - extern "C" char* sbrk(int incr); - extern char *__brkval; -#endif - -// DebugUtil unique instance creation -DebugUtil DebugUtil::Debug; -DebugUtil& Debug = DebugUtil::Debug; - -/* - * Format Help: - * http://www.cplusplus.com/reference/cstdio/printf/ - * - * %i = signed decimal integer - * %u = unsigned decimal integer - * %x = hex - * %X = upper case hex - * %s = string - * %c = character - * 0x%02x = hex representation like 0xff - * %% = % symbol - */ -DebugUtil::DebugUtil() { -} - -void DebugUtil::setPrintStream(Stream* printstream) { - _printstream = printstream; - print(F("DEBUG! free ram: %d bytes \n"), freeRam()); -} - -int DebugUtil::freeRam() { -#if defined(ESP8266) || defined(ESP32) - return ESP.getFreeHeap(); -#elif defined(ARDUINO_ARCH_AVR) - extern int __heap_start, *__brkval; - int v; - return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval); -#elif defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_STM32) - char top; - return &top - reinterpret_cast(sbrk(0)); -#else - return -1; -#endif -} - -void DebugUtil::print(const char *format, ...) { - if (_printstream) { - char buf[128]; // limit to 128chars - va_list args; - va_start(args, format); - vsnprintf(buf, 128, format, args); - va_end(args); - _printstream->print(buf); - } - -} - -void DebugUtil::print(const __FlashStringHelper *format, ...) { - if (_printstream) { - char buf[128]; // limit to 128chars - va_list args; - va_start(args, format); - -#if defined(__AVR__) || defined(ESP8266) || defined(ARDUINO_ARCH_STM32) - vsnprintf_P(buf, sizeof (buf), (const char *) format, args); // progmem for AVR and ESP8266 -#else - vsnprintf(buf, sizeof (buf), (const char *) format, args); // for rest of the world -#endif - va_end(args); - //Serial.print(buf);) - _printstream->print(buf); - } -} - -void DebugUtil::println(const char *format, ...) { - if (_printstream) { - - char buf[128]; // limit to 128chars - va_list args; - va_start(args, format); - vsnprintf(buf, 128, format, args); - va_end(args); - //Serial.println(buf);) - _printstream->println(buf); - } -} - -void DebugUtil::println(const __FlashStringHelper *format, ...) { - if (_printstream) { - - char buf[128]; // limit to 128chars - va_list args; - va_start(args, format); - -#if defined(__AVR__) || defined(ESP8266) || defined(ARDUINO_ARCH_STM32) - vsnprintf_P(buf, sizeof (buf), (const char *) format, args); // progmem for AVR and ESP8266 -#else - vsnprintf(buf, sizeof (buf), (const char *) format, args); // for rest of the world -#endif - - va_end(args); - //Serial.println(buf);) - _printstream->println(buf); - } -} - - - - diff --git a/src/KonnektingDeviceLibrary/DebugUtil.h b/src/KonnektingDeviceLibrary/DebugUtil.h deleted file mode 100644 index 9d19e10..0000000 --- a/src/KonnektingDeviceLibrary/DebugUtil.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * This file is part of KONNEKTING Device Library. - * - * The KONNEKTING Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -// File : KonnektingDebug.h -// Author: Alexander Christian -// Description : project debug, inspired by https://github.com/Naguissa/DebugUtils - -#ifndef DEBUGUTIL_H -#define DEBUGUTIL_H - - -#include -#ifdef ARDUINO_ARCH_SAMD -#include "stdarg.h" -#endif - -#define DEBUG - -#ifdef DEBUG - #define DEBUG_PRINT(...) Debug.print(__VA_ARGS__); - #define DEBUG_PRINTLN(...) Debug.println(__VA_ARGS__); -#else - #define DEBUG_PRINT(...) - #define DEBUG_PRINTLN(...) -#endif - -#define BYTETOBINARYPATTERN "%d%d%d%d%d%d%d%d" -#define BYTETOBINARY(byte) \ - ((byte & 0x80) ? 1 : 0), \ - ((byte & 0x40) ? 1 : 0), \ - ((byte & 0x20) ? 1 : 0), \ - ((byte & 0x10) ? 1 : 0), \ - ((byte & 0x08) ? 1 : 0), \ - ((byte & 0x04) ? 1 : 0), \ - ((byte & 0x02) ? 1 : 0), \ - ((byte & 0x01) ? 1 : 0) - - -class DebugUtil { - - // Constructor, Destructor - DebugUtil(); // private constructor (singleton design pattern) - - ~DebugUtil() { - } // private destructor (singleton design pattern) - DebugUtil(DebugUtil&); // private copy constructor (singleton design pattern) - -private: - Print* _printstream; - -public: - static DebugUtil Debug; - - void setPrintStream(Stream* printstream); - - int freeRam(); - - void print(const char *format, ...); - void print(const __FlashStringHelper *format, ...); - void println(const char *format, ...); - void println(const __FlashStringHelper *format, ...); - - -}; - -// Reference to the KnxDevice unique instance -extern DebugUtil& Debug; - -#endif // DEBUGUTIL_H diff --git a/src/KonnektingDeviceLibrary/KnxComObject.cpp b/src/KonnektingDeviceLibrary/KnxComObject.cpp deleted file mode 100644 index 4fb2ad3..0000000 --- a/src/KonnektingDeviceLibrary/KnxComObject.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * It is derived from another GPLv3 licensed project: - * The Arduino Knx Bus Device library allows to turn Arduino into "self-made" KNX bus device. - * Copyright (C) 2014 2015 Franck MARINI (fm@liwan.fr) - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * Handling of the KNX Communication Objects - * @author Alexander Christian - * @depends KnxTelegram - */ - -#include "DebugUtil.h" -#include "KnxComObject.h" - -/** - * Calculates telegram data length based on DPT - * @param dptId - * @return length in bytes - */ -byte calcLength(KnxDpt dptId) { - return (pgm_read_byte(&KnxDptFormatToLength[ pgm_read_byte(&KnxDptToFormat[dptId])]) / 8) + 1; -} - -/** - * Contructor - * @param dptId - * @param indicator - */ -KnxComObject::KnxComObject(KnxDpt dptId, byte indicator) -: _dptId(dptId), _indicator(indicator), _dataLength(calcLength(dptId)) { - - _active = false; - - if (_indicator & KNX_COM_OBJ_I_INDICATOR) { - // Object with "InitRead" indicator - _validated = false; - } else { - // any other typed object - _validated = true; - } - - if (_dataLength <= 2) { - _longValue = NULL; - } else { - // long value case - _longValue = (byte *) malloc(_dataLength - 1); - for (byte i = 0; i < _dataLength - 1; i++) { - _longValue[i] = 0; - } - } - -} - -/** - * Destructor - */ -KnxComObject::~KnxComObject() { - if (_dataLength > 2) { - free(_longValue); - } -} - -/** - * TODO document me - * @return - */ -bool KnxComObject::isActive() { - return _active; -} - -/** - * TODO document me - * @param flag - */ -void KnxComObject::setActive(bool flag) { - _active = flag; -} - -/** - * Get the com obj value - * Ensure 'value' is sizeOf data-length - * @param value - */ -void KnxComObject::getValue(byte value[]) const { - if (_dataLength <= 2) { - value[0] = _value; // short value case, ReadValue(void) fct should rather be used - } else { - for (byte i = 0; i < _dataLength - 1; i++) { - value[i] = _longValue[i]; // long value case - } - } -} - -/** - * Update comobj value by raw byte[] - * @param other - */ -void KnxComObject::updateValue(const byte other[]) { - if (_dataLength <= 2) { - _value = other[0]; // short value case, UpdateValue(byte) fct should rather be used - } else { - for (byte i = 0; i < _dataLength - 1; i++) { - _longValue[i] = other[i]; // long value case - } - } - _validated = true; -} - -/** - * Update comobj value with payload from telegram - * @param other - * @return KNX_COM_OBJECT_ERROR or KNX_COM_OBJECT_OK - */ -byte KnxComObject::updateValue(const KnxTelegram& other) { - - if (other.GetPayloadLength() != getLength()) { - return KNX_COM_OBJECT_ERROR; // Error : telegram payload length differs from com obj one - } - - switch (_dataLength) { - case 1: - _value = other.GetFirstPayloadByte(); - break; - case 2: - other.GetLongPayload(&_value, 1); - break; - default: - other.GetLongPayload(_longValue, _dataLength - 1); - } - - _validated = true; // com object set to valid - return KNX_COM_OBJECT_OK; -} - -/** - * Copy comobj attributes into a telegram - * @param dest - */ -void KnxComObject::copyAttributes(KnxTelegram& dest) const { - dest.ChangePriority(getPriority()); - dest.SetTargetAddress(getAddr()); - dest.SetPayloadLength(_dataLength); -} - -/** - * Copy the comobj value into a telegram - * @param dest - */ -void KnxComObject::copyValue(KnxTelegram& dest) const { - switch (_dataLength) { - case 1: - dest.SetFirstPayloadByte(_value); - break; - case 2: - dest.SetLongPayload(&_value, 1); - break; - default: - dest.SetLongPayload(_longValue, _dataLength - 1); - } -} \ No newline at end of file diff --git a/src/KonnektingDeviceLibrary/KnxComObject.h b/src/KonnektingDeviceLibrary/KnxComObject.h deleted file mode 100644 index d0bb8c2..0000000 --- a/src/KonnektingDeviceLibrary/KnxComObject.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * It is derived from another GPLv3 licensed project: - * The Arduino Knx Bus Device library allows to turn Arduino into "self-made" KNX bus device. - * Copyright (C) 2014 2015 Franck MARINI (fm@liwan.fr) - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -// File : KnxComObject.h -// Author : Franck Marini -// Modified: Alexander Christian -// Description : Handling of the KNX Communication Objects -// Module dependencies : KnxTelegram - -#ifndef KNXCOMOBJECT_H -#define KNXCOMOBJECT_H - -#include "KnxTelegram.h" -#include "KnxDataPointTypes.h" - -// !!!!!!!!!!!!!!! FLAG OPTIONS !!!!!!!!!!!!!!!!! - -// Definition of comobject indicator values -// See "knx.org" for comobject indicators specification -// See: https://redaktion.knx-user-forum.de/lexikon/flags/ -// INDICATOR field : B7 B6 B5 B4 B3 B2 B1 B0 -// xx xx C R W T U I -// xx xx K L S Ü A I -#define KNX_COM_OBJ_C_INDICATOR 0x20 // Comuunication (C) -#define KNX_COM_OBJ_R_INDICATOR 0x10 // Read (R) -#define KNX_COM_OBJ_W_INDICATOR 0x08 // Write (W) -#define KNX_COM_OBJ_T_INDICATOR 0x04 // Transmit (T) -#define KNX_COM_OBJ_U_INDICATOR 0x02 // Update (U) -#define KNX_COM_OBJ_I_INDICATOR 0x01 // Init Read (I) - -// Definition of predefined com obj profiles -// Sensor profile : COM_OBJ_SENSOR -#define COM_OBJ_SENSOR KNX_COM_OBJ_C_R_T_INDICATOR -#define KNX_COM_OBJ_C_R_T_INDICATOR 0x34 // ( Communication | Read | Transmit ) - -// Logic input profile : COM_OBJ_LOGIC_IN -#define COM_OBJ_LOGIC_IN KNX_COM_OBJ_C_W_U_INDICATOR - -#define KNX_COM_OBJ_C_W_U_INDICATOR 0x2A // ( Communication | Write | Update ) -#define KNX_COM_OBJ_C_W_U_T_INDICATOR 0x2E // ( Communication | Write | Update | Transmit ) - -// Logic input to be initialized at bus power-up profile : COM_OBJ_LOGIC_IN_INIT -#define COM_OBJ_LOGIC_IN_INIT KNX_COM_OBJ_C_W_U_I_INDICATOR -#define KNX_COM_OBJ_C_W_U_I_INDICATOR 0x2B // ( Communication | Write | Update | Init) - -#define KNX_COM_OBJECT_OK 0 -#define KNX_COM_OBJECT_ERROR 255 - -class KnxComObject { - - /** - * true: CO can be used, false: CO is "offline" - */ - bool _active; - - /** - * Group Address value - */ - word _addr; - - /** - * DPT - */ - byte _dptId; - - /** - * C/R/W/T/U/I indicators - */ - byte _indicator; - - /** - * Com object data length is calculated in the same way as telegram payload length - * (See "knx.org" telegram specification for more details) - */ - byte _dataLength; - - /** - * _validated: used for "InitRead" typed comobjects: - * "false" until the object value is updated - * Other typed comobjects get "true" value immediately - */ - bool _validated; - - union { - // field used in case of short value (1 byte max width, i.e. length <= 2) - struct { - byte _value; - byte _notUSed; - }; - // field used in case of long value (2 bytes width or more, i.e. length > 2) - // The data space is allocated dynamically by the constructor - byte *_longValue; - }; - -public: - // Constructor : - KnxComObject(KnxDpt dptId, byte indicator); - - // Destructor - ~KnxComObject(); - - bool isActive(void); - void setActive(bool flag); - - // INLINED functions (see definitions later in this file) - word getAddr(void) const; - - /** - * Overwrite address value defined at construction - * The function is used in case of programming - * @param the GA to set - */ - void setAddr(word); - - byte getDptId(void) const; - - e_KnxPriority getPriority(void) const; - - byte getIndicator(void) const; - - bool getValidity(void) const; - - void setValidity(void); - - byte getLength(void) const; - - /** - * Return the com obj value (short value case only) - * @return - */ - byte getValue(void) const; - - /** - * Update the com obj value (short value case only) - * @param newVal - * @return ERROR if the com obj is long value (invalid use case), else return OK - */ - byte updateValue(byte newVal); - - /** - * Toggle the binary value (for com objs with "B1" format) - */ - void toggleValue(void); - - // functions NOT INLINED : - - /** - * Get the com obj value (short and long value cases) - * @param dest - */ - void getValue(byte dest[]) const; - - /** - * Update the com obj value (short and long value cases) - * @param ori - */ - void updateValue(const byte ori[]); - - /** - * Update the com obj value with a telegram payload content - * @param ori - * @return ERROR if the telegram payload length differs from com obj one, else return OK - */ - byte updateValue(const KnxTelegram& ori); - - /** - * Copy the com obj attributes (addr, prio, length) into a telegram object - * @param dest - */ - void copyAttributes(KnxTelegram& dest) const; - - /** - * Copy the com obj value into a telegram object - * @param dest - */ - void copyValue(KnxTelegram& dest) const; - -}; - - -// --------------- Definition of the INLINE functions ----------------- - -inline word KnxComObject::getAddr(void) const { - return _addr; -} - -inline void KnxComObject::setAddr(word addr) { - _addr = addr; -} - -inline byte KnxComObject::getDptId(void) const { - return _dptId; -} - -inline e_KnxPriority KnxComObject::getPriority(void) const { - return KNX_PRIORITY_NORMAL_VALUE; -} - -inline byte KnxComObject::getIndicator(void) const { - return _indicator; -} - -inline bool KnxComObject::getValidity(void) const { - return _validated; -} - -inline void KnxComObject::setValidity(void) { - _validated = true; -} - -inline byte KnxComObject::getLength(void) const { - return _dataLength; -} - -inline byte KnxComObject::getValue(void) const { - return _value; -} - -inline byte KnxComObject::updateValue(byte newValue) { - if (_dataLength > 2) return KNX_COM_OBJECT_ERROR; - _value = newValue; - _validated = true; - return KNX_COM_OBJECT_OK; -} - -inline void KnxComObject::toggleValue(void) { - _value = !_value; -} - -#endif // KNXCOMOBJECT_H diff --git a/src/KonnektingDeviceLibrary/KnxDataPointTypes.h b/src/KonnektingDeviceLibrary/KnxDataPointTypes.h deleted file mode 100644 index 83c9415..0000000 --- a/src/KonnektingDeviceLibrary/KnxDataPointTypes.h +++ /dev/null @@ -1,450 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * Definition of KNX Datapoints types - * - * @author Alexander Christian - * @author Eugen Burkowski - */ - -#ifndef KNXDATAPOINTTYPES_H -#define KNXDATAPOINTTYPES_H - -// DPT arrays are stored in flash using PROG MEMORY -#ifndef ESP8266 //ESP8266 does't need pgmspace.h -#ifdef ESP32 -#include //ESP32 -#else -#include //rest of the world -#endif -#endif - - -/** - * List of the DPT formats - * A Character - * A[n] String of n characters - * B Boolean / Bit set - * C Control - * E Exponent - * F Floating point value - * M Mantissa - * N eNumeration - * r Reserved bit or field - * S Sign - * U Unsigned value - * V 2's Complement signed value - * Z8 Standardised Status/Command B8. Encoding as in DPT_StatusGen - */ -enum KnxDPTFormat { - KNX_DPT_FORMAT_B1 = 0, - KNX_DPT_FORMAT_B2, - KNX_DPT_FORMAT_B1U3, - KNX_DPT_FORMAT_A8, - KNX_DPT_FORMAT_U8, - KNX_DPT_FORMAT_V8, - KNX_DPT_FORMAT_B5N3, - KNX_DPT_FORMAT_U16, - KNX_DPT_FORMAT_V16, - KNX_DPT_FORMAT_F16, - KNX_DPT_FORMAT_N3N5R2N6R2N6, - KNX_DPT_FORMAT_R3N5R4N4R1U7, - KNX_DPT_FORMAT_U32, - KNX_DPT_FORMAT_V32, - KNX_DPT_FORMAT_F32, - KNX_DPT_FORMAT_U4U4U4U4U4U4B4N4, - KNX_DPT_FORMAT_A112, - KNX_DPT_FORMAT_R2U6, - KNX_DPT_FORMAT_B1R1U6, - KNX_DPT_FORMAT_U8R4U4R3U5U3U5R2U6B16, - KNX_DPT_FORMAT_U8R4U4R3U5U3U5R2U6R2U6B16, - KNX_DPT_FORMAT_N8, - KNX_DPT_FORMAT_B8, - KNX_DPT_FORMAT_B16, - KNX_DPT_FORMAT_N2, - KNX_DPT_FORMAT_AN, - KNX_DPT_FORMAT_U4U4, - KNX_DPT_FORMAT_R1B1U6, - KNX_DPT_FORMAT_B32, - KNX_DPT_FORMAT_V64, - KNX_DPT_FORMAT_B24, - KNX_DPT_FORMAT_N3, - KNX_DPT_FORMAT_B1Z8, - KNX_DPT_FORMAT_N8Z8, - KNX_DPT_FORMAT_U8Z8, - KNX_DPT_FORMAT_U16Z8, - KNX_DPT_FORMAT_V8Z8, - KNX_DPT_FORMAT_V16Z8, - KNX_DPT_FORMAT_U16N8, - KNX_DPT_FORMAT_U8B8, - KNX_DPT_FORMAT_V16B8, - KNX_DPT_FORMAT_V16B16, - KNX_DPT_FORMAT_U8N8, - KNX_DPT_FORMAT_V16V16V16, - KNX_DPT_FORMAT_V16V16V16V16, - KNX_DPT_FORMAT_V16U8B8, - KNX_DPT_FORMAT_V16U8B16, - KNX_DPT_FORMAT_U16U8N8N8P8, - KNX_DPT_FORMAT_U5U5U16, - KNX_DPT_FORMAT_V32Z8, - KNX_DPT_FORMAT_U8N8N8N8B8B8, - KNX_DPT_FORMAT_U16V16, - KNX_DPT_FORMAT_N16U32, - KNX_DPT_FORMAT_F16F16F16, - KNX_DPT_FORMAT_V8N8N8, - KNX_DPT_FORMAT_V16V16N8N8, - KNX_DPT_FORMAT_U16U8, - KNX_DPT_FORMAT_V32N8Z8, - KNX_DPT_FORMAT_U16U32U8N8, - KNX_DPT_FORMAT_A8A8A8A8, - KNX_DPT_FORMAT_U8U8U8, - KNX_DPT_FORMAT_B4U16U16U8, - KNX_DPT_FORMAT_r12B4U8U8U8, - KNX_DPT_FORMAT_A8A8 -}; - -/** - * Definition of all available DPTs - */ -enum KnxDpt { - KNX_DPT_1_000 = 0, // 1.000 B1 general bool - KNX_DPT_1_001, // 1.001 B1 DPT_Switch - KNX_DPT_1_002, // 1.002 B1 DPT_Bool - KNX_DPT_1_003, // 1.003 B1 DPT_Enable - KNX_DPT_1_004, // 1.004 B1 DPT_Ramp - KNX_DPT_1_005, // 1.005 B1 DPT_Alarm - KNX_DPT_1_006, // 1.006 B1 DPT_BinaryValue - KNX_DPT_1_007, // 1.007 B1 DPT_Step - KNX_DPT_1_008, // 1.008 B1 DPT_UpDown - KNX_DPT_1_009, // 1.009 B1 DPT_OpenClose - KNX_DPT_1_010, // 1.010 B1 DPT_Start - KNX_DPT_1_011, // 1.011 B1 DPT_State - KNX_DPT_1_012, // 1.012 B1 DPT_Invert - KNX_DPT_1_013, // 1.013 B1 DPT_DimSendStyle - KNX_DPT_1_014, // 1.014 B1 DPT_InputSource - KNX_DPT_1_015, // 1.015 B1 DPT_Reset - KNX_DPT_1_016, // 1.016 B1 DPT_Ack - KNX_DPT_1_017, // 1.017 B1 DPT_Trigger - KNX_DPT_1_018, // 1.018 B1 DPT_Occupancy - KNX_DPT_1_019, // 1.019 B1 DPT_Window_Door - KNX_DPT_1_021, // 1.021 B1 DPT_LogicalFunction - KNX_DPT_1_022, // 1.022 B1 DPT_Scene_AB - KNX_DPT_1_023, // 1.023 B1 DPT_ShutterBlinds_Mode - KNX_DPT_1_100, // 1.100 B1 DPT_Heat/Cool - KNX_DPT_2_001, // 2.001 B2 DPT_Switch_Control - KNX_DPT_2_002, // 2.002 B2 DPT_Bool_Control - KNX_DPT_2_003, // 2.003 B2 DPT_Enable_Control - KNX_DPT_2_004, // 2.004 B2 DPT_Ramp_Control - KNX_DPT_2_005, // 2.005 B2 DPT_Alarm_Control - KNX_DPT_2_006, // 2.006 B2 DPT_BinaryValue_Control - KNX_DPT_2_007, // 2.007 B2 DPT_Step_Control - KNX_DPT_2_008, // 2.008 B2 DPT_Direction1_Control - KNX_DPT_2_009, // 2.009 B2 DPT_Direction2_Control - KNX_DPT_2_010, // 2.010 B2 DPT_Start_Control - KNX_DPT_2_011, // 2.011 B2 DPT_State_Control - KNX_DPT_2_012, // 2.012 B2 DPT_Invert_Control - KNX_DPT_3_007, // 3.007 B1U3 DPT_Control_Dimming - KNX_DPT_3_008, // 3.008 B1U3 DPT_Control_Blinds - KNX_DPT_4_001, // 4.001 A8 DPT_Char_ASCII - KNX_DPT_4_002, // 4.002 A8 DPT_Char_8859_1 - KNX_DPT_5_000, // 5.000 U8 general byte - KNX_DPT_5_001, // 5.001 U8 DPT_Scaling - KNX_DPT_5_003, // 5.003 U8 DPT_Angle - KNX_DPT_5_004, // 5.004 U8 DPT_Percent_U8 - KNX_DPT_5_005, // 5.005 U8 DPT_DecimalFactor - KNX_DPT_5_006, // 5.006 U8 DPT_Tariff - KNX_DPT_5_010, // 5.010 U8 DPT_Value_1_Ucount - KNX_DPT_6_001, // 6.001 V8 DPT_Percent_V8 - KNX_DPT_6_010, // 6.010 V8 DPT_Value_1_Count - KNX_DPT_6_020, // 6.020 B5N3 DPT_Status_Mode3 - KNX_DPT_7_000, // 7.001 U16 general unsigned integer - KNX_DPT_7_001, // 7.001 U16 DPT_Value_2_Ucount - KNX_DPT_7_002, // 7.002 U16 DPT_TimePeriodMsec - KNX_DPT_7_003, // 7.003 U16 DPT_TimePeriod10MSec - KNX_DPT_7_004, // 7.004 U16 DPT_TimePeriod100MSec - KNX_DPT_7_005, // 7.005 U16 DPT_TimePeriodSec - KNX_DPT_7_006, // 7.006 U16 DPT_TimePeriodMin - KNX_DPT_7_007, // 7.007 U16 DPT_TimePeriodHrs - KNX_DPT_7_010, // 7.010 U16 DPT_PropDataType - KNX_DPT_7_011, // 7.011 U16 DPT_Length_mm - KNX_DPT_7_012, // 7.012 U16 DPT_UElCurrentmA - KNX_DPT_7_013, // 7.013 U16 DPT_Brightness - KNX_DPT_7_600, // 7.600 U16 DPT_Colour_Temperature - KNX_DPT_8_000, // 8.000 V16 general integer - KNX_DPT_8_001, // 8.001 V16 DPT_Value_2_Count - KNX_DPT_8_002, // 8.002 V16 DPT_DeltaTimeMsec - KNX_DPT_8_003, // 8.003 V16 DPT_DeltaTime10MSec - KNX_DPT_8_004, // 8.004 V16 DPT_DeltaTime100MSec - KNX_DPT_8_005, // 8.005 V16 DPT_DeltaTimeSec - KNX_DPT_8_006, // 8.006 V16 DPT_DeltaTimeMin - KNX_DPT_8_007, // 8.007 V16 DPT_DeltaTimeHrs - KNX_DPT_8_010, // 8.010 V16 DPT_Percent_V16 - KNX_DPT_8_011, // 8.011 V16 DPT_Rotation_Angle - KNX_DPT_9_000, // 9.000 F16 general float - KNX_DPT_9_001, // 9.001 F16 DPT_Value_Temp - KNX_DPT_9_002, // 9.002 F16 DPT_Value_Tempd - KNX_DPT_9_003, // 9.003 F16 DPT_Value_Tempa - KNX_DPT_9_004, // 9.004 F16 DPT_Value_Lux - KNX_DPT_9_005, // 9.005 F16 DPT_Value_Wsp - KNX_DPT_9_006, // 9.006 F16 DPT_Value_Pres - KNX_DPT_9_007, // 9.007 F16 DPT_Value_Humidity - KNX_DPT_9_008, // 9.008 F16 DPT_Value_AirQuality - KNX_DPT_9_010, // 9.010 F16 DPT_Value_Time1 - KNX_DPT_9_011, // 9.011 F16 DPT_Value_Time2 - KNX_DPT_9_020, // 9.020 F16 DPT_Value_Volt - KNX_DPT_9_021, // 9.021 F16 DPT_Value_Curr - KNX_DPT_9_022, // 9.022 F16 DPT_PowerDensity - KNX_DPT_9_023, // 9.023 F16 DPT_KelvinPerPercent - KNX_DPT_9_024, // 9.024 F16 DPT_Power - KNX_DPT_9_025, // 9.025 F16 DPT_Value_Volume_Flow - KNX_DPT_9_026, // 9.026 F16 DPT_Rain_Amount - KNX_DPT_9_027, // 9.027 F16 DPT_Value_Temp_F - KNX_DPT_9_028, // 9.028 F16 DPT_Value_Wsp_kmh - KNX_DPT_10_001, // 10.001 N3N5r2N6r2N6 DPT_TimeOfDay - KNX_DPT_11_001, // 11.001 r3N5r4N4r1U7 DPT_Date - KNX_DPT_12_000, // 12.000 U32 general unsigned long - KNX_DPT_12_001, // 12.001 U32 DPT_Value_4_Ucount - KNX_DPT_13_000, // 13.000 V32 general long - KNX_DPT_13_001, // 13.001 V32 DPT_Value_4_Count - KNX_DPT_13_010, // 13.010 V32 DPT_ActiveEnergy - KNX_DPT_13_011, // 13.011 V32 DPT_ApparantEnergy - KNX_DPT_13_012, // 13.012 V32 DPT_ReactiveEnergy - KNX_DPT_13_013, // 13.013 V32 DPT_ActiveEnergy_kWh - KNX_DPT_13_014, // 13.014 V32 DPT_ApparantEnergy_kVAh - KNX_DPT_13_015, // 13.015 V32 DPT_ReactiveEnergy_kVARh - KNX_DPT_13_100, // 13.100 V32 DPT_LongDeltaTimeSec - KNX_DPT_14_000, // 14.000 F32 DPT_Value_Acceleration - KNX_DPT_14_001, // 14.001 F32 DPT_Value_Acceleration_Angular - KNX_DPT_14_002, // 14.002 F32 DPT_Value_Activation_Energy - KNX_DPT_14_003, // 14.003 F32 DPT_Value_Activity - KNX_DPT_14_004, // 14.004 F32 DPT_Value_Mol - KNX_DPT_14_005, // 14.005 F32 DPT_Value_Amplitude - KNX_DPT_14_006, // 14.006 F32 DPT_Value_AngleRad - KNX_DPT_14_007, // 14.007 F32 DPT_Value_AngleDeg - KNX_DPT_16_000, // 16.000 A112 DPT_String_ASCII - KNX_DPT_16_001, // 16.001 A112 DPT_String_8859_1 - KNX_DPT_17_001, // 17.001 r2U6 DPT_SceneNumber - KNX_DPT_19_001, // 19.001 U8R4U4R3U5U3U5R2U6R2U6B16 DPT_DateTime - KNX_DPT_232_600,// 232.600 U8U8U8 DPT_Colour_RGB - KNX_DPT_242_600,// 242.600 B4U16U16U8 DPT_Colour_xyY - KNX_DPT_251_600,// 251.600 r12B4U8U8U8 DPT_Colour_RGBW - KNX_DPT_60000_60000// 60000.60000 A112 DPT_KONNEKTING_PROGRAM -}; - -/** - * Mapping-Table: - * KnxDptFormat -> it's length in bits - */ -const byte KnxDptFormatToLength[] PROGMEM = { - 1 , // KNX_DPT_FORMAT_B1 = 0, - 2 , // KNX_DPT_FORMAT_B2, - 4 , // KNX_DPT_FORMAT_B1U3 - 8 , // KNX_DPT_FORMAT_A8, - 8 , // KNX_DPT_FORMAT_U8, - 8 , // KNX_DPT_FORMAT_V8, - 8 , // KNX_DPT_FORMAT_B5N3, - 16, // KNX_DPT_FORMAT_U16, - 16, // KNX_DPT_FORMAT_V16, - 16, // KNX_DPT_FORMAT_F16, - 24, // KNX_DPT_FORMAT_N3N5R2N6N2N6, - 24, // KNX_DPT_FORMAT_R3N5R4N4R1N7, - 32, // KNX_DPT_FORMAT_U32, - 32, // KNX_DPT_FORMAT_V32, - 32, // KNX_DPT_FORMAT_F32, - 32, // KNX_DPT_FORMAT_U4U4U4U4U4U4B4N4, - 112, // KNX_DPT_FORMAT_A112, - 8 , // KNX_DPT_FORMAT_R2U6, - 8 , // KNX_DPT_FORMAT_B1R1U6, - 56, // KNX_DPT_FORMAT_U8R4U4R3U5U3U5R2U6B16, - 64, // KNX_DPT_FORMAT_U8R4U4R3U5U3U5R2U6R2U6B16, - 8 , // KNX_DPT_FORMAT_N8, - 8 , // KNX_DPT_FORMAT_B8, - 16, // KNX_DPT_FORMAT_B16, - 2 , // KNX_DPT_FORMAT_N2, - 112, // KNX_DPT_FORMAT_AN, - 8 , // KNX_DPT_FORMAT_U4U4, - 8 , // KNX_DPT_FORMAT_R1B1U6, - 32, // KNX_DPT_FORMAT_B32, - 64, // KNX_DPT_FORMAT_V64, - 24, // KNX_DPT_FORMAT_B24, - 3 , // KNX_DPT_FORMAT_N3, - 2 , // KNX_DPT_FORMAT_B1Z8, - 16, // KNX_DPT_FORMAT_N8Z8, - 16, // KNX_DPT_FORMAT_U8Z8, - 24, // KNX_DPT_FORMAT_U16Z8, - 16, // KNX_DPT_FORMAT_V8Z8, - 24, // KNX_DPT_FORMAT_V16Z8, - 24, // KNX_DPT_FORMAT_U16N8, - 16, // KNX_DPT_FORMAT_U8B8, - 24, // KNX_DPT_FORMAT_V16B8, - 32, // KNX_DPT_FORMAT_V16B16, - 16, // KNX_DPT_FORMAT_U8N8, - 48, // KNX_DPT_FORMAT_V16V16V16, - 64, // KNX_DPT_FORMAT_V16V16V16V16, - 32, // KNX_DPT_FORMAT_V16U8B8, - 40, // KNX_DPT_FORMAT_V16U8B16, - 48, // KNX_DPT_FORMAT_U16U8N8N8P8, - 16, // KNX_DPT_FORMAT_U5U5U6, - 40, // KNX_DPT_FORMAT_V32Z8, - 48, // KNX_DPT_FORMAT_U8N8N8N8B8B8, - 32, // KNX_DPT_FORMAT_U16V16, - 48, // KNX_DPT_FORMAT_N16U32, - 48, // KNX_DPT_FORMAT_F16F16F16, - 24, // KNX_DPT_FORMAT_V8N8N8, - 48, // KNX_DPT_FORMAT_V16V16N8N8, - 24, // KNX_DPT_FORMAT_U16U8, - 48, // KNX_DPT_FORMAT_V32N8Z8, - 64, // KNX_DPT_FORMAT_U16U32U8N8, - 24, // KNX_DPT_FORMAT_A8A8A8A8, - 24, // KNX_DPT_FORMAT_U8U8U8, - 48, // KNX_DPT_FORMAT_B4U16U16U8, - 48, // KNX_DPT_FORMAT_r12B4U8U8U8, - 16 // KNX_DPT_FORMAT_A8A8 -}; - - -/** - * Mapping-Table: - * KnxDpt -> KNX DPT Format - */ -const byte KnxDptToFormat[] PROGMEM = { - KNX_DPT_FORMAT_B1, // KNX_DPT_1_000, // 1.000 B1 general bool - KNX_DPT_FORMAT_B1, // KNX_DPT_1_001, // 1.001 B1 DPT_Switch - KNX_DPT_FORMAT_B1, // KNX_DPT_1_002, // 1.002 B1 DPT_Bool - KNX_DPT_FORMAT_B1, // KNX_DPT_1_003, // 1.003 B1 DPT_Enable - KNX_DPT_FORMAT_B1, // KNX_DPT_1_004, // 1.004 B1 DPT_Ramp - KNX_DPT_FORMAT_B1, // KNX_DPT_1_005, // 1.005 B1 DPT_Alarm - KNX_DPT_FORMAT_B1, // KNX_DPT_1_006, // 1.006 B1 DPT_BinaryValue - KNX_DPT_FORMAT_B1, // KNX_DPT_1_007, // 1.007 B1 DPT_Step - KNX_DPT_FORMAT_B1, // KNX_DPT_1_008, // 1.008 B1 DPT_UpDown - KNX_DPT_FORMAT_B1, // KNX_DPT_1_009, // 1.009 B1 DPT_OpenClose - KNX_DPT_FORMAT_B1, // KNX_DPT_1_010, // 1.010 B1 DPT_Start - KNX_DPT_FORMAT_B1, // KNX_DPT_1_011, // 1.011 B1 DPT_State - KNX_DPT_FORMAT_B1, // KNX_DPT_1_012, // 1.012 B1 DPT_Invert - KNX_DPT_FORMAT_B1, // KNX_DPT_1_013, // 1.013 B1 DPT_DimSendStyle - KNX_DPT_FORMAT_B1, // KNX_DPT_1_014, // 1.014 B1 DPT_InputSource - KNX_DPT_FORMAT_B1, // KNX_DPT_1_015, // 1.015 B1 DPT_Reset - KNX_DPT_FORMAT_B1, // KNX_DPT_1_016, // 1.016 B1 DPT_Ack - KNX_DPT_FORMAT_B1, // KNX_DPT_1_017, // 1.017 B1 DPT_Trigger - KNX_DPT_FORMAT_B1, // KNX_DPT_1_018, // 1.018 B1 DPT_Occupancy - KNX_DPT_FORMAT_B1, // KNX_DPT_1_019, // 1.019 B1 DPT_Window_Door - KNX_DPT_FORMAT_B1, // KNX_DPT_1_021, // 1.021 B1 DPT_LogicalFunction - KNX_DPT_FORMAT_B1, // KNX_DPT_1_022, // 1.022 B1 DPT_Scene_AB - KNX_DPT_FORMAT_B1, // KNX_DPT_1_023, // 1.023 B1 DPT_ShutterBlinds_Mode - KNX_DPT_FORMAT_B1, // KNX_DPT_1_100, // 1.100 B1 DPT_Heat/Cool - KNX_DPT_FORMAT_B2, // KNX_DPT_2_001, // 2.001 B2 DPT_Switch_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_002, // 2.002 B2 DPT_Bool_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_003, // 2.003 B2 DPT_Enable_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_004, // 2.004 B2 DPT_Ramp_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_005, // 2.005 B2 DPT_Alarm_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_006, // 2.006 B2 DPT_BinaryValue_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_007, // 2.007 B2 DPT_Step_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_008, // 2.008 B2 DPT_Direction1_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_009, // 2.009 B2 DPT_Direction2_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_010, // 2.010 B2 DPT_Start_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_011, // 2.011 B2 DPT_State_Control - KNX_DPT_FORMAT_B2, // KNX_DPT_2_012, // 2.012 B2 DPT_Invert_Control - KNX_DPT_FORMAT_B1U3, // KNX_DPT_3_007, // 3.007 B1U3 DPT_Control_Dimming - KNX_DPT_FORMAT_B1U3, // KNX_DPT_3_008, // 3.008 B1U3 DPT_Control_Blinds - KNX_DPT_FORMAT_A8, // KNX_DPT_4_001, // 4.001 A8 DPT_Char_ASCII - KNX_DPT_FORMAT_A8, // KNX_DPT_4_002, // 4.002 A8 DPT_Char_8859_1 - KNX_DPT_FORMAT_U8, // KNX_DPT_5_000, // 5.000 U8 general byte - KNX_DPT_FORMAT_U8, // KNX_DPT_5_001, // 5.001 U8 DPT_Scaling - KNX_DPT_FORMAT_U8, // KNX_DPT_5_003, // 5.003 U8 DPT_Angle - KNX_DPT_FORMAT_U8, // KNX_DPT_5_004, // 5.004 U8 DPT_Percent_U8 - KNX_DPT_FORMAT_U8, // KNX_DPT_5_005, // 5.005 U8 DPT_DecimalFactor - KNX_DPT_FORMAT_U8, // KNX_DPT_5_006, // 5.006 U8 DPT_Tariff - KNX_DPT_FORMAT_U8, // KNX_DPT_5_010, // 5.010 U8 DPT_Value_1_Ucount - KNX_DPT_FORMAT_V8, // KNX_DPT_6_001, // 6.001 V8 DPT_Percent_V8 - KNX_DPT_FORMAT_V8, // KNX_DPT_6_010, // 6.010 V8 DPT_Value_1_Count - KNX_DPT_FORMAT_B5N3, // KNX_DPT_6_020, // 6.020 B5N3 DPT_Status_Mode3 - KNX_DPT_FORMAT_U16, // KNX_DPT_7_000, // 7.000 U16 general unsigned integer - KNX_DPT_FORMAT_U16, // KNX_DPT_7_001, // 7.001 U16 DPT_Value_2_Ucount - KNX_DPT_FORMAT_U16, // KNX_DPT_7_002, // 7.002 U16 DPT_TimePeriodMsec - KNX_DPT_FORMAT_U16, // KNX_DPT_7_003, // 7.003 U16 DPT_TimePeriod10MSec - KNX_DPT_FORMAT_U16, // KNX_DPT_7_004, // 7.004 U16 DPT_TimePeriod100MSec - KNX_DPT_FORMAT_U16, // KNX_DPT_7_005, // 7.005 U16 DPT_TimePeriodSec - KNX_DPT_FORMAT_U16, // KNX_DPT_7_006, // 7.006 U16 DPT_TimePeriodMin - KNX_DPT_FORMAT_U16, // KNX_DPT_7_007, // 7.007 U16 DPT_TimePeriodHrs - KNX_DPT_FORMAT_U16, // KNX_DPT_7_010, // 7.010 U16 DPT_PropDataType - KNX_DPT_FORMAT_U16, // KNX_DPT_7_011, // 7.011 U16 DPT_Length_mm - KNX_DPT_FORMAT_U16, // KNX_DPT_7_012, // 7.012 U16 DPT_UElCurrentmA - KNX_DPT_FORMAT_U16, // KNX_DPT_7_013, // 7.013 U16 DPT_Brightness - KNX_DPT_FORMAT_U16, // KNX_DPT_7_600, // 7.600 U16 DPT_Colour_Temperature - KNX_DPT_FORMAT_V16, // KNX_DPT_8_000, // 8.000 V16 general integer - KNX_DPT_FORMAT_V16, // KNX_DPT_8_001, // 8.001 V16 DPT_Value_2_Count - KNX_DPT_FORMAT_V16, // KNX_DPT_8_002, // 8.002 V16 DPT_DeltaTimeMsec - KNX_DPT_FORMAT_V16, // KNX_DPT_8_003, // 8.003 V16 DPT_DeltaTime10MSec - KNX_DPT_FORMAT_V16, // KNX_DPT_8_004, // 8.004 V16 DPT_DeltaTime100MSec - KNX_DPT_FORMAT_V16, // KNX_DPT_8_005, // 8.005 V16 DPT_DeltaTimeSec - KNX_DPT_FORMAT_V16, // KNX_DPT_8_006, // 8.006 V16 DPT_DeltaTimeMin - KNX_DPT_FORMAT_V16, // KNX_DPT_8_007, // 8.007 V16 DPT_DeltaTimeHrs - KNX_DPT_FORMAT_V16, // KNX_DPT_8_010, // 8.010 V16 DPT_Percent_V16 - KNX_DPT_FORMAT_V16, // KNX_DPT_8_011, // 8.011 V16 DPT_Rotation_Angle - KNX_DPT_FORMAT_F16, // KNX_DPT_9_000, // 9.000 F16 general float - KNX_DPT_FORMAT_F16, // KNX_DPT_9_001, // 9.001 F16 DPT_Value_Temp - KNX_DPT_FORMAT_F16, // KNX_DPT_9_002, // 9.002 F16 DPT_Value_Tempd - KNX_DPT_FORMAT_F16, // KNX_DPT_9_003, // 9.003 F16 DPT_Value_Tempa - KNX_DPT_FORMAT_F16, // KNX_DPT_9_004, // 9.004 F16 DPT_Value_Lux - KNX_DPT_FORMAT_F16, // KNX_DPT_9_005, // 9.005 F16 DPT_Value_Wsp - KNX_DPT_FORMAT_F16, // KNX_DPT_9_006, // 9.006 F16 DPT_Value_Pres - KNX_DPT_FORMAT_F16, // KNX_DPT_9_007, // 9.007 F16 DPT_Value_Humidity - KNX_DPT_FORMAT_F16, // KNX_DPT_9_008, // 9.008 F16 DPT_Value_AirQuality - KNX_DPT_FORMAT_F16, // KNX_DPT_9_010, // 9.010 F16 DPT_Value_Time1 - KNX_DPT_FORMAT_F16, // KNX_DPT_9_011, // 9.011 F16 DPT_Value_Time2 - KNX_DPT_FORMAT_F16, // KNX_DPT_9_020, // 9.020 F16 DPT_Value_Volt - KNX_DPT_FORMAT_F16, // KNX_DPT_9_021, // 9.021 F16 DPT_Value_Curr - KNX_DPT_FORMAT_F16, // KNX_DPT_9_022, // 9.022 F16 DPT_PowerDensity - KNX_DPT_FORMAT_F16, // KNX_DPT_9_023, // 9.023 F16 DPT_KelvinPerPercent - KNX_DPT_FORMAT_F16, // KNX_DPT_9_024, // 9.024 F16 DPT_Power - KNX_DPT_FORMAT_F16, // KNX_DPT_9_025, // 9.025 F16 DPT_Value_Volume_Flow - KNX_DPT_FORMAT_F16, // KNX_DPT_9_026, // 9.026 F16 DPT_Rain_Amount - KNX_DPT_FORMAT_F16, // KNX_DPT_9_027, // 9.027 F16 DPT_Value_Temp_F - KNX_DPT_FORMAT_F16, // KNX_DPT_9_028, // 9.028 F16 DPT_Value_Wsp_kmh - KNX_DPT_FORMAT_N3N5R2N6R2N6, // KNX_DPT_10_001, // 10.001 N3N5r2N6r2N6 DPT_TimeOfDay - KNX_DPT_FORMAT_R3N5R4N4R1U7, // KNX_DPT_11_001, // 11.001 r3N5r4N4r1U7 DPT_Date - KNX_DPT_FORMAT_U32, // KNX_DPT_12_000, // 12.000 U32 general unsigned long - KNX_DPT_FORMAT_U32, // KNX_DPT_12_001, // 12.001 U32 DPT_Value_4_Ucount - KNX_DPT_FORMAT_V32, // KNX_DPT_13_000, // 13.000 V32 general long - KNX_DPT_FORMAT_V32, // KNX_DPT_13_001, // 13.001 V32 DPT_Value_4_Count - KNX_DPT_FORMAT_V32, // KNX_DPT_13_010, // 13.010 V32 DPT_ActiveEnergy - KNX_DPT_FORMAT_V32, // KNX_DPT_13_011, // 13.011 V32 DPT_ApparantEnergy - KNX_DPT_FORMAT_V32, // KNX_DPT_13_012, // 13.012 V32 DPT_ReactiveEnergy - KNX_DPT_FORMAT_V32, // KNX_DPT_13_013, // 13.013 V32 DPT_ActiveEnergy_kWh - KNX_DPT_FORMAT_V32, // KNX_DPT_13_014, // 13.014 V32 DPT_ApparantEnergy_kVAh - KNX_DPT_FORMAT_V32, // KNX_DPT_13_015, // 13.015 V32 DPT_ReactiveEnergy_kVARh - KNX_DPT_FORMAT_V32, // KNX_DPT_13_100, // 13.100 V32 DPT_LongDeltaTimeSec - KNX_DPT_FORMAT_F32, // KNX_DPT_14_000, // 14.000 F32 DPT_Value_Acceleration - KNX_DPT_FORMAT_F32, // KNX_DPT_14_001, // 14.001 F32 DPT_Value_Acceleration_Angular - KNX_DPT_FORMAT_F32, // KNX_DPT_14_002, // 14.002 F32 DPT_Value_Activation_Energy - KNX_DPT_FORMAT_F32, // KNX_DPT_14_003, // 14.003 F32 DPT_Value_Activity - KNX_DPT_FORMAT_F32, // KNX_DPT_14_004, // 14.004 F32 DPT_Value_Mol - KNX_DPT_FORMAT_F32, // KNX_DPT_14_005, // 14.005 F32 DPT_Value_Amplitude - KNX_DPT_FORMAT_F32, // KNX_DPT_14_006, // 14.006 F32 DPT_Value_AngleRad - KNX_DPT_FORMAT_F32, // KNX_DPT_14_007, // 14.007 F32 DPT_Value_AngleDeg - KNX_DPT_FORMAT_A112,// KNX_DPT_16_000, // 16.000 A112 DPT_String_ASCII - KNX_DPT_FORMAT_A112,// KNX_DPT_16_001, // 16.001 A112 DPT_String_8859_1 - KNX_DPT_FORMAT_R2U6,// KNX_DPT_17_001, // 17.001 r2U6 DPT_SceneNumber - KNX_DPT_FORMAT_U8R4U4R3U5U3U5R2U6R2U6B16, //KNX_DPT_19_001, // 19.001 U8R4U4R3U5U3U5R2U6R2U6B16 DPT_DateTime - KNX_DPT_FORMAT_U8U8U8, //KNX_DPT_232_600,// 232.600 U8U8U8 DPT_Colour_RGB - KNX_DPT_FORMAT_B4U16U16U8, //KNX_DPT_242_600,// 242.600 B4U16U16U8 DPT_Colour_xyY - KNX_DPT_FORMAT_r12B4U8U8U8, //KNX_DPT_251_600,// 251.600 r12B4U8U8U8 DPT_Colour_RGBW - KNX_DPT_FORMAT_A112 // KNX_DPT_60000_60000// 60000.60000 A112 DPT_KONNEKTING_PROGRAM -}; - -#endif // KNXDATAPOINTTYPES_H diff --git a/src/KonnektingDeviceLibrary/KnxDevice.cpp b/src/KonnektingDeviceLibrary/KnxDevice.cpp deleted file mode 100644 index d809e04..0000000 --- a/src/KonnektingDeviceLibrary/KnxDevice.cpp +++ /dev/null @@ -1,619 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * It is derived from another GPLv3 licensed project: - * The Arduino Knx Bus Device library allows to turn Arduino into "self-made" KNX bus device. - * Copyright (C) 2014 2015 Franck MARINI (fm@liwan.fr) - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// File : KnxDevice.cpp -// Author : Franck Marini -// Modified: Alexander Christian -// Description : KnxDevice Abstraction Layer -// Module dependencies : HardwareSerial, KnxTelegram, KnxComObject, KnxTpUart, RingBuff - -#include "KnxDevice.h" -#include "KonnektingDevice.h" - -static inline word TimeDeltaWord(word now, word before) { - return (word) (now - before); -} - -// KnxDevice unique instance creation -KnxDevice KnxDevice::Knx; -KnxDevice& Knx = KnxDevice::Knx; - - -// Constructor - -KnxDevice::KnxDevice() { - _state = INIT; - _tpuart = NULL; - _txActionList = RingBuff(); - _initCompleted = false; - _initIndex = 0; - _rxTelegram = NULL; - //AC - _progComObj.setAddr(G_ADDR(15, 7, 255)); - _progComObj.setActive(true); -} - -int KnxDevice::getNumberOfComObjects() { - return _numberOfComObjects; -} - - -// Start the KNX Device -// return KNX_DEVICE_ERROR (255) if begin() failed -// else return KNX_DEVICE_OK - -e_KnxDeviceStatus KnxDevice::begin(HardwareSerial& serial, word physicalAddr) { - delete _tpuart; // always safe to delete null ptr - _tpuart = new KnxTpUart(serial, physicalAddr, NORMAL); - _rxTelegram = &_tpuart->GetReceivedTelegram(); - //delay(10000); // Workaround for init issue with bus-powered arduino - // the issue is reproduced on one (faulty?) TPUART device only, so remove it for the moment. - if (_tpuart->Reset() != KNX_TPUART_OK) { - delete(_tpuart); - _tpuart = NULL; - _rxTelegram = NULL; - DEBUG_PRINTLN(F("Init Error!")); - return KNX_DEVICE_INIT_ERROR; - } - _tpuart->AttachComObjectsList(_comObjectsList, _numberOfComObjects); - _tpuart->SetEvtCallback(&KnxDevice::GetTpUartEvents); - _tpuart->SetAckCallback(&KnxDevice::TxTelegramAck); - _tpuart->Init(); - _state = IDLE; - DEBUG_PRINTLN(F("Init successful")); - _lastInitTimeMillis = millis(); - _lastRXTimeMicros = micros(); - _lastTXTimeMicros = _lastRXTimeMicros; -#if defined(KNXDEVICE_DEBUG_INFO) - _nbOfInits = 0; -#endif - return KNX_DEVICE_OK; -} - - -// Stop the KNX Device -void KnxDevice::end() { - type_tx_action action; - - _state = INIT; - while (_txActionList.pop(action)); // empty ring buffer - _initCompleted = false; - _initIndex = 0; - _rxTelegram = NULL; - delete(_tpuart); - _tpuart = NULL; -} - - -/** - * KNX device execution task - * This function call shall be placed in the "loop()" Arduino function - */ -bool KnxDevice::task(void) { - type_tx_action action; - word nowTimeMillis, nowTimeMicros; - //stay in task() if _tpuart.IsActive() - do { - // STEP 1 : Initialize Com Objects having Init Read attribute - if (!_initCompleted) { - nowTimeMillis = millis(); - // To avoid KNX bus overloading, we wait for 500 ms between each Init read request - if (TimeDeltaWord(nowTimeMillis, _lastInitTimeMillis) > 500) { - while ( - (_initIndex < _numberOfComObjects) && - (_comObjectsList[_initIndex].getValidity() || !_comObjectsList[_initIndex].isActive()) /* either valid (=init done or not required) or not-active required to jump to next index */ - ) _initIndex++; - - if (_initIndex == _numberOfComObjects) { - _initCompleted = true; // All the Com Object initialization have been performed - } else { // Com Object to be initialised has been found - // Add a READ request in the TX action list - action.command = KNX_READ_REQUEST; - action.index = _initIndex; - _txActionList.append(action); - //normally, _validated flag will be set after response from KNX bus - //we set it manually with setValidity() after one try to avoid infinity loop if nobody answers - _comObjectsList[_initIndex].setValidity(); - _lastInitTimeMillis = millis(); // Update the timer - } - } - } - - // STEP 2 : Get new received KNX messages from the TPUART - // The TPUART RX task is executed every 400 us - nowTimeMicros = micros(); - if (TimeDeltaWord(nowTimeMicros, _lastRXTimeMicros) > 400) { - _lastRXTimeMicros = nowTimeMicros; - _tpuart->RXTask(); - - // TODO: check for rx_state in tpuart and call rxtask repeatedly until telegram is received?! - } - - // STEP 3 : Send KNX messages following TX actions - if (_state == IDLE) { - if (_txActionList.pop(action)) { // Data to be transmitted - - //DEBUG_PRINTLN(F("Data to be transmitted index=%d"), action.index); - KnxComObject* comObj = (action.index == 255 ? &_progComObj : &_comObjectsList[action.index]); - - //for (byte i = 0; i < comObj.GetLength() - 1; i++) { - // DEBUG_PRINTLN(F("-> action.valuePtr[%d]=0x%02x"), i, action.valuePtr[i]); - //} - - switch (action.command) { - - case KNX_READ_REQUEST: // a read operation of a Com Object on the KNX network is required - //_objectsList[action.index].CopyToTelegram(_txTelegram, KNX_COMMAND_VALUE_READ); - comObj->copyAttributes(_txTelegram); - _txTelegram.ClearLongPayload(); - _txTelegram.ClearFirstPayloadByte(); // Is it required to have a clean payload ?? - _txTelegram.SetCommand(KNX_COMMAND_VALUE_READ); - _txTelegram.UpdateChecksum(); - _tpuart->SendTelegram(_txTelegram); - _state = TX_ONGOING; - break; - - case KNX_RESPONSE_REQUEST: // a response operation of a Com Object on the KNX network is required - comObj->copyAttributes(_txTelegram); - comObj->copyValue(_txTelegram); - _txTelegram.SetCommand(KNX_COMMAND_VALUE_RESPONSE); - _txTelegram.UpdateChecksum(); - _tpuart->SendTelegram(_txTelegram); - _state = TX_ONGOING; - break; - - case KNX_WRITE_REQUEST: // a write operation of a Com Object on the KNX network is required - // update the com obj value - //DEBUG_PRINTLN(F("KNX_WRITE_REQUEST index=%d"), action.index); - - - if ((comObj->getLength()) <= 2) { - //DEBUG_PRINTLN(F("len <= 2")); - comObj->updateValue(action.byteValue); - } else { - //DEBUG_PRINTLN(F("len > 2")); - comObj->updateValue(action.valuePtr); - free(action.valuePtr); - } - // transmit the value through KNX network only if the Com Object has transmit attribute - if ((comObj->getIndicator()) & KNX_COM_OBJ_T_INDICATOR) { - //DEBUG_PRINTLN(F("set tx ongoing")); - comObj->copyAttributes(_txTelegram); - comObj->copyValue(_txTelegram); - _txTelegram.SetCommand(KNX_COMMAND_VALUE_WRITE); - _txTelegram.UpdateChecksum(); - _tpuart->SendTelegram(_txTelegram); - _state = TX_ONGOING; - } - break; - - default: break; - } - } - } - - // STEP 4 : LET THE TP-UART TRANSMIT KNX MESSAGES - // The TPUART TX task is executed every 800 us - nowTimeMicros = micros(); - if (TimeDeltaWord(nowTimeMicros, _lastTXTimeMicros) > 800) { - _lastTXTimeMicros = nowTimeMicros; - _tpuart->TXTask(); - } - } while (_tpuart->IsActive()); - return true; -} - - -/** - * Quick method to read a short (<=1 byte) com object - * NB : The returned value will be hazardous in case of use with long objects - * @param objectIndex - * @retreturn 1-byte value of comobj - */ -byte KnxDevice::read(byte objectIndex) { -// return _comObjectsList[objectIndex].getValue(); - return (objectIndex == 255 ? _progComObj.getValue() : _comObjectsList[objectIndex].getValue()); -} - - -/** - * Read an usual format com object - * Supported DPT formats are short com object, U16, V16, U32, V32, F16 and F32 (not implemented yet) - */ -template e_KnxDeviceStatus KnxDevice::read(byte objectIndex, T& returnedValue) { - KnxComObject* comObj = (objectIndex == 255 ? &_progComObj : &_comObjectsList[objectIndex]); - // Short com object case - if (comObj->getLength() <= 2) { - returnedValue = (T) comObj->getValue(); - return KNX_DEVICE_OK; - } else // long object case, let's see if we are able to translate the DPT value - { - byte dptValue[14]; // define temporary DPT value with max length - comObj->getValue(dptValue); - return ConvertFromDpt(dptValue, returnedValue, pgm_read_byte(&KnxDptToFormat[comObj->getDptId()])); - } -} - -template e_KnxDeviceStatus KnxDevice::read (byte objectIndex, bool& returnedValue); -template e_KnxDeviceStatus KnxDevice::read (byte objectIndex, byte& returnedValue); -template e_KnxDeviceStatus KnxDevice::read (byte objectIndex, short& returnedValue); -template e_KnxDeviceStatus KnxDevice::read (byte objectIndex, unsigned short& returnedValue); -template e_KnxDeviceStatus KnxDevice::read (byte objectIndex, int& returnedValue); -template e_KnxDeviceStatus KnxDevice::read (byte objectIndex, unsigned int& returnedValue); -template e_KnxDeviceStatus KnxDevice::read (byte objectIndex, long& returnedValue); -template e_KnxDeviceStatus KnxDevice::read (byte objectIndex, unsigned long& returnedValue); -template e_KnxDeviceStatus KnxDevice::read (byte objectIndex, float& returnedValue); -template e_KnxDeviceStatus KnxDevice::read (byte objectIndex, double& returnedValue); - - - -// Read any type of com object (DPT value provided as is) - -e_KnxDeviceStatus KnxDevice::read(byte objectIndex, byte returnedValue[]) { - KnxComObject* comObj = (objectIndex == 255 ? &_progComObj : &_comObjectsList[objectIndex]); - comObj->getValue(returnedValue); - return KNX_DEVICE_OK; -} - - -// Update an usual format com object -// Supported DPT types are short com object, U16, V16, U32, V32, F16 and F32 -// The Com Object value is updated locally -// And a telegram is sent on the KNX bus if the com object has communication & transmit attributes - -template e_KnxDeviceStatus KnxDevice::write(byte objectIndex, T value) { - type_tx_action action; - byte *destValue; - - KnxComObject* comObj = (objectIndex == 255 ? &_progComObj : &_comObjectsList[objectIndex]); - if (!comObj->isActive()) { - return KNX_DEVICE_COMOBJ_INACTIVE; - } - byte length = comObj->getLength(); - - if (length <= 2) action.byteValue = (byte) value; // short object case - else { // long object case, let's try to translate value to the com object DPT - destValue = (byte *) malloc(length - 1); // allocate the memory for DPT - e_KnxDeviceStatus status = ConvertToDpt(value, destValue, pgm_read_byte(&KnxDptToFormat[comObj->getDptId()])); - if (status) // translation error - { - free(destValue); - return status; // we cannot convert, we stop here - } else action.valuePtr = destValue; - } - // add WRITE action in the TX action queue - action.command = KNX_WRITE_REQUEST; - action.index = objectIndex; - _txActionList.append(action); - return KNX_DEVICE_OK; -} - -template e_KnxDeviceStatus KnxDevice::write (byte objectIndex, bool value); -template e_KnxDeviceStatus KnxDevice::write (byte objectIndex, byte value); -template e_KnxDeviceStatus KnxDevice::write (byte objectIndex, short value); -template e_KnxDeviceStatus KnxDevice::write (byte objectIndex, unsigned short value); -template e_KnxDeviceStatus KnxDevice::write (byte objectIndex, int value); -template e_KnxDeviceStatus KnxDevice::write (byte objectIndex, unsigned int value); -template e_KnxDeviceStatus KnxDevice::write (byte objectIndex, long value); -template e_KnxDeviceStatus KnxDevice::write (byte objectIndex, unsigned long value); -template e_KnxDeviceStatus KnxDevice::write (byte objectIndex, float value); -template e_KnxDeviceStatus KnxDevice::write (byte objectIndex, double value); - - -/** - * Update any type of com object (rough DPT value shall be provided) - * The Com Object value is updated locally - * And a telegram is sent on the KNX bus if the com object has communication & transmit attributes - */ -e_KnxDeviceStatus KnxDevice::write(byte objectIndex, byte valuePtr[]) { - type_tx_action action; - //type_tx_action action2; - - // get length of comobj for copying value into tx-action struct - KnxComObject* comObj = (objectIndex == 255 ? &_progComObj : &_comObjectsList[objectIndex]); - byte length = comObj->getLength(); - - //if (!(objectIndex == 255 ? _progComObj.isActive() : _comObjectsList[objectIndex].isActive())) { - // return KNX_DEVICE_COMOBJ_INACTIVE; - //} - - //byte length = (objectIndex == 255 ? _progComObj.GetLength() : _comObjectsList[objectIndex].GetLength()); - - // check we are in long object case - if (length > 2) { - - // add WRITE action in the TX action queue - action.command = KNX_WRITE_REQUEST; - action.index = objectIndex; - - // allocate the memory for long value - byte *dptValue = (byte *) malloc(length - 1); - - for (byte i = 0; i < length - 1; i++) { - dptValue[i] = valuePtr[i]; // copy value -// DEBUG_PRINTLN(F("dptValue[%d]=0x%02x == valuePtr[%d]=0x%02x"), i, dptValue[i], i, valuePtr[i]); - } - action.valuePtr = (byte *) dptValue; - - // bis hier hin alles okay - _txActionList.append(action); - //for (byte i = 0; i < length - 1; i++) { - // DEBUG_PRINTLN(F("action.valuePtr[%d]=0x%02x"), i, action.valuePtr[i]); - //} - // immer noch okay. - - // TODO: pop machen und dann daten testen. Wenn dann noch okay, muss jemand die Daten zu späterem zeitpunkt manipulieren. - //_txActionList.pop(action2); - //for (byte i = 0; i < length - 1; i++) { - // DEBUG_PRINTLN(F("action2.valuePtr[%d]=0x%02x"), i, action2.valuePtr[i]); - //} - - - return KNX_DEVICE_OK; - } - return KNX_DEVICE_ERROR; -} - - -/** - * Com Object KNX Bus Update request - * Request the local object to be updated with the value from the bus - * NB : the function is asynchroneous, the update completion is notified by the knxEvents() callback - */ -void KnxDevice::update(byte objectIndex) { - type_tx_action action; - action.command = KNX_READ_REQUEST; - action.index = objectIndex; - _txActionList.append(action); -} - - -/** - * The function returns true if there is rx/tx activity ongoing, else false - */ -bool KnxDevice::isActive() const { - if (_tpuart->IsActive()) return true; // TPUART is active - if (_state == TX_ONGOING) return true; // the Device is sending a request - if (_txActionList.getItemCount()) return true; // there is at least one tx action in the queue - return false; -} - -/** - * Overwrite the address of an attache Com Object - * Overwriting is allowed only when the KnxDevice is in INIT state - * Typically usage is end-user application stored Group Address in EEPROM - */ -e_KnxDeviceStatus KnxDevice::setComObjectAddress(byte index, word addr, bool active) { - if (_state != INIT) return KNX_DEVICE_INIT_ERROR; - if (index >= _numberOfComObjects) return KNX_DEVICE_INVALID_INDEX; - _comObjectsList[index].setAddr(addr); - _comObjectsList[index].setActive(active); - return KNX_DEVICE_OK; -} - -word KnxDevice::getComObjectAddress(byte index) { - return _comObjectsList[index].getAddr(); -} - - -/** - * Static GetTpUartEvents() function called by the KnxTpUart layer (callback) - */ -void KnxDevice::GetTpUartEvents(e_KnxTpUartEvent event) { - type_tx_action action; - byte targetedComObjIndex; // index of the Com Object targeted by the event - - // Manage RECEIVED MESSAGES - if (event == TPUART_EVENT_RECEIVED_KNX_TELEGRAM) { - Knx._state = IDLE; - targetedComObjIndex = Knx._tpuart->GetTargetedComObjectIndex(); - KnxComObject* comObj = (targetedComObjIndex == 255 ? &Knx._progComObj : &_comObjectsList[targetedComObjIndex]); - - switch (Knx._rxTelegram->GetCommand()) { - case KNX_COMMAND_VALUE_READ: - // READ command coming from the bus - // if the Com Object has read attribute, then add RESPONSE action in the TX action list - if ((comObj->getIndicator()) & KNX_COM_OBJ_R_INDICATOR) { // The targeted Com Object can indeed be read - action.command = KNX_RESPONSE_REQUEST; - action.index = targetedComObjIndex; - Knx._txActionList.append(action); - } - break; - - case KNX_COMMAND_VALUE_RESPONSE: - // RESPONSE command coming from KNX network, we update the value of the corresponding Com Object. - // We 1st check that the corresponding Com Object has UPDATE attribute - if ((comObj->getIndicator()) & KNX_COM_OBJ_U_INDICATOR) { - comObj->updateValue(*(Knx._rxTelegram)); - //We notify the upper layer of the update - knxEvents(targetedComObjIndex); - } - break; - - - case KNX_COMMAND_VALUE_WRITE: - // WRITE command coming from KNX network, we update the value of the corresponding Com Object. - // We 1st check that the corresponding Com Object has WRITE attribute - if ((comObj->getIndicator()) & KNX_COM_OBJ_W_INDICATOR) { - comObj->updateValue(*(Knx._rxTelegram)); - //We notify the upper layer of the update - if (Konnekting.isActive()) { -// DEBUG_PRINTLN(F("Routing event to konnektingKnxEvents")); - konnektingKnxEvents(targetedComObjIndex); - } else { -// DEBUG_PRINTLN(F("No event routing")); -// knxEvents(targetedComObjIndex); - } - } - break; - - // case KNX_COMMAND_MEMORY_WRITE : break; // Memory Write not handled - - default: break; // not supposed to happen - } - } else { -// DEBUG_PRINTLN(F("GetTpUartEvents event=%d"), event); - } - - // Manage RESET events - if (event == TPUART_EVENT_RESET) { - while (Knx._tpuart->Reset() == KNX_TPUART_ERROR); - Knx._tpuart->Init(); - Knx._state = IDLE; - } -} - - -// Static TxTelegramAck() function called by the KnxTpUart layer (callback) - -void KnxDevice::TxTelegramAck(e_TpUartTxAck -#ifdef KNXDevice_DEBUG // ifdef to suppress compiler warning about unused variable when not in debug mode - value -#endif // KNXDevice_DEBUG - ) { - Knx._state = IDLE; -} - - -// Functions to convert a standard C type to a DPT format -// NB : only the usual DPT formats are supported (U16, V16, U32, V32, F16 and F32 (not yet implemented) - -template e_KnxDeviceStatus ConvertFromDpt(const byte dptOriginValue[], T& resultValue, byte dptFormat) { - switch (dptFormat) { - case KNX_DPT_FORMAT_U16: - case KNX_DPT_FORMAT_V16: - resultValue = (T) ((unsigned int) dptOriginValue[0] << 8); - resultValue += (T) (dptOriginValue[1]); - return KNX_DEVICE_OK; - break; - - case KNX_DPT_FORMAT_U32: - case KNX_DPT_FORMAT_V32: - resultValue = (T) ((unsigned long) dptOriginValue[0] << 24); - resultValue += (T) ((unsigned long) dptOriginValue[1] << 16); - resultValue += (T) ((unsigned long) dptOriginValue[2] << 8); - resultValue += (T) (dptOriginValue[3]); - return KNX_DEVICE_OK; - break; - - case KNX_DPT_FORMAT_F16: - { - // Get the DPT sign, mantissa and exponent - int signMultiplier = (dptOriginValue[0] & 0x80) ? -1 : 1; - word absoluteMantissa = dptOriginValue[1] + ((dptOriginValue[0]&0x07) << 8); - if (signMultiplier == -1) { // Calculate absolute mantissa value in case of negative mantissa - // Abs = 2's complement + 1 - absoluteMantissa = ((~absoluteMantissa)& 0x07FF) + 1; - } - byte exponent = (dptOriginValue[0]&0x78) >> 3; - resultValue = (T) (0.01 * ((long) absoluteMantissa << exponent) * signMultiplier); - return KNX_DEVICE_OK; - } - break; - - case KNX_DPT_FORMAT_F32: - return KNX_DEVICE_NOT_IMPLEMENTED; - break; - - default: return KNX_DEVICE_ERROR; - } -} - -template e_KnxDeviceStatus ConvertFromDpt (const byte dptOriginValue[], unsigned char&, byte dptFormat); -template e_KnxDeviceStatus ConvertFromDpt (const byte dptOriginValue[], char&, byte dptFormat); -template e_KnxDeviceStatus ConvertFromDpt (const byte dptOriginValue[], unsigned int&, byte dptFormat); -template e_KnxDeviceStatus ConvertFromDpt (const byte dptOriginValue[], int&, byte dptFormat); -template e_KnxDeviceStatus ConvertFromDpt (const byte dptOriginValue[], unsigned long&, byte dptFormat); -template e_KnxDeviceStatus ConvertFromDpt (const byte dptOriginValue[], long&, byte dptFormat); -template e_KnxDeviceStatus ConvertFromDpt (const byte dptOriginValue[], float&, byte dptFormat); -template e_KnxDeviceStatus ConvertFromDpt (const byte dptOriginValue[], double&, byte dptFormat); - - -// Functions to convert a standard C type to a DPT format -// NB : only the usual DPT formats are supported (U16, V16, U32, V32, F16 and F32 (not yet implemented) - -template e_KnxDeviceStatus ConvertToDpt(T originValue, byte dptDestValue[], byte dptFormat) { - switch (dptFormat) { - case KNX_DPT_FORMAT_U16: - case KNX_DPT_FORMAT_V16: - dptDestValue[0] = (byte) ((unsigned int) originValue >> 8); - dptDestValue[1] = (byte) (originValue); - return KNX_DEVICE_OK; - break; - - case KNX_DPT_FORMAT_U32: - case KNX_DPT_FORMAT_V32: - dptDestValue[0] = (byte) ((unsigned long) originValue >> 24); - dptDestValue[1] = (byte) ((unsigned long) originValue >> 16); - dptDestValue[2] = (byte) ((unsigned long) originValue >> 8); - dptDestValue[3] = (byte) (originValue); - return KNX_DEVICE_OK; - break; - - case KNX_DPT_FORMAT_F16: - { - long longValuex100 = (long) (100.0 * originValue); - boolean negativeSign = (longValuex100 & 0x80000000) ? true : false; - byte exponent = 0; - byte round = 0; - - if (negativeSign) { - while (longValuex100 < (long) (-2048)) { - exponent++; - round = (byte) (longValuex100) & 1; - longValuex100 >>= 1; - longValuex100 |= 0x80000000; - } - } else { - while (longValuex100 > (long) (2047)) { - exponent++; - round = (byte) (longValuex100) & 1; - longValuex100 >>= 1; - } - - } - if (round) longValuex100++; - dptDestValue[1] = (byte) longValuex100; - dptDestValue[0] = (byte) (longValuex100 >> 8) & 0x7; - dptDestValue[0] += exponent << 3; - if (negativeSign) dptDestValue[0] += 0x80; - return KNX_DEVICE_OK; - } - break; - - case KNX_DPT_FORMAT_F32: - return KNX_DEVICE_NOT_IMPLEMENTED; - break; - - default: return KNX_DEVICE_ERROR; - } -} - -template e_KnxDeviceStatus ConvertToDpt (unsigned char, byte dptDestValue[], byte dptFormat); -template e_KnxDeviceStatus ConvertToDpt (char, byte dptDestValue[], byte dptFormat); -template e_KnxDeviceStatus ConvertToDpt (unsigned int, byte dptDestValue[], byte dptFormat); -template e_KnxDeviceStatus ConvertToDpt (int, byte dptDestValue[], byte dptFormat); -template e_KnxDeviceStatus ConvertToDpt (unsigned long, byte dptDestValue[], byte dptFormat); -template e_KnxDeviceStatus ConvertToDpt (long, byte dptDestValue[], byte dptFormat); -template e_KnxDeviceStatus ConvertToDpt (float, byte dptDestValue[], byte dptFormat); -template e_KnxDeviceStatus ConvertToDpt (double, byte dptDestValue[], byte dptFormat); - -// EOF diff --git a/src/KonnektingDeviceLibrary/KnxDevice.h b/src/KonnektingDeviceLibrary/KnxDevice.h deleted file mode 100644 index be9778e..0000000 --- a/src/KonnektingDeviceLibrary/KnxDevice.h +++ /dev/null @@ -1,259 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * It is derived from another GPLv3 licensed project: - * The Arduino Knx Bus Device library allows to turn Arduino into "self-made" KNX bus device. - * Copyright (C) 2014 2015 Franck MARINI (fm@liwan.fr) - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// File : KnxDevice.h -// Author : Franck Marini -// Modified: Alexander Christian -// Description : KnxDevice Abstraction Layer -// Module dependencies : HardwareSerial, KnxTelegram, KnxComObject, KnxTpUart, RingBuffer - -#ifndef KNXDEVICE_H -#define KNXDEVICE_H - -#include "Arduino.h" -#include "KnxTelegram.h" -#include "KnxComObject.h" -#include "RingBuff.h" -#include "KnxTpUart.h" -#include "KonnektingDevice.h" - -// !!!!!!!!!!!!!!! FLAG OPTIONS !!!!!!!!!!!!!!!!! -// DEBUG : -//#define KNXDEVICE_DEBUG_INFO // Uncomment to activate info traces - -// Values returned by the KnxDevice member functions : -enum e_KnxDeviceStatus { - KNX_DEVICE_OK = 0, - KNX_DEVICE_INVALID_INDEX = 1, - KNX_DEVICE_INIT_ERROR = 2, - KNX_DEVICE_COMOBJ_INACTIVE = 3, - KNX_DEVICE_NOT_IMPLEMENTED = 254, - KNX_DEVICE_ERROR = 255 -}; - -// Macro functions for conversion of physical and 2/3 level group addresses -inline word P_ADDR(byte area, byte line, byte busdevice) -{ return (word) ( ((area&0xF)<<12) + ((line&0xF)<<8) + busdevice ); } - -inline word G_ADDR(byte maingrp, byte midgrp, byte subgrp) -{ return (word) ( ((maingrp&0x1F)<<11) + ((midgrp&0x7)<<8) + subgrp ); } - -inline word G_ADDR(byte maingrp, word subgrp) -{ return (word) ( ((maingrp&0x1F)<<11) + subgrp ); } - -#define ACTIONS_QUEUE_SIZE 16 - -// KnxDevice internal state -enum e_KnxDeviceState { - INIT, - IDLE, - TX_ONGOING, -}; - -// Action types -enum e_KnxDeviceTxActionType { - KNX_READ_REQUEST, - KNX_WRITE_REQUEST, - KNX_RESPONSE_REQUEST -}; - -struct struct_tx_action{ - e_KnxDeviceTxActionType command; // Action type to be performed - byte index; // Index of the involved ComObject - union { // Value - // Field used in case of short value (value width <= 1 byte) - struct { - byte byteValue; - byte notUsed; - }; - byte *valuePtr; // Field used in case of long value (width > 1 byte), space is allocated dynamically - }; -};// type_tx_action; -typedef struct struct_tx_action type_tx_action; - - -// Callback function to catch and treat KNX events -// The definition shall be provided by the end-user -extern void knxEvents(byte); - - -// --------------- Definition of the functions for DPT translation -------------------- -// Functions to convert a DPT format to a standard C type -// NB : only the usual DPT formats are supported (U16, V16, U32, V32, F16 and F32) -template e_KnxDeviceStatus ConvertFromDpt(const byte dpt[], T& result, byte dptFormat); - -// Functions to convert a standard C type to a DPT format -// NB : only the usual DPT formats are supported (U16, V16, U32, V32, F16 and F32) -template e_KnxDeviceStatus ConvertToDpt(T value, byte dpt[], byte dptFormat); - - -class KnxDevice { - - // List of Com Objects attached to the KNX Device - // The definition shall be provided by the end-user - static KnxComObject _comObjectsList[]; - - // Nb of attached Com Objects - // The value shall be provided by the end-user - static const byte _numberOfComObjects; - - KnxComObject _progComObj = KnxComObject(KNX_DPT_60000_60000 /* KNX PROGRAM */, KNX_COM_OBJ_C_W_U_T_INDICATOR); - - // Current KnxDevice state - e_KnxDeviceState _state; - - // TPUART associated to the KNX Device - KnxTpUart *_tpuart; - - // Queue of transmit actions to be performed - RingBuff _txActionList; - - // True when all the Com Object with Init attr have been initialized - bool _initCompleted; - - // Index to the last initiated object - byte _initIndex; - - // Time (in msec) of the last init (read) request on the bus - word _lastInitTimeMillis; - - // Time (in msec) of the last Tpuart Rx activity; - word _lastRXTimeMicros; - - // Time (in msec) of the last Tpuart Tx activity; - word _lastTXTimeMicros; - - // Telegram object used for telegrams sending - KnxTelegram _txTelegram; - - // Reference to the telegram received by the TPUART - KnxTelegram *_rxTelegram; - - // Constructor, Destructor - // private constructor (singleton design pattern) - KnxDevice(); - // private destructor (singleton design pattern) - ~KnxDevice() {} - // private copy constructor (singleton design pattern) - KnxDevice (const KnxDevice&); - - - public: - - // unique KnxDevice instance (singleton design pattern) - static KnxDevice Knx; - - int getNumberOfComObjects(); - - /* - * Start the KNX Device - * return KNX_DEVICE_ERROR (255) if begin() failed - * else return KNX_DEVICE_OK - */ - e_KnxDeviceStatus begin(HardwareSerial& serial, word physicalAddr); - - /* - * Stop the KNX Device - */ - void end(); - - /* - * KNX device execution task - * This function shall be called in the "loop()" Arduino function - */ - bool task(void); - - /* - * Quick method to read a short (<=1 byte) com object - * NB : The returned value will be hazardous in case of use with long objects - */ - byte read(byte objectIndex); - - /* - * Read an usual format com object - * Supported DPT formats are short com object, U16, V16, U32, V32, F16 and F32 - */ - template e_KnxDeviceStatus read(byte objectIndex, T& returnedValue); - - /* - * Read any type of com object (DPT value provided as is) - */ - e_KnxDeviceStatus read(byte objectIndex, byte returnedValue[]); - - // Update com object functions : - // For all the update functions, the com object value is updated locally - // and a telegram is sent on the KNX bus if the object has both COMMUNICATION & TRANSMIT attributes set - - /* - * Update an usual format com object - * Supported DPT types are short com object, U16, V16, U32, V32, F16 and F32 - */ - template e_KnxDeviceStatus write(byte objectIndex, T value); - - /* - * Update any type of com object (rough DPT value shall be provided) - */ - e_KnxDeviceStatus write(byte objectIndex, byte valuePtr[]); - - - /* - * Com Object KNX Bus Update request - * Request the local object to be updated with the value from the bus - * NB : the function is asynchroneous, the update completion is notified by the knxEvents() callback - */ - void update(byte objectIndex); - - - /** - * TODO document me - * @return - */ - bool isActive(void) const; - - /* - * Overwrite the address of an attache Com Object - * Overwriting is allowed only when the KnxDevice is in INIT state - * Typically usage is end-user application stored Group Address in EEPROM - */ - e_KnxDeviceStatus setComObjectAddress(byte index, word addr, bool active); - - /* - * Gets the address of an commobjects - */ - word getComObjectAddress(byte index); - - private: - /* - * Static GetTpUartEvents() function called by the KnxTpUart layer (callback) - */ - static void GetTpUartEvents(e_KnxTpUartEvent event); - - /* - * Static TxTelegramAck() function called by the KnxTpUart layer (callback) - */ - static void TxTelegramAck(e_TpUartTxAck); - -}; - -// Reference to the KnxDevice unique instance -extern KnxDevice& Knx; - -#endif // KNXDEVICE_H diff --git a/src/KonnektingDeviceLibrary/KnxDptConstants.h b/src/KonnektingDeviceLibrary/KnxDptConstants.h deleted file mode 100644 index 56ec596..0000000 --- a/src/KonnektingDeviceLibrary/KnxDptConstants.h +++ /dev/null @@ -1,36 +0,0 @@ -#define DPT1_001_off 0 -#define DPT1_001_on 1 - -#define DPT1_002_false 0 -#define DPT1_002_true 1 - -/** Lock */ -#define DPT1_003_disable 0 - -/** Unlock */ -#define DPT1_003_enable 1 - -#define DPT1_004_no_ramp 0 -#define DPT1_004_ramp 1 - -#define DPT1_005_no_alarm 0 -#define DPT1_005_alarm 1 - -#define DPT1_006_low 0 -#define DPT1_006_high 1 - -#define DPT1_007_decrease 0 -#define DPT1_007_increase 1 - -#define DPT1_008_up 0 -#define DPT1_008_down 1 - -#define DPT1_009_open 0 -#define DPT1_009_close 1 - -#define DPT1_010_stop 0 -#define DPT1_010_start 1 - -// State -#define DPT1_011_inactive 0 -#define DPT1_011_active 1 diff --git a/src/KonnektingDeviceLibrary/KnxTelegram.cpp b/src/KonnektingDeviceLibrary/KnxTelegram.cpp deleted file mode 100644 index dabb47c..0000000 --- a/src/KonnektingDeviceLibrary/KnxTelegram.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * It is derived from another GPLv3 licensed project: - * The Arduino Knx Bus Device library allows to turn Arduino into "self-made" KNX bus device. - * Copyright (C) 2014 2015 Franck MARINI (fm@liwan.fr) - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -// File : KnxTelegram.h -// Author : Franck Marini -// Modified: Alexander Christian -// Modified: Eugen Burkowski -// Description : Handling of the KNX Telegrams -// Module dependencies : none - -#include "KnxTelegram.h" - -KnxTelegram::KnxTelegram() { ClearTelegram(); }; // Clear telegram with default values - - -void KnxTelegram::ClearTelegram(void) -{ -// clear telegram with default values : -// std FF, no repeat, normal prio, empty payload -// multicast, routing counter = 6, payload length = 1 - memset(_telegram,0,KNX_TELEGRAM_MAX_SIZE); - _controlField = CONTROL_FIELD_DEFAULT_VALUE ; - _routing= ROUTING_FIELD_DEFAULT_VALUE; -} - - -void KnxTelegram::SetLongPayload(const byte origin[], byte nbOfBytes) -{ - if (nbOfBytes > KNX_TELEGRAM_PAYLOAD_MAX_SIZE-2) nbOfBytes = KNX_TELEGRAM_PAYLOAD_MAX_SIZE-2; - for(byte i=0; i < nbOfBytes; i++) _payloadChecksum[i] = origin[i]; -} - - -void KnxTelegram::ClearLongPayload(void) -{ - memset(_payloadChecksum,0,KNX_TELEGRAM_PAYLOAD_MAX_SIZE-1); -} - - -void KnxTelegram::GetLongPayload(byte destination[], byte nbOfBytes) const -{ - if (nbOfBytes > KNX_TELEGRAM_PAYLOAD_MAX_SIZE-2) nbOfBytes = KNX_TELEGRAM_PAYLOAD_MAX_SIZE-2 ; - memcpy(destination, _payloadChecksum, nbOfBytes); -}; - - -byte KnxTelegram::CalculateChecksum(void) const -{ - byte indexChecksum, xorSum=0; - indexChecksum = KNX_TELEGRAM_HEADER_SIZE + GetPayloadLength() + 1; - for (byte i = 0; i < indexChecksum ; i++) xorSum ^= _telegram[i]; // XOR Sum of all the databytes - return (byte)(~xorSum); // Checksum equals 1's complement of databytes XOR sum -} - - -void KnxTelegram::UpdateChecksum(void) -{ - byte indexChecksum, xorSum=0; - indexChecksum = KNX_TELEGRAM_HEADER_SIZE + GetPayloadLength() + 1; - for (byte i = 0; i < indexChecksum ; i++) xorSum ^= _telegram[i]; // XOR Sum of all the databytes - _telegram[indexChecksum] = ~xorSum; // Checksum equals 1's complement of databytes XOR sum -} - - -void KnxTelegram::Copy(KnxTelegram& dest) const -{ - byte length = GetTelegramLength(); - memcpy(dest._telegram, _telegram, length); -} - - -void KnxTelegram::CopyHeader(KnxTelegram& dest) const -{ - memcpy(dest._telegram, _telegram, KNX_TELEGRAM_HEADER_SIZE); -} - - -e_KnxTelegramValidity KnxTelegram::GetValidity(void) const -{ - if ((_controlField & CONTROL_FIELD_PATTERN_MASK) != CONTROL_FIELD_VALID_PATTERN) return KNX_TELEGRAM_INVALID_CONTROL_FIELD; - if ((_controlField & CONTROL_FIELD_FRAME_FORMAT_MASK) != CONTROL_FIELD_STANDARD_FRAME_FORMAT) return KNX_TELEGRAM_UNSUPPORTED_FRAME_FORMAT; - if (!GetPayloadLength()) return KNX_TELEGRAM_INCORRECT_PAYLOAD_LENGTH ; - if ((_commandH & COMMAND_FIELD_PATTERN_MASK) != COMMAND_FIELD_VALID_PATTERN) return KNX_TELEGRAM_INVALID_COMMAND_FIELD; - if ( GetChecksum() != CalculateChecksum()) return KNX_TELEGRAM_INCORRECT_CHECKSUM ; - byte cmd=GetCommand(); - if ( (cmd!=KNX_COMMAND_VALUE_READ) && (cmd!=KNX_COMMAND_VALUE_RESPONSE) - && (cmd!=KNX_COMMAND_VALUE_WRITE) && (cmd!=KNX_COMMAND_MEMORY_WRITE)) return KNX_TELEGRAM_UNKNOWN_COMMAND; - return KNX_TELEGRAM_VALID; -}; - - -void KnxTelegram::Info(String& str) const -{ - byte payloadLength = GetPayloadLength(); - - str+="SrcAddr=" + String(GetSourceAddress(),HEX); - str+="\nTargetAddr=" + String(GetTargetAddress(),HEX); - str+="\nPayloadLgth=" + String(payloadLength,DEC); - str+="\nCommand="; - switch(GetCommand()) - { - case KNX_COMMAND_VALUE_READ : str+="VAL_READ"; break; - case KNX_COMMAND_VALUE_RESPONSE : str+="VAL_RESP"; break; - case KNX_COMMAND_VALUE_WRITE : str+="VAL_WRITE"; break; - case KNX_COMMAND_MEMORY_WRITE : str+="MEM_WRITE"; break; - default : str+="ERR_VAL!"; break; - } - str+="\nPayload=" + String(GetFirstPayloadByte(),HEX)+' '; - for (byte i = 0; i < payloadLength-1; i++) str+=String(_payloadChecksum[i], HEX)+' '; - str+='\n'; -} - - -void KnxTelegram::KnxTelegram::InfoRaw(String& str) const -{ - for (byte i = 0; i < KNX_TELEGRAM_MAX_SIZE; i++) str+=String(_telegram[i], HEX)+' '; - str+='\n'; -} - - -void KnxTelegram::InfoVerbose(String& str) const -{ - byte payloadLength = GetPayloadLength(); - str+= "Repeat="; str+= IsRepeated() ? "YES" : "NO"; - str+="\nPrio="; - switch(GetPriority()) - { - case KNX_PRIORITY_SYSTEM_VALUE : str+="SYSTEM"; break; - case KNX_PRIORITY_ALARM_VALUE : str+="ALARM"; break; - case KNX_PRIORITY_HIGH_VALUE : str+="HIGH"; break; - case KNX_PRIORITY_NORMAL_VALUE : str+="NORMAL"; break; - default : str+="ERR_VAL!"; break; - } - str+="\nSrcAddr=" + String(GetSourceAddress(),HEX); - str+="\nTargetAddr=" + String(GetTargetAddress(),HEX); - str+="\nGroupAddr="; if (IsMulticast()) str+= "YES"; else str+="NO"; - str+="\nRout.Counter=" + String(GetRoutingCounter(),DEC); - str+="\nPayloadLgth=" + String(payloadLength,DEC); - str+="\nTelegramLength=" + String(GetTelegramLength(),DEC); - str+="\nCommand="; - switch(GetCommand()) - { - case KNX_COMMAND_VALUE_READ : str+="VAL_READ"; break; - case KNX_COMMAND_VALUE_RESPONSE : str+="VAL_RESP"; break; - case KNX_COMMAND_VALUE_WRITE : str+="VAL_WRITE"; break; - case KNX_COMMAND_MEMORY_WRITE : str+="MEM_WRITE"; break; - default : str+="ERR_VAL!"; break; - } - str+="\nPayload=" + String(GetFirstPayloadByte(),HEX)+' '; - for (byte i = 0; i < payloadLength-1; i++) str+=String(_payloadChecksum[i], HEX)+' '; - str+="\nValidity="; - switch(GetValidity()) - { - case KNX_TELEGRAM_VALID : str+="VALID"; break; - case KNX_TELEGRAM_INVALID_CONTROL_FIELD : str+="INVALID_CTRL_FIELD"; break; - case KNX_TELEGRAM_UNSUPPORTED_FRAME_FORMAT : str+="UNSUPPORTED_FRAME_FORMAT"; break; - case KNX_TELEGRAM_INCORRECT_PAYLOAD_LENGTH : str+="INCORRECT_PAYLOAD_LGTH"; break; - case KNX_TELEGRAM_INVALID_COMMAND_FIELD : str+="INVALID_CMD_FIELD"; break; - case KNX_TELEGRAM_UNKNOWN_COMMAND : str+="UNKNOWN_CMD"; break; - case KNX_TELEGRAM_INCORRECT_CHECKSUM : str+="INCORRECT_CHKSUM"; break; - default : str+="ERR_VAL!"; break; - } - str+='\n'; -} - -// EOF diff --git a/src/KonnektingDeviceLibrary/KnxTelegram.h b/src/KonnektingDeviceLibrary/KnxTelegram.h deleted file mode 100644 index 9c87d25..0000000 --- a/src/KonnektingDeviceLibrary/KnxTelegram.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * It is derived from another GPLv3 licensed project: - * The Arduino Knx Bus Device library allows to turn Arduino into "self-made" KNX bus device. - * Copyright (C) 2014 2015 Franck MARINI (fm@liwan.fr) - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -// File : KnxTelegram.h -// Author : Franck Marini -// Modified: Alexander Christian -// Description : Handling of the KNX Telegrams -// Module dependencies : none - -#ifndef KNXTELEGRAM_H -#define KNXTELEGRAM_H - -#include "Arduino.h" - -// ---------- Knx Telegram description (visit "www.knx.org" for more info) ----------- -// => Length : 9 bytes min. to 23 bytes max. -// -// => Structure : -// -Header (6 bytes): -// Byte 0 | Control Field -// Byte 1 | Source Address High byte -// Byte 2 | Source Address Low byte -// Byte 3 | Destination Address High byte -// Byte 4 | Destination Address Low byte -// Byte 5 | Routing field -// -Payload (from 2 up to 16 bytes): -// Byte 6 | Commmand field High -// Byte 7 | Command field Low + 1st payload data (6bits) -// Byte 8 up to 21 | payload bytes (optional) -// -Checksum (1 byte) -// -// => Fields details : -// -Control Field : "FFR1 PP00" format with -// FF = Frame Format (10 = Std Length L_DATA service, 00 = extended L_DATA service, 11 = L_POLLDATA service) -// R = Repeatflag (1 = not repeated, 0 = repeated) -// PP = Priority (00 = system, 10 = alarm, 01 = high, 11 = normal) -// -Routing Field : "TCCC LLLL" format with -// T = Target Addr type (1 = group address/muticast, 0 = individual address/unicast) -// CCC = Counter -// LLLL = Payload Length (1-15) -// -Command Field : "00XX XXCC CCDD DDDD" format with -// XX = Not used -// CC = command (0000 = Value Read, 0001 = Value Response, 0010 = Value Write, 1010 = Memory Write) -// DD = Payload Data (1st payload byte) -// -// => Transmit timings : -// -Tbit = 104us, Tbyte=1,35ms (13 bits per character) -// -from 20ms for 1 byte payload telegram (Bus temporisation + Telegram transmit + ACK) -// -up to 40ms for 15 bytes payload (Bus temporisation + Telegram transmit + ACK) -// - -// Define for lengths & offsets -#define KNX_TELEGRAM_HEADER_SIZE 6 -#define KNX_TELEGRAM_PAYLOAD_MAX_SIZE 16 -#define KNX_TELEGRAM_MIN_SIZE 9 -#define KNX_TELEGRAM_MAX_SIZE 23 -#define KNX_TELEGRAM_LENGTH_OFFSET 8 // Offset between payload length and telegram length - -enum e_KnxPriority { - KNX_PRIORITY_SYSTEM_VALUE = B00000000, - KNX_PRIORITY_HIGH_VALUE = B00000100, - KNX_PRIORITY_ALARM_VALUE = B00001000, - KNX_PRIORITY_NORMAL_VALUE = B00001100 -}; - -enum e_KnxCommand { - KNX_COMMAND_VALUE_READ = B00000000, - KNX_COMMAND_VALUE_RESPONSE = B00000001, - KNX_COMMAND_VALUE_WRITE = B00000010, - KNX_COMMAND_MEMORY_WRITE = B00001010 -}; - -//--- CONTROL FIELD values & masks --- -#define CONTROL_FIELD_DEFAULT_VALUE B10111100 // Standard FF; No Repeat; Normal Priority -#define CONTROL_FIELD_FRAME_FORMAT_MASK B11000000 -#define CONTROL_FIELD_STANDARD_FRAME_FORMAT B10000000 -#define CONTROL_FIELD_REPEATED_MASK B00100000 -#define CONTROL_FIELD_SET_REPEATED(x) (x&=B11011111) -#define CONTROL_FIELD_PRIORITY_MASK B00001100 -#define CONTROL_FIELD_PATTERN_MASK B00010011 -#define CONTROL_FIELD_VALID_PATTERN B00010000 - -// --- ROUTING FIELD values & masks --- -#define ROUTING_FIELD_DEFAULT_VALUE B11100001 // Multicast(Target Group @), Routing Counter = 6, Length = 1 -#define ROUTING_FIELD_TARGET_ADDRESS_TYPE_MASK B10000000 -#define ROUTING_FIELD_COUNTER_MASK B01110000 -#define ROUTING_FIELD_PAYLOAD_LENGTH_MASK B00001111 - -// --- COMMAND FIELD values & masks --- -#define COMMAND_FIELD_HIGH_COMMAND_MASK 0x03 -#define COMMAND_FIELD_LOW_COMMAND_MASK 0xC0 // 2 first bytes on _commandL -#define COMMAND_FIELD_LOW_DATA_MASK 0x3F // 6 last bytes are data -#define COMMAND_FIELD_PATTERN_MASK B11000000 -#define COMMAND_FIELD_VALID_PATTERN B00000000 - -enum e_KnxTelegramValidity { KNX_TELEGRAM_VALID = 0 , - KNX_TELEGRAM_INVALID_CONTROL_FIELD, - KNX_TELEGRAM_UNSUPPORTED_FRAME_FORMAT, - KNX_TELEGRAM_INCORRECT_PAYLOAD_LENGTH, - KNX_TELEGRAM_INVALID_COMMAND_FIELD, - KNX_TELEGRAM_UNKNOWN_COMMAND, - KNX_TELEGRAM_INCORRECT_CHECKSUM }; - -class KnxTelegram { - union { - byte _telegram[KNX_TELEGRAM_MAX_SIZE]; // byte 0 to 22 - struct { - byte _controlField; // byte 0 - byte _sourceAddrH; // byte 1 - byte _sourceAddrL; // byte 2 - byte _targetAddrH; // byte 3 - byte _targetAddrL; // byte 4 - byte _routing; // byte 5 - byte _commandH; // byte 6 - byte _commandL; // byte 7 - byte _payloadChecksum[KNX_TELEGRAM_PAYLOAD_MAX_SIZE-1]; // byte 8 to 22 - }; - }; - - public: - // CONSTRUCTOR - // builds telegram with following default values : - // std FF, no repeat, normal prio, empty payload, multicast, routing counter = 6, payload length = 1 - KnxTelegram(); - - // INLINED functions (defined later in this file) - void ChangePriority(e_KnxPriority priority); - e_KnxPriority GetPriority(void) const; - - void SetRepeated(void); - boolean IsRepeated(void) const; - - void SetSourceAddress(word addr); - word GetSourceAddress(void) const; - void SetTargetAddress(word addr); - word GetTargetAddress(void) const; - - void SetMulticast(boolean); - boolean IsMulticast(void) const; - - void ChangeRoutingCounter(byte counter); - byte GetRoutingCounter(void) const; - - void SetPayloadLength(byte length); - byte GetPayloadLength(void) const; - - byte GetTelegramLength(void) const; - - void SetCommand(e_KnxCommand cmd); - e_KnxCommand GetCommand(void) const; - - // Handling of the 1st payload byte (the 6 lowest bits in _commandL field) - void SetFirstPayloadByte(byte data); - void ClearFirstPayloadByte(void); - byte GetFirstPayloadByte(void) const; - - // Read of the telegram byte per byte - // NB : do not check that the index is in the range - byte ReadRawByte(byte byteIndex) const; - - // Write of the telegram byte per byte - // NB : do not check that the index is in the range - void WriteRawByte(byte data, byte byteIndex); - - byte GetChecksum(void) const; - boolean IsChecksumCorrect(void) const; - - // functions NOT INLINED (see definitions in KnxTelegram.cpp) - void ClearTelegram(void); // (re)set telegram with default values - - // Set 'nbOfBytes' bytes of the payload starting from the 2nd payload byte - // if 'nbOfBytes' val is out of range, then we use the max allowed value instead - void SetLongPayload(const byte origin[], byte nbOfBytes); - // Get 'nbOfBytes' bytes of the payload starting from the 2nd payload byte - // if 'nbOfBytes' val is out of range, then we use the max allowed value instead - void GetLongPayload(byte destination[], byte nbOfBytes) const; - - // Clear the whole payload except the 1st payload byte - void ClearLongPayload(void); - - byte CalculateChecksum(void) const; - // Let the class calculate and update the proper checksum value in the telegram - void UpdateChecksum(void); - - // Whole telegram copy - void Copy(KnxTelegram& dest) const; - // Header Copy (6 1st bytes of the telegram) - void CopyHeader(KnxTelegram& dest) const; - - e_KnxTelegramValidity GetValidity(void) const; - - // DEBUG functions : - void Info(String&) const; // copy telegram info into a string - void InfoRaw(String&) const; // copy raw data telegram into a string - void InfoVerbose(String&) const; // copy verbose telegram info into a string -}; - - -// --------------- Definition of the INLINED functions : ----------------- -inline void KnxTelegram::ChangePriority(e_KnxPriority priority) -{ _controlField &= ~CONTROL_FIELD_PRIORITY_MASK; _controlField |= priority & CONTROL_FIELD_PRIORITY_MASK;} - -inline e_KnxPriority KnxTelegram::GetPriority(void) const -{return (e_KnxPriority)(_controlField & CONTROL_FIELD_PRIORITY_MASK);} - -inline void KnxTelegram::SetRepeated(void ) -{ CONTROL_FIELD_SET_REPEATED(_controlField);}; - -inline boolean KnxTelegram::IsRepeated(void) const -{if (_controlField & CONTROL_FIELD_REPEATED_MASK ) return false; else return true ; } - -inline void KnxTelegram::SetSourceAddress(word addr) { - // WARNING : works with little endianness only - // The adresses within KNX telegram are big endian - _sourceAddrL = (byte) addr; _sourceAddrH = byte(addr>>8);} - -inline word KnxTelegram::GetSourceAddress(void) const { - // WARNING : works with little endianness only - // The adresses within KNX telegram are big endian - word addr; addr = _sourceAddrL + (_sourceAddrH<<8); return addr; } - -inline void KnxTelegram:: SetTargetAddress(word addr) { - // WARNING : works with little endianness only - // The adresses within KNX telegram are big endian - _targetAddrL = (byte) addr; _targetAddrH = byte(addr>>8);} - -inline word KnxTelegram::GetTargetAddress(void) const { - // WARNING : endianess sensitive!! Code below is for LITTLE ENDIAN chip - // The KNX telegram uses BIG ENDIANNESS (Hight byte placed before Low Byte) - word addr; addr = _targetAddrL + (_targetAddrH<<8); return addr; } - -inline boolean KnxTelegram::IsMulticast(void) const -{return (_routing & ROUTING_FIELD_TARGET_ADDRESS_TYPE_MASK);} - -inline void KnxTelegram::SetMulticast(boolean mode) -{ if (mode) _routing|= ROUTING_FIELD_TARGET_ADDRESS_TYPE_MASK; - else _routing &= ~ROUTING_FIELD_TARGET_ADDRESS_TYPE_MASK; } - -inline void KnxTelegram::ChangeRoutingCounter(byte counter) -{ counter <<= 4; _routing &= ~ROUTING_FIELD_COUNTER_MASK; _routing |= (counter & ROUTING_FIELD_COUNTER_MASK); } - -inline byte KnxTelegram::GetRoutingCounter(void) const -{ return ((_routing & ROUTING_FIELD_COUNTER_MASK)>>4); } - -inline void KnxTelegram::SetPayloadLength(byte length) -{ _routing&= ~ROUTING_FIELD_PAYLOAD_LENGTH_MASK ; _routing |= length & ROUTING_FIELD_PAYLOAD_LENGTH_MASK; } - -inline byte KnxTelegram::GetPayloadLength(void) const -{return (_routing & ROUTING_FIELD_PAYLOAD_LENGTH_MASK);} - -inline byte KnxTelegram::GetTelegramLength(void) const -{ return (KNX_TELEGRAM_LENGTH_OFFSET + GetPayloadLength());} - -inline void KnxTelegram::SetCommand(e_KnxCommand cmd) { - _commandH &= ~COMMAND_FIELD_HIGH_COMMAND_MASK; _commandH |= (cmd >> 2); - _commandL &= ~COMMAND_FIELD_LOW_COMMAND_MASK; _commandL |= (cmd << 6);} - -inline e_KnxCommand KnxTelegram::GetCommand(void) const -{return (e_KnxCommand)(((_commandL & COMMAND_FIELD_LOW_COMMAND_MASK)>>6) + ((_commandH & COMMAND_FIELD_HIGH_COMMAND_MASK)<<2)); }; - -inline void KnxTelegram::SetFirstPayloadByte(byte data) -{ _commandL &= ~COMMAND_FIELD_LOW_DATA_MASK ; _commandL |= data & COMMAND_FIELD_LOW_DATA_MASK; } - -inline void KnxTelegram::ClearFirstPayloadByte(void) -{ _commandL &= ~COMMAND_FIELD_LOW_DATA_MASK;} - -inline byte KnxTelegram::GetFirstPayloadByte(void) const -{ return (_commandL & COMMAND_FIELD_LOW_DATA_MASK);} - -inline byte KnxTelegram::ReadRawByte(byte byteIndex) const -{ return _telegram[byteIndex];} - -inline void KnxTelegram::WriteRawByte(byte data, byte byteIndex) -{ _telegram[byteIndex] = data;} - -inline byte KnxTelegram::GetChecksum(void) const -{ return (_payloadChecksum[GetPayloadLength() - 1]);} - -inline boolean KnxTelegram::IsChecksumCorrect(void) const -{ return (GetChecksum()==CalculateChecksum());} - -#endif // KNXTELEGRAM_H \ No newline at end of file diff --git a/src/KonnektingDeviceLibrary/KnxTpUart.cpp b/src/KonnektingDeviceLibrary/KnxTpUart.cpp deleted file mode 100644 index ae36dae..0000000 --- a/src/KonnektingDeviceLibrary/KnxTpUart.cpp +++ /dev/null @@ -1,637 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * It is derived from another GPLv3 licensed project: - * The Arduino Knx Bus Device library allows to turn Arduino into "self-made" KNX bus device. - * Copyright (C) 2014 2015 Franck MARINI (fm@liwan.fr) - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -// File : KnxTpUart.cpp -// Author : Franck Marini -// Modified: Alexander Christian -// Eugen Burkowski - -// Description : Communication with TPUART -// Module dependencies : HardwareSerial, KnxTelegram, KnxComObject - -#include "KnxTpUart.h" -#include "wiring_private.h" - -#ifndef ESP8266 //ESP8266 does't need pgmspace.h -#ifdef ESP32 -#include //ESP32 -#else -#include //rest of the world -#endif -#endif - -/* - * !!!!! IMPORTANT !!!!! - * if "#define DEBUG" is set, you must run your KONNEKTING Suite with "-Dde.root1.slicknx.konnekting.debug=true" - * A release-version of your development MUST NOT contain "#define DEBUG" ... - */ -//#define DEBUG - -static inline word TimeDeltaWord(word now, word before) { - return (word) (now - before); -} - -#ifdef KNXTPUART_DEBUG_INFO -const char KnxTpUart::_debugInfoText[] = "KNXTPUART INFO: "; -#endif - -#ifdef KNXTPUART_DEBUG_ERROR -const char KnxTpUart::_debugErrorText[] = "KNXTPUART ERROR: "; -#endif - - -// Constructor - -//KnxTpUart::KnxTpUart(HardwareSerial& serial, word physicalAddr, type_KnxTpUartMode mode) -//: _serial(serial), _physicalAddr(physicalAddr), _mode(mode) { -KnxTpUart::KnxTpUart(HardwareSerial& serial, word physicalAddr, type_KnxTpUartMode mode) -: _serial(serial), _physicalAddr(physicalAddr), _mode(mode) { - _rx.state = RX_RESET; - _rx.addressedComObjectIndex = 0; - _tx.state = TX_RESET; - _tx.sentTelegram = NULL; - _tx.ackFctPtr = NULL; - _tx.nbRemainingBytes = 0; - _tx.txByteIndex = 0; - _stateIndication = 0; - _evtCallbackFct = NULL; - _comObjectsList = NULL; - _assignedComObjectsNb = 0; - _orderedIndexTable = NULL; - _stateIndication = 0; -#if defined(KNXTPUART_DEBUG_INFO) || defined(KNXTPUART_DEBUG_ERROR) - _debugStrPtr = NULL; -#endif -} - - -// Destructor - -KnxTpUart::~KnxTpUart() { - if (_orderedIndexTable) free(_orderedIndexTable); - // close the serial communication if opened - if ((_rx.state > RX_RESET) || (_tx.state > TX_RESET)) { - _serial.end(); - DebugInfo("Destructor: connection closed, byebye\n"); - } else DebugInfo("Desctructor: byebye\n"); -} - - -// Reset the Arduino UART port and the TPUART device -// Return KNX_TPUART_ERROR in case of TPUART Reset failure - -byte KnxTpUart::Reset(void) { - word startTime, nowTime; - byte attempts = 10; - - DEBUG_PRINTLN(F("Reset triggered!")); - - // HOT RESET case - if ((_rx.state > RX_RESET) || (_tx.state > TX_RESET)) { - DEBUG_PRINTLN(F("HOT RESET case")); - // stop the serial communication before restarting it - _serial.end(); - _rx.state = RX_RESET; - _tx.state = TX_RESET; - } - // CONFIGURATION OF THE ARDUINO USART WITH CORRECT FRAME FORMAT (19200, 8 bits, parity even, 1 stop bit) - _serial.begin(19200, SERIAL_8E1); - pinPeripheral(3, PIO_SERCOM_ALT); - pinPeripheral(1, PIO_SERCOM_ALT); -#ifdef ESP8266 - _serial.swap(); -#endif - while (attempts--) { // we send a RESET REQUEST and wait for the reset indication answer - - DEBUG_PRINTLN(F("Reset attempts: %d"), attempts); - - // the sequence is repeated every sec as long as we do not get the reset indication - _serial.write(TPUART_RESET_REQ); // send RESET REQUEST - - for (nowTime = startTime = (word) millis(); TimeDeltaWord(nowTime, startTime) < 1000 /* 1 sec */; nowTime = (word) millis()) { - if (_serial.available() > 0) { - DEBUG_PRINTLN("Data available: %d",_serial.available()); - byte data = _serial.read(); - if (data == TPUART_RESET_INDICATION) { - _rx.state = RX_INIT; - _tx.state = TX_INIT; - DEBUG_PRINTLN(F("Reset successful")); - return KNX_TPUART_OK; - } else { - DEBUG_PRINTLN("data not useable: 0x%02x. Expected: 0x%02x", data, TPUART_RESET_INDICATION); - } - } - } // 1 sec ellapsed - } // while(attempts--) - _serial.end(); - DEBUG_PRINTLN(F("Reset failed, no answer from TPUART device")); - return KNX_TPUART_ERROR; -} - - -// Attach a list of com objects -// NB1 : only the objects with "communication" attribute are considered by the TPUART -// NB2 : In case of objects with identical address, the object with highest index only is considered -// return KNX_TPUART_ERROR_NOT_INIT_STATE (254) if the TPUART is not in Init state -// The function must be called prior to Init() execution - -byte KnxTpUart::AttachComObjectsList(KnxComObject comObjectsList[], byte listSize) { -#define IS_COM(index) (comObjectsList[index].getIndicator() & KNX_COM_OBJ_C_INDICATOR) -#define ADDR(index) (comObjectsList[index].getAddr()) - - if ((_rx.state != RX_INIT) || (_tx.state != TX_INIT)) return KNX_TPUART_ERROR_NOT_INIT_STATE; - - if (_orderedIndexTable) { // a list is already attached, we detach it - free(_orderedIndexTable); - _orderedIndexTable = NULL; - _comObjectsList = NULL; - _assignedComObjectsNb = 0; - } - if ((!comObjectsList) || (!listSize)) { - DEBUG_PRINTLN(F("AttachComObjectsList : warning : empty object list!\n")); - return KNX_TPUART_OK; - } - // Count all the com objects with communication indicator - for (byte i = 0; i < listSize; i++) if (IS_COM(i)) _assignedComObjectsNb++; - if (!_assignedComObjectsNb) { - DEBUG_PRINTLN(F("AttachComObjectsList : warning : no object with com attribute in the list!")); - return KNX_TPUART_OK; - } - - /* - * Removed duplicate check: GAs are initialized as "active=false", so they are not used. - * As soon as an address is set (only done on startup when reading user-settings from eeprom) - * the flag is set to "active=true" and ComObj is able to communicate. - * - * If device starts with factory settings, all ComObjs have *no* GA, which leads to "duplicates" - * if this check is enabled. - * - * Also it makes no sense to check for duplicates, as it is quite a use-case to have - * multiple ComObjs with same GA - */ - // Deduct the duplicate addresses -// for (byte i = 0; i < listSize; i++) { -// if (!IS_COM(i)) continue; -// for (byte j = 0; j < listSize; j++) { -// if ((i != j) && (ADDR(j) == ADDR(i)) && (IS_COM(j))) { // duplicate address found -// if (j < i) break; // duplicate address already treated -// else { -// _assignedComObjectsNb--; -// DEBUG_PRINTLN(F("AttachComObjectsList : warning : duplicate address found! i=%d:0x%04x j=%d:0x%04x"), i, j, ADDR(i), ADDR(j)); -// } -// } -// } -// } - _comObjectsList = comObjectsList; - - // Creation of the ordered index table - _orderedIndexTable = (byte*) malloc(_assignedComObjectsNb); - word minMin = 0x0000; // minimum min value searched - word foundMin = 0xFFFF; // min value found so far - for (byte i = 0; i < _assignedComObjectsNb; i++) { - for (byte j = 0; j < listSize; j++) { - if ((IS_COM(j)) && (ADDR(j) >= minMin) && (ADDR(j) <= foundMin)) { - foundMin = ADDR(j); - _orderedIndexTable[i] = j; - } - } - minMin = foundMin + 1; - foundMin = 0xFFFF; - } -// DEBUG_PRINTLN(F("AttachComObjectsList successful\n")); - return KNX_TPUART_OK; -} - - -// Init -// returns ERROR (255) if the TP-UART is not in INIT state, else returns OK (0) -// Init must be called after every reset() execution - -byte KnxTpUart::Init(void) { -// byte tpuartCmd[3]; - - if ((_rx.state != RX_INIT) || (_tx.state != TX_INIT)) return KNX_TPUART_ERROR_NOT_INIT_STATE; - - // BUS MONITORING MODE in case it is selected - if (_mode == BUS_MONITOR) { - _serial.write(TPUART_ACTIVATEBUSMON_REQ); // Send bus monitoring activation request - DEBUG_PRINTLN(F("Init : Monitoring mode started\n")); - } else // NORMAL mode by default - { - if (_comObjectsList == NULL) DEBUG_PRINTLN(F("Init : warning : empty object list!\n")); - if (_evtCallbackFct == NULL) return KNX_TPUART_ERROR_NULL_EVT_CALLBACK_FCT; - if (_tx.ackFctPtr == NULL) return KNX_TPUART_ERROR_NULL_ACK_CALLBACK_FCT; -/* - // Set Physical address. This allows to activate address evaluation by the TPUART - we don't need it anymore. it fixes also bug with PA 1.1.1 on NCN5120 - tpuartCmd[0] = TPUART_SET_ADDR_REQ; - tpuartCmd[1] = (byte) (_physicalAddr >> 8); - tpuartCmd[2] = (byte) _physicalAddr; - _serial.write(tpuartCmd, 3); - - // Call U_State.request-Service in order to have the field _stateIndication up-to-date - _serial.write(TPUART_STATE_REQ); -*/ - _rx.state = RX_IDLE_WAITING_FOR_CTRL_FIELD; - _tx.state = TX_IDLE; - DEBUG_PRINTLN(F("Init : Normal mode started\n")); - } - return KNX_TPUART_OK; -} - - -// Send a KNX telegram -// returns ERROR (255) if TX is not available, or if the telegram is not valid, else returns OK (0) -// NB : the source address is forced to TPUART physical address value - -byte KnxTpUart::SendTelegram(KnxTelegram& sentTelegram) { - if (_tx.state != TX_IDLE) return KNX_TPUART_ERROR; // TX not initialized or busy - - if (sentTelegram.GetSourceAddress() != _physicalAddr) // Check that source addr equals TPUART physical addr - { // if not, let's force source addr to the correct value - sentTelegram.SetSourceAddress(_physicalAddr); - sentTelegram.UpdateChecksum(); - } - _tx.sentTelegram = &sentTelegram; - _tx.nbRemainingBytes = sentTelegram.GetTelegramLength(); - _tx.txByteIndex = 0; // Set index to 0 - _tx.state = TX_TELEGRAM_SENDING_ONGOING; - return KNX_TPUART_OK; -} - - -/* - * Reception task - * - * This function shall be called periodically in order to allow a correct reception of the KNX bus data - * Assuming the TPUART speed is configured to 19200 baud, a character (8 data + 1 start + 1 parity + 1 stop) - * is transmitted in 0,58ms. - * In order not to miss any End Of Packets (i.e. a gap from 2 to 2,5ms), the function shall be called at a - * max period of 0,5ms. - * Typical calling period is 400 usec. - * - * DO NOT PUT DEBUG PRINT CODE HERE! Telegram receiving will break! - */ -void KnxTpUart::RXTask(void) { - byte incomingByte; - word nowTime; - static bool telegramCompletelyReceived = false; - static byte expectedTelegramLength = 0; - static byte readBytesNb; // Nb of read bytes during an KNX telegram reception - static KnxTelegram telegram; // telegram being received - static byte addressedComObjectIndex; // index of the com object targeted by the received telegram - static word lastByteRxTimeMicrosec; - - // === STEP 1 : Check EOP in case a Telegram is being received === - if (_rx.state >= RX_KNX_TELEGRAM_RECEPTION_STARTED) { // a telegram reception is ongoing - - nowTime = (word) micros(); // word cast because a 65ms looping counter is long enough - if (TimeDeltaWord(nowTime, lastByteRxTimeMicrosec) > KNX_RECEPTION_TIMEOUT || telegramCompletelyReceived) { // EOP detected, the telegram reception is completed -// DEBUG_PRINTLN(F("EOP REACHED")); - telegramCompletelyReceived = false; - switch (_rx.state) { - case RX_KNX_TELEGRAM_RECEPTION_STARTED: // we are not supposed to get EOP now, the telegram is incomplete -// DEBUG_PRINTLN(F("RX_KNX_TELEGRAM_RECEPTION_STARTED")); - case RX_KNX_TELEGRAM_RECEPTION_LENGTH_INVALID: -// DEBUG_PRINTLN(F("RX_KNX_TELEGRAM_RECEPTION_LENGTH_INVALID")); - _evtCallbackFct(TPUART_EVENT_KNX_TELEGRAM_RECEPTION_ERROR); // Notify telegram reception error -// DEBUG_PRINTLN(F("TPUART_EVENT_KNX_TELEGRAM_RECEPTION_ERROR")); - break; - - case RX_KNX_TELEGRAM_RECEPTION_ADDRESSED: -// DEBUG_PRINTLN(F("RX_KNX_TELEGRAM_RECEPTION_ADDRESSED")); - if (telegram.IsChecksumCorrect()) { // checksum correct, let's update the _rx struct with the received telegram and correct index - telegram.Copy(_rx.receivedTelegram); - _rx.addressedComObjectIndex = addressedComObjectIndex; - _evtCallbackFct(TPUART_EVENT_RECEIVED_KNX_TELEGRAM); // Notify the new received telegram - } else { // checksum incorrect, notify error -// DEBUG_PRINTLN(F("checksum incorrect")); - _evtCallbackFct(TPUART_EVENT_KNX_TELEGRAM_RECEPTION_ERROR); // Notify telegram reception error - } - break; - - // case RX_KNX_TELEGRAM_RECEPTION_NOT_ADDRESSED : break; // nothing to do! - - default: - break; - } // end of switch - - // we move state back to RX IDLE in any case - _rx.state = RX_IDLE_WAITING_FOR_CTRL_FIELD; - } // end EOP detected - } - - // === STEP 2 : Get New RX Data === - if (_serial.available() > 0) { - incomingByte = (byte) (_serial.read()); - lastByteRxTimeMicrosec = (word) micros(); -// DEBUG_PRINTLN(F("RX: incomingByte=0x%02x, readBytesNb=%d"), incomingByte, readBytesNb); - - switch (_rx.state) { - - case RX_IDLE_WAITING_FOR_CTRL_FIELD: -// DEBUG_PRINTLN(F("RX_IDLE_WAITING_FOR_CTRL_FIELD incomingByte=0x%02x, readBytesNb=%d"), incomingByte, readBytesNb); - - // CASE OF KNX MESSAGE - if ((incomingByte & KNX_CONTROL_FIELD_PATTERN_MASK) == KNX_CONTROL_FIELD_VALID_PATTERN) { - _rx.state = RX_KNX_TELEGRAM_RECEPTION_STARTED; - readBytesNb = 1; - telegram.WriteRawByte(incomingByte, 0); -// DEBUG_PRINTLN(F("RX_KNX_TELEGRAM_RECEPTION_STARTED")); - } - // CASE OF TPUART_DATA_CONFIRM_SUCCESS NOTIFICATION - else if (incomingByte == TPUART_DATA_CONFIRM_SUCCESS) { - if (_tx.state == TX_WAITING_ACK) { - _tx.ackFctPtr(ACK_RESPONSE); - _tx.state = TX_IDLE; - } else { -// DEBUG_PRINTLN(F("Rx: unexpected TPUART_DATA_CONFIRM_SUCCESS received!")); - } - } - // CASE OF TPUART_RESET NOTIFICATION - else if (incomingByte == TPUART_RESET_INDICATION) { - - if ((_tx.state == TX_TELEGRAM_SENDING_ONGOING) || (_tx.state == TX_WAITING_ACK)) { // response to the TP UART transmission - _tx.ackFctPtr(TPUART_RESET_RESPONSE); - } - _tx.state = TX_STOPPED; - _rx.state = RX_STOPPED; - _evtCallbackFct(TPUART_EVENT_RESET); // Notify RESET -// DEBUG_PRINTLN(F("Rx: Reset Indication Received")); - return; - } - // CASE OF STATE_INDICATION RESPONSE - else if ((incomingByte & TPUART_STATE_INDICATION_MASK) == TPUART_STATE_INDICATION) { - _evtCallbackFct(TPUART_EVENT_STATE_INDICATION); // Notify STATE INDICATION - _stateIndication = incomingByte; -// DEBUG_PRINTLN(F("Rx: State Indication Received")); - } - // CASE OF TPUART_DATA_CONFIRM_FAILED NOTIFICATION - else if (incomingByte == TPUART_DATA_CONFIRM_FAILED) { - // NACK following Telegram transmission - if (_tx.state == TX_WAITING_ACK) { - _tx.ackFctPtr(NACK_RESPONSE); - _tx.state = TX_IDLE; - } else DEBUG_PRINTLN(F("Rx: unexpected TPUART_DATA_CONFIRM_FAILED received!")); - } - // UNKNOWN CONTROL FIELD RECEIVED - else if (incomingByte) { -// DEBUG_PRINTLN(F("Rx: Unknown Control Field received: byte=0x%02x"), incomingByte); - } - // else ignore "0" value sent on Reset by TPUART prior to TPUART_RESET_INDICATION - break; - - case RX_KNX_TELEGRAM_RECEPTION_STARTED: -// DEBUG_PRINTLN(F("RX_KNX_TELEGRAM_RECEPTION_STARTED incomingByte=0x%02x, readBytesNb=%d"), incomingByte, readBytesNb); - telegram.WriteRawByte(incomingByte, readBytesNb); - readBytesNb++; - - //we should try to comment out this check, because we can send telegrams that should be received by own self - if (readBytesNb == 3) { // We have just received the source address - // we check whether the received KNX telegram is coming from us (i.e. telegram is sent by the TPUART itself) -// DEBUG_PRINTLN(F("SourceAddress: %d.%d.%d"), (telegram.GetSourceAddress() >> 12), (telegram.GetSourceAddress() >> 8) & 0x0F, telegram.GetSourceAddress() & 0xFF); - if (telegram.GetSourceAddress() == _physicalAddr) { // the message is coming from us, we consider it as not addressed and we don't send any ACK service -// DEBUG_PRINTLN(F("message from us, skip.")); - _rx.state = RX_KNX_TELEGRAM_RECEPTION_NOT_ADDRESSED; - } - } else if (readBytesNb == 6) // We have just read the routing field containing the address type and the payload length - { - // Telegram length is payload length + 7 bytes "overhead" - expectedTelegramLength = (incomingByte & KNX_PAYLOAD_LENGTH_MASK) + 7; -// DEBUG_PRINTLN(F("TargetAddress: %d/%d/%d"), (telegram.GetTargetAddress() >> 11), (telegram.GetTargetAddress() >> 8) & 0x07, telegram.GetTargetAddress() & 0xFF); - - // We check if the message is addressed to us in order to send the appropriate acknowledge - if (IsAddressAssigned(telegram.GetTargetAddress(), addressedComObjectIndex)) { // Message addressed to us - -// DEBUG_PRINTLN(F("assigned to us: ga=0x%04x index=%d"), telegram.GetTargetAddress(), addressedComObjectIndex); - - _rx.state = RX_KNX_TELEGRAM_RECEPTION_ADDRESSED; - //sent the correct ACK service now - // the ACK info must be sent latest 1,7 ms after receiving the address type octet of an addressed frame - _serial.write(TPUART_RX_ACK_SERVICE_ADDRESSED); - - // dirty workaround fpr sending ACk just before reset? - // _serial.flush(); - } else { // Message NOT addressed to us - _rx.state = RX_KNX_TELEGRAM_RECEPTION_NOT_ADDRESSED; - //sent the correct ACK service now - // the ACK info must be sent latest 1,7 ms after receiving the address type octet of an addressed frame - _serial.write(TPUART_RX_ACK_SERVICE_NOT_ADDRESSED); - - // dirty workaround fpr sending ACk just before reset? - // _serial.flush(); - } - } - break; - - case RX_KNX_TELEGRAM_RECEPTION_ADDRESSED: - -// DEBUG_PRINTLN(F("RX_KNX_TELEGRAM_RECEPTION_ADDRESSED")); - - if (readBytesNb == KNX_TELEGRAM_MAX_SIZE) { - _rx.state = RX_KNX_TELEGRAM_RECEPTION_LENGTH_INVALID; - DEBUG_PRINTLN(F("RX_KNX_TELEGRAM_RECEPTION_LENGTH_INVALID")); - } else { - telegram.WriteRawByte(incomingByte, readBytesNb); - // DEBUG_PRINTLN(F("expectedTelegramLength: %d, readBytesNb: %d"),expectedTelegramLength,readBytesNb); - if (expectedTelegramLength == readBytesNb) { - telegramCompletelyReceived = true; - //we are done with reception -// DEBUG_PRINTLN(F("we are done, telegramCompletelyReceived: %d"),telegramCompletelyReceived); - } else { - - readBytesNb++; - } - } - break; - - // case RX_KNX_TELEGRAM_RECEPTION_LENGTH_INVALID : break; // if the message is too long, nothing to do except waiting for EOP - // case RX_KNX_TELEGRAM_RECEPTION_NOT_ADDRESSED : break; // if the message is not addressed, nothing to do except waiting for EOP - - default: - break; - } // switch (_rx.state) - } // if (_serial.available() > 0) -} - - -/** - * Transmission task - * This function shall be called periodically in order to allow a correct transmission of the KNX bus data - * Assuming the TP-Uart speed is configured to 19200 baud, a character (8 data + 1 start + 1 parity + 1 stop) - * is transmitted in 0,58ms. - * Sending one byte of a telegram consists in transmitting 2 characters (1,16ms) - * Let's wait around 800us between each telegram piece sending so that the 64byte TX buffer remains almost empty. - * Typical calling period is 800 usec. - */ -void KnxTpUart::TXTask(void) { - word nowTime; - byte txByte[2]; - static word sentMessageTimeMillisec; - - // STEP 1 : Manage Message Acknowledge timeout - switch (_tx.state) { - case TX_WAITING_ACK: - // A transmission ACK is awaited, increment Acknowledge timeout - nowTime = (word) millis(); // word is enough to count up to 500 - if (TimeDeltaWord(nowTime, sentMessageTimeMillisec) > 500 /* 500 ms */) { // The no-answer timeout value is defined as follows : - // - The emission duration for a single max sized telegram is 40ms - // - The telegram emission might be repeated 3 times (120ms) - // - The telegram emission might be delayed by another message transmission ongoing - // - The telegram emission might be delayed by the simultaneous transmission of higher prio messages - // Let's take around 3 times the max emission duration (160ms) as arbitrary value - _tx.ackFctPtr(NO_ANSWER_TIMEOUT); // Send a No Answer TIMEOUT - _tx.state = TX_IDLE; - } - break; - - case TX_TELEGRAM_SENDING_ONGOING: - // STEP 2 : send message if any to send - // In case a telegram reception has just started, and the ACK has not been sent yet, - // we block the transmission (for around 3,3ms) till the ACK is sent - // In that way, the TX buffer will remain empty and the ACK will be sent immediately - if (_rx.state != RX_KNX_TELEGRAM_RECEPTION_STARTED) { - if (_tx.nbRemainingBytes == 1) { // We are sending the last byte, i.e checksum - txByte[0] = TPUART_DATA_END_REQ + _tx.txByteIndex; - txByte[1] = _tx.sentTelegram->ReadRawByte(_tx.txByteIndex); - //DEBUG_PRINTLN(F("data1[%d]=0x%02x"),_tx.txByteIndex, txByte[1]); - _serial.write(txByte, 2); // write the UART control field and the data byte - - // Message sending completed - sentMessageTimeMillisec = (word) millis(); // memorize sending time in order to manage ACK timeout - _tx.state = TX_WAITING_ACK; - } else { - txByte[0] = TPUART_DATA_START_CONTINUE_REQ + _tx.txByteIndex; - txByte[1] = _tx.sentTelegram->ReadRawByte(_tx.txByteIndex); - //DEBUG_PRINTLN(F("data2[%d]=0x%02x"),_tx.txByteIndex, txByte[1]); - _serial.write(txByte, 2); // write the UART control field and the data byte - _tx.txByteIndex++; - _tx.nbRemainingBytes--; - } - } - break; - - default: break; - } // switch -} - - -/** Get Bus monitoring data (BUS MONITORING mode) - * The function returns true if a new data has been retrieved (data pointer in argument), else false - * It shall be called periodically (max period of 0,5ms) in order to allow correct data reception - * Typical calling period is 400 usec. - */ -boolean KnxTpUart::GetMonitoringData(type_MonitorData& data) { - word nowTime; - static type_MonitorData currentData = {true, 0}; - static word lastByteRxTimeMicrosec; - - // STEP 1 : Check EOP - if (!(currentData.isEOP)) // check that we have not already detected an EOP - { - nowTime = (word) micros(); // word cast because a 65ms counter is enough - if (TimeDeltaWord(nowTime, lastByteRxTimeMicrosec) > 2000 /* 2 ms */) { // EOP detected - currentData.isEOP = true; - currentData.dataByte = 0; - data = currentData; - return true; - } - } - // STEP 2 : Get New RX Data - if (_serial.available() > 0) { - currentData.dataByte = (byte) (_serial.read()); - currentData.isEOP = false; - data = currentData; - lastByteRxTimeMicrosec = (word) micros(); - return true; - } - return false; // No data received -} - - -/** - * Check if the target address is an assigned com object one - * if yes, then update index parameter with the index (in the list) - * of the targeted com object and return true else return false - * - * WARNING: DO NOT ADD DEBUG CODE HERE, AS IT WILL BREAK TELEGRAM RECEIVIBG (Timing issues) - * - * @param addr the GA to check for assignment - * @param index the index variable will be filled with the index matching this GA - * @return true if assigned & active, false if not - */ -boolean KnxTpUart::IsAddressAssigned(word addr, byte &index) const { - -// DEBUG_PRINTLN(F("IsAddressAssigned: 0x%04x"), addr); - byte divisionCounter = 0; - byte i, searchIndexStart, searchIndexStop, searchIndexRange; - - if (!_assignedComObjectsNb) return false; // in case of empty list, we return immediately - - if (addr == 0x7fff) { - index = 255; -// DEBUG_PRINTLN(F("IsAddressAssigned: 0x%04x == 0x7fff --> progComObj. index=%d"), addr, index); - return true; - } - - // Define how many divisions by 2 shall be done in order to reduce the search list by 8 Addr max - // if _assignedComObjectsNb >= 16 => divisionCounter = 1 - // if _assignedComObjectsNb >= 32 => divisionCounter = 2 - // if _assignedComObjectsNb >= 64 => divisionCounter = 3 - // if _assignedComObjectsNb >= 128 => divisionCounter = 4 - for (i = 4; _assignedComObjectsNb >> i; i++) divisionCounter++; - - // the starting point is to search on the whole address range (0 -> _assignedComObjectsNb -1) - searchIndexStart = 0; - searchIndexStop = _assignedComObjectsNb - 1; - searchIndexRange = _assignedComObjectsNb; - - // reduce the address range if needed - while (divisionCounter) { - searchIndexRange >>= 1; // Divide range width by 2 - if (addr >= _comObjectsList[_orderedIndexTable[searchIndexStart + searchIndexRange]].getAddr()) - searchIndexStart += searchIndexRange; - else searchIndexStop -= searchIndexRange; - divisionCounter--; - } - - // search the address value and index in the reduced range - for (i = searchIndexStart; ((_comObjectsList[_orderedIndexTable[i]].getAddr() != addr) && (i <= searchIndexStop)); i++); - - if (i > searchIndexStop) { - return false; // Address is NOT part of the assigned addresses - } - - // Address is part of the assigned addresses - index = _orderedIndexTable[i]; - -// DEBUG_PRINTLN(F("IsAddressAssigned: index=%d active=%d"), index, _comObjectsList[index].isActive()); - - if (_comObjectsList[index].isActive()) { - // CO is found AND is active - return true; - } else { - // CO is found but is NOT active - return false; - } -} -//EOF diff --git a/src/KonnektingDeviceLibrary/KnxTpUart.h b/src/KonnektingDeviceLibrary/KnxTpUart.h deleted file mode 100644 index 64b2d5f..0000000 --- a/src/KonnektingDeviceLibrary/KnxTpUart.h +++ /dev/null @@ -1,369 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * It is derived from another GPLv3 licensed project: - * The Arduino Knx Bus Device library allows to turn Arduino into "self-made" KNX bus device. - * Copyright (C) 2014 2015 Franck MARINI (fm@liwan.fr) - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -// File : KnxTpUart.h -// Author : Franck Marini -// Modified: Alexander Christian -// Description : Communication with TPUART -// Module dependencies : HardwareSerial, KnxTelegram, KnxComObject - -// This library supports both TPUART version 1 and 2 -// The Siemens KNX TPUART version 1 datasheet is available at : -// http://www.hqs.sbt.siemens.com/Lowvoltage/gamma_product_data/gamma-b2b/tpuart.pdf -// The Siemens KNX TPUART version 2 datasheet is available at : -// http://www.hqs.sbt.siemens.com/Lowvoltage/gamma_product_data/gamma-b2b/TPUART2_technical-data.pdf - -#ifndef KNXTPUART_H -#define KNXTPUART_H - -#include "Arduino.h" -#include "DebugUtil.h" -#include "HardwareSerial.h" -#include "KnxTelegram.h" -#include "KnxComObject.h" - -// !!!!!!!!!!!!!!! FLAG OPTIONS !!!!!!!!!!!!!!!!! -// DEBUG : -// #define KNXTPUART_DEBUG_INFO // Uncomment to activate info traces -// #define KNXTPUART_DEBUG_ERROR // Uncomment to activate error traces - - -// Values returned by the KnxTpUart member functions : -#define KNX_TPUART_OK 0 -#define KNX_TPUART_ERROR 255 -#define KNX_TPUART_ERROR_NOT_INIT_STATE 254 -#define KNX_TPUART_ERROR_NULL_EVT_CALLBACK_FCT 253 -#define KNX_TPUART_ERROR_NULL_ACK_CALLBACK_FCT 252 -#define KNX_TPUART_ERROR_RESET 251 - - -// Services to TPUART (hostcontroller -> TPUART) : -#define TPUART_RESET_REQ 0x01 -#define TPUART_STATE_REQ 0x02 -#define TPUART_SET_ADDR_REQ 0x28 -#define TPUART_DATA_START_CONTINUE_REQ 0x80 -#define TPUART_DATA_END_REQ 0x40 -#define TPUART_ACTIVATEBUSMON_REQ 0x05 -#define TPUART_RX_ACK_SERVICE_ADDRESSED 0x11 -#define TPUART_RX_ACK_SERVICE_NOT_ADDRESSED 0x10 - - -// Services from TPUART (TPUART -> hostcontroller) : -// 3 types of data are transmitted from TPUART to the host : -// 1) KNX bus data (transparently transmitted). Format = KNX control field byte + rest of the telegram -// 2) Additional information from the TP-UART. Format = 1 data byte -// 3) Immediate acknowledge services (BUS MONITOR mode only) -#define TPUART_RESET_INDICATION 0x03 -#define TPUART_DATA_CONFIRM_SUCCESS 0x8B -#define TPUART_DATA_CONFIRM_FAILED 0x0B -#define TPUART_STATE_INDICATION 0x07 -#define TPUART_STATE_INDICATION_MASK 0x07 -#define KNX_CONTROL_FIELD_PATTERN_MASK B11010011 // 0xD3 -#define KNX_CONTROL_FIELD_VALID_PATTERN B10010000 // 0x90, Only Standard Frame Format "10" is handled -#define KNX_PAYLOAD_LENGTH_MASK B00001111 // 0x0F, last 4 bits, only Standard Frame is supported - - -// Mask for STATE INDICATION service -#define TPUART_STATE_INDICATION_SLAVE_COLLISION_MASK 0x80 -#define TPUART_STATE_INDICATION_RECEIVE_ERROR_MASK 0x40 -#define TPUART_STATE_INDICATION_TRANSMIT_ERROR_MASK 0x20 -#define TPUART_STATE_INDICATION_PROTOCOL_ERROR_MASK 0x10 -#define TPUART_STATE_INDICATION_TEMP_WARNING_MASK 0x08 - -// Time out/EOP by telegram recption (us) -#ifdef ESP32 -// ESP32 more time, maybe will be fixed in future -#define KNX_RECEPTION_TIMEOUT 30000 -#else -// all other MCU are fine with 2000us -#define KNX_RECEPTION_TIMEOUT 2000 -#endif - -// Definition of the TP-UART working modes -enum type_KnxTpUartMode { NORMAL, - BUS_MONITOR }; - -// Definition of the TP-UART events sent to the application layer -enum e_KnxTpUartEvent { - TPUART_EVENT_RESET = 0, // reset received from the TPUART device - TPUART_EVENT_RECEIVED_KNX_TELEGRAM, // a new addressed KNX Telegram has been received - TPUART_EVENT_KNX_TELEGRAM_RECEPTION_ERROR, // a new addressed KNX telegram reception failed - TPUART_EVENT_STATE_INDICATION // new TPUART state indication received - }; - -// Typedef for events callback function -typedef void (*type_EventCallbackFctPtr) (e_KnxTpUartEvent); - -// --- Definitions for the RECEPTION part ---- -// RX states -enum e_TpUartRxState { - RX_RESET = 0, // The RX part is awaiting reset execution - RX_STOPPED, // TPUART reset event received, RX activity is stopped - RX_INIT, // The RX part is awaiting init execution - RX_IDLE_WAITING_FOR_CTRL_FIELD, // Idle, no reception ongoing - RX_KNX_TELEGRAM_RECEPTION_STARTED, // Telegram reception started (address evaluation not done yet) - RX_KNX_TELEGRAM_RECEPTION_ADDRESSED, // Addressed telegram reception ongoing - RX_KNX_TELEGRAM_RECEPTION_LENGTH_INVALID, // The telegram being received is too long - RX_KNX_TELEGRAM_RECEPTION_NOT_ADDRESSED // Tegram reception ongoing but not addressed -}; - -typedef struct { - e_TpUartRxState state; // Current TPUART RX state - KnxTelegram receivedTelegram; // Where each received telegram is stored (the content is overwritten on each telegram reception) - // A TPUART_EVENT_RECEIVED_KNX_TELEGRAM event notifies each content change - byte addressedComObjectIndex; // Where the index to the targeted com object is stored (the value is overwritten on each telegram reception) - // A TPUART_EVENT_RECEIVED_KNX_TELEGRAM event notifies each content change -} type_tpuart_rx; - -// --- Definitions for the TRANSMISSION part ---- -// Transmission states -enum e_TpUartTxState { - TX_RESET = 0, // The TX part is awaiting reset execution - TX_STOPPED, // TPUART reset event received, TX activity is stopped - TX_INIT, // The TX part is awaiting init execution - TX_IDLE, // Idle, no transmission ongoing - TX_TELEGRAM_SENDING_ONGOING, // KNX telegram transmission ongoing - TX_WAITING_ACK // Telegram transmitted, waiting for ACK/NACK -}; - -// Acknowledge values following a telegram sending -enum e_TpUartTxAck { - ACK_RESPONSE = 0, // TPUART received an ACK following telegram sending - NACK_RESPONSE, // TPUART received a NACK following telegram sending (1+3 attempts by default) - NO_ANSWER_TIMEOUT, // No answer (Data_Confirm) received from the TPUART - TPUART_RESET_RESPONSE // TPUART RESET before we get any ACK -}; - -// Typedef for TX acknowledge callback function -typedef void (*type_AckCallbackFctPtr) (e_TpUartTxAck); - -typedef struct tpuart_tx { - e_TpUartTxState state; // Current TPUART TX state - KnxTelegram *sentTelegram; // Telegram being sent - type_AckCallbackFctPtr ackFctPtr; // Pointer to callback function for TX ack - byte nbRemainingBytes; // Nb of bytes remaining to be transmitted - byte txByteIndex; // Index of the byte to be sent -} type_tpuart_tx; - - -// --- Typdef for BUS MONITORING mode data ---- -typedef struct { - boolean isEOP; // True if the data is an End Of Packet - byte dataByte; // Last data retrieved on the bus (valid when isEOP is false) -} type_MonitorData; - - -class KnxTpUart { - HardwareSerial& _serial; // Arduino HW serial port connected to the TPUART - const word _physicalAddr; // Physical address set in the TP-UART - const type_KnxTpUartMode _mode; // TpUart working Mode (Normal/Bus Monitor) - type_tpuart_rx _rx; // Reception structure - type_tpuart_tx _tx; // Transmission structure - type_EventCallbackFctPtr _evtCallbackFct; // Pointer to the EVENTS callback function - KnxComObject *_comObjectsList; // Attached list of com objects - byte _assignedComObjectsNb; // Nb of assigned com objects - byte *_orderedIndexTable; // Table containing the assigned com objects indexes ordered by increasing @ - byte _stateIndication; // Value of the last received state indication -#if defined(KNXTPUART_DEBUG_INFO) || defined(KNXTPUART_DEBUG_ERROR) - String *_debugStrPtr; -#endif - -#ifdef KNXTPUART_DEBUG_INFO -static const char _debugInfoText[]; -#endif -#ifdef KNXTPUART_DEBUG_ERROR -static const char _debugErrorText[]; -#endif - - public: - - // Constructor / Destructor - KnxTpUart(HardwareSerial& serial, word physicalAddr, type_KnxTpUartMode _mode); - ~KnxTpUart(); - - // INLINED functions (see definitions later in this file) - - // Set EVENTs callback function - // return KNX_TPUART_ERROR (255) if the parameter is NULL - // return KNX_TPUART_ERROR_NOT_INIT_STATE (254) if the TPUART is not in Init state - // else return OK - // The function must be called prior to Init() execution - byte SetEvtCallback(type_EventCallbackFctPtr); - - // Set ACK callback function - // return KNX_TPUART_ERROR (255) if the parameter is NULL - // return KNX_TPUART_ERROR_NOT_INIT_STATE (254) if the TPUART is not in Init state - // else return OK - // The function must be called prior to Init() execution - byte SetAckCallback(type_AckCallbackFctPtr); - - // Get the value of the last received State Indication - // NB : every state indication value change is notified by a "TPUART_EVENT_STATE_INDICATION" event - byte GetStateIndication(void) const; - - // Get the reference to the telegram received by the TPUART - // NB : every received telegram content change is notified by a "TPUART_EVENT_RECEIVED_KNX_TELEGRAM" event - KnxTelegram& GetReceivedTelegram(void); - - // Get the index of the com object targeted by the last received telegram - byte GetTargetedComObjectIndex(void) const; - - // returns true if there is an activity ongoing (RX/TX) on the TPUART - // false when there's no activity or when the tpuart is not initialized - boolean IsActive(void) const; - - // Set the string used for debug traces - void SetDebugString(String *strPtr); - - // Functions NOT INLINED - // Reset the Arduino UART port and the TPUART device - // Return KNX_TPUART_ERROR in case of TPUART reset failure - byte Reset(void); - - // Attach a list of com objects - // NB1 : only the objects with "communication" attribute are considered by the TPUART - // NB2 : In case of objects with identical address, the object with highest index only is considered - // return KNX_TPUART_ERROR_NOT_INIT_STATE (254) if the TPUART is not in Init state - // The function must be called prior to Init() execution - byte AttachComObjectsList(KnxComObject KnxComObjectsList[], byte listSize); - - // Init - // returns ERROR (255) if the TP-UART is not in INIT state, else returns OK (0) - // Init must be called after every reset() execution - byte Init(void); - - // Send a KNX telegram - // returns ERROR (255) if TX is not available or if the telegram is not valid, else returns OK (0) - // NB : the source address is forced to TPUART physical address value - byte SendTelegram(KnxTelegram& sentTelegram); - - // Reception task - // This function shall be called periodically in order to allow a correct reception of the KNX bus data - // Assuming the TPUART speed is configured to 19200 baud, a character (8 data + 1 start + 1 parity + 1 stop) - // is transmitted in 0,58ms. - // In order not to miss any End Of Packets (i.e. a gap from 2 to 2,5ms), the function shall be called at a max period of 0,5ms. - // Typical calling period is 400 usec. - void RXTask(void); - - // Transmission task - // This function shall be called periodically in order to allow a correct transmission of the KNX bus data - // Assuming the TP-Uart speed is configured to 19200 baud, a character (8 data + 1 start + 1 parity + 1 stop) - // is transmitted in 0,58ms. - // Sending one byte of a telegram consists in transmitting 2 characters (1,16ms) - // Let's wait around 800us between each telegram piece sending so that the 64byte TX buffer remains almost empty. - // Typical calling period is 800 usec. - void TXTask(void); - - // Get Bus monitoring data (BUS MONITORING mode) - // The function returns true if a new data has been retrieved (data pointer in argument), else false - // It shall be called periodically (max period of 0,5ms) in order to allow correct data reception - // Typical calling period is 400 usec. - boolean GetMonitoringData(type_MonitorData&); - - private: - - // Private INLINED functions (see definitions later in this file) - void DebugInfo(const char[]) const; - - void DebugError(const char[]) const; - - // Private NOT INLINED functions - // Check if the target address points to an assigned com object (i.e. the target address equals a com object address) - // if yes, then update index parameter with the index (in the list) of the targeted com object and return true - // else return false - boolean IsAddressAssigned(word addr, byte &index) const; -}; - - -// ----- Definition of the INLINED functions : ------------ - -inline byte KnxTpUart::SetEvtCallback(type_EventCallbackFctPtr evtCallbackFct) -{ - if (evtCallbackFct == NULL) return KNX_TPUART_ERROR; - if ((_rx.state!=RX_INIT) || (_tx.state!=TX_INIT)) return KNX_TPUART_ERROR_NOT_INIT_STATE; - _evtCallbackFct = evtCallbackFct; - return KNX_TPUART_OK; -} - -inline byte KnxTpUart::SetAckCallback(type_AckCallbackFctPtr ackFctPtr) -{ - if (ackFctPtr == NULL) return KNX_TPUART_ERROR; - if ((_rx.state!=RX_INIT) || (_tx.state!=TX_INIT)) return KNX_TPUART_ERROR_NOT_INIT_STATE; - _tx.ackFctPtr = ackFctPtr; - return KNX_TPUART_OK; -} - -inline byte KnxTpUart::GetStateIndication(void) const { return _stateIndication; } - -inline KnxTelegram& KnxTpUart::GetReceivedTelegram(void) -{ return _rx.receivedTelegram; } - - -inline byte KnxTpUart::GetTargetedComObjectIndex(void) const -{ return _rx.addressedComObjectIndex; } // return the index of the adress addressed by the received KNX Telegram - - -inline boolean KnxTpUart::IsActive(void) const -{ - if ( _rx.state > RX_IDLE_WAITING_FOR_CTRL_FIELD) return true; // Rx activity - if ( _tx.state > TX_IDLE) return true; // Tx activity - return false; -} - - - -inline void KnxTpUart::SetDebugString(String * -#if defined(KNXTPUART_DEBUG_INFO) || defined(KNXTPUART_DEBUG_ERROR) // ifdef to suppress compiler warning about unused variable when not in debug mode - strPtr -#endif - ) -{ -#if defined(KNXTPUART_DEBUG_INFO) || defined(KNXTPUART_DEBUG_ERROR) - _debugStrPtr = strPtr; -#endif -} - - -inline void KnxTpUart::DebugInfo(const char -#if defined(KNXTPUART_DEBUG_INFO) // ifdef to suppress compiler warning about unused variable when not in debug mode - comment -#endif - []) const -{ -#if defined(KNXTPUART_DEBUG_INFO) - if (_debugStrPtr != NULL) *_debugStrPtr += String(_debugInfoText) + String(comment); -#endif -} - - -inline void KnxTpUart::DebugError(const char -#if defined(KNXTPUART_DEBUG_ERROR) // ifdef to suppress compiler warning about unused variable when not in debug mode - comment -#endif - []) const -{ -#if defined(KNXTPUART_DEBUG_ERROR) - if (_debugStrPtr != NULL) *_debugStrPtr += String(_debugErrorText) + String(comment); -#endif -} - -#endif // KNXTPUART_H diff --git a/src/KonnektingDeviceLibrary/KonnektingDevice.cpp b/src/KonnektingDeviceLibrary/KonnektingDevice.cpp deleted file mode 100644 index 8c69d9c..0000000 --- a/src/KonnektingDeviceLibrary/KonnektingDevice.cpp +++ /dev/null @@ -1,1193 +0,0 @@ -/*! - * @file KonnektingDevice.cpp - * - * @mainpage KONNEKTING Device Library - * - * @section intro_sec Introduction - * - * This is the documentation for KONNEKTINGs Arduno Device Library. - * - * See https://wiki.konnekting.de for more information - * - * @section dependencies Dependencies - * - * This library depends on - * Foo Bar being present on your system. Please make sure you have - * installed the latest version before using this library. - * - * @section author Author - * - * Written by Alexander Christian. - * - * @section license License - * - * Copyright (C) 2016 Alexander Christian . All rights reserved. - * This file is part of KONNEKTING Knx Device Library. - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - */ - - -/* - * !!!!! IMPORTANT !!!!! - * if "#define DEBUG" is set, you must run your KONNEKTING Suite with "-Dde.root1.slicknx.konnekting.debug=true" - * A release-version of your development MUST NOT contain "#define DEBUG" ... - */ - -#define DEBUG_PROTOCOL -#define WRITEMEM -// reboot feature via progbutton -#define REBOOT_BUTTON - -#include "Arduino.h" -#include "DebugUtil.h" -#include "KnxDevice.h" -#include "KnxComObject.h" -#include "KnxDataPointTypes.h" -#include "KonnektingDevice.h" - -#ifdef ESP8266 -#include -#endif - -#define PROGCOMOBJ_INDEX 255 - - - -// KonnektingDevice unique instance creation -KonnektingDevice KonnektingDevice::Konnekting; -KonnektingDevice& Konnekting = KonnektingDevice::Konnekting; - -/** - * Intercepting knx events to process internal com objects - * @param index - */ -/**************************************************************************/ -/*! - @brief Intercepting knx events to process internal com objects - @param index - Comobject index - @return void - */ - -/**************************************************************************/ -void konnektingKnxEvents(byte index) { - - DEBUG_PRINTLN(F("\n\nkonnektingKnxEvents index=%d"), index); - - // if it's not a internal com object, route back to knxEvents() - if (!Konnekting.internalKnxEvents(index)) { - knxEvents(index); - } -} - -/*************************************************************************** - CONSTRUCTOR - ***************************************************************************/ - -/**************************************************************************/ -/*! - @brief Instantiates a new KONNEKTING Device class - */ - -/**************************************************************************/ -KonnektingDevice::KonnektingDevice() { - DEBUG_PRINTLN(F("\n\n\n\nSetup KonnektingDevice")); -} - -/**************************************************************************/ -/*! - * @brief Internal init function, called by outer init - * @param serial - * serial port reference, f.i. "Serial" or "Serial1" - * @param manufacturerID - * The ID of manufacturer - * @param deviceID - * The ID of the device - * @param revisionID - * The device's revision - * @return void - */ -/**************************************************************************/ -void KonnektingDevice::internalInit(HardwareSerial& serial, - word manufacturerID, - byte deviceID, - byte revisionID){ - - DEBUG_PRINTLN(F("Initialize KonnektingDevice")); - - DEBUG_PRINTLN("15/7/255 = 0x%04x", G_ADDR(15, 7, 255)); - - _initialized = true; - - _manufacturerID = manufacturerID; - _deviceID = deviceID; - _revisionID = revisionID; - - _lastProgbtn = 0; - _progbtnCount = 0; - - setProgState(false); - - - // hardcoded stuff - DEBUG_PRINTLN(F("Manufacturer: 0x%02x Device: 0x%02x Revision: 0x%02x"), _manufacturerID, _deviceID, _revisionID); - - DEBUG_PRINTLN(F("numberOfCommObjects: %d"), Knx.getNumberOfComObjects()); - - // calc of parameter table in eeprom --> depends on number of com objects - _paramTableStartindex = EEPROM_COMOBJECTTABLE_START + (Knx.getNumberOfComObjects() * 3); - - _deviceFlags = memoryRead(EEPROM_DEVICE_FLAGS); - - DEBUG_PRINTLN(F("_deviceFlags: " BYTETOBINARYPATTERN), BYTETOBINARY(_deviceFlags)); - - _individualAddress = P_ADDR(1, 1, 254); - if (!isFactorySetting()) { - DEBUG_PRINTLN(F("->EEPROM")); - /* - * Read eeprom stuff - */ - - // PA - byte hiAddr = memoryRead(EEPROM_INDIVIDUALADDRESS_HI); - byte loAddr = memoryRead(EEPROM_INDIVIDUALADDRESS_LO); - _individualAddress = (hiAddr << 8) + (loAddr << 0); - - // ComObjects - // at most 254 com objects, 255 is progcomobj - for (byte i = 0; i < Knx.getNumberOfComObjects(); i++) { - byte hi = memoryRead(EEPROM_COMOBJECTTABLE_START + (i * 3)); - byte lo = memoryRead(EEPROM_COMOBJECTTABLE_START + (i * 3) + 1); - byte settings = memoryRead(EEPROM_COMOBJECTTABLE_START + (i * 3) + 2); - word comObjAddr = (hi << 8) + (lo << 0); - - bool active = ((settings & 0x80) == 0x80); - Knx.setComObjectAddress(i, comObjAddr, active); - - DEBUG_PRINTLN(F("ComObj index=%d HI=0x%02x LO=0x%02x GA=0x%04x setting=0x%02x active=%d"), i, hi, lo, comObjAddr, settings, active); - } - - } else { - DEBUG_PRINTLN(F("->FACTORY")); - } - DEBUG_PRINTLN(F("IA: 0x%04x"), _individualAddress); - e_KnxDeviceStatus status; - status = Knx.begin(serial, _individualAddress); - DEBUG_PRINTLN(F("KnxDevice startup status: 0x%02x"), status); - - if (status != KNX_DEVICE_OK) { - DEBUG_PRINTLN(F("Knx init ERROR. Retry after reboot!!")); - delay(500); - reboot(); - } - - -#if defined(ESP8266) || defined(ESP32) - // ESP has no EEPROM, but flash and needs to init the EEPROM emulator with an initial size. We create 8k EEPROM - EEPROM.begin(8192); -#endif -} - -/**************************************************************************/ -/*! - * @brief Starts KNX KonnektingDevice, as well as KNX Device - * @param serial - * serial port reference, f.i. "Serial" or "Serial1" - * @param progIndicatorFunc - * function pointer to the function to toggle programming mode - * @param manufacturerID - * The ID of manufacturer - * @param deviceID - * The ID of the device - * @param revisionID - * The device's revision - * @return void - */ -/**************************************************************************/ - -void KonnektingDevice::init(HardwareSerial& serial, - void (*progIndicatorFunc)(bool), - word manufacturerID, - byte deviceID, - byte revisionID - ) { - _progIndicatorFunc = progIndicatorFunc; - - internalInit(serial,manufacturerID,deviceID,revisionID); -} - -/**************************************************************************/ -/*! - * @brief Starts KNX KonnektingDevice, as well as KNX Device - * @param serial - * serial port reference, f.i. "Serial" or "Serial1" - * @param progButtonPin - * pin which toggles programming mode, needs an interrupt capable pin! - * @param progLedPin - * pin which drives LED when in programming mode - * @param manufacturerID - * The ID of manufacturer - * @param deviceID - * The ID of the device - * @param revisionID - * The device's revision - * @return void - */ -/**************************************************************************/ -void KonnektingDevice::init(HardwareSerial& serial, - int progButtonPin, - int progLedPin, - word manufacturerID, - byte deviceID, - byte revisionID - ) { - - _progLED = progLedPin; - _progButton = progButtonPin; - - pinMode(_progLED, OUTPUT); - pinMode(_progButton, INPUT); - attachInterrupt(digitalPinToInterrupt(_progButton), KonnektingProgButtonPressed, RISING); - - internalInit(serial,manufacturerID,deviceID,revisionID); -} - -/**************************************************************************/ -/*! - * @brief checks if the device is already initialized and active. - * @return True if the device has been initialized (by calling one of the init() functions). - */ -/**************************************************************************/ -bool KonnektingDevice::isActive() { - return _initialized; -} - -/**************************************************************************/ -/*! - * @brief checks if the device is in factory settings mode, means: has not been programmed so far. - * @return True if factory settings are active - */ -/**************************************************************************/ -bool KonnektingDevice::isFactorySetting() { - bool isFactory = (_deviceFlags == 0xff); - // DEBUG_PRINTLN(F("isFactorySetting: %d"), isFactory); - return isFactory; -} - -/**************************************************************************/ -/*! - * @brief Bytes to skip when reading/writing in param-table - * @param index - * parameter-id to calc skipbytes for - * @return bytes to skip - */ - -/**************************************************************************/ -int KonnektingDevice::calcParamSkipBytes(int index) { - // calc bytes to skip - int skipBytes = 0; - if (index > 0) { - for (int i = 0; i < index; i++) { - skipBytes += getParamSize(i); - } - } - return skipBytes; -} - -/**************************************************************************/ -/*! - * @brief Gets the size in byte of a param identified by its index - * @param index - * parameter-id to get the size of - * @return size in bytes - */ - -/**************************************************************************/ -byte KonnektingDevice::getParamSize(int index) { - return _paramSizeList[index]; -} - -/**************************************************************************/ -/*! - * @brief Gets the size in byte of a param identified by its index - * @param index - * parameter-id of the parameter to get the value for - * @param[out] value - * the value of the parameter - * @return void - */ - -/**************************************************************************/ -void KonnektingDevice::getParamValue(int index, byte value[]) { - - if (index > _numberOfParams - 1) { - return; - } - - int skipBytes = calcParamSkipBytes(index); - int paramLen = getParamSize(index); - - DEBUG_PRINTLN(F("getParamValue: index=%d _paramTableStartindex=%d skipbytes=%d paremLen=%d"), index, _paramTableStartindex, skipBytes, paramLen); - - // read byte by byte - for (int i = 0; i < paramLen; i++) { - - int addr = _paramTableStartindex + skipBytes + i; - - value[i] = memoryRead(addr); - DEBUG_PRINTLN(F(" val[%d]@%d -> 0x%02x"), i, addr, value[i]); - } -} - -/**************************************************************************/ -/*! - * @brief Interrupt Service Routines for the prog-button - * Used when actually using the built-int prog-button-feature that requires an interrupt enabled pin. - * Although this function is "public", it's NOT part of the API and should not be called by users. - * @return void - */ - -/**************************************************************************/ -void KonnektingProgButtonPressed() { - DEBUG_PRINTLN(F("PrgBtn toggle")); - Konnekting.toggleProgState(); -} - -/**************************************************************************/ -/*! - * @brief Toggle the "programming mode" state. - * This is typically called by prog-button-implementation. - * @return void - */ -/**************************************************************************/ -void KonnektingDevice::toggleProgState() { - -#ifdef REBOOT_BUTTON - if (millis() - _lastProgbtn < 300) { - _progbtnCount++; - - if (_progbtnCount == 3) { - DEBUG_PRINTLN(F("Forced-Reboot-Request detected")); - reboot(); - } - } else { - _progbtnCount = 1; - } - _lastProgbtn = millis(); -#endif - - setProgState(!_progState); // toggle and set - if (_rebootRequired) { - DEBUG_PRINTLN(F("found rebootRequired flag, triggering reboot")); - reboot(); - } -} - -/**************************************************************************/ -/*! - * @brief Gets programming mode state - * @return true, if programming is active, false if not - */ - -/**************************************************************************/ -bool KonnektingDevice::isProgState() { - return _progState; -} - -/**************************************************************************/ -/*! - * @brief Check whether Konnekting is ready for application logic. - * Means: not busy with programming-mode and not running with factory settings - * @return true if it's safe to run application logic - */ - -/**************************************************************************/ -bool KonnektingDevice::isReadyForApplication() { - bool isReady = (!isProgState() && !isFactorySetting()); - return isReady; -} - -/**************************************************************************/ -/*! - * @brief Sets the prog state to given boolean value - * @param state - * new prog state - * @return void - */ - -/**************************************************************************/ -void KonnektingDevice::setProgState(bool state) { - _progState = state; - setProgLed(state); - DEBUG_PRINTLN(F("PrgState %d"),state); - if (*_progIndicatorFunc == NULL) { - digitalWrite(_progLED, state); - } -} - -/**************************************************************************/ -/*! - * @brief Sets the prog LED to given boolean value - * @param state - * new prog state - * @return void - */ - -/**************************************************************************/ -void KonnektingDevice::setProgLed(bool state) { - if (*_progIndicatorFunc != NULL) { - _progIndicatorFunc(state); - }else{ - digitalWrite(_progLED, state); - } - DEBUG_PRINTLN(F("PrgLed %d"),state); -} - -/**************************************************************************/ -/*! - * @brief Check if given 2byte ID is matching the current set IA - * @param hi - * high byte of IA - * @param lo - * low byte of IA - * @return true if match, false if not - */ - -/**************************************************************************/ -bool KonnektingDevice::isMatchingIA(byte hi, byte lo) { - byte iaHi = (_individualAddress >> 8) & 0xff; - byte iaLo = (_individualAddress >> 0) & 0xff; - - return (hi == iaHi && lo == iaLo); -} - -/**************************************************************************/ -/*! - * @brief Creates internal programming ComObj - * @return KnxComObject - */ -/**************************************************************************/ -KnxComObject KonnektingDevice::createProgComObject() { - DEBUG_PRINTLN(F("createProgComObject")); - KnxComObject p = KnxComObject(KNX_DPT_60000_60000 /* KNX PROGRAM */, KNX_COM_OBJ_C_W_U_T_INDICATOR); /* NEEDS TO BE THERE FOR PROGRAMMING PURPOSE */ - p.setAddr(G_ADDR(15, 7, 255)); - p.setActive(true); - return /* Index 0 */ p; -} - -/**************************************************************************/ -/*! - * @brief Reboot the device - * This is typically done after finishing the programming process - * to get the device back in a well-known state with new settings - * @return void - */ -/**************************************************************************/ -void KonnektingDevice::reboot() { - Knx.end(); - -#if defined(ESP8266) || defined(ESP32) - DEBUG_PRINTLN(F("ESP restart")); - ESP.restart(); -#elif ARDUINO_ARCH_SAMD - // do reset of arduino zero, inspired by http://forum.arduino.cc/index.php?topic=366836.0 - DEBUG_PRINTLN(F("SAMD SystemReset")); - WDT->CTRL.reg = 0; // disable watchdog - while (WDT->STATUS.bit.SYNCBUSY == 1); //Just wait till WDT is free - WDT->CONFIG.reg = 0; // see Table 17-5 Timeout Period (valid values 0-11) - WDT->CTRL.reg = WDT_CTRL_ENABLE; //enable watchdog - while (WDT->STATUS.bit.SYNCBUSY == 1); //Just wait till WDT is free - while (1) { - } -#elif ARDUINO_ARCH_STM32 - DEBUG_PRINTLN(F("STM32 SystemReset")); - delay(100); - NVIC_SystemReset(); -#elif __AVR_ATmega32U4__ - DEBUG_PRINTLN(F("WDT reset NOW")); - wdt_enable(WDTO_500MS); - while (1) { - } -#else - // to overcome WDT infinite reboot-loop issue - // see: https://github.com/arduino/Arduino/issues/4492 - DEBUG_PRINTLN(F("software reset NOW")); - delay(500); - asm volatile (" jmp 0"); -#endif - -} - -/**************************************************************************/ -/*! - * @brief processes internal comobj for programming purpose. - * This method is feed with _all_ comobj events. If it's internal comobj, it's handled and return value is true. - * If it's a user defined comobj, all processing is skipped and false is returned. - * @param index - * index of incoming comobj - * @return true, if index was internal comobject and has been handled, false if not - */ -/**************************************************************************/ -bool KonnektingDevice::internalKnxEvents(byte index) { - - DEBUG_PRINTLN(F("internalKnxEvents index=%d"), index); - bool consumed = false; - switch (index) { - case 255: // prog com object index 255 has been updated - - byte buffer[14]; - Knx.read(PROGCOMOBJ_INDEX, buffer); -#ifdef DEBUG_PROTOCOL - for (int i = 0; i < 14; i++) { - DEBUG_PRINTLN(F("buffer[%d]\thex=0x%02x bin=" BYTETOBINARYPATTERN), i, buffer[i], BYTETOBINARY(buffer[i])); - } -#endif - - byte protocolversion = buffer[0]; - byte msgType = buffer[1]; - - DEBUG_PRINTLN(F("protocolversion=0x%02x"), protocolversion); - - DEBUG_PRINTLN(F("msgType=0x%02x"), msgType); - - if (protocolversion != PROTOCOLVERSION) { - DEBUG_PRINTLN(F("Unsupported protocol version. Using: %d Got: %d !"), PROTOCOLVERSION, protocolversion); - } else { - - switch (msgType) { - case MSGTYPE_ACK: - DEBUG_PRINTLN(F("Will not handle received ACK. Skipping message.")); - break; - case MSGTYPE_READ_DEVICE_INFO: - handleMsgReadDeviceInfo(buffer); - break; - case MSGTYPE_RESTART: - handleMsgRestart(buffer); - break; - case MSGTYPE_WRITE_PROGRAMMING_MODE: - handleMsgWriteProgrammingMode(buffer); - break; - case MSGTYPE_READ_PROGRAMMING_MODE: - handleMsgReadProgrammingMode(buffer); - break; - case MSGTYPE_WRITE_INDIVIDUAL_ADDRESS: - if (_progState) handleMsgWriteIndividualAddress(buffer); - break; - case MSGTYPE_READ_INDIVIDUAL_ADDRESS: - if (_progState) handleMsgReadIndividualAddress(buffer); - break; - case MSGTYPE_WRITE_PARAMETER: - if (_progState) handleMsgWriteParameter(buffer); - break; - case MSGTYPE_READ_PARAMETER: - handleMsgReadParameter(buffer); - break; - case MSGTYPE_WRITE_COM_OBJECT: - if (_progState) handleMsgWriteComObject(buffer); - break; - case MSGTYPE_READ_COM_OBJECT: - handleMsgReadComObject(buffer); - break; - default: - DEBUG_PRINTLN(F("Unsupported msgtype: 0x%02x"), msgType); - DEBUG_PRINTLN(F(" !!! Skipping message.")); - break; - } - - } - consumed = true; - break; - - } - return consumed; - -} - -/**************************************************************************/ -/*! - * @brief Sending ACK message back to the bus - * @param errorcode - * error code, if any - * @param indexinformation - * indexinformation, if error is related to an index - * @return void - */ -/**************************************************************************/ -void KonnektingDevice::sendAck(byte errorcode, int indexinformation) { - DEBUG_PRINTLN(F("sendAck errorcode=0x%02x indexInformation=0x%04x"), errorcode, indexinformation); - byte response[14]; - response[0] = PROTOCOLVERSION; - response[1] = MSGTYPE_ACK; - response[2] = (errorcode == 0x00 ? 0x00 : 0xFF); - response[3] = errorcode; - response[4] = (indexinformation >> 8) & 0xff; - response[5] = (indexinformation >> 0) & 0xff; - for (byte i = 6; i < 14; i++) { - response[i] = 0x00; - } - Knx.write(PROGCOMOBJ_INDEX, response); -} - -void KonnektingDevice::handleMsgReadDeviceInfo(byte msg[]) { - DEBUG_PRINTLN(F("handleMsgReadDeviceInfo")); - - if (isMatchingIA(msg[2], msg[3])) { - byte response[14]; - response[0] = PROTOCOLVERSION; - response[1] = MSGTYPE_ANSWER_DEVICE_INFO; - response[2] = (_manufacturerID >> 8) & 0xff; - response[3] = (_manufacturerID >> 0) & 0xff; - response[4] = _deviceID; - response[5] = _revisionID; - response[6] = _deviceFlags; - response[7] = (_individualAddress >> 8) & 0xff; - response[8] = (_individualAddress >> 0) & 0xff; - response[9] = 0x00; - response[10] = 0x00; - response[11] = 0x00; - response[12] = 0x00; - response[13] = 0x00; - Knx.write(PROGCOMOBJ_INDEX, response); - } else { -#ifdef DEBUG_PROTOCOL - DEBUG_PRINTLN(F("no matching IA")); -#endif - } -} - -void KonnektingDevice::handleMsgRestart(byte msg[]) { - DEBUG_PRINTLN(F("handleMsgRestart")); - - if (isMatchingIA(msg[2], msg[3])) { -#ifdef DEBUG_PROTOCOL - DEBUG_PRINTLN(F("matching IA")); -#endif - // trigger restart - reboot(); - } else { -#ifdef DEBUG_PROTOCOL - DEBUG_PRINTLN(F("no matching IA")); -#endif - } - -} - -void KonnektingDevice::handleMsgWriteProgrammingMode(byte msg[]) { - DEBUG_PRINTLN(F("handleMsgWriteProgrammingMode")); - //word addr = (msg[2] << 8) + (msg[3] << 0); - - - if (isMatchingIA(msg[2], msg[3])) { -#ifdef DEBUG_PROTOCOL - DEBUG_PRINTLN(F("matching IA")); -#endif - setProgState(msg[4] == 0x01); - sendAck(0x00, 0x00); - -#if defined(ESP8266) || defined(ESP32) - // ESP8266/ESP32 uses own EEPROM implementation which requires commit() call - if (msg[4] == 0x00) { - DEBUG_PRINTLN(F("ESP8266/ESP32: EEPROM.commit()")); - EEPROM.commit(); - } -#else - // commit memory changes - memoryCommit(); -#endif - - } else { - DEBUG_PRINTLN(F("no matching IA")); - } -} - -void KonnektingDevice::handleMsgReadProgrammingMode(byte /*msg*/[]) { - // to suppress compiler warning about unused variable, "msg" has been commented out - DEBUG_PRINTLN(F("handleMsgReadProgrammingMode")); - if (_progState) { - byte response[14]; - response[0] = PROTOCOLVERSION; - response[1] = MSGTYPE_ANSWER_PROGRAMMING_MODE; - response[2] = (_individualAddress >> 8) & 0xff; - response[3] = (_individualAddress >> 0) & 0xff; - response[4] = 0x00; - response[5] = 0x00; - response[6] = 0x00; - response[7] = 0x00; - response[8] = 0x00; - response[9] = 0x00; - response[10] = 0x00; - response[11] = 0x00; - response[12] = 0x00; - response[13] = 0x00; - Knx.write(PROGCOMOBJ_INDEX, response); - } -} - -void KonnektingDevice::handleMsgWriteIndividualAddress(byte msg[]) { - DEBUG_PRINTLN(F("handleMsgWriteIndividualAddress")); -#if defined(WRITEMEM) - memoryUpdate(EEPROM_INDIVIDUALADDRESS_HI, msg[2]); - memoryUpdate(EEPROM_INDIVIDUALADDRESS_LO, msg[3]); - - // see: http://stackoverflow.com/questions/3920307/how-can-i-remove-a-flag-in-c - _deviceFlags &= ~0x80; // remove factory setting bit (left most bit)) -#ifdef DEBUG_PROTOCOL - DEBUG_PRINTLN(F("DeviceFlags after =0x%02x"), _deviceFlags); -#endif - - memoryUpdate(EEPROM_DEVICE_FLAGS, _deviceFlags); -#endif - _individualAddress = (msg[2] << 8) + (msg[3] << 0); - sendAck(0x00, 0x00); -} - -void KonnektingDevice::handleMsgReadIndividualAddress(byte /*msg*/[]) { - // to suppress compiler warning about unused variable, "msg" has been commented out - DEBUG_PRINTLN(F("handleMsgReadIndividualAddress")); - byte response[14]; - response[0] = PROTOCOLVERSION; - response[1] = MSGTYPE_ANSWER_INDIVIDUAL_ADDRESS; - response[2] = (_individualAddress >> 8) & 0xff; - response[3] = (_individualAddress >> 0) & 0xff; - response[4] = 0x00; - response[5] = 0x00; - response[6] = 0x00; - response[7] = 0x00; - response[8] = 0x00; - response[9] = 0x00; - response[10] = 0x00; - response[11] = 0x00; - response[12] = 0x00; - response[13] = 0x00; - Knx.write(PROGCOMOBJ_INDEX, response); -} - -void KonnektingDevice::handleMsgWriteParameter(byte msg[]) { - DEBUG_PRINTLN(F("handleMsgWriteParameter")); - - int index = msg[2]; - - if (index > _numberOfParams - 1) { - sendAck(KNX_DEVICE_INVALID_INDEX, index); - return; - } - - int skipBytes = calcParamSkipBytes(index); - int paramLen = getParamSize(index); - -#ifdef DEBUG_PROTOCOL - DEBUG_PRINTLN(F("id=%d"), index); -#endif - -#if defined(WRITEMEM) - // write byte by byte - for (byte i = 0; i < paramLen; i++) { -#ifdef DEBUG_PROTOCOL - DEBUG_PRINTLN(F(" data[%d]=0x%02x"), i, msg[3 + i]); -#endif - memoryUpdate(_paramTableStartindex + skipBytes + i, msg[3 + i]); - } -#endif - sendAck(0x00, 0x00); -} - -void KonnektingDevice::handleMsgReadParameter(byte msg[]) { - DEBUG_PRINTLN(F("handleMsgReadParameter")); - int index = msg[0]; - - byte paramSize = getParamSize(index); - - byte paramValue[paramSize]; - getParamValue(index, paramValue); - - byte response[14]; - response[0] = PROTOCOLVERSION; - response[1] = MSGTYPE_ANSWER_PARAMETER; - response[2] = index; - - // fill in param value - for (byte i = 0; i < paramSize; i++) { - response[3 + i] = paramValue[i]; - } - - // fill rest with 0x00 - for (byte i = 0; i < 11 /* max param length */ - paramSize; i++) { - response[3 + paramSize + i] = 0; - } - - Knx.write(PROGCOMOBJ_INDEX, response); - -} - -void KonnektingDevice::handleMsgWriteComObject(byte msg[]) { - DEBUG_PRINTLN(F("handleMsgWriteComObject")); - - byte comObjId = msg[2]; - byte gaHi = msg[3]; - byte gaLo = msg[4]; - byte settings = msg[5]; - word ga = (gaHi << 8) + (gaLo << 0); - -#ifdef DEBUG_PROTOCOL - DEBUG_PRINTLN(F("CO id=%d hi=0x%02x lo=0x%02x GA=0x%04x settings=0x%02x"), comObjId, gaHi, gaLo, ga, settings); - - bool foundWrongUndefined = false; - for (int i = 6; i < 13; i++) { - if (msg[i] != 0x00) foundWrongUndefined = true; - } - if (foundWrongUndefined) { - DEBUG_PRINTLN(F("!!!!!!!!!!! WARNING: Suite is sending wrong data. Ensure Suite version matches the Device Lib !!!!!")); - } -#endif - - if (comObjId >= Knx.getNumberOfComObjects()) { - sendAck(KNX_DEVICE_INVALID_INDEX, comObjId); - return; - } - -#if defined(WRITEMEM) - // write to eeprom?! - memoryUpdate(EEPROM_COMOBJECTTABLE_START + (comObjId * 3) + 0, gaHi); - memoryUpdate(EEPROM_COMOBJECTTABLE_START + (comObjId * 3) + 1, gaLo); - memoryUpdate(EEPROM_COMOBJECTTABLE_START + (comObjId * 3) + 2, settings); -#endif - // } - - sendAck(0x00, 0x00); -} - -void KonnektingDevice::handleMsgReadComObject(byte msg[]) { -#ifdef DEBUG_PROTOCOL - DEBUG_PRINTLN(F("handleMsgReadComObject")); -#endif - - byte comObjId = msg[2]; - - - word ga = Knx.getComObjectAddress(comObjId); - - byte response[14]; - response[0] = PROTOCOLVERSION; - response[1] = MSGTYPE_ANSWER_COM_OBJECT; - response[2] = comObjId; - response[3] = (ga >> 8) & 0xff; // GA Hi - response[4] = (ga >> 0) & 0xff; // GA Lo - response[5] = 0x00; // Settings - - // fill rest with 0x00 - for (byte i = 6; i < 13; i++) { - response[i] = 0; - } - - Knx.write(PROGCOMOBJ_INDEX, response); -} - -int KonnektingDevice::memoryRead(int index) { - DEBUG_PRINT(F("memRead: index=0x%02x"), index); - byte d = 0xFF; - - if (*_eepromReadFunc != NULL) { - DEBUG_PRINT(F(" using fctptr")); - d = _eepromReadFunc(index); - } else { -#ifdef ARDUINO_ARCH_SAMD - DEBUG_PRINTLN(F("memRead: EEPROM NOT SUPPORTED. USE FCTPTR!")); -#else - d = EEPROM.read(index); -#endif - } - DEBUG_PRINTLN(F(" data=0x%02x"), d); - return d; -} - -void KonnektingDevice::memoryWrite(int index, byte data) { - - DEBUG_PRINT(F("memWrite: index=0x%02x data=0x%02x"), index, data); - if (*_eepromWriteFunc != NULL) { - DEBUG_PRINTLN(F(" using fctptr")); - _eepromWriteFunc(index, data); - } else { - DEBUG_PRINTLN(F("")); -#ifdef ARDUINO_ARCH_SAMD - DEBUG_PRINTLN(F("memoryWrite: EEPROM NOT SUPPORTED. USE FCTPTR!")); -#else - EEPROM.write(index, data); -#endif - } - // EEPROM has been changed, reboot will be required - _rebootRequired = true; -} - -void KonnektingDevice::memoryUpdate(int index, byte data) { - - DEBUG_PRINT(F("memUpdate: index=0x%02x data=0x%02x"), index, data); - - if (*_eepromUpdateFunc != NULL) { - DEBUG_PRINTLN(F(" using fctptr")); - _eepromUpdateFunc(index, data); - } else { - DEBUG_PRINTLN(F("")); -#if defined(ESP8266) || defined(ESP32) - DEBUG_PRINTLN(F("ESP8266/ESP32: EEPROM.update")); - byte d = EEPROM.read(index); - if (d != data) { - EEPROM.write(index, data); - } -#elif ARDUINO_ARCH_SAMD - DEBUG_PRINTLN(F("memoryUpdate: EEPROM NOT SUPPORTED. USE FCTPTR!")); -#else - EEPROM.update(index, data); -#endif - } - // EEPROM has been changed, reboot will be required - _rebootRequired = true; - -} - -void KonnektingDevice::memoryCommit() { - if (*_eepromCommitFunc != NULL) { - DEBUG_PRINTLN(F("memCommit: using fctptr")); - _eepromCommitFunc(); - } -} - -/**************************************************************************/ -/*! - * @brief Gets the uint8 value of given parameter - * @param index - * index of parameter - * @return uint8 value of parameter - */ -/**************************************************************************/ -uint8_t KonnektingDevice::getUINT8Param(int index) { - if (getParamSize(index) != PARAM_UINT8) { - DEBUG_PRINTLN(F("Requested UINT8 param for index %d but param has different length! Will Return 0."), index); - return 0; - } - - byte paramValue[1]; - getParamValue(index, paramValue); - - return paramValue[0]; -} - -/**************************************************************************/ -/*! - * @brief Gets the int8 value of given parameter - * @param index - * index of parameter - * @return int8 value of parameter - */ -/**************************************************************************/ -int8_t KonnektingDevice::getINT8Param(int index) { - if (getParamSize(index) != PARAM_INT8) { - DEBUG_PRINTLN(F("Requested INT8 param for index %d but param has different length! Will Return 0."), index); - return 0; - } - - byte paramValue[1]; - getParamValue(index, paramValue); - - return paramValue[0]; -} - -/**************************************************************************/ -/*! - * @brief Gets the uint16 value of given parameter - * @param index - * index of parameter - * @return uint16 value of parameter - */ -/**************************************************************************/ -uint16_t KonnektingDevice::getUINT16Param(int index) { - if (getParamSize(index) != PARAM_UINT16) { - DEBUG_PRINTLN(F("Requested UINT16 param for index %d but param has different length! Will Return 0."), index); - return 0; - } - - byte paramValue[2]; - getParamValue(index, paramValue); - - uint16_t val = (paramValue[0] << 8) + (paramValue[1] << 0); - - return val; -} - -/**************************************************************************/ -/*! - * @brief Gets the int16 value of given parameter - * @param index - * index of parameter - * @return int16 value of parameter - */ -/**************************************************************************/ -int16_t KonnektingDevice::getINT16Param(int index) { - if (getParamSize(index) != PARAM_INT16) { - DEBUG_PRINTLN(F("Requested INT16 param for index %d but param has different length! Will Return 0."), index); - return 0; - } - - byte paramValue[2]; - getParamValue(index, paramValue); - - // //DEBUG_PRINT((F(" int16: [1]=0x")); - // //DEBUG_PRINT2(paramValue[0], HEX); - // //DEBUG_PRINT((F(" [0]=0x")); - // DEBUG_PRINTLN2(paramValue[1], HEX); - - int16_t val = (paramValue[0] << 8) + (paramValue[1] << 0); - - return val; -} - -/**************************************************************************/ -/*! - * @brief Gets the uint32 value of given parameter - * @param index - * index of parameter - * @return uint32 value of parameter - */ -/**************************************************************************/ -uint32_t KonnektingDevice::getUINT32Param(int index) { - if (getParamSize(index) != PARAM_UINT32) { - DEBUG_PRINTLN(F("Requested UINT32 param for index %d but param has different length! Will Return 0."), index); - return 0; - } - - byte paramValue[4]; - getParamValue(index, paramValue); - - uint32_t val = ((uint32_t) paramValue[0] << 24) + ((uint32_t) paramValue[1] << 16) + ((uint32_t) paramValue[2] << 8) + ((uint32_t) paramValue[3] << 0); - - return val; -} - -/**************************************************************************/ -/*! - * @brief Gets the int32 value of given parameter - * @param index - * index of parameter - * @return int32 value of parameter - */ -/**************************************************************************/ -int32_t KonnektingDevice::getINT32Param(int index) { - if (getParamSize(index) != PARAM_INT32) { - DEBUG_PRINTLN(F("Requested INT32 param for index %d but param has different length! Will Return 0."), index); - return 0; - } - - byte paramValue[4]; - getParamValue(index, paramValue); - - int32_t val = ((uint32_t) paramValue[0] << 24) + ((uint32_t) paramValue[1] << 16) + ((uint32_t) paramValue[2] << 8) + ((uint32_t) paramValue[3] << 0); - - return val; -} - -/**************************************************************************/ -/*! - * @brief Gets the string value of given parameter - * @param index - * index of parameter - * @return string value of parameter - */ -/**************************************************************************/ -String KonnektingDevice::getSTRING11Param(int index) { - String ret; - if (getParamSize(index) != PARAM_STRING11) { - DEBUG_PRINTLN(F("Requested STRING11 param for index %d but param has different length! Will Return \"\""), index); - ret = ""; - return ret; - } - - byte paramValue[PARAM_STRING11]; - getParamValue(index, paramValue); - - // check if string is 0x00 terminated (means <11 chars) - for (int i = 0; i < PARAM_STRING11; i++) { - if (paramValue[i] == 0x00) { - break; // stop at null-termination - } else { - ret += (char) paramValue[i]; // copy char by char into string - } - } - - return ret; -} - -/**************************************************************************/ -/*! - * @brief Returns the address at which the "user space" in eeprom starts. - * The area in front of this address is used by KONNEKTING and writing to this area is not allowed - * @return eeprom address at which the "user space" starts - */ -/**************************************************************************/ -int KonnektingDevice::getFreeEepromOffset() { - - int offset = _paramTableStartindex; - for (int i = 0; i < _numberOfParams; i++) { - offset += _paramSizeList[i]; - } - return offset; -} - -/**************************************************************************/ -/*! - * @brief Sets the function to call when doing 'read' on memory. - * @param func - * function pointer to memory read function - * @return void - */ -/**************************************************************************/ -void KonnektingDevice::setMemoryReadFunc(byte(*func)(int)) { - _eepromReadFunc = func; -} - -/**************************************************************************/ -/*! - * @brief Sets the function to call when doing 'write' on memory. - * @param func - * function pointer to memory write function - * @return void - */ -/**************************************************************************/ -void KonnektingDevice::setMemoryWriteFunc(void (*func)(int, byte)) { - _eepromWriteFunc = func; -} - -/**************************************************************************/ -/*! - * @brief Sets the function to call when doing 'update' on memory. - * @param func - * function pointer to memory update function - * @return void - */ -/**************************************************************************/ -void KonnektingDevice::setMemoryUpdateFunc(void (*func)(int, byte)) { - _eepromUpdateFunc = func; -} - -/**************************************************************************/ -/*! - * @brief Sets the function to call when memory changes are done ('commit'). - * @param func - * function pointer to memory commit function - * @return void - */ -/**************************************************************************/ -void KonnektingDevice::setMemoryCommitFunc(void (*func)(void)) { - _eepromCommitFunc = func; -} diff --git a/src/KonnektingDeviceLibrary/KonnektingDevice.h b/src/KonnektingDeviceLibrary/KonnektingDevice.h deleted file mode 100644 index 05fe1ec..0000000 --- a/src/KonnektingDeviceLibrary/KonnektingDevice.h +++ /dev/null @@ -1,239 +0,0 @@ -/*! - * @file KonnektingDevice.h - * - * This is part of KONNEKTING Device Library for the Arduino platform. - * - * Copyright (C) 2016 Alexander Christian . All rights reserved. - * This file is part of KONNEKTING Knx Device Library. - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef KONNEKTING_h -#define KONNEKTING_h - -#define KONNEKTING_DEVICE_LIBRARY_VERSION 10000 -#define KONNEKTING_DEVICE_LIBRARY_SNAPSHOT -#define KONNEKTING_1_0_0_beta4b - -#include -#include "DebugUtil.h" -#include "KnxDevice.h" -#include "KnxDptConstants.h" - -// AVR, ESP8266, ESP32 and STM32 uses EEPROM (SAMD21 not ...) -#if defined(__AVR__) || defined(ESP8266) || defined(ESP32) || defined(ARDUINO_ARCH_STM32) -#include -#ifdef ARDUINO_ARCH_AVR -#include -#endif -#endif - -#define EEPROM_DEVICE_FLAGS 0 ///< EEPROM index for device flags -#define EEPROM_INDIVIDUALADDRESS_HI 1 ///< EEPROM index for IA, high byte -#define EEPROM_INDIVIDUALADDRESS_LO 2 ///< EEPROM index for IA, low byte -#define EEPROM_COMOBJECTTABLE_START 10 ///< EEPROM index start of comobj table - -#define PROTOCOLVERSION 0 - -#define MSGTYPE_ACK 0 ///< Message Type: ACK 0x00 -#define MSGTYPE_READ_DEVICE_INFO 1 ///< Message Type: Read Device Information 0x01 -#define MSGTYPE_ANSWER_DEVICE_INFO 2 ///< Message Type: Answer Device Information 0x02 -#define MSGTYPE_RESTART 9 ///< Message Type: Restart 0x09 - -#define MSGTYPE_WRITE_PROGRAMMING_MODE 10 // 0x0A -#define MSGTYPE_READ_PROGRAMMING_MODE 11 // 0x0B -#define MSGTYPE_ANSWER_PROGRAMMING_MODE 12 // 0x0C - -#define MSGTYPE_WRITE_INDIVIDUAL_ADDRESS 20 // 0x14 -#define MSGTYPE_READ_INDIVIDUAL_ADDRESS 21 // 0x15 -#define MSGTYPE_ANSWER_INDIVIDUAL_ADDRESS 22 // 0x16 - -#define MSGTYPE_WRITE_PARAMETER 30 // 0x1E -#define MSGTYPE_READ_PARAMETER 31 // 0x1F -#define MSGTYPE_ANSWER_PARAMETER 32 // 0x20 - -#define MSGTYPE_WRITE_COM_OBJECT 40 // 0x28 -#define MSGTYPE_READ_COM_OBJECT 41 // 0x29 -#define MSGTYPE_ANSWER_COM_OBJECT 42 // 0x2A - -#define PARAM_INT8 1 -#define PARAM_UINT8 1 -#define PARAM_INT16 2 -#define PARAM_UINT16 2 -#define PARAM_INT32 4 -#define PARAM_UINT32 4 -#define PARAM_RAW1 1 -#define PARAM_RAW2 2 -#define PARAM_RAW3 3 -#define PARAM_RAW4 4 -#define PARAM_RAW5 5 -#define PARAM_RAW6 6 -#define PARAM_RAW7 7 -#define PARAM_RAW8 8 -#define PARAM_RAW9 9 -#define PARAM_RAW10 10 -#define PARAM_RAW11 11 -#define PARAM_STRING11 11 - - -// process intercepted knxEvents-calls with this method -extern void konnektingKnxEvents(byte index); - -/**************************************************************************/ -/*! - * @brief Main class provides KONNEKTING Device API - */ - -/**************************************************************************/ -class KonnektingDevice { - static byte _paramSizeList[]; - static const int _numberOfParams; - - byte (*_eepromReadFunc)(int); - void (*_eepromWriteFunc)(int, byte); - void (*_eepromUpdateFunc)(int, byte); - void (*_eepromCommitFunc)(void); - void (*_progIndicatorFunc)(bool); - - // Constructor, Destructor - KonnektingDevice(); // private constructor (singleton design pattern) - - ~KonnektingDevice() { - } // private destructor (singleton design pattern) - KonnektingDevice(KonnektingDevice&); // private copy constructor (singleton design pattern) - -public: - static KonnektingDevice Konnekting; - - void setMemoryReadFunc(byte(*func)(int)); - void setMemoryWriteFunc(void (*func)(int, byte)); - void setMemoryUpdateFunc(void (*func)(int, byte)); - void setMemoryCommitFunc(void (*func)(void)); - - void init(HardwareSerial& serial, - void (*progIndicatorFunc)(bool), - word manufacturerID, - byte deviceID, - byte revisionID - ); - - void init(HardwareSerial& serial, - int progButtonPin, - int progLedPin, - word manufacturerID, - byte deviceID, - byte revisionID - ); - - // needs to be public too, due to ISR handler mechanism :-( - bool internalKnxEvents(byte index); - - // must be public to be accessible from KonnektingProgButtonPressed() - void toggleProgState(); - - - - byte getParamSize(int index); - void getParamValue(int index, byte* value); - - uint8_t getUINT8Param(int index); - int8_t getINT8Param(int index); - - uint16_t getUINT16Param(int index); - int16_t getINT16Param(int index); - - uint32_t getUINT32Param(int index); - int32_t getINT32Param(int index); - - String getSTRING11Param(int index); - - bool isActive(); - bool isFactorySetting(); - - bool isProgState(); - - bool isReadyForApplication(); - - void setProgState(bool state); - - int getFreeEepromOffset(); - - void reboot(); - -private: - - bool _rebootRequired = false; - bool _initialized = false; -#ifdef REBOOT_BUTTON - byte _progbtnCount = 0; - long _lastProgbtn = 0; -#endif - word _individualAddress; - - byte _deviceFlags; - word _manufacturerID; - byte _deviceID; - byte _revisionID; - - int _paramTableStartindex; - - - int _progLED; - int _progButton; // (->interrupt) - void setProgLed(bool state); - - bool _progState; - - KnxComObject createProgComObject(); - - void internalInit(HardwareSerial& serial, - word manufacturerID, - byte deviceID, - byte revisionID - ); - int calcParamSkipBytes(int index); - - bool isMatchingIA(byte hi, byte lo); - - - - // prog methods - void sendAck(byte errorcode, int indexinformation); - void handleMsgReadDeviceInfo(byte* msg); - void handleMsgRestart(byte* msg); - void handleMsgWriteProgrammingMode(byte* msg); - void handleMsgReadProgrammingMode(byte* msg); - void handleMsgWriteIndividualAddress(byte* msg); - void handleMsgReadIndividualAddress(byte* msg); - void handleMsgWriteParameter(byte* msg); - void handleMsgReadParameter(byte* msg); - void handleMsgWriteComObject(byte* msg); - void handleMsgReadComObject(byte* msg); - - int memoryRead(int index); - void memoryWrite(int index, byte date); - void memoryUpdate(int index, byte date); - void memoryCommit(); - -}; - -// not part of Konnekting class -void KonnektingProgButtonPressed(); - -// Reference to the KnxDevice unique instance -extern KonnektingDevice& Konnekting; - -#endif // KONNEKTING_h - diff --git a/src/KonnektingDeviceLibrary/RingBuff.h b/src/KonnektingDeviceLibrary/RingBuff.h deleted file mode 100644 index 12fd21d..0000000 --- a/src/KonnektingDeviceLibrary/RingBuff.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * This file is part of KONNEKTING Knx Device Library. - * - * The KONNEKTING Knx Device Library is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -// File : RingBuff.h -// Initial Author : Alexander Christian -// Description : Implementation of a ring buffer -// Module dependencies : none - -#ifndef RINGBUFF_H -#define RINGBUFF_H - -#include "Arduino.h" -#include "DebugUtil.h" - -template -class RingBuff { - byte _head; - byte _tail; - T _buffer[size]; // item buffer - byte _size; - byte _itemCount; - -public: - - /** - * Constructor - */ - RingBuff() { - _head = 0; - _tail = 0; - _itemCount = 0; - _size = size; - }; - - - /** - * Append data to tail - * @param appendedData - */ - void append(const T& data) { - if (_itemCount == _size) { // buffer full, overwriting oldest data - incHead(); - } else { - _itemCount++; - } - _buffer[_tail] = data; - incTail(); - } - - /** - * Pop data from head - * @param data the popped data - * @return false, if no items available - */ - boolean pop(T& data) { - if (_itemCount==0) return false; - data = _buffer[_head]; - incHead(); - _itemCount--; - return true; - } - - /** - * Returns number of items in buffer - * @return item count - */ - byte getItemCount(void) const { - return _itemCount; - } - -private: - - void incHead(void) { - _head = (_head + 1) % _size; - } - - void incTail(void) { - _tail = (_tail + 1) % _size; - } -}; - -#endif // RINGBUFF_H diff --git a/virtualEEPROM.h b/virtualEEPROM.h new file mode 100644 index 0000000..0297a3b --- /dev/null +++ b/virtualEEPROM.h @@ -0,0 +1,1440 @@ +#ifdef VIRTUAL_EEPROM +byte virtualEEPROM[256]; + +byte readMemory(int index){ + return virtualEEPROM[index]; +} + +void writeMemory(int index, byte val) { + virtualEEPROM[index] = val; +} + +void updateMemory(int index, byte val) { + if (readMemory(index) != val) { + writeMemory(index, val); + } +} + +void commitMemory() { + +} + +void initVirtualEeprom(){ + writeMemory(0,0x00); + writeMemory(1,0x00); + writeMemory(2,0x0F); + writeMemory(3,0x00); + writeMemory(4,0x40); + writeMemory(5,0x02); + writeMemory(6,0x3F); + writeMemory(7,0x04); + writeMemory(8,0x3E); + writeMemory(9,0x05); + writeMemory(10,0x3F); + writeMemory(11,0x64); + writeMemory(12,0x67); + writeMemory(13,0xE2); + writeMemory(14,0xB5); + writeMemory(15,0xEE); + writeMemory(16,0x02); + writeMemory(17,0x54); + writeMemory(18,0x09); + writeMemory(19,0xA7); + writeMemory(20,0x2F); + writeMemory(21,0x26); + writeMemory(22,0x10); + writeMemory(23,0x04); + writeMemory(24,0xB0); + writeMemory(25,0xBB); + writeMemory(26,0xDE); + writeMemory(27,0x4F); + writeMemory(28,0x80); + writeMemory(29,0x1B); + writeMemory(30,0x4E); + writeMemory(31,0xFF); + writeMemory(32,0xFF); + writeMemory(33,0xFF); + writeMemory(34,0xFF); + writeMemory(35,0xFF); + writeMemory(36,0xFF); + writeMemory(37,0xFF); + writeMemory(38,0xFF); + writeMemory(39,0xFF); + writeMemory(40,0xFF); + writeMemory(41,0xFF); + writeMemory(42,0xFF); + writeMemory(43,0xFF); + writeMemory(44,0xFF); + writeMemory(45,0xFF); + writeMemory(46,0xFF); + writeMemory(47,0xFF); + writeMemory(48,0x11); + writeMemory(49,0x24); + writeMemory(50,0xFF); + writeMemory(51,0xFF); + writeMemory(52,0xFF); + writeMemory(53,0xFF); + writeMemory(54,0xFF); + writeMemory(55,0xFF); + writeMemory(56,0xFF); + writeMemory(57,0xFF); + writeMemory(58,0xFF); + writeMemory(59,0xFF); + writeMemory(60,0xFF); + writeMemory(61,0xFF); + writeMemory(62,0xFF); + writeMemory(63,0xFF); + writeMemory(64,0x13); + writeMemory(65,0x28); + writeMemory(66,0x16); + writeMemory(67,0x29); + writeMemory(68,0x16); + writeMemory(69,0x2B); + writeMemory(70,0x16); + writeMemory(71,0x2C); + writeMemory(72,0x16); + writeMemory(73,0x2D); + writeMemory(74,0x16); + writeMemory(75,0x3E); + writeMemory(76,0x0A); + writeMemory(77,0x3E); + writeMemory(78,0x0B); + writeMemory(79,0x3E); + writeMemory(80,0x0C); + writeMemory(81,0x3E); + writeMemory(82,0x0D); + writeMemory(83,0x3E); + writeMemory(84,0x0E); + writeMemory(85,0x3E); + writeMemory(86,0x0F); + writeMemory(87,0x3E); + writeMemory(88,0x10); + writeMemory(89,0x3E); + writeMemory(90,0x11); + writeMemory(91,0x3E); + writeMemory(92,0x14); + writeMemory(93,0x3E); + writeMemory(94,0x15); + writeMemory(95,0x3E); + writeMemory(96,0x1E); + writeMemory(97,0x3E); + writeMemory(98,0x1F); + writeMemory(99,0x3E); + writeMemory(100,0x20); + writeMemory(101,0x3E); + writeMemory(102,0x21); + writeMemory(103,0xFF); + writeMemory(104,0xFF); + writeMemory(105,0xFF); + writeMemory(106,0xFF); + writeMemory(107,0xFF); + writeMemory(108,0xFF); + writeMemory(109,0xFF); + writeMemory(110,0xFF); + writeMemory(111,0xFF); + writeMemory(112,0xFF); + writeMemory(113,0xFF); + writeMemory(114,0xFF); + writeMemory(115,0xFF); + writeMemory(116,0xFF); + writeMemory(117,0xFF); + writeMemory(118,0xFF); + writeMemory(119,0xFF); + writeMemory(120,0xFF); + writeMemory(121,0xFF); + writeMemory(122,0xFF); + writeMemory(123,0xFF); + writeMemory(124,0xFF); + writeMemory(125,0xFF); + writeMemory(126,0xFF); + writeMemory(127,0xFF); + writeMemory(128,0xFF); + writeMemory(129,0xFF); + writeMemory(130,0xFF); + writeMemory(131,0xFF); + writeMemory(132,0xFF); + writeMemory(133,0xFF); + writeMemory(134,0xFF); + writeMemory(135,0xFF); + writeMemory(136,0xFF); + writeMemory(137,0xFF); + writeMemory(138,0xFF); + writeMemory(139,0xFF); + writeMemory(140,0xFF); + writeMemory(141,0xFF); + writeMemory(142,0xFF); + writeMemory(143,0xFF); + writeMemory(144,0xFF); + writeMemory(145,0xFF); + writeMemory(146,0xFF); + writeMemory(147,0xFF); + writeMemory(148,0xFF); + writeMemory(149,0xFF); + writeMemory(150,0xFF); + writeMemory(151,0xFF); + writeMemory(152,0xFF); + writeMemory(153,0xFF); + writeMemory(154,0xFF); + writeMemory(155,0xFF); + writeMemory(156,0xFF); + writeMemory(157,0xFF); + writeMemory(158,0xFF); + writeMemory(159,0xFF); + writeMemory(160,0xFF); + writeMemory(161,0xFF); + writeMemory(162,0xFF); + writeMemory(163,0xFF); + writeMemory(164,0xFF); + writeMemory(165,0xFF); + writeMemory(166,0xFF); + writeMemory(167,0xFF); + writeMemory(168,0xFF); + writeMemory(169,0xFF); + writeMemory(170,0xFF); + writeMemory(171,0xFF); + writeMemory(172,0xFF); + writeMemory(173,0xFF); + writeMemory(174,0xFF); + writeMemory(175,0xFF); + writeMemory(176,0xFF); + writeMemory(177,0xFF); + writeMemory(178,0xFF); + writeMemory(179,0xFF); + writeMemory(180,0xFF); + writeMemory(181,0xFF); + writeMemory(182,0xFF); + writeMemory(183,0xFF); + writeMemory(184,0xFF); + writeMemory(185,0xFF); + writeMemory(186,0xFF); + writeMemory(187,0xFF); + writeMemory(188,0xFF); + writeMemory(189,0xFF); + writeMemory(190,0xFF); + writeMemory(191,0xFF); + writeMemory(192,0xFF); + writeMemory(193,0xFF); + writeMemory(194,0xFF); + writeMemory(195,0xFF); + writeMemory(196,0xFF); + writeMemory(197,0xFF); + writeMemory(198,0xFF); + writeMemory(199,0xFF); + writeMemory(200,0xFF); + writeMemory(201,0xFF); + writeMemory(202,0xFF); + writeMemory(203,0xFF); + writeMemory(204,0xFF); + writeMemory(205,0xFF); + writeMemory(206,0xFF); + writeMemory(207,0xFF); + writeMemory(208,0xFF); + writeMemory(209,0xFF); + writeMemory(210,0xFF); + writeMemory(211,0xFF); + writeMemory(212,0xFF); + writeMemory(213,0xFF); + writeMemory(214,0xFF); + writeMemory(215,0xFF); + writeMemory(216,0xFF); + writeMemory(217,0xFF); + writeMemory(218,0xFF); + writeMemory(219,0xFF); + writeMemory(220,0xFF); + writeMemory(221,0xFF); + writeMemory(222,0xFF); + writeMemory(223,0xFF); + writeMemory(224,0xFF); + writeMemory(225,0xFF); + writeMemory(226,0xFF); + writeMemory(227,0xFF); + writeMemory(228,0xFF); + writeMemory(229,0xFF); + writeMemory(230,0xFF); + writeMemory(231,0xFF); + writeMemory(232,0xFF); + writeMemory(233,0xFF); + writeMemory(234,0xFF); + writeMemory(235,0xFF); + writeMemory(236,0xFF); + writeMemory(237,0xFF); + writeMemory(238,0xFF); + writeMemory(239,0xFF); + writeMemory(240,0xFF); + writeMemory(241,0xFF); + writeMemory(242,0xFF); + writeMemory(243,0xFF); + writeMemory(244,0xFF); + writeMemory(245,0xFF); + writeMemory(246,0xFF); + writeMemory(247,0xFF); + writeMemory(248,0xFF); + writeMemory(249,0xFF); + writeMemory(250,0xFF); + writeMemory(251,0xFF); + writeMemory(252,0xFF); + writeMemory(253,0xFF); + writeMemory(254,0xFF); + writeMemory(255,0xFF); + writeMemory(256,0xFF); + writeMemory(257,0xFF); + writeMemory(258,0xFF); + writeMemory(259,0xFF); + writeMemory(260,0xFF); + writeMemory(261,0xFF); + writeMemory(262,0xFF); + writeMemory(263,0xFF); + writeMemory(264,0xFF); + writeMemory(265,0xFF); + writeMemory(266,0xFF); + writeMemory(267,0xFF); + writeMemory(268,0xFF); + writeMemory(269,0xFF); + writeMemory(270,0xFF); + writeMemory(271,0xFF); + writeMemory(272,0xFF); + writeMemory(273,0xFF); + writeMemory(274,0xFF); + writeMemory(275,0xFF); + writeMemory(276,0xFF); + writeMemory(277,0xFF); + writeMemory(278,0xFF); + writeMemory(279,0xFF); + writeMemory(280,0xFF); + writeMemory(281,0xFF); + writeMemory(282,0xFF); + writeMemory(283,0xFF); + writeMemory(284,0xFF); + writeMemory(285,0xFF); + writeMemory(286,0xFF); + writeMemory(287,0xFF); + writeMemory(288,0xFF); + writeMemory(289,0xFF); + writeMemory(290,0xFF); + writeMemory(291,0xFF); + writeMemory(292,0xFF); + writeMemory(293,0xFF); + writeMemory(294,0xFF); + writeMemory(295,0xFF); + writeMemory(296,0xFF); + writeMemory(297,0xFF); + writeMemory(298,0xFF); + writeMemory(299,0xFF); + writeMemory(300,0xFF); + writeMemory(301,0xFF); + writeMemory(302,0xFF); + writeMemory(303,0xFF); + writeMemory(304,0xFF); + writeMemory(305,0xFF); + writeMemory(306,0xFF); + writeMemory(307,0xFF); + writeMemory(308,0xFF); + writeMemory(309,0xFF); + writeMemory(310,0xFF); + writeMemory(311,0xFF); + writeMemory(312,0xFF); + writeMemory(313,0xFF); + writeMemory(314,0xFF); + writeMemory(315,0xFF); + writeMemory(316,0xFF); + writeMemory(317,0xFF); + writeMemory(318,0xFF); + writeMemory(319,0xFF); + writeMemory(320,0xFF); + writeMemory(321,0xFF); + writeMemory(322,0xFF); + writeMemory(323,0xFF); + writeMemory(324,0xFF); + writeMemory(325,0xFF); + writeMemory(326,0xFF); + writeMemory(327,0xFF); + writeMemory(328,0xFF); + writeMemory(329,0xFF); + writeMemory(330,0xFF); + writeMemory(331,0xFF); + writeMemory(332,0xFF); + writeMemory(333,0xFF); + writeMemory(334,0xFF); + writeMemory(335,0xFF); + writeMemory(336,0xFF); + writeMemory(337,0xFF); + writeMemory(338,0xFF); + writeMemory(339,0xFF); + writeMemory(340,0xFF); + writeMemory(341,0xFF); + writeMemory(342,0xFF); + writeMemory(343,0xFF); + writeMemory(344,0xFF); + writeMemory(345,0xFF); + writeMemory(346,0xFF); + writeMemory(347,0xFF); + writeMemory(348,0xFF); + writeMemory(349,0xFF); + writeMemory(350,0xFF); + writeMemory(351,0xFF); + writeMemory(352,0xFF); + writeMemory(353,0xFF); + writeMemory(354,0xFF); + writeMemory(355,0xFF); + writeMemory(356,0xFF); + writeMemory(357,0xFF); + writeMemory(358,0xFF); + writeMemory(359,0xFF); + writeMemory(360,0xFF); + writeMemory(361,0xFF); + writeMemory(362,0xFF); + writeMemory(363,0xFF); + writeMemory(364,0xFF); + writeMemory(365,0xFF); + writeMemory(366,0xFF); + writeMemory(367,0xFF); + writeMemory(368,0xFF); + writeMemory(369,0xFF); + writeMemory(370,0xFF); + writeMemory(371,0xFF); + writeMemory(372,0xFF); + writeMemory(373,0xFF); + writeMemory(374,0xFF); + writeMemory(375,0xFF); + writeMemory(376,0xFF); + writeMemory(377,0xFF); + writeMemory(378,0xFF); + writeMemory(379,0xFF); + writeMemory(380,0xFF); + writeMemory(381,0xFF); + writeMemory(382,0xFF); + writeMemory(383,0xFF); + writeMemory(384,0xFF); + writeMemory(385,0xFF); + writeMemory(386,0xFF); + writeMemory(387,0xFF); + writeMemory(388,0xFF); + writeMemory(389,0xFF); + writeMemory(390,0xFF); + writeMemory(391,0xFF); + writeMemory(392,0xFF); + writeMemory(393,0xFF); + writeMemory(394,0xFF); + writeMemory(395,0xFF); + writeMemory(396,0xFF); + writeMemory(397,0xFF); + writeMemory(398,0xFF); + writeMemory(399,0xFF); + writeMemory(400,0xFF); + writeMemory(401,0xFF); + writeMemory(402,0xFF); + writeMemory(403,0xFF); + writeMemory(404,0xFF); + writeMemory(405,0xFF); + writeMemory(406,0xFF); + writeMemory(407,0xFF); + writeMemory(408,0xFF); + writeMemory(409,0xFF); + writeMemory(410,0xFF); + writeMemory(411,0xFF); + writeMemory(412,0xFF); + writeMemory(413,0xFF); + writeMemory(414,0xFF); + writeMemory(415,0xFF); + writeMemory(416,0xFF); + writeMemory(417,0xFF); + writeMemory(418,0xFF); + writeMemory(419,0xFF); + writeMemory(420,0xFF); + writeMemory(421,0xFF); + writeMemory(422,0xFF); + writeMemory(423,0xFF); + writeMemory(424,0xFF); + writeMemory(425,0xFF); + writeMemory(426,0xFF); + writeMemory(427,0xFF); + writeMemory(428,0xFF); + writeMemory(429,0xFF); + writeMemory(430,0xFF); + writeMemory(431,0xFF); + writeMemory(432,0xFF); + writeMemory(433,0xFF); + writeMemory(434,0xFF); + writeMemory(435,0xFF); + writeMemory(436,0xFF); + writeMemory(437,0xFF); + writeMemory(438,0xFF); + writeMemory(439,0xFF); + writeMemory(440,0xFF); + writeMemory(441,0xFF); + writeMemory(442,0xFF); + writeMemory(443,0xFF); + writeMemory(444,0xFF); + writeMemory(445,0xFF); + writeMemory(446,0xFF); + writeMemory(447,0xFF); + writeMemory(448,0xFF); + writeMemory(449,0xFF); + writeMemory(450,0xFF); + writeMemory(451,0xFF); + writeMemory(452,0xFF); + writeMemory(453,0xFF); + writeMemory(454,0xFF); + writeMemory(455,0xFF); + writeMemory(456,0xFF); + writeMemory(457,0xFF); + writeMemory(458,0xFF); + writeMemory(459,0xFF); + writeMemory(460,0xFF); + writeMemory(461,0xFF); + writeMemory(462,0xFF); + writeMemory(463,0xFF); + writeMemory(464,0xFF); + writeMemory(465,0xFF); + writeMemory(466,0xFF); + writeMemory(467,0xFF); + writeMemory(468,0xFF); + writeMemory(469,0xFF); + writeMemory(470,0xFF); + writeMemory(471,0xFF); + writeMemory(472,0xFF); + writeMemory(473,0xFF); + writeMemory(474,0xFF); + writeMemory(475,0xFF); + writeMemory(476,0xFF); + writeMemory(477,0xFF); + writeMemory(478,0xFF); + writeMemory(479,0xFF); + writeMemory(480,0xFF); + writeMemory(481,0xFF); + writeMemory(482,0xFF); + writeMemory(483,0xFF); + writeMemory(484,0xFF); + writeMemory(485,0xFF); + writeMemory(486,0xFF); + writeMemory(487,0xFF); + writeMemory(488,0xFF); + writeMemory(489,0xFF); + writeMemory(490,0xFF); + writeMemory(491,0xFF); + writeMemory(492,0xFF); + writeMemory(493,0xFF); + writeMemory(494,0xFF); + writeMemory(495,0xFF); + writeMemory(496,0xFF); + writeMemory(497,0xFF); + writeMemory(498,0xFF); + writeMemory(499,0xFF); + writeMemory(500,0xFF); + writeMemory(501,0xFF); + writeMemory(502,0xFF); + writeMemory(503,0xFF); + writeMemory(504,0xFF); + writeMemory(505,0xFF); + writeMemory(506,0xFF); + writeMemory(507,0xFF); + writeMemory(508,0xFF); + writeMemory(509,0xFF); + writeMemory(510,0xFF); + writeMemory(511,0xFF); + writeMemory(512,0xFF); + writeMemory(513,0xFF); + writeMemory(514,0xFF); + writeMemory(515,0xFF); + writeMemory(516,0xFF); + writeMemory(517,0xFF); + writeMemory(518,0xFF); + writeMemory(519,0xFF); + writeMemory(520,0xFF); + writeMemory(521,0xFF); + writeMemory(522,0xFF); + writeMemory(523,0xFF); + writeMemory(524,0xFF); + writeMemory(525,0xFF); + writeMemory(526,0xFF); + writeMemory(527,0xFF); + writeMemory(528,0xFF); + writeMemory(529,0xFF); + writeMemory(530,0xFF); + writeMemory(531,0xFF); + writeMemory(532,0xFF); + writeMemory(533,0xFF); + writeMemory(534,0xFF); + writeMemory(535,0xFF); + writeMemory(536,0xFF); + writeMemory(537,0xFF); + writeMemory(538,0xFF); + writeMemory(539,0xFF); + writeMemory(540,0xFF); + writeMemory(541,0xFF); + writeMemory(542,0xFF); + writeMemory(543,0xFF); + writeMemory(544,0xFF); + writeMemory(545,0xFF); + writeMemory(546,0xFF); + writeMemory(547,0xFF); + writeMemory(548,0xFF); + writeMemory(549,0xFF); + writeMemory(550,0xFF); + writeMemory(551,0xFF); + writeMemory(552,0xFF); + writeMemory(553,0xFF); + writeMemory(554,0xFF); + writeMemory(555,0xFF); + writeMemory(556,0xFF); + writeMemory(557,0xFF); + writeMemory(558,0xFF); + writeMemory(559,0xFF); + writeMemory(560,0xFF); + writeMemory(561,0xFF); + writeMemory(562,0xFF); + writeMemory(563,0xFF); + writeMemory(564,0xFF); + writeMemory(565,0xFF); + writeMemory(566,0xFF); + writeMemory(567,0xFF); + writeMemory(568,0xFF); + writeMemory(569,0xFF); + writeMemory(570,0xFF); + writeMemory(571,0xFF); + writeMemory(572,0xFF); + writeMemory(573,0xFF); + writeMemory(574,0xFF); + writeMemory(575,0x14); + writeMemory(576,0x00); + writeMemory(577,0x00); + writeMemory(578,0x01); + writeMemory(579,0x01); + writeMemory(580,0x02); + writeMemory(581,0x02); + writeMemory(582,0x02); + writeMemory(583,0x05); + writeMemory(584,0x03); + writeMemory(585,0x03); + writeMemory(586,0x04); + writeMemory(587,0x04); + writeMemory(588,0x05); + writeMemory(589,0x06); + writeMemory(590,0x06); + writeMemory(591,0x07); + writeMemory(592,0x07); + writeMemory(593,0x08); + writeMemory(594,0x08); + writeMemory(595,0x09); + writeMemory(596,0x09); + writeMemory(597,0x0C); + writeMemory(598,0x0A); + writeMemory(599,0x0D); + writeMemory(600,0x0B); + writeMemory(601,0x0E); + writeMemory(602,0x0C); + writeMemory(603,0x0F); + writeMemory(604,0x0D); + writeMemory(605,0x0A); + writeMemory(606,0x0E); + writeMemory(607,0x0B); + writeMemory(608,0x0F); + writeMemory(609,0x11); + writeMemory(610,0x10); + writeMemory(611,0x12); + writeMemory(612,0x11); + writeMemory(613,0x13); + writeMemory(614,0x12); + writeMemory(615,0x14); + writeMemory(616,0xFF); + writeMemory(617,0xFF); + writeMemory(618,0xFF); + writeMemory(619,0xFF); + writeMemory(620,0xFF); + writeMemory(621,0xFF); + writeMemory(622,0xFF); + writeMemory(623,0xFF); + writeMemory(624,0xFF); + writeMemory(625,0xFF); + writeMemory(626,0xFF); + writeMemory(627,0xFF); + writeMemory(628,0xFF); + writeMemory(629,0xFF); + writeMemory(630,0xFF); + writeMemory(631,0xFF); + writeMemory(632,0xFF); + writeMemory(633,0xFF); + writeMemory(634,0xFF); + writeMemory(635,0xFF); + writeMemory(636,0xFF); + writeMemory(637,0xFF); + writeMemory(638,0xFF); + writeMemory(639,0xFF); + writeMemory(640,0xFF); + writeMemory(641,0xFF); + writeMemory(642,0xFF); + writeMemory(643,0xFF); + writeMemory(644,0xFF); + writeMemory(645,0xFF); + writeMemory(646,0xFF); + writeMemory(647,0xFF); + writeMemory(648,0xFF); + writeMemory(649,0xFF); + writeMemory(650,0xFF); + writeMemory(651,0xFF); + writeMemory(652,0xFF); + writeMemory(653,0xFF); + writeMemory(654,0xFF); + writeMemory(655,0xFF); + writeMemory(656,0xFF); + writeMemory(657,0xFF); + writeMemory(658,0xFF); + writeMemory(659,0xFF); + writeMemory(660,0xFF); + writeMemory(661,0xFF); + writeMemory(662,0xFF); + writeMemory(663,0xFF); + writeMemory(664,0xFF); + writeMemory(665,0xFF); + writeMemory(666,0xFF); + writeMemory(667,0xFF); + writeMemory(668,0xFF); + writeMemory(669,0xFF); + writeMemory(670,0xFF); + writeMemory(671,0xFF); + writeMemory(672,0xFF); + writeMemory(673,0xFF); + writeMemory(674,0xFF); + writeMemory(675,0xFF); + writeMemory(676,0xFF); + writeMemory(677,0xFF); + writeMemory(678,0xFF); + writeMemory(679,0xFF); + writeMemory(680,0xFF); + writeMemory(681,0xFF); + writeMemory(682,0xFF); + writeMemory(683,0xFF); + writeMemory(684,0xFF); + writeMemory(685,0xFF); + writeMemory(686,0xFF); + writeMemory(687,0xFF); + writeMemory(688,0xFF); + writeMemory(689,0xFF); + writeMemory(690,0xFF); + writeMemory(691,0xFF); + writeMemory(692,0xFF); + writeMemory(693,0xFF); + writeMemory(694,0xFF); + writeMemory(695,0xFF); + writeMemory(696,0xFF); + writeMemory(697,0xFF); + writeMemory(698,0xFF); + writeMemory(699,0xFF); + writeMemory(700,0xFF); + writeMemory(701,0xFF); + writeMemory(702,0xFF); + writeMemory(703,0xFF); + writeMemory(704,0xFF); + writeMemory(705,0xFF); + writeMemory(706,0xFF); + writeMemory(707,0xFF); + writeMemory(708,0xFF); + writeMemory(709,0xFF); + writeMemory(710,0xFF); + writeMemory(711,0xFF); + writeMemory(712,0xFF); + writeMemory(713,0xFF); + writeMemory(714,0xFF); + writeMemory(715,0xFF); + writeMemory(716,0xFF); + writeMemory(717,0xFF); + writeMemory(718,0xFF); + writeMemory(719,0xFF); + writeMemory(720,0xFF); + writeMemory(721,0xFF); + writeMemory(722,0xFF); + writeMemory(723,0xFF); + writeMemory(724,0xFF); + writeMemory(725,0xFF); + writeMemory(726,0xFF); + writeMemory(727,0xFF); + writeMemory(728,0xFF); + writeMemory(729,0xFF); + writeMemory(730,0xFF); + writeMemory(731,0xFF); + writeMemory(732,0xFF); + writeMemory(733,0xFF); + writeMemory(734,0xFF); + writeMemory(735,0xFF); + writeMemory(736,0xFF); + writeMemory(737,0xFF); + writeMemory(738,0xFF); + writeMemory(739,0xFF); + writeMemory(740,0xFF); + writeMemory(741,0xFF); + writeMemory(742,0xFF); + writeMemory(743,0xFF); + writeMemory(744,0xFF); + writeMemory(745,0xFF); + writeMemory(746,0xFF); + writeMemory(747,0xFF); + writeMemory(748,0xFF); + writeMemory(749,0xFF); + writeMemory(750,0xFF); + writeMemory(751,0xFF); + writeMemory(752,0xFF); + writeMemory(753,0xFF); + writeMemory(754,0xFF); + writeMemory(755,0xFF); + writeMemory(756,0xFF); + writeMemory(757,0xFF); + writeMemory(758,0xFF); + writeMemory(759,0xFF); + writeMemory(760,0xFF); + writeMemory(761,0xFF); + writeMemory(762,0xFF); + writeMemory(763,0xFF); + writeMemory(764,0xFF); + writeMemory(765,0xFF); + writeMemory(766,0xFF); + writeMemory(767,0xFF); + writeMemory(768,0xFF); + writeMemory(769,0xFF); + writeMemory(770,0xFF); + writeMemory(771,0xFF); + writeMemory(772,0xFF); + writeMemory(773,0xFF); + writeMemory(774,0xFF); + writeMemory(775,0xFF); + writeMemory(776,0xFF); + writeMemory(777,0xFF); + writeMemory(778,0xFF); + writeMemory(779,0xFF); + writeMemory(780,0xFF); + writeMemory(781,0xFF); + writeMemory(782,0xFF); + writeMemory(783,0xFF); + writeMemory(784,0xFF); + writeMemory(785,0xFF); + writeMemory(786,0xFF); + writeMemory(787,0xFF); + writeMemory(788,0xFF); + writeMemory(789,0xFF); + writeMemory(790,0xFF); + writeMemory(791,0xFF); + writeMemory(792,0xFF); + writeMemory(793,0xFF); + writeMemory(794,0xFF); + writeMemory(795,0xFF); + writeMemory(796,0xFF); + writeMemory(797,0xFF); + writeMemory(798,0xFF); + writeMemory(799,0xFF); + writeMemory(800,0xFF); + writeMemory(801,0xFF); + writeMemory(802,0xFF); + writeMemory(803,0xFF); + writeMemory(804,0xFF); + writeMemory(805,0xFF); + writeMemory(806,0xFF); + writeMemory(807,0xFF); + writeMemory(808,0xFF); + writeMemory(809,0xFF); + writeMemory(810,0xFF); + writeMemory(811,0xFF); + writeMemory(812,0xFF); + writeMemory(813,0xFF); + writeMemory(814,0xFF); + writeMemory(815,0xFF); + writeMemory(816,0xFF); + writeMemory(817,0xFF); + writeMemory(818,0xFF); + writeMemory(819,0xFF); + writeMemory(820,0xFF); + writeMemory(821,0xFF); + writeMemory(822,0xFF); + writeMemory(823,0xFF); + writeMemory(824,0xFF); + writeMemory(825,0xFF); + writeMemory(826,0xFF); + writeMemory(827,0xFF); + writeMemory(828,0xFF); + writeMemory(829,0xFF); + writeMemory(830,0xFF); + writeMemory(831,0xFF); + writeMemory(832,0xFF); + writeMemory(833,0xFF); + writeMemory(834,0xFF); + writeMemory(835,0xFF); + writeMemory(836,0xFF); + writeMemory(837,0xFF); + writeMemory(838,0xFF); + writeMemory(839,0xFF); + writeMemory(840,0xFF); + writeMemory(841,0xFF); + writeMemory(842,0xFF); + writeMemory(843,0xFF); + writeMemory(844,0xFF); + writeMemory(845,0xFF); + writeMemory(846,0xFF); + writeMemory(847,0xFF); + writeMemory(848,0xFF); + writeMemory(849,0xFF); + writeMemory(850,0xFF); + writeMemory(851,0xFF); + writeMemory(852,0xFF); + writeMemory(853,0xFF); + writeMemory(854,0xFF); + writeMemory(855,0xFF); + writeMemory(856,0xFF); + writeMemory(857,0xFF); + writeMemory(858,0xFF); + writeMemory(859,0xFF); + writeMemory(860,0xFF); + writeMemory(861,0xFF); + writeMemory(862,0xFF); + writeMemory(863,0xFF); + writeMemory(864,0xFF); + writeMemory(865,0xFF); + writeMemory(866,0xFF); + writeMemory(867,0xFF); + writeMemory(868,0xFF); + writeMemory(869,0xFF); + writeMemory(870,0xFF); + writeMemory(871,0xFF); + writeMemory(872,0xFF); + writeMemory(873,0xFF); + writeMemory(874,0xFF); + writeMemory(875,0xFF); + writeMemory(876,0xFF); + writeMemory(877,0xFF); + writeMemory(878,0xFF); + writeMemory(879,0xFF); + writeMemory(880,0xFF); + writeMemory(881,0xFF); + writeMemory(882,0xFF); + writeMemory(883,0xFF); + writeMemory(884,0xFF); + writeMemory(885,0xFF); + writeMemory(886,0xFF); + writeMemory(887,0xFF); + writeMemory(888,0xFF); + writeMemory(889,0xFF); + writeMemory(890,0xFF); + writeMemory(891,0xFF); + writeMemory(892,0xFF); + writeMemory(893,0xFF); + writeMemory(894,0xFF); + writeMemory(895,0xFF); + writeMemory(896,0xFF); + writeMemory(897,0xFF); + writeMemory(898,0xFF); + writeMemory(899,0xFF); + writeMemory(900,0xFF); + writeMemory(901,0xFF); + writeMemory(902,0xFF); + writeMemory(903,0xFF); + writeMemory(904,0xFF); + writeMemory(905,0xFF); + writeMemory(906,0xFF); + writeMemory(907,0xFF); + writeMemory(908,0xFF); + writeMemory(909,0xFF); + writeMemory(910,0xFF); + writeMemory(911,0xFF); + writeMemory(912,0xFF); + writeMemory(913,0xFF); + writeMemory(914,0xFF); + writeMemory(915,0xFF); + writeMemory(916,0xFF); + writeMemory(917,0xFF); + writeMemory(918,0xFF); + writeMemory(919,0xFF); + writeMemory(920,0xFF); + writeMemory(921,0xFF); + writeMemory(922,0xFF); + writeMemory(923,0xFF); + writeMemory(924,0xFF); + writeMemory(925,0xFF); + writeMemory(926,0xFF); + writeMemory(927,0xFF); + writeMemory(928,0xFF); + writeMemory(929,0xFF); + writeMemory(930,0xFF); + writeMemory(931,0xFF); + writeMemory(932,0xFF); + writeMemory(933,0xFF); + writeMemory(934,0xFF); + writeMemory(935,0xFF); + writeMemory(936,0xFF); + writeMemory(937,0xFF); + writeMemory(938,0xFF); + writeMemory(939,0xFF); + writeMemory(940,0xFF); + writeMemory(941,0xFF); + writeMemory(942,0xFF); + writeMemory(943,0xFF); + writeMemory(944,0xFF); + writeMemory(945,0xFF); + writeMemory(946,0xFF); + writeMemory(947,0xFF); + writeMemory(948,0xFF); + writeMemory(949,0xFF); + writeMemory(950,0xFF); + writeMemory(951,0xFF); + writeMemory(952,0xFF); + writeMemory(953,0xFF); + writeMemory(954,0xFF); + writeMemory(955,0xFF); + writeMemory(956,0xFF); + writeMemory(957,0xFF); + writeMemory(958,0xFF); + writeMemory(959,0xFF); + writeMemory(960,0xFF); + writeMemory(961,0xFF); + writeMemory(962,0xFF); + writeMemory(963,0xFF); + writeMemory(964,0xFF); + writeMemory(965,0xFF); + writeMemory(966,0xFF); + writeMemory(967,0xFF); + writeMemory(968,0xFF); + writeMemory(969,0xFF); + writeMemory(970,0xFF); + writeMemory(971,0xFF); + writeMemory(972,0xFF); + writeMemory(973,0xFF); + writeMemory(974,0xFF); + writeMemory(975,0xFF); + writeMemory(976,0xFF); + writeMemory(977,0xFF); + writeMemory(978,0xFF); + writeMemory(979,0xFF); + writeMemory(980,0xFF); + writeMemory(981,0xFF); + writeMemory(982,0xFF); + writeMemory(983,0xFF); + writeMemory(984,0xFF); + writeMemory(985,0xFF); + writeMemory(986,0xFF); + writeMemory(987,0xFF); + writeMemory(988,0xFF); + writeMemory(989,0xFF); + writeMemory(990,0xFF); + writeMemory(991,0xFF); + writeMemory(992,0xFF); + writeMemory(993,0xFF); + writeMemory(994,0xFF); + writeMemory(995,0xFF); + writeMemory(996,0xFF); + writeMemory(997,0xFF); + writeMemory(998,0xFF); + writeMemory(999,0xFF); + writeMemory(1000,0xFF); + writeMemory(1001,0xFF); + writeMemory(1002,0xFF); + writeMemory(1003,0xFF); + writeMemory(1004,0xFF); + writeMemory(1005,0xFF); + writeMemory(1006,0xFF); + writeMemory(1007,0xFF); + writeMemory(1008,0xFF); + writeMemory(1009,0xFF); + writeMemory(1010,0xFF); + writeMemory(1011,0xFF); + writeMemory(1012,0xFF); + writeMemory(1013,0xFF); + writeMemory(1014,0xFF); + writeMemory(1015,0xFF); + writeMemory(1016,0xFF); + writeMemory(1017,0xFF); + writeMemory(1018,0xFF); + writeMemory(1019,0xFF); + writeMemory(1020,0xFF); + writeMemory(1021,0xFF); + writeMemory(1022,0xFF); + writeMemory(1023,0xFF); + writeMemory(1024,0xFF); + writeMemory(1025,0xFF); + writeMemory(1026,0xFF); + writeMemory(1027,0xFF); + writeMemory(1028,0xFF); + writeMemory(1029,0xFF); + writeMemory(1030,0xFF); + writeMemory(1031,0xFF); + writeMemory(1032,0xFF); + writeMemory(1033,0xFF); + writeMemory(1034,0xFF); + writeMemory(1035,0xFF); + writeMemory(1036,0xFF); + writeMemory(1037,0xFF); + writeMemory(1038,0xFF); + writeMemory(1039,0xFF); + writeMemory(1040,0xFF); + writeMemory(1041,0xFF); + writeMemory(1042,0xFF); + writeMemory(1043,0xFF); + writeMemory(1044,0xFF); + writeMemory(1045,0xFF); + writeMemory(1046,0xFF); + writeMemory(1047,0xFF); + writeMemory(1048,0xFF); + writeMemory(1049,0xFF); + writeMemory(1050,0xFF); + writeMemory(1051,0xFF); + writeMemory(1052,0xFF); + writeMemory(1053,0xFF); + writeMemory(1054,0xFF); + writeMemory(1055,0xFF); + writeMemory(1056,0xFF); + writeMemory(1057,0xFF); + writeMemory(1058,0xFF); + writeMemory(1059,0xFF); + writeMemory(1060,0xFF); + writeMemory(1061,0xFF); + writeMemory(1062,0xFF); + writeMemory(1063,0xFF); + writeMemory(1064,0xFF); + writeMemory(1065,0xFF); + writeMemory(1066,0xFF); + writeMemory(1067,0xFF); + writeMemory(1068,0xFF); + writeMemory(1069,0xFF); + writeMemory(1070,0xFF); + writeMemory(1071,0xFF); + writeMemory(1072,0xFF); + writeMemory(1073,0xFF); + writeMemory(1074,0xFF); + writeMemory(1075,0xFF); + writeMemory(1076,0xFF); + writeMemory(1077,0xFF); + writeMemory(1078,0xFF); + writeMemory(1079,0xFF); + writeMemory(1080,0xFF); + writeMemory(1081,0xFF); + writeMemory(1082,0xFF); + writeMemory(1083,0xFF); + writeMemory(1084,0xFF); + writeMemory(1085,0xFF); + writeMemory(1086,0x23); + writeMemory(1087,0x2B); + writeMemory(1088,0x2A); + writeMemory(1089,0x2A); + writeMemory(1090,0x34); + writeMemory(1091,0x34); + writeMemory(1092,0x2A); + writeMemory(1093,0x2A); + writeMemory(1094,0x2A); + writeMemory(1095,0x2A); + writeMemory(1096,0x2A); + writeMemory(1097,0x2A); + writeMemory(1098,0x2A); + writeMemory(1099,0x2A); + writeMemory(1100,0x2A); + writeMemory(1101,0x2A); + writeMemory(1102,0x2A); + writeMemory(1103,0x34); + writeMemory(1104,0x2A); + writeMemory(1105,0x2A); + writeMemory(1106,0x2A); + writeMemory(1107,0x2A); + writeMemory(1108,0x2A); + writeMemory(1109,0x2A); + writeMemory(1110,0x2A); + writeMemory(1111,0x2A); + writeMemory(1112,0x2A); + writeMemory(1113,0x2A); + writeMemory(1114,0x2A); + writeMemory(1115,0x2A); + writeMemory(1116,0x2A); + writeMemory(1117,0x2A); + writeMemory(1118,0x2A); + writeMemory(1119,0x2A); + writeMemory(1120,0x34); + writeMemory(1121,0x2B); + writeMemory(1122,0xFF); + writeMemory(1123,0xFF); + writeMemory(1124,0xFF); + writeMemory(1125,0xFF); + writeMemory(1126,0xFF); + writeMemory(1127,0xFF); + writeMemory(1128,0xFF); + writeMemory(1129,0xFF); + writeMemory(1130,0xFF); + writeMemory(1131,0xFF); + writeMemory(1132,0xFF); + writeMemory(1133,0xFF); + writeMemory(1134,0xFF); + writeMemory(1135,0xFF); + writeMemory(1136,0xFF); + writeMemory(1137,0xFF); + writeMemory(1138,0xFF); + writeMemory(1139,0xFF); + writeMemory(1140,0xFF); + writeMemory(1141,0xFF); + writeMemory(1142,0xFF); + writeMemory(1143,0xFF); + writeMemory(1144,0xFF); + writeMemory(1145,0xFF); + writeMemory(1146,0xFF); + writeMemory(1147,0xFF); + writeMemory(1148,0xFF); + writeMemory(1149,0xFF); + writeMemory(1150,0xFF); + writeMemory(1151,0xFF); + writeMemory(1152,0xFF); + writeMemory(1153,0xFF); + writeMemory(1154,0xFF); + writeMemory(1155,0xFF); + writeMemory(1156,0xFF); + writeMemory(1157,0xFF); + writeMemory(1158,0xFF); + writeMemory(1159,0xFF); + writeMemory(1160,0xFF); + writeMemory(1161,0xFF); + writeMemory(1162,0xFF); + writeMemory(1163,0xFF); + writeMemory(1164,0xFF); + writeMemory(1165,0xFF); + writeMemory(1166,0xFF); + writeMemory(1167,0xFF); + writeMemory(1168,0xFF); + writeMemory(1169,0xFF); + writeMemory(1170,0xFF); + writeMemory(1171,0xFF); + writeMemory(1172,0xFF); + writeMemory(1173,0xFF); + writeMemory(1174,0xFF); + writeMemory(1175,0xFF); + writeMemory(1176,0xFF); + writeMemory(1177,0xFF); + writeMemory(1178,0xFF); + writeMemory(1179,0xFF); + writeMemory(1180,0xFF); + writeMemory(1181,0xFF); + writeMemory(1182,0xFF); + writeMemory(1183,0xFF); + writeMemory(1184,0xFF); + writeMemory(1185,0xFF); + writeMemory(1186,0xFF); + writeMemory(1187,0xFF); + writeMemory(1188,0xFF); + writeMemory(1189,0xFF); + writeMemory(1190,0xFF); + writeMemory(1191,0xFF); + writeMemory(1192,0xFF); + writeMemory(1193,0xFF); + writeMemory(1194,0xFF); + writeMemory(1195,0xFF); + writeMemory(1196,0xFF); + writeMemory(1197,0xFF); + writeMemory(1198,0xFF); + writeMemory(1199,0xFF); + writeMemory(1200,0xFF); + writeMemory(1201,0xFF); + writeMemory(1202,0xFF); + writeMemory(1203,0xFF); + writeMemory(1204,0xFF); + writeMemory(1205,0xFF); + writeMemory(1206,0xFF); + writeMemory(1207,0xFF); + writeMemory(1208,0xFF); + writeMemory(1209,0xFF); + writeMemory(1210,0xFF); + writeMemory(1211,0xFF); + writeMemory(1212,0xFF); + writeMemory(1213,0xFF); + writeMemory(1214,0xFF); + writeMemory(1215,0xFF); + writeMemory(1216,0xFF); + writeMemory(1217,0xFF); + writeMemory(1218,0xFF); + writeMemory(1219,0xFF); + writeMemory(1220,0xFF); + writeMemory(1221,0xFF); + writeMemory(1222,0xFF); + writeMemory(1223,0xFF); + writeMemory(1224,0xFF); + writeMemory(1225,0xFF); + writeMemory(1226,0xFF); + writeMemory(1227,0xFF); + writeMemory(1228,0xFF); + writeMemory(1229,0xFF); + writeMemory(1230,0xFF); + writeMemory(1231,0xFF); + writeMemory(1232,0xFF); + writeMemory(1233,0xFF); + writeMemory(1234,0xFF); + writeMemory(1235,0xFF); + writeMemory(1236,0xFF); + writeMemory(1237,0xFF); + writeMemory(1238,0xFF); + writeMemory(1239,0xFF); + writeMemory(1240,0xFF); + writeMemory(1241,0xFF); + writeMemory(1242,0xFF); + writeMemory(1243,0xFF); + writeMemory(1244,0xFF); + writeMemory(1245,0xFF); + writeMemory(1246,0xFF); + writeMemory(1247,0xFF); + writeMemory(1248,0xFF); + writeMemory(1249,0xFF); + writeMemory(1250,0xFF); + writeMemory(1251,0xFF); + writeMemory(1252,0xFF); + writeMemory(1253,0xFF); + writeMemory(1254,0xFF); + writeMemory(1255,0xFF); + writeMemory(1256,0xFF); + writeMemory(1257,0xFF); + writeMemory(1258,0xFF); + writeMemory(1259,0xFF); + writeMemory(1260,0xFF); + writeMemory(1261,0xFF); + writeMemory(1262,0xFF); + writeMemory(1263,0xFF); + writeMemory(1264,0xFF); + writeMemory(1265,0xFF); + writeMemory(1266,0xFF); + writeMemory(1267,0xFF); + writeMemory(1268,0xFF); + writeMemory(1269,0xFF); + writeMemory(1270,0xFF); + writeMemory(1271,0xFF); + writeMemory(1272,0xFF); + writeMemory(1273,0xFF); + writeMemory(1274,0xFF); + writeMemory(1275,0xFF); + writeMemory(1276,0xFF); + writeMemory(1277,0xFF); + writeMemory(1278,0xFF); + writeMemory(1279,0xFF); + writeMemory(1280,0xFF); + writeMemory(1281,0xFF); + writeMemory(1282,0xFF); + writeMemory(1283,0xFF); + writeMemory(1284,0xFF); + writeMemory(1285,0xFF); + writeMemory(1286,0xFF); + writeMemory(1287,0xFF); + writeMemory(1288,0xFF); + writeMemory(1289,0xFF); + writeMemory(1290,0xFF); + writeMemory(1291,0xFF); + writeMemory(1292,0xFF); + writeMemory(1293,0xFF); + writeMemory(1294,0xFF); + writeMemory(1295,0xFF); + writeMemory(1296,0xFF); + writeMemory(1297,0xFF); + writeMemory(1298,0xFF); + writeMemory(1299,0xFF); + writeMemory(1300,0xFF); + writeMemory(1301,0xFF); + writeMemory(1302,0xFF); + writeMemory(1303,0xFF); + writeMemory(1304,0xFF); + writeMemory(1305,0xFF); + writeMemory(1306,0xFF); + writeMemory(1307,0xFF); + writeMemory(1308,0xFF); + writeMemory(1309,0xFF); + writeMemory(1310,0xFF); + writeMemory(1311,0xFF); + writeMemory(1312,0xFF); + writeMemory(1313,0xFF); + writeMemory(1314,0xFF); + writeMemory(1315,0xFF); + writeMemory(1316,0xFF); + writeMemory(1317,0xFF); + writeMemory(1318,0xFF); + writeMemory(1319,0xFF); + writeMemory(1320,0xFF); + writeMemory(1321,0xFF); + writeMemory(1322,0xFF); + writeMemory(1323,0xFF); + writeMemory(1324,0xFF); + writeMemory(1325,0xFF); + writeMemory(1326,0xFF); + writeMemory(1327,0xFF); + writeMemory(1328,0xFF); + writeMemory(1329,0xFF); + writeMemory(1330,0xFF); + writeMemory(1331,0xFF); + writeMemory(1332,0xFF); + writeMemory(1333,0xFF); + writeMemory(1334,0xFF); + writeMemory(1335,0xFF); + writeMemory(1336,0xFF); + writeMemory(1337,0xFF); + writeMemory(1338,0xFF); + writeMemory(1339,0xFF); + writeMemory(1340,0xFF); + writeMemory(1341,0xFF); + writeMemory(1342,0xFF); + writeMemory(1343,0xD2); + writeMemory(1344,0x00); + writeMemory(1345,0x1E); + writeMemory(1346,0x0A); + writeMemory(1347,0xFF); + writeMemory(1348,0xFF); + writeMemory(1349,0xFF); + writeMemory(1350,0xFF); + writeMemory(1351,0x1C); + writeMemory(1352,0xFF); + writeMemory(1353,0xFA); + writeMemory(1354,0xE0); + writeMemory(1355,0x02); + writeMemory(1356,0x03); + writeMemory(1357,0x00); + writeMemory(1358,0xFF); + writeMemory(1359,0x00); + writeMemory(1360,0xFF); + writeMemory(1361,0x00); + writeMemory(1362,0x00); + writeMemory(1363,0x00); + writeMemory(1364,0x00); + writeMemory(1365,0x00); + writeMemory(1366,0x00); + writeMemory(1367,0x00); + writeMemory(1368,0x00); + writeMemory(1369,0x00); + writeMemory(1370,0x00); + writeMemory(1371,0x00); + writeMemory(1372,0x00); + writeMemory(1373,0x00); + writeMemory(1374,0x00); + writeMemory(1375,0x00); + writeMemory(1376,0x00); + writeMemory(1377,0x00); + writeMemory(1378,0x00); + writeMemory(1379,0x00); + writeMemory(1380,0x00); + writeMemory(1381,0x00); + writeMemory(1382,0x01); + writeMemory(1383,0x00); + writeMemory(1384,0x01); + writeMemory(1385,0x00); + writeMemory(1386,0x00); + writeMemory(1387,0x00); + writeMemory(1388,0x00); + writeMemory(1389,0x00); + writeMemory(1390,0x01); + writeMemory(1391,0x00); + writeMemory(1392,0x01); + writeMemory(1393,0x00); + writeMemory(1394,0x00); + writeMemory(1395,0x00); + writeMemory(1396,0x00); + writeMemory(1397,0x00); + writeMemory(1398,0x01); + writeMemory(1399,0x00); + writeMemory(1400,0x01); + writeMemory(1401,0x00); + writeMemory(1402,0x00); + writeMemory(1403,0x00); + writeMemory(1404,0x00); + writeMemory(1405,0x00); + writeMemory(1406,0x01); + writeMemory(1407,0x00); + writeMemory(1408,0x01); + writeMemory(1409,0x00); + writeMemory(1410,0x00); + writeMemory(1411,0x00); + writeMemory(1412,0x00); + writeMemory(1413,0x00); + writeMemory(1414,0x1E); + +} +#endif