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.

Dependents:   X10Svr

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?

UserRevisionLine numberNew 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 }