Sorry, I figured it out… the n00b mistake was that I wasn’t thinking asynchronously, and that the full received string wouldn’t come in all at once.
So, for those who see this, do getchar() in a continous loop, character-match on the receive buffer for the received signal, then break out when done.
Edit: This code works with STDIO to send/receive modem commands. Note for every transmit, there is a receive, and for every receive, there is a transmit.
/********************************************************************
stdioModemCommander.c
pm1759, 2008
This program is used with RCM4300 series controllers with
prototyping boards.
Description
===========
This program demonstrates controlling port outputs with X10 communication
from STDIO by menu driven functions.
I/O control On proto-board
-------------- ----------------------
See Defines Serial Port D
Instructions
============
1. Compile and run this program. Start a HEX-driven terminal software device
like Docklight, or find an RS232-compatible power line modem.
2. The program will prompt you for to send or receive an X10 command if the
modem is ready. Build commands using X10 HEX protocol.
3. You'll be prompted to select an ON or OFF state. Verify the system works
with an X10 lamp or appliance module. See that the devices turn on and
off.
*********************************************************************/
#class auto
#define TCPCONFIG 0
/////
// configure your serial port connection here
// presently configured serial port D
///
#define SERPORT D
#define DINBUFSIZE 15
#define DOUTBUFSIZE 15
#define CH_ESCAPE 27
#define serXopen CONCAT(ser, CONCAT(SERPORT, open))
#define serXclose CONCAT(ser, CONCAT(SERPORT, close))
#define myserport CONCAT(SER_PORT_, SERPORT)
#define SXSR CONCAT(S, CONCAT(SERPORT, SR))
#define INBUFSIZE CONCAT(SERPORT, INBUFSIZE)
#define OUTBUFSIZE CONCAT(SERPORT, OUTBUFSIZE)
// Note: Hyperterminal, or other end, must use this baud rate
#define BAUDRATE 9600L
/* These are the X10 format codes possible sent through the Powerlinc II Modem.
Not all will be used right away, but if expansion happens all can be used.
*/
#define startcommand 0x02
#define ack 0x06
#define nak 0x15
#define creturn 0x0D
#define sendx10 0x63
#define send1 0x41
#define send2 0x42
#define send3 0x43
#define send4 0x44
#define send5 0x45
#define send6 0x46
#define send7 0x47
#define send8 0x48
#define send9 0x49
#define send10 0x4A
#define send11 0x4B
#define send12 0x4C
#define send13 0x4D
#define send14 0x4E
#define send15 0x4F
#define x10rcvd 0x58
#define sent1 0x31
#define sent2 0x32
#define sent3 0x33
#define sent4 0x34
#define sent5 0x35
#define sent6 0x36
#define sent7 0x37
#define sent8 0x38
#define sent9 0x39
#define sent10 0x3A
#define sent11 0x3B
#define sent12 0x3C
#define sent13 0x3D
#define sent14 0x3E
#define sent15 0x3F
#define x_A 0x46
#define x_B 0x4E
#define x_C 0x42
#define x_D 0x4A
#define x_E 0x41
#define x_F 0x49
#define x_G 0x45
#define x_H 0x4D
#define x_I 0x47
#define x_J 0x4F
#define x_K 0x43
#define x_L 0x4B
#define x_M 0x40
#define x_N 0x48
#define x_O 0x44
#define x_P 0x4C
#define x_1 0x4C
#define x_2 0x5C
#define x_3 0x44
#define x_4 0x54
#define x_5 0x42
#define x_6 0x52
#define x_7 0x4A
#define x_8 0x5A
#define x_9 0x4E
#define x_10 0x5E
#define x_11 0x46
#define x_12 0x56
#define x_13 0x40
#define x_14 0x50
#define x_15 0x48
#define x_16 0x58
#define x_alloff 0x41
#define x_lightson 0x43
#define x_on 0x45
#define x_off 0x47
#define x_bright 0x4B
#define x_lightsoff 0x4D
#define x_extendcode 0x4F
#define x_hail 0x51
#define x_predimhi 0x57
#define x_predimlo 0x55
#define x_extenddata 0x59
#define x_statuson 0x5B
#define x_statusoff 0x5D
#define x_statusreq 0x5F
// RCM43xx boards have no pull-up on serial Rx lines, and we assume in this
// sample the possibility of disconnected or non-driven Rx line. This sample
// has no need of asynchronous line break recognition. By defining the
// following macro we choose the default of disabled character assembly during
// line break condition. This prevents possible spurious line break interrupts.
/**************************************************************/
#define RS232_NOCHARASSYINBRK
//#define FILEBUFSIZE 4096 //4K max file size
//#define TERMINATOR '
'
//#memmap xmem
#use RCM43xx.LIB
#if RAM_COMPILE
#error "This sample is not intended to run in \"Code and BIOS in RAM\" compile mode."
#error "The User block's calibration constants are by default not accessible in this compile mode."
#endif
void encode(int room, int device, int cmd, int txrx);
int* rx(void);
int* decode(char *cmdrcvd, int txrx);
void main(void) {
auto int r, d, s, tr;
auto char c;
char *getter;
int *rcvdcmd;
c = ' ';
tr = 1; //initially set to transmit a command
serXopen(BAUDRATE); //set baud rates for the serial ports to be used
serXwrFlush(myserport); //clear Rx and Tx data buffers
serXrdFlush(myserport);
printf("
----------Menu----------
");
printf("
1 to send Modem Command
2 to listen for Commands
ESC to exit.
");
c = getchar();
while (c != CH_ESCAPE) { // Exit on Escape
while (c == '1') { //transmit setup
if (tr == 1) {
printf("
Rooms 1-16, select then return.
Choice: ");
r = _n_atoi(gets(getter));
while (r < 1 || r > 16) {
printf("
Nope, wrong character. (CAPS!) Try again: ");
r = _n_atoi(gets(getter));
} //while
printf("
Devices 1-16, select then return.
Choice: ");
d = _n_atoi(gets(getter));
while (d < 1 || d > 16) {
printf("
Nope, wrong number. Try again: ");
d = _n_atoi(gets(getter));
} //while
printf("
1 to turn r%d d%d On
2 to turn r%d d%d Off
Then return.
Choice: ",r,d,r,d);
s = _n_atoi(gets(getter));
while (s < 1 || s > 2) {
printf("Nope, wrong character. Try again: ");
s = _n_atoi(gets(getter));
} //while
encode(r,d,s,tr);
c = '2'; //set 2 to handle receive
} //if
else if (tr == 0) {
printf("
%d Means acknowledging Room %d Device %d is in State %d.
",rcvdcmd[3],rcvdcmd[0],rcvdcmd[1],rcvdcmd[2]);
encode(rcvdcmd[0],rcvdcmd[1],rcvdcmd[2],rcvdcmd[3]);
c = 'M';
} //end else if
} //while
while(c == '2') {
rcvdcmd = rx();
if (rcvdcmd[3] == 0) {
printf("
Receiving a command...
");
tr = 0;
c = '1';
} //if
else if (rcvdcmd[3] == 1) {
tr = 1;
c = 'M';
}
} //while
while(c == 'M') {
printf("
Continue? 1 to Send, 2 to Receive, ESC to quit
");
c = getchar();
if(c == '1'){
tr = 1;
}
else {
tr = 0;
}
} //end while
} //while
printf("
Done
");
// allow transmission to complete before closing
while (serXwrFree(myserport) != OUTBUFSIZE);
serXclose(); // close serial port
} //main
void encode (int r, int d, int s, int txrx) {
char command[6];
char cmdsent[12];
switch (r) {
case 1:
command[2] = x_A;
break;
case 2:
command[2] = x_B;
break;
case 3:
command[2] = x_C;
break;
case 4:
command[2] = x_D;
break;
case 5:
command[2] = x_E;
break;
case 6:
command[2] = x_F;
break;
case 7:
command[2] = x_G;
break;
case 8:
command[2] = x_H;
break;
case 9:
command[2] = x_I;
break;
case 10:
command[2] = x_J;
break;
case 11:
command[2] = x_K;
break;
case 12:
command[2] = x_L;
break;
case 13:
command[2] = x_M;
break;
case 14:
command[2] = x_N;
break;
case 15:
command[2] = x_O;
break;
case 16:
command[2] = x_P;
break;
default:
break;
} //switch
switch (d) {
case 1:
command[3] = x_1;
break;
case 2:
command[3] = x_2;
break;
case 3:
command[3] = x_3;
break;
case 4:
command[3] = x_4;
break;
case 5:
command[3] = x_5;
break;
case 6:
command[3] = x_6;
break;
case 7:
command[3] = x_7;
break;
case 8:
command[3] = x_8;
break;
case 9:
command[3] = x_9;
break;
case 10:
command[3] = x_10;
break;
case 11:
command[3] = x_11;
break;
case 12:
command[3] = x_12;
break;
case 13:
command[3] = x_13;
break;
case 14:
command[3] = x_15;
break;
case 15:
command[3] = x_15;
break;
case 16:
command[3] = x_16;
break;
default:
break;
} //switch
switch (s) {
case 1:
command[4] = x_on;
break;
case 2:
command[4] = x_off;
break;
default:
break;
} //switch
if (txrx == 1) {
command[0] = startcommand;
command[1] = sendx10;
command[5] = send1;
printf("
Initializing %s.
", command);
serXwrite(myserport, command, sizeof(command));
}
else if (txrx == 0) {
cmdsent[0] = ack;
cmdsent[1] = creturn;
cmdsent[2] = x10rcvd;
cmdsent[3] = command[2];
cmdsent[4] = command[3];
cmdsent[5] = sent1;
cmdsent[6] = creturn;
cmdsent[7] = x10rcvd;
cmdsent[8] = command[2];
cmdsent[9] = command[4];
cmdsent[10] = sent1;
cmdsent[11] = creturn;
printf("
Initializing
%s
", cmdsent);
serXwrite(myserport, cmdsent, sizeof(cmdsent));
}
} //txcmd
int* rx(void) {
int cnt, max, tr, pos;
char p;
char cmd_rx[3];
int *rcvdcmd;
strcpy(cmd_rx, " ");
pos = 0;
cnt = 0;
max = 12;
while (cnt < max) {
printf("receiving...
");
p = serXgetc(myserport);
if (p == startcommand) {
tr = 0;
max = 5;
cnt=cnt+1;
}
else if (p == sendx10) {
cnt=cnt+1;
} //else if
else if (p == ack) {
tr = 1;
max = 11;
cnt=cnt+1;
} //if
else if (p == creturn) {
cnt=cnt+1;
} //else if
else if (p == x10rcvd) {
cnt=cnt+1;
} //else if
else if ((p >= send1)&&(p <= send15)&&((cnt == 5)&&(tr == 1))) { //number of times to send the message
cnt=cnt+1;
} //else if
else if ((p >= sent1)&&(p <= sent15)) { //number of times the other end sent the message
cnt=cnt+1;
} //else if
else if ((p >= x_M)&&(p <= x_J)&&(((cnt == 3)&&(tr == 1))||((cnt == 2)&&(tr == 0)))) { //x_M = 40, x_J = 4F
cmd_rx[pos] = p;
pos=pos+1;
cnt=cnt+1;
} //else if
else if ((p >= x_13)&&(p <= x_10)&&(((cnt == 4)&&(tr == 1))||((cnt == 3)&&(tr == 0)))) { //x_13 = 40, x_10 = 5E
cmd_rx[pos] = p;
pos=pos+1;
cnt=cnt+1;
} //else if
else if ((p >= x_M)&&(p <= x_J)&&(cnt == 8)) { //forget 2nd House Code
cnt=cnt+1;
} //if
else if ((p >= x_alloff)&&(p <= x_statusreq)&&(((cnt == 9)&&(tr == 1))||((cnt == 4)&&(tr == 0)))) { //x_alloff = 41, x_statusreq = 5F
cmd_rx[pos] = p;
cnt=cnt+1;
} //else if
else if (p == nak) {
break;
} //else if
} //while
if (tr == 1) {
printf("
Ensuring Receipt...
");
rcvdcmd = decode(cmd_rx, tr);
strcpy(cmd_rx, " ");
return rcvdcmd;
} //if
else if (tr == 0) {
printf("
Incoming Request...
");
rcvdcmd = decode(cmd_rx, tr);
strcpy(cmd_rx, " ");
return rcvdcmd;
}
else {
printf("
Sorry didn't work
");
} // else
} //end rx
int* decode(char *rx, int tr) {
int r, d, s;
int rcvdcmd[4];
char *c;
switch (rx[0]) {
case x_A:
r = 1;
break;
case x_B:
r = 2;
break;
case x_C:
r = 3;
break;
case x_D:
r = 4;
break;
case x_E:
r = 5;
break;
case x_F:
r = 6;
break;
case x_G:
r = 7;
break;
case x_H:
r = 8;
break;
case x_I:
r = 9;
break;
case x_J:
r = 10;
break;
case x_K:
r = 11;
break;
case x_L:
r = 12;
break;
case x_M:
r = 13;
break;
case x_N:
r = 14;
break;
case x_O:
r = 15;
break;
case x_P:
r = 16;
break;
default:
r = 0;
break;
} //switch
switch (rx[1]) {
case x_1:
d = 1;
break;
case x_2:
d = 2;
break;
case x_3:
d = 3;
break;
case x_4:
d = 4;
break;
case x_5:
d = 5;
break;
case x_6:
d = 6;
break;
case x_7:
d = 7;
break;
case x_8:
d = 8;
break;
case x_9:
d = 9;
break;
case x_10:
d = 10;
break;
case x_11:
d = 11;
break;
case x_12:
d = 12;
break;
case x_13:
d = 13;
break;
case x_14:
d = 15;
break;
case x_15:
d = 15;
break;
case x_16:
d = 16;
break;
default:
d = 0;
break;
} //switch
switch (rx[2]) {
case x_on:
s = 1;
c = "ON";
break;
case x_off:
s = 2;
c = "OFF";
break;
default:
s = 0;
c = "in error";
printf ("
Something is %s with Room %d Device %d
",r,d,c);
break;
} //switch
rcvdcmd[0] = r;
rcvdcmd[1] = d;
rcvdcmd[2] = s;
rcvdcmd[3] = tr;
if (tr == 1) {
printf ("
Room %d Device %d is %s.
",r,d,c);
return rcvdcmd;
} //if
if (tr == 0) {
printf ("
Room %d Device %d wants to go %s.
",r,d,c);
return rcvdcmd;
}
} //end decode