GIDForums  

Go Back   GIDForums > Computer Programming Forums > C++ Forum
User Name
Password
Register FAQ Members List Calendar Search Today's Posts Mark Forums Read

 
 
Thread Tools Search this Thread Rate Thread
  #1  
Old 06-Jul-2006, 14:44
soldstatic soldstatic is offline
New Member
 
Join Date: Jul 2006
Posts: 16
soldstatic is on a distinguished road

receive X10 signals with w800rf32a serial


This is mostly to help others who have the same type of issues as i did. Took me forever to figure out how to simply read the w800rf32a by wgldesigns and decode the X10 signals from it.

Some of the problems are listed below, so please if you can help that'd be great, but at any rate.......

Anyway here's how to get X10 off the serial port in linux!

CPP / C++ / C Code:

//-----------------------
// Included for serial port
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stropts.h>
#define BAUDRATE B4800
#define MODEMDEVICE "/dev/ttyS0"	// later we will read this from a config file
#define _POSIX_SOURCE 1 /* POSIX compliant source */
#define FALSE 0
#define TRUE 1
//
//-----------------------

// Include other C classes
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fstream>
#include <iostream>
#include <signal.h>

// Include other classes
#include "edit_sensors.h"
#include "edit_database.h"
#include "options.h"

// Namespaces
using namespace std;

// Global variables
int fd;
struct termios oldtio;

//*****************************************************
//*****************************************************

//Begin functions

//*****************************************************
//*****************************************************


void receiveX10::init()
{
    // This is run as the main for this class since the main 
    // isn't actually availible for edit through QT
    open_serial();    	// get the serial port ready to go        

}


int receiveX10::open_serial()
{
    // This method saves the current termio settings so that they can be restored later,
    // then it opens the serial port for reading and returns the fildes int of the open port
    
    int c;
    struct termios newtio;
    
    fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 	// Open the serial device
    if (fd <0) {perror(MODEMDEVICE); exit(-1); }	// If unable to open, exit
    
    tcgetattr(fd,&oldtio); /* save current port settings */
    ioctl(fd,I_SRDOPT,RPROTDAT);
    bzero(&newtio, sizeof(newtio));
    newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;	// Set baudrate (defined earlier), character size = 8 bit, local control only, and allow read
    newtio.c_iflag = IGNPAR;	// Ignore parity
    newtio.c_oflag = 0;
    
    /* set input mode (non-canonical, no echo,...) */
    //    newtio.c_lflag = 0;
    newtio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
    
    newtio.c_cc[VTIME]    = 0;   /* inter-character timer unused */
    newtio.c_cc[VMIN]     = 4;   /* blocking read until 4 chars received */
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd,TCSANOW,&newtio);	// Set the new conditions to be the current conditions
    signal ( SIGPOLL, poll_handler );	// Should tell the program to run a function upon receipt of SIGPOLL    
    ioctl(fd,I_SETSIG,S_INPUT | S_HIPRI);	// Should tell the serial port to send us the signal SIGPOLL whenever any input is on the port
    return fd;	// return fildes
}


void receiveX10::poll_handler(int signum)
{
    // Handle the "SIGPOLL" signal sent by serial port
    // Just send the program to the read function to get data off the port

    cout << "got ->" << signum <<"<-";	// Just to see if it works
    // receiveX10::read_serial();	// In the end should call the read function	currently crashes compiler... not sure why?????
}


void receiveX10::read_serial()
{
    // This method reads the data off the serial port
    
    int res;	// Initialize the resolution
    unsigned char buf[255];	// Initialize the array for storage
    
    res = read(fd,buf,4);   // returns after 4 chars have been input, also sets res to the number of characters actually read [should always be 4] 
    buf[res]=0;               // so we can printf... 
    
    /* Prints for debugging:
       
	printf("%X",  buf[0]);
	printf(":%X", buf[1]);
	printf(":%X", buf[2]);
	printf(":%X\t%d", buf[3],res);
	   time_t rawtime;
	   time ( &rawtime );
	printf ( "\t\t%s", ctime (&rawtime) );
	
	*/
    
    decode_serial(buf[0],buf[1],buf[2],buf[3]);
}


void receiveX10::close_serial()
{
    // This sets the current struct termios to the old settings from before open_serial() was called
    
    tcsetattr(fd,TCSANOW,&oldtio);
}


void receiveX10::decode_serial(unsigned char buf0,unsigned char buf1,unsigned char buf2,unsigned char buf3){
    
    unsigned char buf[4];
    buf[0]=buf0;
    buf[1]=buf1;
    buf[2]=buf2;
    buf[3]=buf3;
    
    // Prints for debugging:
    printf("%X", buf[0]);
    printf(":%X", (unsigned char) buf[1]);
    printf(":%X", (unsigned char) buf[2]);
    printf(":%X", (unsigned char) buf[3]);


    if ( ( (buf[0] ^ buf[1]) == 0xff ) & ( (buf[2] ^ buf[3]) == 0xff ) ){
	// If this is a device w/o security X10 protocol (ie a motion sensor), we expect byte 0 to be the complement of byte 1, and byte 2 to be the complement of byte 3
	// If the complements are received, we know its not a security enabled devices and can then determine the rest of the packet
	// Example: 10010000 01101111 01010000 10101111 would be a non-secure packet.

        QString house;	
	house = decode_house( buf[0] );	// determine the house code
	cout << "\t" << house;

	int unit;
	unit = decode_unit(buf[0], buf[2]);	// determine the unit number
	cout << "\t" << unit;

	QString command;
	command = decode_command( buf[2] );	//determine the command
	cout << "\t" << command;
	
    }
    else {
	printf("\t\tcomplement=no\t\tERROR");
    }
    printf("\n");
    
}


QString receiveX10::decode_house(unsigned char buf)
{
    // This method examines the byte passed to it and determines the house code
    
    unsigned char nib1 = buf & 0xf0;
    // In order to determine the house code, we look at only the first nibble of the first byte. IE the first four bits of first byte.
    // Example: 01100000 and 01100100 both indicate a "house" code of A
    switch ( nib1 ) {
    case 0x60:
	return "a";
	break;
    case 0x70:
	return "b";
	break;
    case 0x40:
	return "c";
	break;
    case 0x50:
	return "d";
	break;
    case 0x80:
	return "e";
	break;
    case 0x90:
	return "f";
	break;
    case 0xA0:
	return "g";
	break;
    case 0xB0:
	return "h";
	break;
    case 0xE0:
	return "i";
	break;
    case 0xF0:
	return "j";
	break;
    case 0xC0:
	return "k";
	break;
    case 0xD0:
	return "l";
	break;
    case 0x00:
	return "m";
	break;
    case 0x10:
	return "n";
	break;
    case 0x20:
	return "o";
	break;
    case 0x30:
	return "p";
	break;	    
    default:
	return "ERROR";
	break;
    }
}


QString receiveX10::decode_command(unsigned char buf)
{
    // This method examines the byte passed to it and determines the house code. This should be the 3rd byte from the w800
    
    if( (buf & 0x20) == 0x20)	// if bit is set, always indicates an "off" command
    {
	return "off";
    }
    else if(buf == 0x88)	// 0x88 always indicaates a "bright" command
    {
	return "bright";
    }
    else if(buf == 0x98)	// 0x98 always indicaates a "dim" command
    {
	return "dim";
    }    
    else	// otherwise, the unit is sending an "on" command
    {
	return "on";
    }
}


int receiveX10::decode_unit(unsigned char buf1, unsigned char buf2)
{
    int unit = 0;
    unsigned char sw = buf2 & 0xDF;		// set the command code to constant value
    
    switch ( sw ){	    // determine the unit code based on X10 protocol
    case 0x00:
	unit = 1;
	break;
    case 0x10:
	unit = 2;
	break;
    case 0x08:
	unit = 3;
	break;
    case 0x18:
	unit = 4;
	break;	
    case 0x40:
	unit = 5;
	break;	
    case 0x50:
	unit = 6;
	break;	
    case 0x48:
	unit = 7;
	break;	
    case 0x58:
	unit = 8;
	break;
    default:	// if a different unit code is determined, then the command is bright or dim, or there is an error
	unit = 99;
	break;
    }
    
    
    if( (buf1 & 0x04) == 0x04 ) // If the 3rd bit of byte 1 is set, we know that the unit code needs to be 9-16 instead of 0-8
    {
	return ( unit+8 );
    }
    else 
    {
	return unit;
    }
}



There may be a couple extra includes in there and what not, and there's a couple of things that aren't working, but its basically one big fat example for others trying to do the same thing. I know for a fact it reads the motion detectors around my office and prints out their status and whatnot.

problems that need to be addressed:
--- if the signals aren't 'framed' correctly: ie you start the program up in the middle of a device sending the signal 906f00ff, but the read_serial might get 6f00ff90. That's a big problem I don't know how to watch out for so that needs some help :-/

--- compiler crash: when you uncomment the the ioctl calls for the signal handler and stuff then it crashes with the following err:
Quote:
X10.ui.h:122: error: argument of type `void (receiverX10::)(int)' does not match `void (*)(int)'
where line 122 =
Quote:
signal ( SIGPOLL, poll_handler ); // Should tell the program to run a function upon receipt of SIGPOLL


--- sigpoll doesn't work: might be part of the above problem but I can not figure out how the hell to get the serial port to notify my program when there is data available. this i need. badly. please help that one out if you can.


its fairly easy to follow I think... if you've got questions post em, if you can help with the errors please please do so. Otherwise I hope this bit helps everyone with their X10 endeavors.
 
 

Recent GIDBlogAccepted for Ph.D. program by crystalattice

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
WinDVD v1.2.96c serial number TK1799 Computer Software Forum - Windows 5 26-Jun-2006 15:54
Monitor biological signals ted C++ Forum 2 14-Jun-2005 16:57
Problem to read on a serial port collinm C Programming Language 2 30-Mar-2005 02:42
Send and receive data through port using MFC Dialog Based mithila MS Visual C++ / MFC Forum 1 10-Sep-2004 03:01

Network Sites: GIDNetwork · GIDWebHosts · GIDSearch · Learning Journal by J de Silva, The

All times are GMT -6. The time now is 05:13.


vBulletin, Copyright © 2000 - 2009, Jelsoft Enterprises Ltd.