This library contains a simple device driver for the X10 CM17a module. It also contains a simple X10Server, which listens for network commands to be forwarded to the module.
X10.cpp@0:12ed8bd4909a, 2014-06-28 (annotated)
- Committer:
- WiredHome
- Date:
- Sat Jun 28 19:45:20 2014 +0000
- Revision:
- 0:12ed8bd4909a
- Child:
- 1:4006f1419bc2
Working X10 Driver for CM17a module.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WiredHome | 0:12ed8bd4909a | 1 | |
WiredHome | 0:12ed8bd4909a | 2 | #include "X10.h" |
WiredHome | 0:12ed8bd4909a | 3 | |
WiredHome | 0:12ed8bd4909a | 4 | |
WiredHome | 0:12ed8bd4909a | 5 | //#define DEBUG "x10 " |
WiredHome | 0:12ed8bd4909a | 6 | #ifdef WIN32 |
WiredHome | 0:12ed8bd4909a | 7 | #define LF "\n" |
WiredHome | 0:12ed8bd4909a | 8 | #else // mbed |
WiredHome | 0:12ed8bd4909a | 9 | #define LF "\r\n" |
WiredHome | 0:12ed8bd4909a | 10 | #endif // WIN32 |
WiredHome | 0:12ed8bd4909a | 11 | #include <cstdio> |
WiredHome | 0:12ed8bd4909a | 12 | #if (defined(DEBUG) && !defined(TARGET_LPC11U24)) |
WiredHome | 0:12ed8bd4909a | 13 | #define DBG(x, ...) std::printf("[DBG %s %3d] " x LF, DEBUG, __LINE__, ##__VA_ARGS__) |
WiredHome | 0:12ed8bd4909a | 14 | #define WARN(x, ...) std::printf("[WRN %s %3d] " x LF, DEBUG, __LINE__, ##__VA_ARGS__) |
WiredHome | 0:12ed8bd4909a | 15 | #define ERR(x, ...) std::printf("[ERR %s %3d] " x LF, DEBUG, __LINE__, ##__VA_ARGS__) |
WiredHome | 0:12ed8bd4909a | 16 | #define INFO(x, ...) std::printf("[INF %s %3d] " x LF, DEBUG, __LINE__, ##__VA_ARGS__) |
WiredHome | 0:12ed8bd4909a | 17 | #else |
WiredHome | 0:12ed8bd4909a | 18 | #define DBG(x, ...) |
WiredHome | 0:12ed8bd4909a | 19 | #define WARN(x, ...) |
WiredHome | 0:12ed8bd4909a | 20 | #define ERR(x, ...) |
WiredHome | 0:12ed8bd4909a | 21 | #define INFO(x, ...) |
WiredHome | 0:12ed8bd4909a | 22 | #endif |
WiredHome | 0:12ed8bd4909a | 23 | |
WiredHome | 0:12ed8bd4909a | 24 | #define CMD_MASK 0xFF00 |
WiredHome | 0:12ed8bd4909a | 25 | #define CMD_DELAY 0x0100 |
WiredHome | 0:12ed8bd4909a | 26 | |
WiredHome | 0:12ed8bd4909a | 27 | |
WiredHome | 0:12ed8bd4909a | 28 | /* The house code is the high nibble of the command data. */ |
WiredHome | 0:12ed8bd4909a | 29 | /* 1111 0000 0000 0000 House Mask */ |
WiredHome | 0:12ed8bd4909a | 30 | /* 0000 0100 1101 1000 Device Mask */ |
WiredHome | 0:12ed8bd4909a | 31 | /* 0000 0000 1011 1000 Command Mask */ |
WiredHome | 0:12ed8bd4909a | 32 | /* 1111 0101 1111 1000 Composite Mask */ |
WiredHome | 0:12ed8bd4909a | 33 | const uint16_t house_codes[16] = { |
WiredHome | 0:12ed8bd4909a | 34 | /* 1111 0000 0000 0000 House Mask */ |
WiredHome | 0:12ed8bd4909a | 35 | 0x6000, /* 0110 0000 0000 0000 A */ |
WiredHome | 0:12ed8bd4909a | 36 | 0x7000, /* 0111 0000 0000 0000 B */ |
WiredHome | 0:12ed8bd4909a | 37 | 0x4000, /* 0100 0000 0000 0000 C */ |
WiredHome | 0:12ed8bd4909a | 38 | 0x5000, /* 0101 0000 0000 0000 D */ |
WiredHome | 0:12ed8bd4909a | 39 | 0x8000, /* 1000 0000 0000 0000 E */ |
WiredHome | 0:12ed8bd4909a | 40 | 0x9000, /* 1001 0000 0000 0000 F */ |
WiredHome | 0:12ed8bd4909a | 41 | 0xA000, /* 1010 0000 0000 0000 G */ |
WiredHome | 0:12ed8bd4909a | 42 | 0xB000, /* 1011 0000 0000 0000 H */ |
WiredHome | 0:12ed8bd4909a | 43 | 0xE000, /* 1110 0000 0000 0000 I */ |
WiredHome | 0:12ed8bd4909a | 44 | 0xF000, /* 1111 0000 0000 0000 J */ |
WiredHome | 0:12ed8bd4909a | 45 | 0xC000, /* 1100 0000 0000 0000 K */ |
WiredHome | 0:12ed8bd4909a | 46 | 0xD000, /* 1101 0000 0000 0000 L */ |
WiredHome | 0:12ed8bd4909a | 47 | 0x0000, /* 0000 0000 0000 0000 M */ |
WiredHome | 0:12ed8bd4909a | 48 | 0x1000, /* 0001 0000 0000 0000 N */ |
WiredHome | 0:12ed8bd4909a | 49 | 0x2000, /* 0010 0000 0000 0000 O */ |
WiredHome | 0:12ed8bd4909a | 50 | 0x3000, /* 0011 0000 0000 0000 P */ |
WiredHome | 0:12ed8bd4909a | 51 | }; |
WiredHome | 0:12ed8bd4909a | 52 | |
WiredHome | 0:12ed8bd4909a | 53 | /* The device codes are described by bits 3, 4, 6, and 10. */ |
WiredHome | 0:12ed8bd4909a | 54 | #define DEVICE_BITS 0x0458 |
WiredHome | 0:12ed8bd4909a | 55 | const uint16_t device_codes[16] = { |
WiredHome | 0:12ed8bd4909a | 56 | /* 0000 0100 0101 1000 Device Mask */ |
WiredHome | 0:12ed8bd4909a | 57 | 0x0000, /* 0000 0000 0000 0000 1 */ |
WiredHome | 0:12ed8bd4909a | 58 | 0x0010, /* 0000 0000 0001 0000 2 */ |
WiredHome | 0:12ed8bd4909a | 59 | 0x0008, /* 0000 0000 0000 1000 3 */ |
WiredHome | 0:12ed8bd4909a | 60 | 0x0018, /* 0000 0000 0001 1000 4 */ |
WiredHome | 0:12ed8bd4909a | 61 | 0x0040, /* 0000 0000 0100 0000 5 */ |
WiredHome | 0:12ed8bd4909a | 62 | 0x0050, /* 0000 0000 0101 0000 6 */ |
WiredHome | 0:12ed8bd4909a | 63 | 0x0048, /* 0000 0000 0100 1000 7 */ |
WiredHome | 0:12ed8bd4909a | 64 | 0x0058, /* 0000 0000 0101 1000 8 */ |
WiredHome | 0:12ed8bd4909a | 65 | 0x0400, /* 0000 0100 0000 0000 9 */ |
WiredHome | 0:12ed8bd4909a | 66 | 0x0410, /* 0000 0100 0001 0000 10 */ |
WiredHome | 0:12ed8bd4909a | 67 | 0x0408, /* 0000 0100 0000 1000 11 */ |
WiredHome | 0:12ed8bd4909a | 68 | 0x0418, /* 0000 0100 0001 1000 12 */ |
WiredHome | 0:12ed8bd4909a | 69 | 0x0440, /* 0000 0100 0100 0000 13 */ |
WiredHome | 0:12ed8bd4909a | 70 | 0x0450, /* 0000 0100 0101 0000 14 */ |
WiredHome | 0:12ed8bd4909a | 71 | 0x0448, /* 0000 0100 0100 1000 15 */ |
WiredHome | 0:12ed8bd4909a | 72 | 0x0458, /* 0000 0100 0101 1000 16 */ |
WiredHome | 0:12ed8bd4909a | 73 | }; |
WiredHome | 0:12ed8bd4909a | 74 | |
WiredHome | 0:12ed8bd4909a | 75 | |
WiredHome | 0:12ed8bd4909a | 76 | /* The command codes are described by bits 1, 2, 5, 7, 8, 9, and 11. */ |
WiredHome | 0:12ed8bd4909a | 77 | const uint16_t command_codes[] = { |
WiredHome | 0:12ed8bd4909a | 78 | /* 0000 0000 1011 1000 Command Mask */ |
WiredHome | 0:12ed8bd4909a | 79 | 0x0000, /* 0000 0000 0000 0000 ON */ |
WiredHome | 0:12ed8bd4909a | 80 | 0x0020, /* 0000 0000 0010 0000 OFF */ |
WiredHome | 0:12ed8bd4909a | 81 | 0x0088, /* 0000 0000 1000 1000 BRIGHT */ |
WiredHome | 0:12ed8bd4909a | 82 | 0x0098, /* 0000 0000 1001 1000 DIM */ |
WiredHome | 0:12ed8bd4909a | 83 | }; |
WiredHome | 0:12ed8bd4909a | 84 | |
WiredHome | 0:12ed8bd4909a | 85 | const unsigned char header[] = { 0xD5, 0xAA }; |
WiredHome | 0:12ed8bd4909a | 86 | const unsigned char footer[] = { 0xAD }; |
WiredHome | 0:12ed8bd4909a | 87 | |
WiredHome | 0:12ed8bd4909a | 88 | enum command_index { |
WiredHome | 0:12ed8bd4909a | 89 | ON, OFF, BRIGHTEN, DIM |
WiredHome | 0:12ed8bd4909a | 90 | }; |
WiredHome | 0:12ed8bd4909a | 91 | |
WiredHome | 0:12ed8bd4909a | 92 | bool fSentOn[16][16]; |
WiredHome | 0:12ed8bd4909a | 93 | |
WiredHome | 0:12ed8bd4909a | 94 | X10Interface::X10Interface(PinName RTS, PinName DTR, uint8_t MultiMessageDelay_s, uint32_t BaudRate) |
WiredHome | 0:12ed8bd4909a | 95 | { |
WiredHome | 0:12ed8bd4909a | 96 | cm17Pins = new BusOut(RTS, DTR); |
WiredHome | 0:12ed8bd4909a | 97 | bitEnqueue = bitDequeue = 0; |
WiredHome | 0:12ed8bd4909a | 98 | mask = 0x80; |
WiredHome | 0:12ed8bd4909a | 99 | baud(BaudRate); |
WiredHome | 0:12ed8bd4909a | 100 | multiMsgDelay_s = MultiMessageDelay_s; |
WiredHome | 0:12ed8bd4909a | 101 | *cm17Pins = RESET; |
WiredHome | 0:12ed8bd4909a | 102 | wait_ms(200); |
WiredHome | 0:12ed8bd4909a | 103 | *cm17Pins = STANDBY; |
WiredHome | 0:12ed8bd4909a | 104 | |
WiredHome | 0:12ed8bd4909a | 105 | } |
WiredHome | 0:12ed8bd4909a | 106 | |
WiredHome | 0:12ed8bd4909a | 107 | |
WiredHome | 0:12ed8bd4909a | 108 | X10Interface::ERR_EXIT X10Interface::baud(uint32_t baudrate) |
WiredHome | 0:12ed8bd4909a | 109 | { |
WiredHome | 0:12ed8bd4909a | 110 | bitperiod_us = 1000000/baudrate/2; |
WiredHome | 0:12ed8bd4909a | 111 | return ERR_SUCCESS; |
WiredHome | 0:12ed8bd4909a | 112 | } |
WiredHome | 0:12ed8bd4909a | 113 | |
WiredHome | 0:12ed8bd4909a | 114 | X10Interface::ERR_EXIT X10Interface::delay(uint8_t MultiMessageDelay_s) |
WiredHome | 0:12ed8bd4909a | 115 | { |
WiredHome | 0:12ed8bd4909a | 116 | multiMsgDelay_s = MultiMessageDelay_s; |
WiredHome | 0:12ed8bd4909a | 117 | return ERR_SUCCESS; |
WiredHome | 0:12ed8bd4909a | 118 | } |
WiredHome | 0:12ed8bd4909a | 119 | |
WiredHome | 0:12ed8bd4909a | 120 | X10Interface::ERR_EXIT X10Interface::ParseCommand(char * message) |
WiredHome | 0:12ed8bd4909a | 121 | { |
WiredHome | 0:12ed8bd4909a | 122 | const char seps[] = " ,\t\n"; |
WiredHome | 0:12ed8bd4909a | 123 | char *token; |
WiredHome | 0:12ed8bd4909a | 124 | int argc = 0; |
WiredHome | 0:12ed8bd4909a | 125 | char *argv[20]; |
WiredHome | 0:12ed8bd4909a | 126 | |
WiredHome | 0:12ed8bd4909a | 127 | strcpy(commandBuffer, message); |
WiredHome | 0:12ed8bd4909a | 128 | INFO("ParseCommand(%s)", commandBuffer); |
WiredHome | 0:12ed8bd4909a | 129 | // tokenize into individual items |
WiredHome | 0:12ed8bd4909a | 130 | token = strtok(commandBuffer, seps); |
WiredHome | 0:12ed8bd4909a | 131 | while( token != NULL ) { |
WiredHome | 0:12ed8bd4909a | 132 | argv[argc++] = token; |
WiredHome | 0:12ed8bd4909a | 133 | token = strtok( NULL, seps ); |
WiredHome | 0:12ed8bd4909a | 134 | INFO("argv[%d] = %s", argc-1, argv[argc-1]); |
WiredHome | 0:12ed8bd4909a | 135 | } |
WiredHome | 0:12ed8bd4909a | 136 | for (int i = 0; i < argc; i++) { |
WiredHome | 0:12ed8bd4909a | 137 | if (strchr("ABCDEFGHIJKLMNOPabcdefghijklmnop", *argv[i]) && (i + 1) < argc) { |
WiredHome | 0:12ed8bd4909a | 138 | ERR_EXIT z; // return # args to increment |
WiredHome | 0:12ed8bd4909a | 139 | z = DoCommand(argv[i], argv[i + 1]); |
WiredHome | 0:12ed8bd4909a | 140 | if (z == ERR_SUCCESS) |
WiredHome | 0:12ed8bd4909a | 141 | i += 1; |
WiredHome | 0:12ed8bd4909a | 142 | } else if (*argv[i] == '/') { |
WiredHome | 0:12ed8bd4909a | 143 | // direct hex code with /XXXX |
WiredHome | 0:12ed8bd4909a | 144 | unsigned int command_word; |
WiredHome | 0:12ed8bd4909a | 145 | |
WiredHome | 0:12ed8bd4909a | 146 | sscanf(argv[i],"/%X", &command_word); |
WiredHome | 0:12ed8bd4909a | 147 | if (cm17a_CmdSend(command_word)) { |
WiredHome | 0:12ed8bd4909a | 148 | return ERR_BADARGS; |
WiredHome | 0:12ed8bd4909a | 149 | } |
WiredHome | 0:12ed8bd4909a | 150 | wait_us(1000); // Wait 1 sec between commands |
WiredHome | 0:12ed8bd4909a | 151 | } else if (*argv[i] >= '0' && *argv[i] <= '9') { |
WiredHome | 0:12ed8bd4909a | 152 | // change bit period |
WiredHome | 0:12ed8bd4909a | 153 | uint32_t b = atol(argv[i]); |
WiredHome | 0:12ed8bd4909a | 154 | INFO("set baud %s => %d", argv[i], b); |
WiredHome | 0:12ed8bd4909a | 155 | baud(b); |
WiredHome | 0:12ed8bd4909a | 156 | } else { |
WiredHome | 0:12ed8bd4909a | 157 | ERR("Can't parse %s\n", argv[i]); |
WiredHome | 0:12ed8bd4909a | 158 | return ERR_BADARGS; |
WiredHome | 0:12ed8bd4909a | 159 | } |
WiredHome | 0:12ed8bd4909a | 160 | if (i +1 < argc) { |
WiredHome | 0:12ed8bd4909a | 161 | enqueueData(CMD_DELAY | multiMsgDelay_s); |
WiredHome | 0:12ed8bd4909a | 162 | } |
WiredHome | 0:12ed8bd4909a | 163 | } |
WiredHome | 0:12ed8bd4909a | 164 | return ERR_SUCCESS; |
WiredHome | 0:12ed8bd4909a | 165 | } |
WiredHome | 0:12ed8bd4909a | 166 | |
WiredHome | 0:12ed8bd4909a | 167 | |
WiredHome | 0:12ed8bd4909a | 168 | uint16_t X10Interface::cm17a_CmdLookup(int iHouse, int iUnit, enum command_index command) |
WiredHome | 0:12ed8bd4909a | 169 | { |
WiredHome | 0:12ed8bd4909a | 170 | uint16_t retval; |
WiredHome | 0:12ed8bd4909a | 171 | |
WiredHome | 0:12ed8bd4909a | 172 | switch (command) { |
WiredHome | 0:12ed8bd4909a | 173 | case BRIGHTEN: |
WiredHome | 0:12ed8bd4909a | 174 | case DIM: |
WiredHome | 0:12ed8bd4909a | 175 | retval = house_codes[iHouse] | command_codes[command]; |
WiredHome | 0:12ed8bd4909a | 176 | break; |
WiredHome | 0:12ed8bd4909a | 177 | default: |
WiredHome | 0:12ed8bd4909a | 178 | retval = (house_codes[iHouse] | device_codes[iUnit] | command_codes[command]); |
WiredHome | 0:12ed8bd4909a | 179 | break; |
WiredHome | 0:12ed8bd4909a | 180 | } |
WiredHome | 0:12ed8bd4909a | 181 | return retval; |
WiredHome | 0:12ed8bd4909a | 182 | } |
WiredHome | 0:12ed8bd4909a | 183 | |
WiredHome | 0:12ed8bd4909a | 184 | |
WiredHome | 0:12ed8bd4909a | 185 | X10Interface::ERR_EXIT X10Interface::cm17a_CmdSend(uint16_t command) |
WiredHome | 0:12ed8bd4909a | 186 | { |
WiredHome | 0:12ed8bd4909a | 187 | INFO("cm17a_CmdSend(%04X)", command); |
WiredHome | 0:12ed8bd4909a | 188 | if (cm17a_Header() |
WiredHome | 0:12ed8bd4909a | 189 | || enqueueData((unsigned char)(command >> 8)) |
WiredHome | 0:12ed8bd4909a | 190 | || enqueueData((unsigned char)command) |
WiredHome | 0:12ed8bd4909a | 191 | || cm17a_Footer()) { |
WiredHome | 0:12ed8bd4909a | 192 | return ERR_COMERR; |
WiredHome | 0:12ed8bd4909a | 193 | } |
WiredHome | 0:12ed8bd4909a | 194 | return ERR_SUCCESS; |
WiredHome | 0:12ed8bd4909a | 195 | } |
WiredHome | 0:12ed8bd4909a | 196 | |
WiredHome | 0:12ed8bd4909a | 197 | |
WiredHome | 0:12ed8bd4909a | 198 | X10Interface::ERR_EXIT X10Interface::cm17a_CmdSend(int iHouse, int iUnit, enum command_index command) |
WiredHome | 0:12ed8bd4909a | 199 | { |
WiredHome | 0:12ed8bd4909a | 200 | uint16_t command_word; |
WiredHome | 0:12ed8bd4909a | 201 | |
WiredHome | 0:12ed8bd4909a | 202 | command_word = cm17a_CmdLookup(iHouse, iUnit, command); |
WiredHome | 0:12ed8bd4909a | 203 | return cm17a_CmdSend(command_word); |
WiredHome | 0:12ed8bd4909a | 204 | } |
WiredHome | 0:12ed8bd4909a | 205 | |
WiredHome | 0:12ed8bd4909a | 206 | |
WiredHome | 0:12ed8bd4909a | 207 | X10Interface::ERR_EXIT X10Interface::cm17a_Header(void) |
WiredHome | 0:12ed8bd4909a | 208 | { |
WiredHome | 0:12ed8bd4909a | 209 | return write_stream(header, sizeof(header)); |
WiredHome | 0:12ed8bd4909a | 210 | } |
WiredHome | 0:12ed8bd4909a | 211 | |
WiredHome | 0:12ed8bd4909a | 212 | |
WiredHome | 0:12ed8bd4909a | 213 | X10Interface::ERR_EXIT X10Interface::enqueueData(uint16_t word) |
WiredHome | 0:12ed8bd4909a | 214 | { |
WiredHome | 0:12ed8bd4909a | 215 | if (bitEnqueue < sizeof(bitBuffer)) { |
WiredHome | 0:12ed8bd4909a | 216 | bitBuffer[bitEnqueue++] = word; |
WiredHome | 0:12ed8bd4909a | 217 | //for (int i=0; i<bitEnqueue; i++) |
WiredHome | 0:12ed8bd4909a | 218 | // INFO("%2d: %04X", i, bitBuffer[i]); |
WiredHome | 0:12ed8bd4909a | 219 | return ERR_SUCCESS; |
WiredHome | 0:12ed8bd4909a | 220 | } else { |
WiredHome | 0:12ed8bd4909a | 221 | ERR("bitBuffer is full, can't accept more"); |
WiredHome | 0:12ed8bd4909a | 222 | return ERR_COMERR; |
WiredHome | 0:12ed8bd4909a | 223 | } |
WiredHome | 0:12ed8bd4909a | 224 | } |
WiredHome | 0:12ed8bd4909a | 225 | |
WiredHome | 0:12ed8bd4909a | 226 | |
WiredHome | 0:12ed8bd4909a | 227 | X10Interface::ERR_EXIT X10Interface::cm17a_Footer(void) |
WiredHome | 0:12ed8bd4909a | 228 | { |
WiredHome | 0:12ed8bd4909a | 229 | X10Interface::ERR_EXIT i; |
WiredHome | 0:12ed8bd4909a | 230 | |
WiredHome | 0:12ed8bd4909a | 231 | i = write_stream(footer, sizeof(footer)); |
WiredHome | 0:12ed8bd4909a | 232 | ticker.attach_us(this, &X10Interface::x10stream, bitperiod_us/2); |
WiredHome | 0:12ed8bd4909a | 233 | return i; |
WiredHome | 0:12ed8bd4909a | 234 | } |
WiredHome | 0:12ed8bd4909a | 235 | |
WiredHome | 0:12ed8bd4909a | 236 | |
WiredHome | 0:12ed8bd4909a | 237 | |
WiredHome | 0:12ed8bd4909a | 238 | |
WiredHome | 0:12ed8bd4909a | 239 | void X10Interface::x10stream(void) |
WiredHome | 0:12ed8bd4909a | 240 | { |
WiredHome | 0:12ed8bd4909a | 241 | uint16_t msg = bitBuffer[bitDequeue]; |
WiredHome | 0:12ed8bd4909a | 242 | static bool timerIsRunning = false; |
WiredHome | 0:12ed8bd4909a | 243 | |
WiredHome | 0:12ed8bd4909a | 244 | if (msg & CMD_MASK) { |
WiredHome | 0:12ed8bd4909a | 245 | if (*cm17Pins != STANDBY) |
WiredHome | 0:12ed8bd4909a | 246 | *cm17Pins = STANDBY; |
WiredHome | 0:12ed8bd4909a | 247 | // msg & CMD_DELAY, but this is the only possible command |
WiredHome | 0:12ed8bd4909a | 248 | // if (msg & CMD_MASK == CMD_DELAY) ... |
WiredHome | 0:12ed8bd4909a | 249 | // Delay, the low byte number of seconds |
WiredHome | 0:12ed8bd4909a | 250 | if (!timerIsRunning) { |
WiredHome | 0:12ed8bd4909a | 251 | timer.reset(); |
WiredHome | 0:12ed8bd4909a | 252 | timer.start(); |
WiredHome | 0:12ed8bd4909a | 253 | timerIsRunning = true; |
WiredHome | 0:12ed8bd4909a | 254 | } else { |
WiredHome | 0:12ed8bd4909a | 255 | if (timer.read_ms() >= 1000 * (msg & 0xFF)) { |
WiredHome | 0:12ed8bd4909a | 256 | // timed out, so advance past this entry |
WiredHome | 0:12ed8bd4909a | 257 | timer.stop(); |
WiredHome | 0:12ed8bd4909a | 258 | timerIsRunning = false; |
WiredHome | 0:12ed8bd4909a | 259 | bitDequeue++; |
WiredHome | 0:12ed8bd4909a | 260 | if (bitDequeue >= bitEnqueue) { |
WiredHome | 0:12ed8bd4909a | 261 | INFO("detach"); |
WiredHome | 0:12ed8bd4909a | 262 | ticker.detach(); |
WiredHome | 0:12ed8bd4909a | 263 | bitEnqueue = bitDequeue = 0; |
WiredHome | 0:12ed8bd4909a | 264 | mask = 0x80; |
WiredHome | 0:12ed8bd4909a | 265 | return; //false; |
WiredHome | 0:12ed8bd4909a | 266 | } |
WiredHome | 0:12ed8bd4909a | 267 | } |
WiredHome | 0:12ed8bd4909a | 268 | } |
WiredHome | 0:12ed8bd4909a | 269 | return; |
WiredHome | 0:12ed8bd4909a | 270 | } else { |
WiredHome | 0:12ed8bd4909a | 271 | // bitstream |
WiredHome | 0:12ed8bd4909a | 272 | enum SIGNAL signal = (msg & mask) ? HIGH : LOW; |
WiredHome | 0:12ed8bd4909a | 273 | if (*cm17Pins != STANDBY) { |
WiredHome | 0:12ed8bd4909a | 274 | *cm17Pins = STANDBY; |
WiredHome | 0:12ed8bd4909a | 275 | if (bitDequeue >= bitEnqueue) { |
WiredHome | 0:12ed8bd4909a | 276 | ticker.detach(); |
WiredHome | 0:12ed8bd4909a | 277 | bitEnqueue = bitDequeue = 0; |
WiredHome | 0:12ed8bd4909a | 278 | mask = 0x80; |
WiredHome | 0:12ed8bd4909a | 279 | return; //false; |
WiredHome | 0:12ed8bd4909a | 280 | } |
WiredHome | 0:12ed8bd4909a | 281 | return; //true; |
WiredHome | 0:12ed8bd4909a | 282 | } |
WiredHome | 0:12ed8bd4909a | 283 | *cm17Pins = signal; |
WiredHome | 0:12ed8bd4909a | 284 | mask >>= 1; |
WiredHome | 0:12ed8bd4909a | 285 | if (mask == 0) { |
WiredHome | 0:12ed8bd4909a | 286 | mask = 0x80; |
WiredHome | 0:12ed8bd4909a | 287 | bitDequeue++; |
WiredHome | 0:12ed8bd4909a | 288 | } |
WiredHome | 0:12ed8bd4909a | 289 | } |
WiredHome | 0:12ed8bd4909a | 290 | return; //true; |
WiredHome | 0:12ed8bd4909a | 291 | } |
WiredHome | 0:12ed8bd4909a | 292 | |
WiredHome | 0:12ed8bd4909a | 293 | |
WiredHome | 0:12ed8bd4909a | 294 | X10Interface::ERR_EXIT X10Interface::write_stream(const unsigned char * data, size_t byte_count) |
WiredHome | 0:12ed8bd4909a | 295 | { |
WiredHome | 0:12ed8bd4909a | 296 | size_t i; |
WiredHome | 0:12ed8bd4909a | 297 | ERR_EXIT ret = ERR_SUCCESS; |
WiredHome | 0:12ed8bd4909a | 298 | |
WiredHome | 0:12ed8bd4909a | 299 | for (i = 0; i < byte_count; i++) { |
WiredHome | 0:12ed8bd4909a | 300 | ret = enqueueData(data[i]); |
WiredHome | 0:12ed8bd4909a | 301 | if (ret) |
WiredHome | 0:12ed8bd4909a | 302 | break; |
WiredHome | 0:12ed8bd4909a | 303 | } |
WiredHome | 0:12ed8bd4909a | 304 | return ret; |
WiredHome | 0:12ed8bd4909a | 305 | } |
WiredHome | 0:12ed8bd4909a | 306 | |
WiredHome | 0:12ed8bd4909a | 307 | |
WiredHome | 0:12ed8bd4909a | 308 | char toupper(char x) |
WiredHome | 0:12ed8bd4909a | 309 | { |
WiredHome | 0:12ed8bd4909a | 310 | if (x >= 'a') |
WiredHome | 0:12ed8bd4909a | 311 | x -= ('a' - 'A'); |
WiredHome | 0:12ed8bd4909a | 312 | return x; |
WiredHome | 0:12ed8bd4909a | 313 | } |
WiredHome | 0:12ed8bd4909a | 314 | |
WiredHome | 0:12ed8bd4909a | 315 | |
WiredHome | 0:12ed8bd4909a | 316 | X10Interface::ERR_EXIT X10Interface::parse_device(const char* szDevice, int* iHouse, int* iUnit) |
WiredHome | 0:12ed8bd4909a | 317 | { |
WiredHome | 0:12ed8bd4909a | 318 | *iHouse = -1; |
WiredHome | 0:12ed8bd4909a | 319 | *iUnit = -1; |
WiredHome | 0:12ed8bd4909a | 320 | |
WiredHome | 0:12ed8bd4909a | 321 | if (strlen(szDevice) >= 2) { |
WiredHome | 0:12ed8bd4909a | 322 | *iHouse = toupper(szDevice[0]) - 'A'; |
WiredHome | 0:12ed8bd4909a | 323 | *iUnit = atoi(&szDevice[1]) - 1; |
WiredHome | 0:12ed8bd4909a | 324 | } |
WiredHome | 0:12ed8bd4909a | 325 | if (*iHouse < 0 || *iHouse > 15 || *iUnit < 0 || *iUnit > 15) { |
WiredHome | 0:12ed8bd4909a | 326 | ERR("Invalid house/device specification %s\n",szDevice); |
WiredHome | 0:12ed8bd4909a | 327 | return ERR_NODESPEC; |
WiredHome | 0:12ed8bd4909a | 328 | } |
WiredHome | 0:12ed8bd4909a | 329 | return ERR_SUCCESS; |
WiredHome | 0:12ed8bd4909a | 330 | } |
WiredHome | 0:12ed8bd4909a | 331 | |
WiredHome | 0:12ed8bd4909a | 332 | |
WiredHome | 0:12ed8bd4909a | 333 | /* DoCommand |
WiredHome | 0:12ed8bd4909a | 334 | * |
WiredHome | 0:12ed8bd4909a | 335 | * <house><unit> [+|-]0|1|2|3|4|5|6 |
WiredHome | 0:12ed8bd4909a | 336 | */ |
WiredHome | 0:12ed8bd4909a | 337 | X10Interface::ERR_EXIT X10Interface::DoCommand(const char* szDevice, const char* szOp) |
WiredHome | 0:12ed8bd4909a | 338 | { |
WiredHome | 0:12ed8bd4909a | 339 | int iHouse; |
WiredHome | 0:12ed8bd4909a | 340 | int iUnit; |
WiredHome | 0:12ed8bd4909a | 341 | int steps; |
WiredHome | 0:12ed8bd4909a | 342 | |
WiredHome | 0:12ed8bd4909a | 343 | if (parse_device(szDevice, &iHouse, &iUnit)) |
WiredHome | 0:12ed8bd4909a | 344 | return ERR_BADCMD; |
WiredHome | 0:12ed8bd4909a | 345 | |
WiredHome | 0:12ed8bd4909a | 346 | if (*szOp == '+' || *szOp == '-') { |
WiredHome | 0:12ed8bd4909a | 347 | // Increment up or down # times |
WiredHome | 0:12ed8bd4909a | 348 | steps = abs(atoi(szOp)); |
WiredHome | 0:12ed8bd4909a | 349 | if (steps < 1 || steps > 6) { |
WiredHome | 0:12ed8bd4909a | 350 | ERR("Invalid steps (%d). Must be [1..6].\n", steps); |
WiredHome | 0:12ed8bd4909a | 351 | return ERR_BADSTEP; |
WiredHome | 0:12ed8bd4909a | 352 | } |
WiredHome | 0:12ed8bd4909a | 353 | |
WiredHome | 0:12ed8bd4909a | 354 | /* Turn the device we wish to control on first. If we don't |
WiredHome | 0:12ed8bd4909a | 355 | do this, the dim command gets handled by the last device |
WiredHome | 0:12ed8bd4909a | 356 | that got turned on. The cm17a dim/brighten command doesn't |
WiredHome | 0:12ed8bd4909a | 357 | use a device code. */ |
WiredHome | 0:12ed8bd4909a | 358 | if (!fSentOn[iHouse][iUnit]) { |
WiredHome | 0:12ed8bd4909a | 359 | if (cm17a_CmdSend(iHouse, iUnit, ON) != 0) { |
WiredHome | 0:12ed8bd4909a | 360 | ERR("Command failed.\n"); |
WiredHome | 0:12ed8bd4909a | 361 | return ERR_BADCMD; |
WiredHome | 0:12ed8bd4909a | 362 | } else |
WiredHome | 0:12ed8bd4909a | 363 | fSentOn[iHouse][iUnit] = 1; |
WiredHome | 0:12ed8bd4909a | 364 | } |
WiredHome | 0:12ed8bd4909a | 365 | do { |
WiredHome | 0:12ed8bd4909a | 366 | if (cm17a_CmdSend(iHouse, iUnit, (*szOp == '+') ? BRIGHTEN : DIM)) |
WiredHome | 0:12ed8bd4909a | 367 | ERR("Command failed.\n"); |
WiredHome | 0:12ed8bd4909a | 368 | } while (--steps > 0); |
WiredHome | 0:12ed8bd4909a | 369 | } else if (*szOp == '1') { |
WiredHome | 0:12ed8bd4909a | 370 | if (cm17a_CmdSend(iHouse, iUnit, ON) != 0) |
WiredHome | 0:12ed8bd4909a | 371 | ERR("Command failed.\n"); |
WiredHome | 0:12ed8bd4909a | 372 | else |
WiredHome | 0:12ed8bd4909a | 373 | fSentOn[iHouse][iUnit] = 1; |
WiredHome | 0:12ed8bd4909a | 374 | } else if (*szOp == '0') { |
WiredHome | 0:12ed8bd4909a | 375 | if (cm17a_CmdSend(iHouse, iUnit, OFF) != 0) |
WiredHome | 0:12ed8bd4909a | 376 | ERR("Command failed.\n"); |
WiredHome | 0:12ed8bd4909a | 377 | else |
WiredHome | 0:12ed8bd4909a | 378 | fSentOn[iHouse][iUnit] = 0; |
WiredHome | 0:12ed8bd4909a | 379 | } else { |
WiredHome | 0:12ed8bd4909a | 380 | /* Could be leadin to multiple unit command */ |
WiredHome | 0:12ed8bd4909a | 381 | if (!fSentOn[iHouse][iUnit]) { |
WiredHome | 0:12ed8bd4909a | 382 | if (cm17a_CmdSend(iHouse, iUnit, ON) != 0) { |
WiredHome | 0:12ed8bd4909a | 383 | ERR("Command failed.\n"); |
WiredHome | 0:12ed8bd4909a | 384 | return ERR_BADCMD; |
WiredHome | 0:12ed8bd4909a | 385 | } else |
WiredHome | 0:12ed8bd4909a | 386 | fSentOn[iHouse][iUnit] = 1; |
WiredHome | 0:12ed8bd4909a | 387 | } |
WiredHome | 0:12ed8bd4909a | 388 | ERR("can't parse [%s]\n", szDevice); |
WiredHome | 0:12ed8bd4909a | 389 | return ERR_BADCMD; |
WiredHome | 0:12ed8bd4909a | 390 | } |
WiredHome | 0:12ed8bd4909a | 391 | return ERR_SUCCESS; |
WiredHome | 0:12ed8bd4909a | 392 | } |