Test program to send MAX!-Messages with a RFM22-Module

Dependencies:   RF22 TextLCD TextLCDScroll mbed RF22Max

Revision:
4:6c72714f5886
Parent:
3:4254b4c3557e
--- a/main.cpp	Mon Sep 09 19:47:45 2013 +0000
+++ b/main.cpp	Tue Oct 22 19:43:01 2013 +0000
@@ -1,21 +1,21 @@
-// Testprogramm for RFM22B with RF22-Library to read ELV MAX! window Shutter-Contacts and PushBottons
-// Quick and dirty code!!!!!!
-// needs refactoring
+// Testprogramm for RFM22B with RF22Max-Library to read ELV MAX! window Shutter-Contacts and PushBottons
 
+//show debug output on Serial pc
+#define DEBUG
 
 #include "mbed.h"
-#include <RF22.h>
+#include <RF22Max.h>
 #include "TextLCDScroll.h"
 
-
-#define lengthof(x) (sizeof(x) / sizeof(*x))
+// show debug-output on console
+//#define DEBUG
 
 Serial pc(USBTX, USBRX);
 
-//Freebus-RS-Interface connected to serial
-Serial knxrs(p9, p10);  // tx, rx
+Ticker SendTicker;
 
-//TextLCDScroll lcd(p30, p29, p28, p27, p26, p25, TextLCD::LCD16x2); // rs, e, d4-d7
+volatile int doSend = 0;     // set to 1 by Ticker-Interrupt and read in main-loop
+
 TextLCDScroll lcd(p30, p29, p28, p27, p26, p25, TextLCD::LCD16x2); // rs, e, d4-d7
 
 // mbed LEDs
@@ -24,585 +24,100 @@
 DigitalOut led3(LED3);
 DigitalOut led4(LED4);
 
-struct max_knx_mapping_t {
-    uint32_t         device_id;
-    char             knx_adr[255];
-};
-
-#define MAX_KNX_MAPPINGS 10
-
-// a message from the max!-Device
-struct max_message {
-    uint8_t    len;                //message-length
-    uint8_t    cnt;                //message-counter
-    uint8_t    flags;              // ??
-    uint8_t    type;               //message-type
-    char       type_str[50];       // type in text
-    uint32_t   frm_adr;            // unique address of device
-    uint32_t   to_adr;             // unique address of device
-    uint8_t    groupid;            //groupid
-    uint8_t    payload[50];        // data
-    uint16_t   crc;                // crc fro the message
-    char       state[50];          // state of the device: open, closed, auto, eco,...
-    char       battery_state[50];  // Battery-state of the device : good, low
-};
-
-
-
 // Singleton instance of the radio
 //rf22(PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
-RF22 rf22(p14,p11,p12,p13,p15);
-
-
-const RF22::ModemConfig config = { // for MAX! protocol
-    .reg_1c = 0x01,
-    .reg_1f = 0x03,
-    .reg_20 = 0x90,
-    .reg_21 = 0x20,
-    .reg_22 = 0x51,
-    .reg_23 = 0xea,
-    .reg_24 = 0x00,
-    .reg_25 = 0x58,
-    /* 2c - 2e are only for OOK */
-    .reg_2c = 0x00,
-    .reg_2d = 0x00,
-    .reg_2e = 0x00,
-    .reg_58 = 0x80, /* Copied from RF22 defaults */
-    .reg_69 = 0x60, /* Copied from RF22 defaults */
-    .reg_6e = 0x08,
-    .reg_6f = 0x31,
-    .reg_70 = 0x24,
-    .reg_71 = RF22_DTMOD_FIFO | RF22_MODTYP_FSK,
-    .reg_72 = 0x1e,
-};
-
-/* Sync words to send / check for. Don't forget to update RF22_SYNCLEN
-* below if changing the length of this array. */
-const uint8_t sync_words[] = {
-    0xc6,
-    0x26,
-    0xc6,
-    0x26,
-};
-
-enum modes {MODE_AUTO, MODE_MANUAL, MODE_TEMPORARY, MODE_BOOST};
-const char *mode_str[] = {
-    [MODE_AUTO] = "auto",
-    [MODE_MANUAL] = "manual",
-    [MODE_TEMPORARY] = "temporary",
-    [MODE_BOOST] = "boost"
-};
-
-char *type_str(uint8_t type)
-{
-    switch(type) {
-        case 0x00:
-            return "PairPing";
-        case 0x01:
-            return "PairPong";
-        case 0x02:
-            return "Ack";
-        case 0x03:
-            return "TimeInformation";
-        case 0x10:
-            return "ConfigWeekProfile";
-        case 0x11:
-            return "ConfigTemperatures";
-        case 0x12:
-            return "ConfigValve";
-        case 0x20:
-            return "AddLinkPartner";
-        case 0x21:
-            return "RemoveLinkPartner";
-        case 0x22:
-            return "SetGroupId";
-        case 0x23:
-            return "RemoveGroupId";
-        case 0x30:
-            return "ShutterContactState";
-        case 0x40:
-            return "SetTemperature";
-        case 0x42:
-            return "WallThermostatState";
-        case 0x43:
-            return "SetComfortTemperature";
-        case 0x44:
-            return "SetEcoTemperature";
-        case 0x50:
-            return "PushButtonState";
-        case 0x60:
-            return "ThermostatState";
-        case 0x82:
-            return "SetDisplayActualTemperature";
-        case 0xF1:
-            return "WakeUp";
-        case 0xF0:
-            return "Reset";
-    }
-    return "Unknown";
-}
-
-
-/* First 255 bytes of PN9 sequence used for data whitening by the CC1101
-* chip. The RF22 chip is documented to support the same data whitening
-* algorithm, but in practice seems to use a different sequence.
-*
-* Data was generated using the following python snippet:
-*
-import itertools
-def pn9(state):
-    while True:
-        yield hex(state & 0xff)
-        # The pn9 generator is clocked 8 times while shifting in the
-        # next data byte
-        for i in range(8):
-            state = (state >> 1) + (((state & 1) ^ (state >> 5) & 1) << 8)
-print(list(itertools.islice(pn9(0x1ff), 255)))
-*/
-
-const uint8_t pn9[] = {
-    0xff, 0xe1, 0x1d, 0x9a, 0xed, 0x85, 0x33, 0x24,
-    0xea, 0x7a, 0xd2, 0x39, 0x70, 0x97, 0x57, 0x0a,
-    0x54, 0x7d, 0x2d, 0xd8, 0x6d, 0x0d, 0xba, 0x8f,
-    0x67, 0x59, 0xc7, 0xa2, 0xbf, 0x34, 0xca, 0x18,
-    0x30, 0x53, 0x93, 0xdf, 0x92, 0xec, 0xa7, 0x15,
-    0x8a, 0xdc, 0xf4, 0x86, 0x55, 0x4e, 0x18, 0x21,
-    0x40, 0xc4, 0xc4, 0xd5, 0xc6, 0x91, 0x8a, 0xcd,
-    0xe7, 0xd1, 0x4e, 0x09, 0x32, 0x17, 0xdf, 0x83,
-    0xff, 0xf0, 0x0e, 0xcd, 0xf6, 0xc2, 0x19, 0x12,
-    0x75, 0x3d, 0xe9, 0x1c, 0xb8, 0xcb, 0x2b, 0x05,
-    0xaa, 0xbe, 0x16, 0xec, 0xb6, 0x06, 0xdd, 0xc7,
-    0xb3, 0xac, 0x63, 0xd1, 0x5f, 0x1a, 0x65, 0x0c,
-    0x98, 0xa9, 0xc9, 0x6f, 0x49, 0xf6, 0xd3, 0x0a,
-    0x45, 0x6e, 0x7a, 0xc3, 0x2a, 0x27, 0x8c, 0x10,
-    0x20, 0x62, 0xe2, 0x6a, 0xe3, 0x48, 0xc5, 0xe6,
-    0xf3, 0x68, 0xa7, 0x04, 0x99, 0x8b, 0xef, 0xc1,
-    0x7f, 0x78, 0x87, 0x66, 0x7b, 0xe1, 0x0c, 0x89,
-    0xba, 0x9e, 0x74, 0x0e, 0xdc, 0xe5, 0x95, 0x02,
-    0x55, 0x5f, 0x0b, 0x76, 0x5b, 0x83, 0xee, 0xe3,
-    0x59, 0xd6, 0xb1, 0xe8, 0x2f, 0x8d, 0x32, 0x06,
-    0xcc, 0xd4, 0xe4, 0xb7, 0x24, 0xfb, 0x69, 0x85,
-    0x22, 0x37, 0xbd, 0x61, 0x95, 0x13, 0x46, 0x08,
-    0x10, 0x31, 0x71, 0xb5, 0x71, 0xa4, 0x62, 0xf3,
-    0x79, 0xb4, 0x53, 0x82, 0xcc, 0xc5, 0xf7, 0xe0,
-    0x3f, 0xbc, 0x43, 0xb3, 0xbd, 0x70, 0x86, 0x44,
-    0x5d, 0x4f, 0x3a, 0x07, 0xee, 0xf2, 0x4a, 0x81,
-    0xaa, 0xaf, 0x05, 0xbb, 0xad, 0x41, 0xf7, 0xf1,
-    0x2c, 0xeb, 0x58, 0xf4, 0x97, 0x46, 0x19, 0x03,
-    0x66, 0x6a, 0xf2, 0x5b, 0x92, 0xfd, 0xb4, 0x42,
-    0x91, 0x9b, 0xde, 0xb0, 0xca, 0x09, 0x23, 0x04,
-    0x88, 0x98, 0xb8, 0xda, 0x38, 0x52, 0xb1, 0xf9,
-    0x3c, 0xda, 0x29, 0x41, 0xe6, 0xe2, 0x7b
-};
-
-/**
-* CRC code based on example from Texas Instruments DN502, matches
-* CC1101 implementation
-*/
-#define CRC16_POLY 0x8005
-uint16_t calc_crc_step(uint8_t crcData, uint16_t crcReg)
-{
-    uint8_t i;
-    for (i = 0; i < 8; i++) {
-        if (((crcReg & 0x8000) >> 8) ^ (crcData & 0x80))
-            crcReg = (crcReg << 1) ^ CRC16_POLY;
-        else
-            crcReg = (crcReg << 1);
-        crcData <<= 1;
-    }
-    return crcReg;
-} // culCalcCRC
-
-#define CRC_INIT 0xFFFF
-uint16_t calc_crc(uint8_t *buf, size_t len)
-{
-    uint16_t checksum;
-    checksum = CRC_INIT;
-    // Init value for CRC calculation
-    for (size_t i = 0; i < len; i++)
-        checksum = calc_crc_step(buf[i], checksum);
-    return checksum;
-}
-
-void printHex(uint8_t *buf, size_t len, bool nl)
-{
-    for (size_t i = 0; i < len; i++) {
-        pc.printf("%02X ",buf[i]);
-    }
-    if (nl)
-        pc.printf("\n\r");
-}
-
-void printUntil(uint8_t *buf)
-{
-    uint8_t year = buf[1] & 0x3f;
-    uint8_t month = ((buf[0] & 0xE0) >> 4) | (buf[1] >> 7);
-    uint8_t day = buf[0] & 0x1f;
-    /* In 30-minute increments */
-    uint8_t time = buf[2] & 0x3f;
-
-    pc.printf("Until:         20");
-    if (year < 10) pc.printf("0");
-    pc.printf("%i",year);
-    pc.printf(".");
-    if (month < 10) pc.printf("0");
-    pc.printf("%i",month);
-    pc.printf(".");
-    if (day < 10) pc.printf("0");
-    pc.printf("%i",day);
-    pc.printf(" ");
-    if (time < 20) pc.printf("0");
-    pc.printf("%i",time / 2);
-    if (time % 2)
-        pc.printf(":30");
-    else
-        pc.printf(":00");
-    pc.printf("\n\r");
-}
-
-
-max_message max_rx_msg()
-{
-    uint8_t buf[RF22_MAX_MESSAGE_LEN];
-
-    uint8_t len = sizeof(buf);
-    uint8_t sbuf[RF22_MAX_MESSAGE_LEN];
-    uint8_t slen = 0;
-
-    max_message message;               // holds a message from the max device
-
-    message.len = 0;
+RF22Max rf22(p14,p11,p12,p13,p15);
 
-    if (rf22.recv(buf, &len)) {
-        pc.printf("Recv: ");
-        pc.printf("len: %i\n\r",len);
-        len = 50;  // limit message to 50 Bytes as device receives all 255 Bytes
-
-        //pc.printf("buf: >%s<\n\r",(char*)buf);
-        printHex(buf, len, true);
-
-        /* Dewhiten data */
-        for (int i = 0; i < len; i++)
-            buf[i] ^= pn9[i];
-
-        // now read the real length
-        len = buf[0]+3; // 1 length-Byte + 2 CRC
-        pc.printf("len: %i\n\r",len);
-
-        if (len < 3 || len > lengthof(pn9)) {
-            pc.printf("Packet length too short/long (%i)\n\r",len);
-            return message;
-        }
-        pc.printf("dewhiten: ");
-        printHex(buf, len, true);
-
-        /* Calculate CRC (but don't include the CRC itself) */
-        uint16_t crc = calc_crc(buf, len - 2);
-        if (buf[len - 1] != (crc & 0xff) || buf[len - 2] != (crc >> 8)) {
-            pc.printf("CRC error: CRC: %04X\n\r",crc);
-            //return;
-        }
-
-        /* Don't use the CRC as data */
-        len -= 2;
-
-        uint8_t type = buf[3];
-
-        message.len     = len;                   //message-length
-        message.cnt     = buf[1];                //message-counter
-        message.flags   = buf[2];
-        message.type    = type;
-        strcpy(message.type_str,type_str(type));
-        message.frm_adr = buf[4]<<16 | buf[5]<<8| buf[6];            // unique address of device
-        message.to_adr  = buf[7]<<16 | buf[8]<<8| buf[9]; ;             // unique address of device
-        message.groupid = buf[10];            //groupid
-        memcpy( (void *) message.payload, (void *) buf[11],len-11);               // data
-        message.crc     = buf[len-2]<<8 | buf[len-1];                // crc for the message
-
-
-        pc.printf("Message count: ");
-        printHex(buf + 1, 1, true);
-        pc.printf("Flags:         ");
-        printHex(buf + 2, 1, true);
-        pc.printf("Packet type:   ");
-        printHex(&type, 1, false);
-        pc.printf(" (");
-        pc.printf(type_str(type));
-        pc.printf(")\n\r");
-        pc.printf("Packet from:   ");
-        printHex(buf + 4, 3, true);
-        pc.printf("Packet to:     ");
-        printHex(buf + 7, 3, true);
-        pc.printf("GroupID:       ");
-        printHex(buf + 10, 1, true);
-        pc.printf("Payload:       ");
-        printHex(buf + 11, len-11, true);
-        //pc.printf("Payload:      >%s<\n\r",(char*)buf+11);
-
-        lcd.setLine(1,"");
-        if (type == 0x30 && len >= 11) { //ShutterContactState
-            bool baterry_low = (buf[11] >> 7) & 0x1;
-            bool state = (buf[11]>>1) & 0x1;
-
-            pc.printf("State:      ");
-            if (state) {
-                strcpy(message.state,"open");
-                pc.printf("open\n\r");
-                lcd.setLine(1,"open   ");
-            } else {
-                strcpy(message.state,"closed");
-                pc.printf("closed\n\r");
-                lcd.setLine(1,"closed ");
-            }
-            pc.printf("Battery:    ");
-            if (baterry_low) {
-                pc.printf("low\n\r");
-                strcpy(message.battery_state,"low");
-            } else {
-                pc.printf("good\n\r");
-                strcpy(message.battery_state,"good");
-            }
-        }
-
-        if (type == 0x50 && len >= 11) { //PushButtonState
-            bool baterry_low = (buf[11] >> 7) & 0x1;    // to validate!!!
-            bool state = (buf[12]) & 0x1;
-
-            pc.printf("State:      ");
-            if (state) {
-                strcpy(message.state,"auto");
-                pc.printf("auto\n\r");
-                lcd.setLine(1,"auto");
-            } else {
-                strcpy(message.state,"eco");
-                pc.printf("eco\n\r");
-                lcd.setLine(1,"eco");
-            }
-            pc.printf("Battery:    ");
-            if (baterry_low) {
-                pc.printf("low\n\r");
-                strcpy(message.battery_state,"low");
-            } else {
-                pc.printf("good\n\r");
-                strcpy(message.battery_state,"good");
-            }
-
-        }
-
-
-
-#if 0
-        if (type == 0x00 && len >= 11) { //PairPing
-            char serial[20]="";
-            strncpy(serial,(char*)buf+14,10); //10 Characters for Seial Number
-            serial[11] = '\0';
-            pc.printf("Serial:        %s\n\r",serial);
-
-            // try to send PairPong
-            // wait some time
-            wait_ms(10);
-            sbuf[0] = 11; // MsgLen
-            sbuf[1] = buf[1]+1 &0xFF; // MsgCount ??
-            sbuf[2] = 0x00; // Flag
-            sbuf[3] = 0x01; // Type = Cmd = PairPong
-            sbuf[4] = 0x11; // From Fake Address
-            sbuf[5] = 0x11; // From
-            sbuf[6] = 0x11; // From
-            sbuf[7] = buf[4] ; // To Address = From address of Windowcontact
-            sbuf[8] = buf[5] ;
-            sbuf[9] = buf[6] ;
-            sbuf[10] = 0x00; // GroupId
-            sbuf[11] = 0x00;  //Payload is 0x00 for pairpong?
-            slen = 12+2; //+2Byte CRC????
-            /* Calculate CRC */
-            uint16_t scrc = calc_crc(sbuf, slen - 2);
-            sbuf[12] = crc >> 8;
-            sbuf[13] = crc & 0xff;
-
-
-            if (rf22.send(sbuf,slen)) {
-                pc.printf("Send PairPong OK\n\r");
-            } else {
-                pc.printf("Send PairPong NOT OK\n\r");
-            }
-
-        }
-#endif
-        /*
-                else if (type == 0x60 && len >= 13) { // ThermostatState
-                    uint8_t mode = buf[11] & 0x3;
-                    bool dst = (buf[11] >> 2) & 0x1;
-                    bool locked = (buf[11] >> 5) & 0x1;
-                    bool baterry_low = (buf[11] >> 7) & 0x1;
-                    // 0 - 64
-                    uint8_t valve = buf[12];
-                    uint8_t set_temp = buf[13];
-
-                    pc.printf("Mode:          ");
-                    pc.printf(mode_str[mode]);
-
-                    pc.printf("Valve pos:     %i%",100 * valve / 64);
-
-                    pc.printf("Set temp:      %2.1i",set_temp / 2);
-
-                    if (len > 15 && mode != MODE_TEMPORARY) {
-                        // In tenths of degrees
-                        uint8_t actual_temp = ((buf[14] & 0x1) << 8) + buf[15];
-                        pc.printf("Actual temp:   ");
-                        pc.printf(actual_temp / 10);
-                        pc.printf(".");
-                        pc.printf(actual_temp % 10);
-                    }
-                    if (len > 16 && mode == MODE_TEMPORARY) {
-                        printUntil(buf + 14);
-                    }
-                } else if (type == 0x40 && len >= 11) { // SetTemperature
-                    uint8_t set_temp = buf[11] & 0x3f;
-                    uint8_t mode = buf[11] >> 6;
-
-                    pc.printf("Mode:          ");
-                    pc.printf(mode_str[mode]);
-
-                    pc.print("Set temp:      ");
-                    pc.printf(set_temp / 2);
-                    pc.printf(set_temp % 2 ? ".5" : ".0");
-                    if (len > 14) {
-                        printUntil(buf + 12);
-                    }
-                }
-
-                // Print the data
-                int i, j;
-                for (i = 0; i < len; i += 16) {
-                    // Hex
-                    for (j = 0; j < 16 && i+j < len; j++) {
-                        if (buf[i+j] < 16)
-                            pc.print("0"); // Sigh, pc.print does not know how to pad hex
-                        pc.print(buf[i+j], HEX);
-                        pc.print(" ");
-                    }
-                    // Padding on last block
-                    while (j++ < 16)
-                        pc.print("   ");
-
-                    pc.print("   ");
-                    // ASCII
-                    for (j = 0; j < 16 && i+j < len; j++)
-                        pc.write(isprint(buf[i+j]) ? buf[i+j] : '.');
-                    pc.println("");
-                }
-        */
-
-        pc.printf("\n\r");
-    }
-    return message;
+void Ticker_isr()
+{
+    led1 = !led1;
+    doSend = 1;
 }
 
 
 int main()
 {
 
-    char group[255];                          // the KNX-Group-address
-    char command[255];                        // a command to send to the freebus rs-interface
-    char lcdline[255];
 
-    max_message MyMessage;
+    char lcdline[500];
+
+    RF22Max::max_message MyMessage;
     int  i;
 
-
-
-    max_knx_mapping_t max_knx_map[MAX_KNX_MAPPINGS];
+    uint8_t sbuf[RF22_MAX_MESSAGE_LEN];
 
-    //Mapping of MAX!-Device-IDs to KNX-Group-addresses
-    max_knx_map[0].device_id = 0x04B5F7;      // MAX!-Pushbutton
-    strcpy(max_knx_map[0].knx_adr,"3/1/1");   // PushButton01 = Licht Büro
-
-    max_knx_map[1].device_id = 0x04B5B9;      // MAX!-Pushbutton
-    sprintf(max_knx_map[1].knx_adr, "3/1/2"); // Pushbutton 02 = Licht Carina
-
-
+    uint8_t slen = sizeof(sbuf);
 
     pc.baud(115200);
 
     pc.printf("\n\rConnected to mbed\n\r");
 
 
-    char version_str [80] = "RF22-MAX!-V2.5";
+    char version_str [80] = "RF22-Send-Test!-V1.0";
     lcd.cls();
     lcd.setLine(0,version_str);
     pc.printf("%s\n\r",version_str);
 
 
-    // initialize freebus-rs-interface
-    // 115.200 Baud,n,8,1
-    knxrs.baud(115200);
-
-    knxrs.printf("fbecho=0\r");   //switch off echo
-
-
     pc.printf("Pre-init|");
     if (!rf22.init())
-        pc.printf("RF22 init failed\n\r");
+        pc.printf("RF22Max init failed\n\r");
     pc.printf("Post-init\n\r");
 
 
-    // try to detect Window-Shutter
-
-    rf22.setModemRegisters(&config);
-    rf22.setFrequency(868.3, 0.035);
-    /* Disable TX packet control, since the RF22 doesn't do proper
-     * whitening so can't read the length header or CRC. We need RX packet
-     * control so the RF22 actually sends pkvalid interrupts when the
-     * manually set packet length is reached. */
-    rf22.spiWrite(RF22_REG_30_DATA_ACCESS_CONTROL, RF22_MSBFRST | RF22_ENPACRX);
-    /* No packet headers, 4 sync words, fixed packet length */
-    rf22.spiWrite(RF22_REG_32_HEADER_CONTROL1, RF22_BCEN_NONE | RF22_HDCH_NONE);
-    rf22.spiWrite(RF22_REG_33_HEADER_CONTROL2, RF22_HDLEN_0 | RF22_FIXPKLEN | RF22_SYNCLEN_4);
-    rf22.setSyncWords(sync_words, lengthof(sync_words));
-    /* Detect preamble after 4 nibbles */
-    rf22.spiWrite(RF22_REG_35_PREAMBLE_DETECTION_CONTROL1, (0x4 << 3));
-    /* Send 8 bytes of preamble */
-    rf22.setPreambleLength(8); // in nibbles
-    rf22.spiWrite(RF22_REG_3E_PACKET_LENGTH, 30); // maximum length of a MAX!-packet
-
-
     rf22.setModeRx();
 
 
+    SendTicker.attach(&Ticker_isr, 5.0); // Send every 5 seconds
 
     //wait forever and see what comes in
     while (1) {
 
-        // look for a message
-        MyMessage = max_rx_msg();
         // did we get a MAX!-Message?
-        if (MyMessage.len > 0) {
+        if (rf22.recv_max(&MyMessage)) {
             // we got a message
-            pc.printf("Got Message type: %s Msg-Nr:%i from Device-ID:%06X State:%s Battery %s\n\r", MyMessage.type_str,MyMessage.cnt, MyMessage.frm_adr, MyMessage.state, MyMessage.battery_state);
+            led2 = !led2;
+            sprintf(lcdline,"Got Message type: %s Msg-Nr:%i from Device-ID:%06X State:%s Battery %s", MyMessage.type_str,MyMessage.cnt, MyMessage.frm_adr, MyMessage.state, MyMessage.battery_state);
+            pc.printf("%s\n\r",lcdline);
+            lcd.setLine(0,lcdline);
 
-            // should we send an KNX-command?
-            strcpy(group ,"");
-            for (i=0; i< MAX_KNX_MAPPINGS; i++) {
-                if (max_knx_map[i].device_id == MyMessage.frm_adr) {
-                    strcpy(group ,max_knx_map[i].knx_adr);
-                }
-            }
+        }
 
-            if (strlen(group) > 0) {
-                sprintf(command, "fbs01/%s=%s\r",group,(strcmp(MyMessage.state,"auto")) ? "0" : "1");  // EIS01 on Group-address group : auto=1 eco=0
-                // Send a KNX-Telegramm
-                knxrs.printf("%s",command);
-                pc.printf("%s\n\r",command);
-                sprintf(lcdline,"Got Message type: %s Msg-Nr:%i from Device-ID:%06X State:%s Battery %s. Sending to KNX:%s",
-                              MyMessage.type_str,MyMessage.cnt, MyMessage.frm_adr, MyMessage.state, MyMessage.battery_state,command);
-                lcd.setLine(1,lcdline);
+        if (doSend) {
+            //we should send something
+            doSend = 0;
+            led4=1;
+            // try to send a simulated window-shutterContact-message
+            // wait some time
+            sbuf[0] = 11; // MsgLen
+            sbuf[1] = 0x21; // MsgCount ??
+            sbuf[2] = 0x00; // Flag
+            sbuf[3] = 0x30; // Type = Cmd = ShutterContactState
+            sbuf[4] = 0x11; // From Fake Address
+            sbuf[5] = 0x11; // From
+            sbuf[6] = 0x11; // From
+            sbuf[7] = 0x00; // To Address : broadcast
+            sbuf[8] = 0x00;
+            sbuf[9] = 0x00;
+            sbuf[10] = 0x00; // GroupId
+            sbuf[11] = 0x02;  //Payload is 0x02: State Open, Battery: good
+            slen = 12+2; //+2Byte CRC????
+            /* Calculate CRC */
+            uint16_t scrc = rf22.calc_crc(sbuf, slen - 2);
+            sbuf[12] = scrc >> 8;
+            sbuf[13] = scrc & 0xff;
+
+
+            if (rf22.send(sbuf,slen)) {
+#ifdef DEBUG
+                pc.printf("Send window-shutterContact-message OK\n\r");
+#endif
             } else {
-                // device not found in mapping
-                pc.printf("new unknown device!\n\r");
-                sprintf(lcdline,"Got Message type: %s Msg-Nr:%i from Device-ID:%06X State:%s Battery %s. Unknown New Device",
-                              MyMessage.type_str,MyMessage.cnt, MyMessage.frm_adr, MyMessage.state, MyMessage.battery_state);
-                lcd.setLine(1,lcdline);
+#ifdef DEBUG
+                pc.printf("Send window-shutterContact-message NOT OK\n\r");
+#endif
             }
+            led4 = 0;
 
         }