Test program to send MAX!-Messages with a RFM22-Module
Dependencies: RF22 TextLCD TextLCDScroll mbed RF22Max
main.cpp@2:941c46d37d7e, 2013-08-20 (annotated)
- Committer:
- charly
- Date:
- Tue Aug 20 20:22:43 2013 +0000
- Revision:
- 2:941c46d37d7e
- Parent:
- 1:b71f9a293c54
- Child:
- 3:4254b4c3557e
Initial version! Reads and decodes a window sensor. No Send, No ACK, No other devices
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
charly | 2:941c46d37d7e | 1 | // Testprogramm for RFM22B with RF22-Library to read ELV MAX! window Shutter-Contacts |
charly |
0:94dd393bd9bb | 2 | |
charly |
0:94dd393bd9bb | 3 | #include "mbed.h" |
charly | 2:941c46d37d7e | 4 | #include <RF22.h> |
charly |
0:94dd393bd9bb | 5 | |
charly | 2:941c46d37d7e | 6 | #include "TextLCDScroll.h" |
charly | 2:941c46d37d7e | 7 | |
charly | 2:941c46d37d7e | 8 | |
charly | 2:941c46d37d7e | 9 | #define lengthof(x) (sizeof(x) / sizeof(*x)) |
charly |
0:94dd393bd9bb | 10 | |
charly |
0:94dd393bd9bb | 11 | Serial pc(USBTX, USBRX); |
charly |
0:94dd393bd9bb | 12 | |
charly | 2:941c46d37d7e | 13 | //TextLCDScroll lcd(p30, p29, p28, p27, p26, p25, TextLCD::LCD16x2); // rs, e, d4-d7 |
charly | 2:941c46d37d7e | 14 | TextLCDScroll lcd(p30, p29, p28, p27, p26, p25, TextLCD::LCD16x2); // rs, e, d4-d7 |
charly |
1:b71f9a293c54 | 15 | |
charly |
0:94dd393bd9bb | 16 | // mbed LEDs |
charly | 2:941c46d37d7e | 17 | DigitalOut led1(LED1); |
charly | 2:941c46d37d7e | 18 | DigitalOut led2(LED2); |
charly | 2:941c46d37d7e | 19 | DigitalOut led3(LED3); |
charly | 2:941c46d37d7e | 20 | DigitalOut led4(LED4); |
charly |
0:94dd393bd9bb | 21 | |
charly |
0:94dd393bd9bb | 22 | |
charly |
0:94dd393bd9bb | 23 | // Singleton instance of the radio |
charly |
0:94dd393bd9bb | 24 | //rf22(PinName slaveSelectPin , PinName mosi, PinName miso, PinName sclk, PinName interrupt ); |
charly |
0:94dd393bd9bb | 25 | RF22 rf22(p14,p11,p12,p13,p15); |
charly |
0:94dd393bd9bb | 26 | |
charly |
1:b71f9a293c54 | 27 | |
charly | 2:941c46d37d7e | 28 | const RF22::ModemConfig config = { // for MAX! protocol |
charly | 2:941c46d37d7e | 29 | .reg_1c = 0x01, |
charly | 2:941c46d37d7e | 30 | .reg_1f = 0x03, |
charly | 2:941c46d37d7e | 31 | .reg_20 = 0x90, |
charly | 2:941c46d37d7e | 32 | .reg_21 = 0x20, |
charly | 2:941c46d37d7e | 33 | .reg_22 = 0x51, |
charly | 2:941c46d37d7e | 34 | .reg_23 = 0xea, |
charly | 2:941c46d37d7e | 35 | .reg_24 = 0x00, |
charly | 2:941c46d37d7e | 36 | .reg_25 = 0x58, |
charly | 2:941c46d37d7e | 37 | /* 2c - 2e are only for OOK */ |
charly | 2:941c46d37d7e | 38 | .reg_2c = 0x00, |
charly | 2:941c46d37d7e | 39 | .reg_2d = 0x00, |
charly | 2:941c46d37d7e | 40 | .reg_2e = 0x00, |
charly | 2:941c46d37d7e | 41 | .reg_58 = 0x80, /* Copied from RF22 defaults */ |
charly | 2:941c46d37d7e | 42 | .reg_69 = 0x60, /* Copied from RF22 defaults */ |
charly | 2:941c46d37d7e | 43 | .reg_6e = 0x08, |
charly | 2:941c46d37d7e | 44 | .reg_6f = 0x31, |
charly | 2:941c46d37d7e | 45 | .reg_70 = 0x24, |
charly | 2:941c46d37d7e | 46 | .reg_71 = RF22_DTMOD_FIFO | RF22_MODTYP_FSK, |
charly | 2:941c46d37d7e | 47 | .reg_72 = 0x1e, |
charly | 2:941c46d37d7e | 48 | }; |
charly | 2:941c46d37d7e | 49 | |
charly | 2:941c46d37d7e | 50 | /* Sync words to send / check for. Don't forget to update RF22_SYNCLEN |
charly | 2:941c46d37d7e | 51 | * below if changing the length of this array. */ |
charly | 2:941c46d37d7e | 52 | const uint8_t sync_words[] = { |
charly | 2:941c46d37d7e | 53 | 0xc6, |
charly | 2:941c46d37d7e | 54 | 0x26, |
charly | 2:941c46d37d7e | 55 | 0xc6, |
charly | 2:941c46d37d7e | 56 | 0x26, |
charly | 2:941c46d37d7e | 57 | }; |
charly | 2:941c46d37d7e | 58 | |
charly | 2:941c46d37d7e | 59 | enum modes {MODE_AUTO, MODE_MANUAL, MODE_TEMPORARY, MODE_BOOST}; |
charly | 2:941c46d37d7e | 60 | const char *mode_str[] = { |
charly | 2:941c46d37d7e | 61 | [MODE_AUTO] = "auto", |
charly | 2:941c46d37d7e | 62 | [MODE_MANUAL] = "manual", |
charly | 2:941c46d37d7e | 63 | [MODE_TEMPORARY] = "temporary", |
charly | 2:941c46d37d7e | 64 | [MODE_BOOST] = "boost" |
charly | 2:941c46d37d7e | 65 | }; |
charly |
1:b71f9a293c54 | 66 | |
charly | 2:941c46d37d7e | 67 | char *type_str(uint8_t type) |
charly | 2:941c46d37d7e | 68 | { |
charly | 2:941c46d37d7e | 69 | switch(type) { |
charly | 2:941c46d37d7e | 70 | case 0x00: |
charly | 2:941c46d37d7e | 71 | return "PairPing"; |
charly | 2:941c46d37d7e | 72 | case 0x01: |
charly | 2:941c46d37d7e | 73 | return "PairPong"; |
charly | 2:941c46d37d7e | 74 | case 0x02: |
charly | 2:941c46d37d7e | 75 | return "Ack"; |
charly | 2:941c46d37d7e | 76 | case 0x03: |
charly | 2:941c46d37d7e | 77 | return "TimeInformation"; |
charly | 2:941c46d37d7e | 78 | case 0x10: |
charly | 2:941c46d37d7e | 79 | return "ConfigWeekProfile"; |
charly | 2:941c46d37d7e | 80 | case 0x11: |
charly | 2:941c46d37d7e | 81 | return "ConfigTemperatures"; |
charly | 2:941c46d37d7e | 82 | case 0x12: |
charly | 2:941c46d37d7e | 83 | return "ConfigValve"; |
charly | 2:941c46d37d7e | 84 | case 0x20: |
charly | 2:941c46d37d7e | 85 | return "AddLinkPartner"; |
charly | 2:941c46d37d7e | 86 | case 0x21: |
charly | 2:941c46d37d7e | 87 | return "RemoveLinkPartner"; |
charly | 2:941c46d37d7e | 88 | case 0x22: |
charly | 2:941c46d37d7e | 89 | return "SetGroupId"; |
charly | 2:941c46d37d7e | 90 | case 0x23: |
charly | 2:941c46d37d7e | 91 | return "RemoveGroupId"; |
charly | 2:941c46d37d7e | 92 | case 0x30: |
charly | 2:941c46d37d7e | 93 | return "ShutterContactState"; |
charly | 2:941c46d37d7e | 94 | case 0x40: |
charly | 2:941c46d37d7e | 95 | return "SetTemperature"; |
charly | 2:941c46d37d7e | 96 | case 0x42: |
charly | 2:941c46d37d7e | 97 | return "WallThermostatState"; |
charly | 2:941c46d37d7e | 98 | case 0x43: |
charly | 2:941c46d37d7e | 99 | return "SetComfortTemperature"; |
charly | 2:941c46d37d7e | 100 | case 0x44: |
charly | 2:941c46d37d7e | 101 | return "SetEcoTemperature"; |
charly | 2:941c46d37d7e | 102 | case 0x50: |
charly | 2:941c46d37d7e | 103 | return "PushButtonState"; |
charly | 2:941c46d37d7e | 104 | case 0x60: |
charly | 2:941c46d37d7e | 105 | return "ThermostatState"; |
charly | 2:941c46d37d7e | 106 | case 0x82: |
charly | 2:941c46d37d7e | 107 | return "SetDisplayActualTemperature"; |
charly | 2:941c46d37d7e | 108 | case 0xF1: |
charly | 2:941c46d37d7e | 109 | return "WakeUp"; |
charly | 2:941c46d37d7e | 110 | case 0xF0: |
charly | 2:941c46d37d7e | 111 | return "Reset"; |
charly | 2:941c46d37d7e | 112 | } |
charly | 2:941c46d37d7e | 113 | return "Unknown"; |
charly |
1:b71f9a293c54 | 114 | } |
charly |
1:b71f9a293c54 | 115 | |
charly | 2:941c46d37d7e | 116 | |
charly | 2:941c46d37d7e | 117 | /* First 255 bytes of PN9 sequence used for data whitening by the CC1101 |
charly | 2:941c46d37d7e | 118 | * chip. The RF22 chip is documented to support the same data whitening |
charly | 2:941c46d37d7e | 119 | * algorithm, but in practice seems to use a different sequence. |
charly | 2:941c46d37d7e | 120 | * |
charly | 2:941c46d37d7e | 121 | * Data was generated using the following python snippet: |
charly | 2:941c46d37d7e | 122 | * |
charly | 2:941c46d37d7e | 123 | import itertools |
charly | 2:941c46d37d7e | 124 | def pn9(state): |
charly | 2:941c46d37d7e | 125 | while True: |
charly | 2:941c46d37d7e | 126 | yield hex(state & 0xff) |
charly | 2:941c46d37d7e | 127 | # The pn9 generator is clocked 8 times while shifting in the |
charly | 2:941c46d37d7e | 128 | # next data byte |
charly | 2:941c46d37d7e | 129 | for i in range(8): |
charly | 2:941c46d37d7e | 130 | state = (state >> 1) + (((state & 1) ^ (state >> 5) & 1) << 8) |
charly | 2:941c46d37d7e | 131 | print(list(itertools.islice(pn9(0x1ff), 255))) |
charly | 2:941c46d37d7e | 132 | */ |
charly |
1:b71f9a293c54 | 133 | |
charly | 2:941c46d37d7e | 134 | const uint8_t pn9[] = { |
charly | 2:941c46d37d7e | 135 | 0xff, 0xe1, 0x1d, 0x9a, 0xed, 0x85, 0x33, 0x24, |
charly | 2:941c46d37d7e | 136 | 0xea, 0x7a, 0xd2, 0x39, 0x70, 0x97, 0x57, 0x0a, |
charly | 2:941c46d37d7e | 137 | 0x54, 0x7d, 0x2d, 0xd8, 0x6d, 0x0d, 0xba, 0x8f, |
charly | 2:941c46d37d7e | 138 | 0x67, 0x59, 0xc7, 0xa2, 0xbf, 0x34, 0xca, 0x18, |
charly | 2:941c46d37d7e | 139 | 0x30, 0x53, 0x93, 0xdf, 0x92, 0xec, 0xa7, 0x15, |
charly | 2:941c46d37d7e | 140 | 0x8a, 0xdc, 0xf4, 0x86, 0x55, 0x4e, 0x18, 0x21, |
charly | 2:941c46d37d7e | 141 | 0x40, 0xc4, 0xc4, 0xd5, 0xc6, 0x91, 0x8a, 0xcd, |
charly | 2:941c46d37d7e | 142 | 0xe7, 0xd1, 0x4e, 0x09, 0x32, 0x17, 0xdf, 0x83, |
charly | 2:941c46d37d7e | 143 | 0xff, 0xf0, 0x0e, 0xcd, 0xf6, 0xc2, 0x19, 0x12, |
charly | 2:941c46d37d7e | 144 | 0x75, 0x3d, 0xe9, 0x1c, 0xb8, 0xcb, 0x2b, 0x05, |
charly | 2:941c46d37d7e | 145 | 0xaa, 0xbe, 0x16, 0xec, 0xb6, 0x06, 0xdd, 0xc7, |
charly | 2:941c46d37d7e | 146 | 0xb3, 0xac, 0x63, 0xd1, 0x5f, 0x1a, 0x65, 0x0c, |
charly | 2:941c46d37d7e | 147 | 0x98, 0xa9, 0xc9, 0x6f, 0x49, 0xf6, 0xd3, 0x0a, |
charly | 2:941c46d37d7e | 148 | 0x45, 0x6e, 0x7a, 0xc3, 0x2a, 0x27, 0x8c, 0x10, |
charly | 2:941c46d37d7e | 149 | 0x20, 0x62, 0xe2, 0x6a, 0xe3, 0x48, 0xc5, 0xe6, |
charly | 2:941c46d37d7e | 150 | 0xf3, 0x68, 0xa7, 0x04, 0x99, 0x8b, 0xef, 0xc1, |
charly | 2:941c46d37d7e | 151 | 0x7f, 0x78, 0x87, 0x66, 0x7b, 0xe1, 0x0c, 0x89, |
charly | 2:941c46d37d7e | 152 | 0xba, 0x9e, 0x74, 0x0e, 0xdc, 0xe5, 0x95, 0x02, |
charly | 2:941c46d37d7e | 153 | 0x55, 0x5f, 0x0b, 0x76, 0x5b, 0x83, 0xee, 0xe3, |
charly | 2:941c46d37d7e | 154 | 0x59, 0xd6, 0xb1, 0xe8, 0x2f, 0x8d, 0x32, 0x06, |
charly | 2:941c46d37d7e | 155 | 0xcc, 0xd4, 0xe4, 0xb7, 0x24, 0xfb, 0x69, 0x85, |
charly | 2:941c46d37d7e | 156 | 0x22, 0x37, 0xbd, 0x61, 0x95, 0x13, 0x46, 0x08, |
charly | 2:941c46d37d7e | 157 | 0x10, 0x31, 0x71, 0xb5, 0x71, 0xa4, 0x62, 0xf3, |
charly | 2:941c46d37d7e | 158 | 0x79, 0xb4, 0x53, 0x82, 0xcc, 0xc5, 0xf7, 0xe0, |
charly | 2:941c46d37d7e | 159 | 0x3f, 0xbc, 0x43, 0xb3, 0xbd, 0x70, 0x86, 0x44, |
charly | 2:941c46d37d7e | 160 | 0x5d, 0x4f, 0x3a, 0x07, 0xee, 0xf2, 0x4a, 0x81, |
charly | 2:941c46d37d7e | 161 | 0xaa, 0xaf, 0x05, 0xbb, 0xad, 0x41, 0xf7, 0xf1, |
charly | 2:941c46d37d7e | 162 | 0x2c, 0xeb, 0x58, 0xf4, 0x97, 0x46, 0x19, 0x03, |
charly | 2:941c46d37d7e | 163 | 0x66, 0x6a, 0xf2, 0x5b, 0x92, 0xfd, 0xb4, 0x42, |
charly | 2:941c46d37d7e | 164 | 0x91, 0x9b, 0xde, 0xb0, 0xca, 0x09, 0x23, 0x04, |
charly | 2:941c46d37d7e | 165 | 0x88, 0x98, 0xb8, 0xda, 0x38, 0x52, 0xb1, 0xf9, |
charly | 2:941c46d37d7e | 166 | 0x3c, 0xda, 0x29, 0x41, 0xe6, 0xe2, 0x7b |
charly | 2:941c46d37d7e | 167 | }; |
charly |
0:94dd393bd9bb | 168 | |
charly | 2:941c46d37d7e | 169 | /** |
charly | 2:941c46d37d7e | 170 | * CRC code based on example from Texas Instruments DN502, matches |
charly | 2:941c46d37d7e | 171 | * CC1101 implementation |
charly | 2:941c46d37d7e | 172 | */ |
charly | 2:941c46d37d7e | 173 | #define CRC16_POLY 0x8005 |
charly | 2:941c46d37d7e | 174 | uint16_t calc_crc_step(uint8_t crcData, uint16_t crcReg) |
charly | 2:941c46d37d7e | 175 | { |
charly | 2:941c46d37d7e | 176 | uint8_t i; |
charly | 2:941c46d37d7e | 177 | for (i = 0; i < 8; i++) { |
charly | 2:941c46d37d7e | 178 | if (((crcReg & 0x8000) >> 8) ^ (crcData & 0x80)) |
charly | 2:941c46d37d7e | 179 | crcReg = (crcReg << 1) ^ CRC16_POLY; |
charly | 2:941c46d37d7e | 180 | else |
charly | 2:941c46d37d7e | 181 | crcReg = (crcReg << 1); |
charly | 2:941c46d37d7e | 182 | crcData <<= 1; |
charly | 2:941c46d37d7e | 183 | } |
charly | 2:941c46d37d7e | 184 | return crcReg; |
charly | 2:941c46d37d7e | 185 | } // culCalcCRC |
charly | 2:941c46d37d7e | 186 | |
charly | 2:941c46d37d7e | 187 | #define CRC_INIT 0xFFFF |
charly | 2:941c46d37d7e | 188 | uint16_t calc_crc(uint8_t *buf, size_t len) |
charly | 2:941c46d37d7e | 189 | { |
charly | 2:941c46d37d7e | 190 | uint16_t checksum; |
charly | 2:941c46d37d7e | 191 | checksum = CRC_INIT; |
charly | 2:941c46d37d7e | 192 | // Init value for CRC calculation |
charly | 2:941c46d37d7e | 193 | for (size_t i = 0; i < len; i++) |
charly | 2:941c46d37d7e | 194 | checksum = calc_crc_step(buf[i], checksum); |
charly | 2:941c46d37d7e | 195 | return checksum; |
charly |
0:94dd393bd9bb | 196 | } |
charly |
0:94dd393bd9bb | 197 | |
charly | 2:941c46d37d7e | 198 | void printHex(uint8_t *buf, size_t len, bool nl) |
charly | 2:941c46d37d7e | 199 | { |
charly | 2:941c46d37d7e | 200 | for (size_t i = 0; i < len; i++) { |
charly | 2:941c46d37d7e | 201 | pc.printf("%02X ",buf[i]); |
charly | 2:941c46d37d7e | 202 | } |
charly | 2:941c46d37d7e | 203 | if (nl) |
charly | 2:941c46d37d7e | 204 | pc.printf("\n\r"); |
charly | 2:941c46d37d7e | 205 | } |
charly | 2:941c46d37d7e | 206 | |
charly | 2:941c46d37d7e | 207 | void printUntil(uint8_t *buf) |
charly | 2:941c46d37d7e | 208 | { |
charly | 2:941c46d37d7e | 209 | uint8_t year = buf[1] & 0x3f; |
charly | 2:941c46d37d7e | 210 | uint8_t month = ((buf[0] & 0xE0) >> 4) | (buf[1] >> 7); |
charly | 2:941c46d37d7e | 211 | uint8_t day = buf[0] & 0x1f; |
charly | 2:941c46d37d7e | 212 | /* In 30-minute increments */ |
charly | 2:941c46d37d7e | 213 | uint8_t time = buf[2] & 0x3f; |
charly |
0:94dd393bd9bb | 214 | |
charly | 2:941c46d37d7e | 215 | pc.printf("Until: 20"); |
charly | 2:941c46d37d7e | 216 | if (year < 10) pc.printf("0"); |
charly | 2:941c46d37d7e | 217 | pc.printf("%i",year); |
charly | 2:941c46d37d7e | 218 | pc.printf("."); |
charly | 2:941c46d37d7e | 219 | if (month < 10) pc.printf("0"); |
charly | 2:941c46d37d7e | 220 | pc.printf("%i",month); |
charly | 2:941c46d37d7e | 221 | pc.printf("."); |
charly | 2:941c46d37d7e | 222 | if (day < 10) pc.printf("0"); |
charly | 2:941c46d37d7e | 223 | pc.printf("%i",day); |
charly | 2:941c46d37d7e | 224 | pc.printf(" "); |
charly | 2:941c46d37d7e | 225 | if (time < 20) pc.printf("0"); |
charly | 2:941c46d37d7e | 226 | pc.printf("%i",time / 2); |
charly | 2:941c46d37d7e | 227 | if (time % 2) |
charly | 2:941c46d37d7e | 228 | pc.printf(":30"); |
charly | 2:941c46d37d7e | 229 | else |
charly | 2:941c46d37d7e | 230 | pc.printf(":00"); |
charly | 2:941c46d37d7e | 231 | pc.printf("\n\r"); |
charly |
0:94dd393bd9bb | 232 | } |
charly |
0:94dd393bd9bb | 233 | |
charly | 2:941c46d37d7e | 234 | |
charly | 2:941c46d37d7e | 235 | void max_rx_loop() |
charly | 2:941c46d37d7e | 236 | { |
charly | 2:941c46d37d7e | 237 | uint8_t buf[RF22_MAX_MESSAGE_LEN]; |
charly | 2:941c46d37d7e | 238 | uint8_t len = sizeof(buf); |
charly | 2:941c46d37d7e | 239 | |
charly | 2:941c46d37d7e | 240 | if (rf22.recv(buf, &len)) { |
charly | 2:941c46d37d7e | 241 | pc.printf("Recv: "); |
charly | 2:941c46d37d7e | 242 | pc.printf("len: %i\n\r",len); |
charly | 2:941c46d37d7e | 243 | len = 30; // limit message to 30 Bytes as device receives all 255 Bytes |
charly | 2:941c46d37d7e | 244 | |
charly | 2:941c46d37d7e | 245 | //pc.printf("buf: >%s<\n\r",(char*)buf); |
charly | 2:941c46d37d7e | 246 | printHex(buf, len, true); |
charly | 2:941c46d37d7e | 247 | |
charly | 2:941c46d37d7e | 248 | /* Dewhiten data */ |
charly | 2:941c46d37d7e | 249 | for (int i = 0; i < len; i++) |
charly | 2:941c46d37d7e | 250 | buf[i] ^= pn9[i]; |
charly | 2:941c46d37d7e | 251 | |
charly | 2:941c46d37d7e | 252 | // now read the real length |
charly | 2:941c46d37d7e | 253 | len = buf[0]+3; // 1 length-Byte + 2 CRC |
charly | 2:941c46d37d7e | 254 | pc.printf("len: %i\n\r",len); |
charly | 2:941c46d37d7e | 255 | |
charly | 2:941c46d37d7e | 256 | if (len < 3 || len > lengthof(pn9)) { |
charly | 2:941c46d37d7e | 257 | pc.printf("Packet length too short/long (%i)\n\r",len); |
charly | 2:941c46d37d7e | 258 | return; |
charly | 2:941c46d37d7e | 259 | } |
charly | 2:941c46d37d7e | 260 | pc.printf("dewhiten: "); |
charly | 2:941c46d37d7e | 261 | printHex(buf, len, true); |
charly | 2:941c46d37d7e | 262 | |
charly | 2:941c46d37d7e | 263 | /* Calculate CRC (but don't include the CRC itself) */ |
charly | 2:941c46d37d7e | 264 | uint16_t crc = calc_crc(buf, len - 2); |
charly | 2:941c46d37d7e | 265 | if (buf[len - 1] != (crc & 0xff) || buf[len - 2] != (crc >> 8)) { |
charly | 2:941c46d37d7e | 266 | pc.printf("CRC error\n\r"); |
charly | 2:941c46d37d7e | 267 | return; |
charly | 2:941c46d37d7e | 268 | } |
charly | 2:941c46d37d7e | 269 | |
charly | 2:941c46d37d7e | 270 | /* Don't use the CRC as data */ |
charly | 2:941c46d37d7e | 271 | len -= 2; |
charly | 2:941c46d37d7e | 272 | |
charly | 2:941c46d37d7e | 273 | uint8_t type = buf[3]; |
charly | 2:941c46d37d7e | 274 | #if 1 |
charly | 2:941c46d37d7e | 275 | pc.printf("Message count: "); |
charly | 2:941c46d37d7e | 276 | printHex(buf + 1, 1, true); |
charly | 2:941c46d37d7e | 277 | pc.printf("Flags: "); |
charly | 2:941c46d37d7e | 278 | printHex(buf + 2, 1, true); |
charly | 2:941c46d37d7e | 279 | pc.printf("Packet type: "); |
charly | 2:941c46d37d7e | 280 | printHex(&type, 1, false); |
charly | 2:941c46d37d7e | 281 | pc.printf(" ("); |
charly | 2:941c46d37d7e | 282 | pc.printf(type_str(type)); |
charly | 2:941c46d37d7e | 283 | pc.printf(")\n\r"); |
charly | 2:941c46d37d7e | 284 | pc.printf("Packet from: "); |
charly | 2:941c46d37d7e | 285 | printHex(buf + 4, 3, true); |
charly | 2:941c46d37d7e | 286 | pc.printf("Packet to: "); |
charly | 2:941c46d37d7e | 287 | printHex(buf + 7, 3, true); |
charly | 2:941c46d37d7e | 288 | pc.printf("GroupID: "); |
charly | 2:941c46d37d7e | 289 | printHex(buf + 10, 1, true); |
charly | 2:941c46d37d7e | 290 | pc.printf("Payload: "); |
charly | 2:941c46d37d7e | 291 | printHex(buf + 11, len-11, true); |
charly |
0:94dd393bd9bb | 292 | |
charly | 2:941c46d37d7e | 293 | if (type == 0x30 && len >= 11) { //ShutterContactState |
charly | 2:941c46d37d7e | 294 | bool baterry_low = (buf[11] >> 7) & 0x1; |
charly | 2:941c46d37d7e | 295 | bool state = (buf[11]>>1) & 0x1; |
charly | 2:941c46d37d7e | 296 | pc.printf("State: "); |
charly | 2:941c46d37d7e | 297 | if (state) { |
charly | 2:941c46d37d7e | 298 | pc.printf("open\n\r"); |
charly | 2:941c46d37d7e | 299 | lcd.setLine(1,"open "); |
charly | 2:941c46d37d7e | 300 | } else { |
charly | 2:941c46d37d7e | 301 | pc.printf("closed\n\r"); |
charly | 2:941c46d37d7e | 302 | lcd.setLine(1,"closed "); |
charly | 2:941c46d37d7e | 303 | } |
charly | 2:941c46d37d7e | 304 | pc.printf("Battery: "); |
charly | 2:941c46d37d7e | 305 | if (baterry_low) { |
charly | 2:941c46d37d7e | 306 | pc.printf("low\n\r"); |
charly | 2:941c46d37d7e | 307 | } else { |
charly | 2:941c46d37d7e | 308 | pc.printf("good\n\r"); |
charly | 2:941c46d37d7e | 309 | } |
charly | 2:941c46d37d7e | 310 | |
charly | 2:941c46d37d7e | 311 | } |
charly | 2:941c46d37d7e | 312 | |
charly | 2:941c46d37d7e | 313 | /* |
charly | 2:941c46d37d7e | 314 | else if (type == 0x60 && len >= 13) { // ThermostatState |
charly | 2:941c46d37d7e | 315 | uint8_t mode = buf[11] & 0x3; |
charly | 2:941c46d37d7e | 316 | bool dst = (buf[11] >> 2) & 0x1; |
charly | 2:941c46d37d7e | 317 | bool locked = (buf[11] >> 5) & 0x1; |
charly | 2:941c46d37d7e | 318 | bool baterry_low = (buf[11] >> 7) & 0x1; |
charly | 2:941c46d37d7e | 319 | // 0 - 64 |
charly | 2:941c46d37d7e | 320 | uint8_t valve = buf[12]; |
charly | 2:941c46d37d7e | 321 | uint8_t set_temp = buf[13]; |
charly | 2:941c46d37d7e | 322 | |
charly | 2:941c46d37d7e | 323 | pc.printf("Mode: "); |
charly | 2:941c46d37d7e | 324 | pc.printf(mode_str[mode]); |
charly | 2:941c46d37d7e | 325 | |
charly | 2:941c46d37d7e | 326 | pc.printf("Valve pos: %i%",100 * valve / 64); |
charly | 2:941c46d37d7e | 327 | |
charly | 2:941c46d37d7e | 328 | pc.printf("Set temp: %2.1i",set_temp / 2); |
charly |
0:94dd393bd9bb | 329 | |
charly | 2:941c46d37d7e | 330 | if (len > 15 && mode != MODE_TEMPORARY) { |
charly | 2:941c46d37d7e | 331 | // In tenths of degrees |
charly | 2:941c46d37d7e | 332 | uint8_t actual_temp = ((buf[14] & 0x1) << 8) + buf[15]; |
charly | 2:941c46d37d7e | 333 | pc.printf("Actual temp: "); |
charly | 2:941c46d37d7e | 334 | pc.printf(actual_temp / 10); |
charly | 2:941c46d37d7e | 335 | pc.printf("."); |
charly | 2:941c46d37d7e | 336 | pc.printf(actual_temp % 10); |
charly | 2:941c46d37d7e | 337 | } |
charly | 2:941c46d37d7e | 338 | if (len > 16 && mode == MODE_TEMPORARY) { |
charly | 2:941c46d37d7e | 339 | printUntil(buf + 14); |
charly | 2:941c46d37d7e | 340 | } |
charly | 2:941c46d37d7e | 341 | } else if (type == 0x40 && len >= 11) { // SetTemperature |
charly | 2:941c46d37d7e | 342 | uint8_t set_temp = buf[11] & 0x3f; |
charly | 2:941c46d37d7e | 343 | uint8_t mode = buf[11] >> 6; |
charly | 2:941c46d37d7e | 344 | |
charly | 2:941c46d37d7e | 345 | pc.printf("Mode: "); |
charly | 2:941c46d37d7e | 346 | pc.printf(mode_str[mode]); |
charly | 2:941c46d37d7e | 347 | |
charly | 2:941c46d37d7e | 348 | pc.print("Set temp: "); |
charly | 2:941c46d37d7e | 349 | pc.printf(set_temp / 2); |
charly | 2:941c46d37d7e | 350 | pc.printf(set_temp % 2 ? ".5" : ".0"); |
charly | 2:941c46d37d7e | 351 | if (len > 14) { |
charly | 2:941c46d37d7e | 352 | printUntil(buf + 12); |
charly | 2:941c46d37d7e | 353 | } |
charly | 2:941c46d37d7e | 354 | } |
charly | 2:941c46d37d7e | 355 | |
charly | 2:941c46d37d7e | 356 | // Print the data |
charly | 2:941c46d37d7e | 357 | int i, j; |
charly | 2:941c46d37d7e | 358 | for (i = 0; i < len; i += 16) { |
charly | 2:941c46d37d7e | 359 | // Hex |
charly | 2:941c46d37d7e | 360 | for (j = 0; j < 16 && i+j < len; j++) { |
charly | 2:941c46d37d7e | 361 | if (buf[i+j] < 16) |
charly | 2:941c46d37d7e | 362 | pc.print("0"); // Sigh, pc.print does not know how to pad hex |
charly | 2:941c46d37d7e | 363 | pc.print(buf[i+j], HEX); |
charly | 2:941c46d37d7e | 364 | pc.print(" "); |
charly | 2:941c46d37d7e | 365 | } |
charly | 2:941c46d37d7e | 366 | // Padding on last block |
charly | 2:941c46d37d7e | 367 | while (j++ < 16) |
charly | 2:941c46d37d7e | 368 | pc.print(" "); |
charly | 2:941c46d37d7e | 369 | |
charly | 2:941c46d37d7e | 370 | pc.print(" "); |
charly | 2:941c46d37d7e | 371 | // ASCII |
charly | 2:941c46d37d7e | 372 | for (j = 0; j < 16 && i+j < len; j++) |
charly | 2:941c46d37d7e | 373 | pc.write(isprint(buf[i+j]) ? buf[i+j] : '.'); |
charly | 2:941c46d37d7e | 374 | pc.println(""); |
charly | 2:941c46d37d7e | 375 | } |
charly | 2:941c46d37d7e | 376 | */ |
charly | 2:941c46d37d7e | 377 | pc.printf("\n\r"); |
charly | 2:941c46d37d7e | 378 | #endif |
charly |
0:94dd393bd9bb | 379 | } |
charly |
0:94dd393bd9bb | 380 | } |
charly |
0:94dd393bd9bb | 381 | |
charly | 2:941c46d37d7e | 382 | int main() |
charly | 2:941c46d37d7e | 383 | { |
charly |
1:b71f9a293c54 | 384 | |
charly |
0:94dd393bd9bb | 385 | pc.baud(115200); |
charly |
0:94dd393bd9bb | 386 | |
charly |
0:94dd393bd9bb | 387 | pc.printf("\n\rConnected to mbed\n\r"); |
charly |
0:94dd393bd9bb | 388 | |
charly |
0:94dd393bd9bb | 389 | |
charly | 2:941c46d37d7e | 390 | char version_str [80] = "RF22-MAX!-V1.1"; |
charly | 2:941c46d37d7e | 391 | lcd.cls(); |
charly | 2:941c46d37d7e | 392 | lcd.setLine(0,version_str); |
charly | 2:941c46d37d7e | 393 | pc.printf("%s\n\r",version_str); |
charly |
1:b71f9a293c54 | 394 | |
charly | 2:941c46d37d7e | 395 | pc.printf("Pre-init|"); |
charly | 2:941c46d37d7e | 396 | if (!rf22.init()) |
charly | 2:941c46d37d7e | 397 | pc.printf("RF22 init failed\n\r"); |
charly | 2:941c46d37d7e | 398 | pc.printf("Post-init\n\r"); |
charly |
1:b71f9a293c54 | 399 | |
charly |
1:b71f9a293c54 | 400 | |
charly | 2:941c46d37d7e | 401 | // try to detect Window-Shutter |
charly |
1:b71f9a293c54 | 402 | |
charly | 2:941c46d37d7e | 403 | rf22.setModemRegisters(&config); |
charly | 2:941c46d37d7e | 404 | rf22.setFrequency(868.3, 0.035); |
charly | 2:941c46d37d7e | 405 | /* Disable TX packet control, since the RF22 doesn't do proper |
charly | 2:941c46d37d7e | 406 | * whitening so can't read the length header or CRC. We need RX packet |
charly | 2:941c46d37d7e | 407 | * control so the RF22 actually sends pkvalid interrupts when the |
charly | 2:941c46d37d7e | 408 | * manually set packet length is reached. */ |
charly | 2:941c46d37d7e | 409 | rf22.spiWrite(RF22_REG_30_DATA_ACCESS_CONTROL, RF22_MSBFRST | RF22_ENPACRX); |
charly | 2:941c46d37d7e | 410 | /* No packet headers, 4 sync words, fixed packet length */ |
charly | 2:941c46d37d7e | 411 | rf22.spiWrite(RF22_REG_32_HEADER_CONTROL1, RF22_BCEN_NONE | RF22_HDCH_NONE); |
charly | 2:941c46d37d7e | 412 | rf22.spiWrite(RF22_REG_33_HEADER_CONTROL2, RF22_HDLEN_0 | RF22_FIXPKLEN | RF22_SYNCLEN_4); |
charly | 2:941c46d37d7e | 413 | rf22.setSyncWords(sync_words, lengthof(sync_words)); |
charly | 2:941c46d37d7e | 414 | /* Detect preamble after 4 nibbles */ |
charly | 2:941c46d37d7e | 415 | rf22.spiWrite(RF22_REG_35_PREAMBLE_DETECTION_CONTROL1, (0x4 << 3)); |
charly | 2:941c46d37d7e | 416 | /* Send 8 bytes of preamble */ |
charly | 2:941c46d37d7e | 417 | rf22.setPreambleLength(8); // in nibbles |
charly | 2:941c46d37d7e | 418 | rf22.spiWrite(RF22_REG_3E_PACKET_LENGTH, 20); |
charly |
1:b71f9a293c54 | 419 | |
charly |
1:b71f9a293c54 | 420 | |
charly | 2:941c46d37d7e | 421 | rf22.setModeRx(); |
charly |
1:b71f9a293c54 | 422 | |
charly |
1:b71f9a293c54 | 423 | |
charly |
1:b71f9a293c54 | 424 | |
charly | 2:941c46d37d7e | 425 | //wait forever and see if interrrupt occurs(led1) |
charly | 2:941c46d37d7e | 426 | while (1) { |
charly |
1:b71f9a293c54 | 427 | |
charly | 2:941c46d37d7e | 428 | max_rx_loop(); |
charly | 2:941c46d37d7e | 429 | }; |
charly |
0:94dd393bd9bb | 430 | } |
charly |
0:94dd393bd9bb | 431 | |
charly |
0:94dd393bd9bb | 432 |