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

Dependencies:   RF22 TextLCD TextLCDScroll mbed RF22Max

Committer:
charly
Date:
Mon Sep 09 19:47:45 2013 +0000
Revision:
3:4254b4c3557e
Parent:
2:941c46d37d7e
Child:
4:6c72714f5886
working version but code is quick and dirty!

Who changed what in which revision?

UserRevisionLine numberNew contents of line
charly 3:4254b4c3557e 1 // Testprogramm for RFM22B with RF22-Library to read ELV MAX! window Shutter-Contacts and PushBottons
charly 3:4254b4c3557e 2 // Quick and dirty code!!!!!!
charly 3:4254b4c3557e 3 // needs refactoring
charly 3:4254b4c3557e 4
charly 0:94dd393bd9bb 5
charly 0:94dd393bd9bb 6 #include "mbed.h"
charly 2:941c46d37d7e 7 #include <RF22.h>
charly 2:941c46d37d7e 8 #include "TextLCDScroll.h"
charly 2:941c46d37d7e 9
charly 2:941c46d37d7e 10
charly 2:941c46d37d7e 11 #define lengthof(x) (sizeof(x) / sizeof(*x))
charly 0:94dd393bd9bb 12
charly 0:94dd393bd9bb 13 Serial pc(USBTX, USBRX);
charly 0:94dd393bd9bb 14
charly 3:4254b4c3557e 15 //Freebus-RS-Interface connected to serial
charly 3:4254b4c3557e 16 Serial knxrs(p9, p10); // tx, rx
charly 3:4254b4c3557e 17
charly 2:941c46d37d7e 18 //TextLCDScroll lcd(p30, p29, p28, p27, p26, p25, TextLCD::LCD16x2); // rs, e, d4-d7
charly 2:941c46d37d7e 19 TextLCDScroll lcd(p30, p29, p28, p27, p26, p25, TextLCD::LCD16x2); // rs, e, d4-d7
charly 1:b71f9a293c54 20
charly 0:94dd393bd9bb 21 // mbed LEDs
charly 2:941c46d37d7e 22 DigitalOut led1(LED1);
charly 2:941c46d37d7e 23 DigitalOut led2(LED2);
charly 2:941c46d37d7e 24 DigitalOut led3(LED3);
charly 2:941c46d37d7e 25 DigitalOut led4(LED4);
charly 0:94dd393bd9bb 26
charly 3:4254b4c3557e 27 struct max_knx_mapping_t {
charly 3:4254b4c3557e 28 uint32_t device_id;
charly 3:4254b4c3557e 29 char knx_adr[255];
charly 3:4254b4c3557e 30 };
charly 3:4254b4c3557e 31
charly 3:4254b4c3557e 32 #define MAX_KNX_MAPPINGS 10
charly 3:4254b4c3557e 33
charly 3:4254b4c3557e 34 // a message from the max!-Device
charly 3:4254b4c3557e 35 struct max_message {
charly 3:4254b4c3557e 36 uint8_t len; //message-length
charly 3:4254b4c3557e 37 uint8_t cnt; //message-counter
charly 3:4254b4c3557e 38 uint8_t flags; // ??
charly 3:4254b4c3557e 39 uint8_t type; //message-type
charly 3:4254b4c3557e 40 char type_str[50]; // type in text
charly 3:4254b4c3557e 41 uint32_t frm_adr; // unique address of device
charly 3:4254b4c3557e 42 uint32_t to_adr; // unique address of device
charly 3:4254b4c3557e 43 uint8_t groupid; //groupid
charly 3:4254b4c3557e 44 uint8_t payload[50]; // data
charly 3:4254b4c3557e 45 uint16_t crc; // crc fro the message
charly 3:4254b4c3557e 46 char state[50]; // state of the device: open, closed, auto, eco,...
charly 3:4254b4c3557e 47 char battery_state[50]; // Battery-state of the device : good, low
charly 3:4254b4c3557e 48 };
charly 3:4254b4c3557e 49
charly 3:4254b4c3557e 50
charly 0:94dd393bd9bb 51
charly 0:94dd393bd9bb 52 // Singleton instance of the radio
charly 0:94dd393bd9bb 53 //rf22(PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt );
charly 0:94dd393bd9bb 54 RF22 rf22(p14,p11,p12,p13,p15);
charly 0:94dd393bd9bb 55
charly 1:b71f9a293c54 56
charly 2:941c46d37d7e 57 const RF22::ModemConfig config = { // for MAX! protocol
charly 2:941c46d37d7e 58 .reg_1c = 0x01,
charly 2:941c46d37d7e 59 .reg_1f = 0x03,
charly 2:941c46d37d7e 60 .reg_20 = 0x90,
charly 2:941c46d37d7e 61 .reg_21 = 0x20,
charly 2:941c46d37d7e 62 .reg_22 = 0x51,
charly 2:941c46d37d7e 63 .reg_23 = 0xea,
charly 2:941c46d37d7e 64 .reg_24 = 0x00,
charly 2:941c46d37d7e 65 .reg_25 = 0x58,
charly 2:941c46d37d7e 66 /* 2c - 2e are only for OOK */
charly 2:941c46d37d7e 67 .reg_2c = 0x00,
charly 2:941c46d37d7e 68 .reg_2d = 0x00,
charly 2:941c46d37d7e 69 .reg_2e = 0x00,
charly 2:941c46d37d7e 70 .reg_58 = 0x80, /* Copied from RF22 defaults */
charly 2:941c46d37d7e 71 .reg_69 = 0x60, /* Copied from RF22 defaults */
charly 2:941c46d37d7e 72 .reg_6e = 0x08,
charly 2:941c46d37d7e 73 .reg_6f = 0x31,
charly 2:941c46d37d7e 74 .reg_70 = 0x24,
charly 2:941c46d37d7e 75 .reg_71 = RF22_DTMOD_FIFO | RF22_MODTYP_FSK,
charly 2:941c46d37d7e 76 .reg_72 = 0x1e,
charly 2:941c46d37d7e 77 };
charly 2:941c46d37d7e 78
charly 2:941c46d37d7e 79 /* Sync words to send / check for. Don't forget to update RF22_SYNCLEN
charly 2:941c46d37d7e 80 * below if changing the length of this array. */
charly 2:941c46d37d7e 81 const uint8_t sync_words[] = {
charly 2:941c46d37d7e 82 0xc6,
charly 2:941c46d37d7e 83 0x26,
charly 2:941c46d37d7e 84 0xc6,
charly 2:941c46d37d7e 85 0x26,
charly 2:941c46d37d7e 86 };
charly 2:941c46d37d7e 87
charly 2:941c46d37d7e 88 enum modes {MODE_AUTO, MODE_MANUAL, MODE_TEMPORARY, MODE_BOOST};
charly 2:941c46d37d7e 89 const char *mode_str[] = {
charly 2:941c46d37d7e 90 [MODE_AUTO] = "auto",
charly 2:941c46d37d7e 91 [MODE_MANUAL] = "manual",
charly 2:941c46d37d7e 92 [MODE_TEMPORARY] = "temporary",
charly 2:941c46d37d7e 93 [MODE_BOOST] = "boost"
charly 2:941c46d37d7e 94 };
charly 1:b71f9a293c54 95
charly 2:941c46d37d7e 96 char *type_str(uint8_t type)
charly 2:941c46d37d7e 97 {
charly 2:941c46d37d7e 98 switch(type) {
charly 2:941c46d37d7e 99 case 0x00:
charly 2:941c46d37d7e 100 return "PairPing";
charly 2:941c46d37d7e 101 case 0x01:
charly 2:941c46d37d7e 102 return "PairPong";
charly 2:941c46d37d7e 103 case 0x02:
charly 2:941c46d37d7e 104 return "Ack";
charly 2:941c46d37d7e 105 case 0x03:
charly 2:941c46d37d7e 106 return "TimeInformation";
charly 2:941c46d37d7e 107 case 0x10:
charly 2:941c46d37d7e 108 return "ConfigWeekProfile";
charly 2:941c46d37d7e 109 case 0x11:
charly 2:941c46d37d7e 110 return "ConfigTemperatures";
charly 2:941c46d37d7e 111 case 0x12:
charly 2:941c46d37d7e 112 return "ConfigValve";
charly 2:941c46d37d7e 113 case 0x20:
charly 2:941c46d37d7e 114 return "AddLinkPartner";
charly 2:941c46d37d7e 115 case 0x21:
charly 2:941c46d37d7e 116 return "RemoveLinkPartner";
charly 2:941c46d37d7e 117 case 0x22:
charly 2:941c46d37d7e 118 return "SetGroupId";
charly 2:941c46d37d7e 119 case 0x23:
charly 2:941c46d37d7e 120 return "RemoveGroupId";
charly 2:941c46d37d7e 121 case 0x30:
charly 2:941c46d37d7e 122 return "ShutterContactState";
charly 2:941c46d37d7e 123 case 0x40:
charly 2:941c46d37d7e 124 return "SetTemperature";
charly 2:941c46d37d7e 125 case 0x42:
charly 2:941c46d37d7e 126 return "WallThermostatState";
charly 2:941c46d37d7e 127 case 0x43:
charly 2:941c46d37d7e 128 return "SetComfortTemperature";
charly 2:941c46d37d7e 129 case 0x44:
charly 2:941c46d37d7e 130 return "SetEcoTemperature";
charly 2:941c46d37d7e 131 case 0x50:
charly 2:941c46d37d7e 132 return "PushButtonState";
charly 2:941c46d37d7e 133 case 0x60:
charly 2:941c46d37d7e 134 return "ThermostatState";
charly 2:941c46d37d7e 135 case 0x82:
charly 2:941c46d37d7e 136 return "SetDisplayActualTemperature";
charly 2:941c46d37d7e 137 case 0xF1:
charly 2:941c46d37d7e 138 return "WakeUp";
charly 2:941c46d37d7e 139 case 0xF0:
charly 2:941c46d37d7e 140 return "Reset";
charly 2:941c46d37d7e 141 }
charly 2:941c46d37d7e 142 return "Unknown";
charly 1:b71f9a293c54 143 }
charly 1:b71f9a293c54 144
charly 2:941c46d37d7e 145
charly 2:941c46d37d7e 146 /* First 255 bytes of PN9 sequence used for data whitening by the CC1101
charly 2:941c46d37d7e 147 * chip. The RF22 chip is documented to support the same data whitening
charly 2:941c46d37d7e 148 * algorithm, but in practice seems to use a different sequence.
charly 2:941c46d37d7e 149 *
charly 2:941c46d37d7e 150 * Data was generated using the following python snippet:
charly 2:941c46d37d7e 151 *
charly 2:941c46d37d7e 152 import itertools
charly 2:941c46d37d7e 153 def pn9(state):
charly 2:941c46d37d7e 154 while True:
charly 2:941c46d37d7e 155 yield hex(state & 0xff)
charly 2:941c46d37d7e 156 # The pn9 generator is clocked 8 times while shifting in the
charly 2:941c46d37d7e 157 # next data byte
charly 2:941c46d37d7e 158 for i in range(8):
charly 2:941c46d37d7e 159 state = (state >> 1) + (((state & 1) ^ (state >> 5) & 1) << 8)
charly 2:941c46d37d7e 160 print(list(itertools.islice(pn9(0x1ff), 255)))
charly 2:941c46d37d7e 161 */
charly 1:b71f9a293c54 162
charly 2:941c46d37d7e 163 const uint8_t pn9[] = {
charly 2:941c46d37d7e 164 0xff, 0xe1, 0x1d, 0x9a, 0xed, 0x85, 0x33, 0x24,
charly 2:941c46d37d7e 165 0xea, 0x7a, 0xd2, 0x39, 0x70, 0x97, 0x57, 0x0a,
charly 2:941c46d37d7e 166 0x54, 0x7d, 0x2d, 0xd8, 0x6d, 0x0d, 0xba, 0x8f,
charly 2:941c46d37d7e 167 0x67, 0x59, 0xc7, 0xa2, 0xbf, 0x34, 0xca, 0x18,
charly 2:941c46d37d7e 168 0x30, 0x53, 0x93, 0xdf, 0x92, 0xec, 0xa7, 0x15,
charly 2:941c46d37d7e 169 0x8a, 0xdc, 0xf4, 0x86, 0x55, 0x4e, 0x18, 0x21,
charly 2:941c46d37d7e 170 0x40, 0xc4, 0xc4, 0xd5, 0xc6, 0x91, 0x8a, 0xcd,
charly 2:941c46d37d7e 171 0xe7, 0xd1, 0x4e, 0x09, 0x32, 0x17, 0xdf, 0x83,
charly 2:941c46d37d7e 172 0xff, 0xf0, 0x0e, 0xcd, 0xf6, 0xc2, 0x19, 0x12,
charly 2:941c46d37d7e 173 0x75, 0x3d, 0xe9, 0x1c, 0xb8, 0xcb, 0x2b, 0x05,
charly 2:941c46d37d7e 174 0xaa, 0xbe, 0x16, 0xec, 0xb6, 0x06, 0xdd, 0xc7,
charly 2:941c46d37d7e 175 0xb3, 0xac, 0x63, 0xd1, 0x5f, 0x1a, 0x65, 0x0c,
charly 2:941c46d37d7e 176 0x98, 0xa9, 0xc9, 0x6f, 0x49, 0xf6, 0xd3, 0x0a,
charly 2:941c46d37d7e 177 0x45, 0x6e, 0x7a, 0xc3, 0x2a, 0x27, 0x8c, 0x10,
charly 2:941c46d37d7e 178 0x20, 0x62, 0xe2, 0x6a, 0xe3, 0x48, 0xc5, 0xe6,
charly 2:941c46d37d7e 179 0xf3, 0x68, 0xa7, 0x04, 0x99, 0x8b, 0xef, 0xc1,
charly 2:941c46d37d7e 180 0x7f, 0x78, 0x87, 0x66, 0x7b, 0xe1, 0x0c, 0x89,
charly 2:941c46d37d7e 181 0xba, 0x9e, 0x74, 0x0e, 0xdc, 0xe5, 0x95, 0x02,
charly 2:941c46d37d7e 182 0x55, 0x5f, 0x0b, 0x76, 0x5b, 0x83, 0xee, 0xe3,
charly 2:941c46d37d7e 183 0x59, 0xd6, 0xb1, 0xe8, 0x2f, 0x8d, 0x32, 0x06,
charly 2:941c46d37d7e 184 0xcc, 0xd4, 0xe4, 0xb7, 0x24, 0xfb, 0x69, 0x85,
charly 2:941c46d37d7e 185 0x22, 0x37, 0xbd, 0x61, 0x95, 0x13, 0x46, 0x08,
charly 2:941c46d37d7e 186 0x10, 0x31, 0x71, 0xb5, 0x71, 0xa4, 0x62, 0xf3,
charly 2:941c46d37d7e 187 0x79, 0xb4, 0x53, 0x82, 0xcc, 0xc5, 0xf7, 0xe0,
charly 2:941c46d37d7e 188 0x3f, 0xbc, 0x43, 0xb3, 0xbd, 0x70, 0x86, 0x44,
charly 2:941c46d37d7e 189 0x5d, 0x4f, 0x3a, 0x07, 0xee, 0xf2, 0x4a, 0x81,
charly 2:941c46d37d7e 190 0xaa, 0xaf, 0x05, 0xbb, 0xad, 0x41, 0xf7, 0xf1,
charly 2:941c46d37d7e 191 0x2c, 0xeb, 0x58, 0xf4, 0x97, 0x46, 0x19, 0x03,
charly 2:941c46d37d7e 192 0x66, 0x6a, 0xf2, 0x5b, 0x92, 0xfd, 0xb4, 0x42,
charly 2:941c46d37d7e 193 0x91, 0x9b, 0xde, 0xb0, 0xca, 0x09, 0x23, 0x04,
charly 2:941c46d37d7e 194 0x88, 0x98, 0xb8, 0xda, 0x38, 0x52, 0xb1, 0xf9,
charly 2:941c46d37d7e 195 0x3c, 0xda, 0x29, 0x41, 0xe6, 0xe2, 0x7b
charly 2:941c46d37d7e 196 };
charly 0:94dd393bd9bb 197
charly 2:941c46d37d7e 198 /**
charly 2:941c46d37d7e 199 * CRC code based on example from Texas Instruments DN502, matches
charly 2:941c46d37d7e 200 * CC1101 implementation
charly 2:941c46d37d7e 201 */
charly 2:941c46d37d7e 202 #define CRC16_POLY 0x8005
charly 2:941c46d37d7e 203 uint16_t calc_crc_step(uint8_t crcData, uint16_t crcReg)
charly 2:941c46d37d7e 204 {
charly 2:941c46d37d7e 205 uint8_t i;
charly 2:941c46d37d7e 206 for (i = 0; i < 8; i++) {
charly 2:941c46d37d7e 207 if (((crcReg & 0x8000) >> 8) ^ (crcData & 0x80))
charly 2:941c46d37d7e 208 crcReg = (crcReg << 1) ^ CRC16_POLY;
charly 2:941c46d37d7e 209 else
charly 2:941c46d37d7e 210 crcReg = (crcReg << 1);
charly 2:941c46d37d7e 211 crcData <<= 1;
charly 2:941c46d37d7e 212 }
charly 2:941c46d37d7e 213 return crcReg;
charly 2:941c46d37d7e 214 } // culCalcCRC
charly 2:941c46d37d7e 215
charly 2:941c46d37d7e 216 #define CRC_INIT 0xFFFF
charly 2:941c46d37d7e 217 uint16_t calc_crc(uint8_t *buf, size_t len)
charly 2:941c46d37d7e 218 {
charly 2:941c46d37d7e 219 uint16_t checksum;
charly 2:941c46d37d7e 220 checksum = CRC_INIT;
charly 2:941c46d37d7e 221 // Init value for CRC calculation
charly 2:941c46d37d7e 222 for (size_t i = 0; i < len; i++)
charly 2:941c46d37d7e 223 checksum = calc_crc_step(buf[i], checksum);
charly 2:941c46d37d7e 224 return checksum;
charly 0:94dd393bd9bb 225 }
charly 0:94dd393bd9bb 226
charly 2:941c46d37d7e 227 void printHex(uint8_t *buf, size_t len, bool nl)
charly 2:941c46d37d7e 228 {
charly 2:941c46d37d7e 229 for (size_t i = 0; i < len; i++) {
charly 2:941c46d37d7e 230 pc.printf("%02X ",buf[i]);
charly 2:941c46d37d7e 231 }
charly 2:941c46d37d7e 232 if (nl)
charly 2:941c46d37d7e 233 pc.printf("\n\r");
charly 2:941c46d37d7e 234 }
charly 2:941c46d37d7e 235
charly 2:941c46d37d7e 236 void printUntil(uint8_t *buf)
charly 2:941c46d37d7e 237 {
charly 2:941c46d37d7e 238 uint8_t year = buf[1] & 0x3f;
charly 2:941c46d37d7e 239 uint8_t month = ((buf[0] & 0xE0) >> 4) | (buf[1] >> 7);
charly 2:941c46d37d7e 240 uint8_t day = buf[0] & 0x1f;
charly 2:941c46d37d7e 241 /* In 30-minute increments */
charly 2:941c46d37d7e 242 uint8_t time = buf[2] & 0x3f;
charly 0:94dd393bd9bb 243
charly 2:941c46d37d7e 244 pc.printf("Until: 20");
charly 2:941c46d37d7e 245 if (year < 10) pc.printf("0");
charly 2:941c46d37d7e 246 pc.printf("%i",year);
charly 2:941c46d37d7e 247 pc.printf(".");
charly 2:941c46d37d7e 248 if (month < 10) pc.printf("0");
charly 2:941c46d37d7e 249 pc.printf("%i",month);
charly 2:941c46d37d7e 250 pc.printf(".");
charly 2:941c46d37d7e 251 if (day < 10) pc.printf("0");
charly 2:941c46d37d7e 252 pc.printf("%i",day);
charly 2:941c46d37d7e 253 pc.printf(" ");
charly 2:941c46d37d7e 254 if (time < 20) pc.printf("0");
charly 2:941c46d37d7e 255 pc.printf("%i",time / 2);
charly 2:941c46d37d7e 256 if (time % 2)
charly 2:941c46d37d7e 257 pc.printf(":30");
charly 2:941c46d37d7e 258 else
charly 2:941c46d37d7e 259 pc.printf(":00");
charly 2:941c46d37d7e 260 pc.printf("\n\r");
charly 0:94dd393bd9bb 261 }
charly 0:94dd393bd9bb 262
charly 2:941c46d37d7e 263
charly 3:4254b4c3557e 264 max_message max_rx_msg()
charly 2:941c46d37d7e 265 {
charly 2:941c46d37d7e 266 uint8_t buf[RF22_MAX_MESSAGE_LEN];
charly 3:4254b4c3557e 267
charly 2:941c46d37d7e 268 uint8_t len = sizeof(buf);
charly 3:4254b4c3557e 269 uint8_t sbuf[RF22_MAX_MESSAGE_LEN];
charly 3:4254b4c3557e 270 uint8_t slen = 0;
charly 3:4254b4c3557e 271
charly 3:4254b4c3557e 272 max_message message; // holds a message from the max device
charly 3:4254b4c3557e 273
charly 3:4254b4c3557e 274 message.len = 0;
charly 2:941c46d37d7e 275
charly 2:941c46d37d7e 276 if (rf22.recv(buf, &len)) {
charly 2:941c46d37d7e 277 pc.printf("Recv: ");
charly 2:941c46d37d7e 278 pc.printf("len: %i\n\r",len);
charly 3:4254b4c3557e 279 len = 50; // limit message to 50 Bytes as device receives all 255 Bytes
charly 2:941c46d37d7e 280
charly 2:941c46d37d7e 281 //pc.printf("buf: >%s<\n\r",(char*)buf);
charly 2:941c46d37d7e 282 printHex(buf, len, true);
charly 2:941c46d37d7e 283
charly 2:941c46d37d7e 284 /* Dewhiten data */
charly 2:941c46d37d7e 285 for (int i = 0; i < len; i++)
charly 2:941c46d37d7e 286 buf[i] ^= pn9[i];
charly 2:941c46d37d7e 287
charly 2:941c46d37d7e 288 // now read the real length
charly 2:941c46d37d7e 289 len = buf[0]+3; // 1 length-Byte + 2 CRC
charly 2:941c46d37d7e 290 pc.printf("len: %i\n\r",len);
charly 2:941c46d37d7e 291
charly 2:941c46d37d7e 292 if (len < 3 || len > lengthof(pn9)) {
charly 2:941c46d37d7e 293 pc.printf("Packet length too short/long (%i)\n\r",len);
charly 3:4254b4c3557e 294 return message;
charly 2:941c46d37d7e 295 }
charly 2:941c46d37d7e 296 pc.printf("dewhiten: ");
charly 2:941c46d37d7e 297 printHex(buf, len, true);
charly 2:941c46d37d7e 298
charly 2:941c46d37d7e 299 /* Calculate CRC (but don't include the CRC itself) */
charly 2:941c46d37d7e 300 uint16_t crc = calc_crc(buf, len - 2);
charly 2:941c46d37d7e 301 if (buf[len - 1] != (crc & 0xff) || buf[len - 2] != (crc >> 8)) {
charly 3:4254b4c3557e 302 pc.printf("CRC error: CRC: %04X\n\r",crc);
charly 3:4254b4c3557e 303 //return;
charly 2:941c46d37d7e 304 }
charly 2:941c46d37d7e 305
charly 2:941c46d37d7e 306 /* Don't use the CRC as data */
charly 2:941c46d37d7e 307 len -= 2;
charly 2:941c46d37d7e 308
charly 2:941c46d37d7e 309 uint8_t type = buf[3];
charly 3:4254b4c3557e 310
charly 3:4254b4c3557e 311 message.len = len; //message-length
charly 3:4254b4c3557e 312 message.cnt = buf[1]; //message-counter
charly 3:4254b4c3557e 313 message.flags = buf[2];
charly 3:4254b4c3557e 314 message.type = type;
charly 3:4254b4c3557e 315 strcpy(message.type_str,type_str(type));
charly 3:4254b4c3557e 316 message.frm_adr = buf[4]<<16 | buf[5]<<8| buf[6]; // unique address of device
charly 3:4254b4c3557e 317 message.to_adr = buf[7]<<16 | buf[8]<<8| buf[9]; ; // unique address of device
charly 3:4254b4c3557e 318 message.groupid = buf[10]; //groupid
charly 3:4254b4c3557e 319 memcpy( (void *) message.payload, (void *) buf[11],len-11); // data
charly 3:4254b4c3557e 320 message.crc = buf[len-2]<<8 | buf[len-1]; // crc for the message
charly 3:4254b4c3557e 321
charly 3:4254b4c3557e 322
charly 2:941c46d37d7e 323 pc.printf("Message count: ");
charly 2:941c46d37d7e 324 printHex(buf + 1, 1, true);
charly 2:941c46d37d7e 325 pc.printf("Flags: ");
charly 2:941c46d37d7e 326 printHex(buf + 2, 1, true);
charly 2:941c46d37d7e 327 pc.printf("Packet type: ");
charly 2:941c46d37d7e 328 printHex(&type, 1, false);
charly 2:941c46d37d7e 329 pc.printf(" (");
charly 2:941c46d37d7e 330 pc.printf(type_str(type));
charly 2:941c46d37d7e 331 pc.printf(")\n\r");
charly 2:941c46d37d7e 332 pc.printf("Packet from: ");
charly 2:941c46d37d7e 333 printHex(buf + 4, 3, true);
charly 2:941c46d37d7e 334 pc.printf("Packet to: ");
charly 2:941c46d37d7e 335 printHex(buf + 7, 3, true);
charly 2:941c46d37d7e 336 pc.printf("GroupID: ");
charly 2:941c46d37d7e 337 printHex(buf + 10, 1, true);
charly 2:941c46d37d7e 338 pc.printf("Payload: ");
charly 2:941c46d37d7e 339 printHex(buf + 11, len-11, true);
charly 3:4254b4c3557e 340 //pc.printf("Payload: >%s<\n\r",(char*)buf+11);
charly 0:94dd393bd9bb 341
charly 3:4254b4c3557e 342 lcd.setLine(1,"");
charly 2:941c46d37d7e 343 if (type == 0x30 && len >= 11) { //ShutterContactState
charly 2:941c46d37d7e 344 bool baterry_low = (buf[11] >> 7) & 0x1;
charly 2:941c46d37d7e 345 bool state = (buf[11]>>1) & 0x1;
charly 3:4254b4c3557e 346
charly 2:941c46d37d7e 347 pc.printf("State: ");
charly 2:941c46d37d7e 348 if (state) {
charly 3:4254b4c3557e 349 strcpy(message.state,"open");
charly 2:941c46d37d7e 350 pc.printf("open\n\r");
charly 2:941c46d37d7e 351 lcd.setLine(1,"open ");
charly 2:941c46d37d7e 352 } else {
charly 3:4254b4c3557e 353 strcpy(message.state,"closed");
charly 2:941c46d37d7e 354 pc.printf("closed\n\r");
charly 2:941c46d37d7e 355 lcd.setLine(1,"closed ");
charly 2:941c46d37d7e 356 }
charly 2:941c46d37d7e 357 pc.printf("Battery: ");
charly 2:941c46d37d7e 358 if (baterry_low) {
charly 2:941c46d37d7e 359 pc.printf("low\n\r");
charly 3:4254b4c3557e 360 strcpy(message.battery_state,"low");
charly 2:941c46d37d7e 361 } else {
charly 2:941c46d37d7e 362 pc.printf("good\n\r");
charly 3:4254b4c3557e 363 strcpy(message.battery_state,"good");
charly 3:4254b4c3557e 364 }
charly 3:4254b4c3557e 365 }
charly 3:4254b4c3557e 366
charly 3:4254b4c3557e 367 if (type == 0x50 && len >= 11) { //PushButtonState
charly 3:4254b4c3557e 368 bool baterry_low = (buf[11] >> 7) & 0x1; // to validate!!!
charly 3:4254b4c3557e 369 bool state = (buf[12]) & 0x1;
charly 3:4254b4c3557e 370
charly 3:4254b4c3557e 371 pc.printf("State: ");
charly 3:4254b4c3557e 372 if (state) {
charly 3:4254b4c3557e 373 strcpy(message.state,"auto");
charly 3:4254b4c3557e 374 pc.printf("auto\n\r");
charly 3:4254b4c3557e 375 lcd.setLine(1,"auto");
charly 3:4254b4c3557e 376 } else {
charly 3:4254b4c3557e 377 strcpy(message.state,"eco");
charly 3:4254b4c3557e 378 pc.printf("eco\n\r");
charly 3:4254b4c3557e 379 lcd.setLine(1,"eco");
charly 3:4254b4c3557e 380 }
charly 3:4254b4c3557e 381 pc.printf("Battery: ");
charly 3:4254b4c3557e 382 if (baterry_low) {
charly 3:4254b4c3557e 383 pc.printf("low\n\r");
charly 3:4254b4c3557e 384 strcpy(message.battery_state,"low");
charly 3:4254b4c3557e 385 } else {
charly 3:4254b4c3557e 386 pc.printf("good\n\r");
charly 3:4254b4c3557e 387 strcpy(message.battery_state,"good");
charly 2:941c46d37d7e 388 }
charly 2:941c46d37d7e 389
charly 2:941c46d37d7e 390 }
charly 2:941c46d37d7e 391
charly 3:4254b4c3557e 392
charly 3:4254b4c3557e 393
charly 3:4254b4c3557e 394 #if 0
charly 3:4254b4c3557e 395 if (type == 0x00 && len >= 11) { //PairPing
charly 3:4254b4c3557e 396 char serial[20]="";
charly 3:4254b4c3557e 397 strncpy(serial,(char*)buf+14,10); //10 Characters for Seial Number
charly 3:4254b4c3557e 398 serial[11] = '\0';
charly 3:4254b4c3557e 399 pc.printf("Serial: %s\n\r",serial);
charly 3:4254b4c3557e 400
charly 3:4254b4c3557e 401 // try to send PairPong
charly 3:4254b4c3557e 402 // wait some time
charly 3:4254b4c3557e 403 wait_ms(10);
charly 3:4254b4c3557e 404 sbuf[0] = 11; // MsgLen
charly 3:4254b4c3557e 405 sbuf[1] = buf[1]+1 &0xFF; // MsgCount ??
charly 3:4254b4c3557e 406 sbuf[2] = 0x00; // Flag
charly 3:4254b4c3557e 407 sbuf[3] = 0x01; // Type = Cmd = PairPong
charly 3:4254b4c3557e 408 sbuf[4] = 0x11; // From Fake Address
charly 3:4254b4c3557e 409 sbuf[5] = 0x11; // From
charly 3:4254b4c3557e 410 sbuf[6] = 0x11; // From
charly 3:4254b4c3557e 411 sbuf[7] = buf[4] ; // To Address = From address of Windowcontact
charly 3:4254b4c3557e 412 sbuf[8] = buf[5] ;
charly 3:4254b4c3557e 413 sbuf[9] = buf[6] ;
charly 3:4254b4c3557e 414 sbuf[10] = 0x00; // GroupId
charly 3:4254b4c3557e 415 sbuf[11] = 0x00; //Payload is 0x00 for pairpong?
charly 3:4254b4c3557e 416 slen = 12+2; //+2Byte CRC????
charly 3:4254b4c3557e 417 /* Calculate CRC */
charly 3:4254b4c3557e 418 uint16_t scrc = calc_crc(sbuf, slen - 2);
charly 3:4254b4c3557e 419 sbuf[12] = crc >> 8;
charly 3:4254b4c3557e 420 sbuf[13] = crc & 0xff;
charly 3:4254b4c3557e 421
charly 3:4254b4c3557e 422
charly 3:4254b4c3557e 423 if (rf22.send(sbuf,slen)) {
charly 3:4254b4c3557e 424 pc.printf("Send PairPong OK\n\r");
charly 3:4254b4c3557e 425 } else {
charly 3:4254b4c3557e 426 pc.printf("Send PairPong NOT OK\n\r");
charly 3:4254b4c3557e 427 }
charly 3:4254b4c3557e 428
charly 3:4254b4c3557e 429 }
charly 3:4254b4c3557e 430 #endif
charly 2:941c46d37d7e 431 /*
charly 2:941c46d37d7e 432 else if (type == 0x60 && len >= 13) { // ThermostatState
charly 2:941c46d37d7e 433 uint8_t mode = buf[11] & 0x3;
charly 2:941c46d37d7e 434 bool dst = (buf[11] >> 2) & 0x1;
charly 2:941c46d37d7e 435 bool locked = (buf[11] >> 5) & 0x1;
charly 2:941c46d37d7e 436 bool baterry_low = (buf[11] >> 7) & 0x1;
charly 2:941c46d37d7e 437 // 0 - 64
charly 2:941c46d37d7e 438 uint8_t valve = buf[12];
charly 2:941c46d37d7e 439 uint8_t set_temp = buf[13];
charly 2:941c46d37d7e 440
charly 2:941c46d37d7e 441 pc.printf("Mode: ");
charly 2:941c46d37d7e 442 pc.printf(mode_str[mode]);
charly 2:941c46d37d7e 443
charly 2:941c46d37d7e 444 pc.printf("Valve pos: %i%",100 * valve / 64);
charly 2:941c46d37d7e 445
charly 2:941c46d37d7e 446 pc.printf("Set temp: %2.1i",set_temp / 2);
charly 0:94dd393bd9bb 447
charly 2:941c46d37d7e 448 if (len > 15 && mode != MODE_TEMPORARY) {
charly 2:941c46d37d7e 449 // In tenths of degrees
charly 2:941c46d37d7e 450 uint8_t actual_temp = ((buf[14] & 0x1) << 8) + buf[15];
charly 2:941c46d37d7e 451 pc.printf("Actual temp: ");
charly 2:941c46d37d7e 452 pc.printf(actual_temp / 10);
charly 2:941c46d37d7e 453 pc.printf(".");
charly 2:941c46d37d7e 454 pc.printf(actual_temp % 10);
charly 2:941c46d37d7e 455 }
charly 2:941c46d37d7e 456 if (len > 16 && mode == MODE_TEMPORARY) {
charly 2:941c46d37d7e 457 printUntil(buf + 14);
charly 2:941c46d37d7e 458 }
charly 2:941c46d37d7e 459 } else if (type == 0x40 && len >= 11) { // SetTemperature
charly 2:941c46d37d7e 460 uint8_t set_temp = buf[11] & 0x3f;
charly 2:941c46d37d7e 461 uint8_t mode = buf[11] >> 6;
charly 2:941c46d37d7e 462
charly 2:941c46d37d7e 463 pc.printf("Mode: ");
charly 2:941c46d37d7e 464 pc.printf(mode_str[mode]);
charly 2:941c46d37d7e 465
charly 2:941c46d37d7e 466 pc.print("Set temp: ");
charly 2:941c46d37d7e 467 pc.printf(set_temp / 2);
charly 2:941c46d37d7e 468 pc.printf(set_temp % 2 ? ".5" : ".0");
charly 2:941c46d37d7e 469 if (len > 14) {
charly 2:941c46d37d7e 470 printUntil(buf + 12);
charly 2:941c46d37d7e 471 }
charly 2:941c46d37d7e 472 }
charly 2:941c46d37d7e 473
charly 2:941c46d37d7e 474 // Print the data
charly 2:941c46d37d7e 475 int i, j;
charly 2:941c46d37d7e 476 for (i = 0; i < len; i += 16) {
charly 2:941c46d37d7e 477 // Hex
charly 2:941c46d37d7e 478 for (j = 0; j < 16 && i+j < len; j++) {
charly 2:941c46d37d7e 479 if (buf[i+j] < 16)
charly 2:941c46d37d7e 480 pc.print("0"); // Sigh, pc.print does not know how to pad hex
charly 2:941c46d37d7e 481 pc.print(buf[i+j], HEX);
charly 2:941c46d37d7e 482 pc.print(" ");
charly 2:941c46d37d7e 483 }
charly 2:941c46d37d7e 484 // Padding on last block
charly 2:941c46d37d7e 485 while (j++ < 16)
charly 2:941c46d37d7e 486 pc.print(" ");
charly 2:941c46d37d7e 487
charly 2:941c46d37d7e 488 pc.print(" ");
charly 2:941c46d37d7e 489 // ASCII
charly 2:941c46d37d7e 490 for (j = 0; j < 16 && i+j < len; j++)
charly 2:941c46d37d7e 491 pc.write(isprint(buf[i+j]) ? buf[i+j] : '.');
charly 2:941c46d37d7e 492 pc.println("");
charly 2:941c46d37d7e 493 }
charly 2:941c46d37d7e 494 */
charly 3:4254b4c3557e 495
charly 2:941c46d37d7e 496 pc.printf("\n\r");
charly 0:94dd393bd9bb 497 }
charly 3:4254b4c3557e 498 return message;
charly 0:94dd393bd9bb 499 }
charly 0:94dd393bd9bb 500
charly 3:4254b4c3557e 501
charly 2:941c46d37d7e 502 int main()
charly 2:941c46d37d7e 503 {
charly 1:b71f9a293c54 504
charly 3:4254b4c3557e 505 char group[255]; // the KNX-Group-address
charly 3:4254b4c3557e 506 char command[255]; // a command to send to the freebus rs-interface
charly 3:4254b4c3557e 507 char lcdline[255];
charly 3:4254b4c3557e 508
charly 3:4254b4c3557e 509 max_message MyMessage;
charly 3:4254b4c3557e 510 int i;
charly 3:4254b4c3557e 511
charly 3:4254b4c3557e 512
charly 3:4254b4c3557e 513
charly 3:4254b4c3557e 514 max_knx_mapping_t max_knx_map[MAX_KNX_MAPPINGS];
charly 3:4254b4c3557e 515
charly 3:4254b4c3557e 516 //Mapping of MAX!-Device-IDs to KNX-Group-addresses
charly 3:4254b4c3557e 517 max_knx_map[0].device_id = 0x04B5F7; // MAX!-Pushbutton
charly 3:4254b4c3557e 518 strcpy(max_knx_map[0].knx_adr,"3/1/1"); // PushButton01 = Licht Büro
charly 3:4254b4c3557e 519
charly 3:4254b4c3557e 520 max_knx_map[1].device_id = 0x04B5B9; // MAX!-Pushbutton
charly 3:4254b4c3557e 521 sprintf(max_knx_map[1].knx_adr, "3/1/2"); // Pushbutton 02 = Licht Carina
charly 3:4254b4c3557e 522
charly 3:4254b4c3557e 523
charly 3:4254b4c3557e 524
charly 0:94dd393bd9bb 525 pc.baud(115200);
charly 0:94dd393bd9bb 526
charly 0:94dd393bd9bb 527 pc.printf("\n\rConnected to mbed\n\r");
charly 0:94dd393bd9bb 528
charly 0:94dd393bd9bb 529
charly 3:4254b4c3557e 530 char version_str [80] = "RF22-MAX!-V2.5";
charly 2:941c46d37d7e 531 lcd.cls();
charly 2:941c46d37d7e 532 lcd.setLine(0,version_str);
charly 2:941c46d37d7e 533 pc.printf("%s\n\r",version_str);
charly 1:b71f9a293c54 534
charly 3:4254b4c3557e 535
charly 3:4254b4c3557e 536 // initialize freebus-rs-interface
charly 3:4254b4c3557e 537 // 115.200 Baud,n,8,1
charly 3:4254b4c3557e 538 knxrs.baud(115200);
charly 3:4254b4c3557e 539
charly 3:4254b4c3557e 540 knxrs.printf("fbecho=0\r"); //switch off echo
charly 3:4254b4c3557e 541
charly 3:4254b4c3557e 542
charly 2:941c46d37d7e 543 pc.printf("Pre-init|");
charly 2:941c46d37d7e 544 if (!rf22.init())
charly 2:941c46d37d7e 545 pc.printf("RF22 init failed\n\r");
charly 2:941c46d37d7e 546 pc.printf("Post-init\n\r");
charly 1:b71f9a293c54 547
charly 1:b71f9a293c54 548
charly 2:941c46d37d7e 549 // try to detect Window-Shutter
charly 1:b71f9a293c54 550
charly 2:941c46d37d7e 551 rf22.setModemRegisters(&config);
charly 2:941c46d37d7e 552 rf22.setFrequency(868.3, 0.035);
charly 2:941c46d37d7e 553 /* Disable TX packet control, since the RF22 doesn't do proper
charly 2:941c46d37d7e 554 * whitening so can't read the length header or CRC. We need RX packet
charly 2:941c46d37d7e 555 * control so the RF22 actually sends pkvalid interrupts when the
charly 2:941c46d37d7e 556 * manually set packet length is reached. */
charly 2:941c46d37d7e 557 rf22.spiWrite(RF22_REG_30_DATA_ACCESS_CONTROL, RF22_MSBFRST | RF22_ENPACRX);
charly 2:941c46d37d7e 558 /* No packet headers, 4 sync words, fixed packet length */
charly 2:941c46d37d7e 559 rf22.spiWrite(RF22_REG_32_HEADER_CONTROL1, RF22_BCEN_NONE | RF22_HDCH_NONE);
charly 2:941c46d37d7e 560 rf22.spiWrite(RF22_REG_33_HEADER_CONTROL2, RF22_HDLEN_0 | RF22_FIXPKLEN | RF22_SYNCLEN_4);
charly 2:941c46d37d7e 561 rf22.setSyncWords(sync_words, lengthof(sync_words));
charly 2:941c46d37d7e 562 /* Detect preamble after 4 nibbles */
charly 2:941c46d37d7e 563 rf22.spiWrite(RF22_REG_35_PREAMBLE_DETECTION_CONTROL1, (0x4 << 3));
charly 2:941c46d37d7e 564 /* Send 8 bytes of preamble */
charly 2:941c46d37d7e 565 rf22.setPreambleLength(8); // in nibbles
charly 3:4254b4c3557e 566 rf22.spiWrite(RF22_REG_3E_PACKET_LENGTH, 30); // maximum length of a MAX!-packet
charly 1:b71f9a293c54 567
charly 1:b71f9a293c54 568
charly 2:941c46d37d7e 569 rf22.setModeRx();
charly 1:b71f9a293c54 570
charly 1:b71f9a293c54 571
charly 1:b71f9a293c54 572
charly 3:4254b4c3557e 573 //wait forever and see what comes in
charly 2:941c46d37d7e 574 while (1) {
charly 1:b71f9a293c54 575
charly 3:4254b4c3557e 576 // look for a message
charly 3:4254b4c3557e 577 MyMessage = max_rx_msg();
charly 3:4254b4c3557e 578 // did we get a MAX!-Message?
charly 3:4254b4c3557e 579 if (MyMessage.len > 0) {
charly 3:4254b4c3557e 580 // we got a message
charly 3:4254b4c3557e 581 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);
charly 3:4254b4c3557e 582
charly 3:4254b4c3557e 583 // should we send an KNX-command?
charly 3:4254b4c3557e 584 strcpy(group ,"");
charly 3:4254b4c3557e 585 for (i=0; i< MAX_KNX_MAPPINGS; i++) {
charly 3:4254b4c3557e 586 if (max_knx_map[i].device_id == MyMessage.frm_adr) {
charly 3:4254b4c3557e 587 strcpy(group ,max_knx_map[i].knx_adr);
charly 3:4254b4c3557e 588 }
charly 3:4254b4c3557e 589 }
charly 3:4254b4c3557e 590
charly 3:4254b4c3557e 591 if (strlen(group) > 0) {
charly 3:4254b4c3557e 592 sprintf(command, "fbs01/%s=%s\r",group,(strcmp(MyMessage.state,"auto")) ? "0" : "1"); // EIS01 on Group-address group : auto=1 eco=0
charly 3:4254b4c3557e 593 // Send a KNX-Telegramm
charly 3:4254b4c3557e 594 knxrs.printf("%s",command);
charly 3:4254b4c3557e 595 pc.printf("%s\n\r",command);
charly 3:4254b4c3557e 596 sprintf(lcdline,"Got Message type: %s Msg-Nr:%i from Device-ID:%06X State:%s Battery %s. Sending to KNX:%s",
charly 3:4254b4c3557e 597 MyMessage.type_str,MyMessage.cnt, MyMessage.frm_adr, MyMessage.state, MyMessage.battery_state,command);
charly 3:4254b4c3557e 598 lcd.setLine(1,lcdline);
charly 3:4254b4c3557e 599 } else {
charly 3:4254b4c3557e 600 // device not found in mapping
charly 3:4254b4c3557e 601 pc.printf("new unknown device!\n\r");
charly 3:4254b4c3557e 602 sprintf(lcdline,"Got Message type: %s Msg-Nr:%i from Device-ID:%06X State:%s Battery %s. Unknown New Device",
charly 3:4254b4c3557e 603 MyMessage.type_str,MyMessage.cnt, MyMessage.frm_adr, MyMessage.state, MyMessage.battery_state);
charly 3:4254b4c3557e 604 lcd.setLine(1,lcdline);
charly 3:4254b4c3557e 605 }
charly 3:4254b4c3557e 606
charly 3:4254b4c3557e 607 }
charly 3:4254b4c3557e 608
charly 3:4254b4c3557e 609 }
charly 0:94dd393bd9bb 610 }
charly 0:94dd393bd9bb 611
charly 0:94dd393bd9bb 612