// Talk to base station via serial port over radio link // need to link with serials.c to get coms stuff and logfile // we usually talk to /dev/ttyS05 for the radio modem // and log to a file called /home/km/incoming/basecoms.log #include #include // need this to set the serial speed like B9600 #include #include #include // Royan's packets // HDR(1 nibble) // HDRSIZE(1 nibble) // SRC_ID(1) // CMD(1) // data[1-16] // checksum(1) #define CURRENT_ID 0xF0 //ID of this device #define CMD_HEADER_ID 0x30 //command message header (send or rcv) #define REPLY_HEADER_ID 0x50 //reply message header #define BROADCAST_ID 0xA0 //the ID boadcasting #define GROUP_ID 0xA3 //the ID for group response #define CMD_SYS_BAT_READ 0x12 // battery voltage #define CMD_SYS_I_AM_AWAKE 20 // to test if things are awake #define CMD_SYS_READ_STR_READINGS 0x15 // read stored readings #define CMD_EEPROM_READ_16 0x5D // read eeprom // a load of ugly globals to store packet data in! unsigned char RX_STATE = 0; unsigned char RX_HEADER; // a copy of the packet header unsigned char RX_SIZE; //received data field size unsigned char RX_MODULE; //target or source module ID unsigned char RX_COMMAND; //received or sent command unsigned char RX_DATA[16]; //data unsigned char TX_HEADER; // out packet header unsigned char TX_SIZE; //out data field size unsigned char TX_MODULE; //out target or source module ID unsigned char TX_COMMAND; //out pkt type unsigned char TX_DATA[16]; //out data FILE *storefile; /* bin file where we store all received bytes*/ FILE *datafile; /* txt file where we store all the parsed data */ // CATCH SIGNALS and close us down nicely void sigcatch(int s) { extern FILE *logfd; fclose(storefile); fclose(datafile); //close(serialport); fclose(logfd); // logging file used by serials.c exit(0); } void COMINTInterpret (unsigned char c) { static unsigned int _checksum; printf("got %x\n",c); if (RX_STATE == 0) //handle data in other conditions { //idle //read packet if valid header detected if (((c & 0xF0) == CMD_HEADER_ID) || ((c & 0xF0) == REPLY_HEADER_ID)) { _checksum = c; //checksum calculation RX_SIZE = c & 0x0F; //size of data field is lower nibble RX_HEADER = c & 0xF0; // Copy header type for later RX_STATE = 1; //goto next state } } else if (RX_STATE == 1) { //module RX_MODULE = c; //read module _checksum += RX_MODULE; //checksum RX_STATE = 2; //goto next state } else if (RX_STATE == 2) { //command RX_COMMAND = c; //read command _checksum += RX_COMMAND; //checksum RX_STATE = 3; //goto next state } else if (RX_STATE == (RX_SIZE + 4)) // Whole packet read, check & exec { if ((_checksum % 256) == c) if( RX_HEADER == CMD_HEADER_ID) { //checksum tallies with data //DebugRXPACKET(); print out the packet headers for DEBUG only! if ((RX_MODULE == CURRENT_ID) || (RX_MODULE == BROADCAST_ID) || (RX_MODULE == GROUP_ID)) ExecuteCommand (); } else ExecuteReply(); RX_STATE = 0; //back to idle mode } else { //data RX_DATA[RX_STATE - 3] = c; //read data _checksum += RX_DATA[RX_STATE - 3]; //checksum RX_STATE++; //goto next state } } store_bat() { unsigned short value; value = (unsigned short)RX_DATA[0] | (RX_DATA[1] << 8); /* if RX_MOD==basesttaion mult by 3 else */ sprintf(datafile, "%d Voltage %g\n",(int)RX_MODULE, 5.25 * 2 * value/1024); } // tell them I am awake i_am_awake() { TX_HEADER = REPLY_HEADER_ID; TX_SIZE = 1; TX_MODULE = CURRENT_ID; TX_COMMAND = CMD_SYS_I_AM_AWAKE; TX_DATA[0] = 0; // just for fun SendPacket(); } // Write a packet from our global variables, to the serial port SendPacket() { unsigned char firstbyte; unsigned short checksum; int n; firstbyte = TX_HEADER + TX_SIZE -1; checksum = firstbyte; putbyte(firstbyte); putbyte(TX_MODULE); checksum += TX_MODULE; putbyte(TX_COMMAND); checksum += TX_COMMAND; for(n = 0; n < TX_SIZE; n++){ putbyte(TX_DATA[n]); checksum += TX_DATA[n]; } putbyte((unsigned char)(checksum & 0xFF) ); } write_readings() { int tmp; int ftmp; // ID month date hour are hex as BCD time is OK as Hex! fprintf(datafile,"%x %x %x %x ",TX_DATA[0], TX_DATA[1], TX_DATA[2], TX_DATA[3]); // temp ftmp = (TX_DATA[4] + 256 * TX_DATA[5]) / 256.0; fprintf(datafile,"%g ",ftmp); // pressure ftmp = 5.25 *((TX_DATA[6] + 256 * TX_DATA[7])-71)/(1024 * 0.05); fprintf(datafile,"%g ",ftmp); //accel X tmp = TX_DATA[8] + 256 * TX_DATA[9]; fprintf(datafile,"%d ",tmp); //accel Y tmp = TX_DATA[10] + 256 * TX_DATA[11]; fprintf(datafile,"%d ",tmp); //accel Z tmp = TX_DATA[12] + 256 * TX_DATA[13]; fprintf(datafile,"%d\n",tmp); } DebugRXPACKET() { int n; printf("ST HDR SIZ MOD CMD\n"); printf("%3d %3x %3x %3x %3x\n", RX_STATE, RX_HEADER, RX_SIZE+1, RX_MODULE, RX_COMMAND); if(RX_COMMAND == 0x18){ for(n=0; n < RX_SIZE+1; n++) printf("%c",RX_DATA[n]); printf("\n"); } else { for(n=0; n < RX_SIZE+1; n++) printf("%2x ",RX_DATA[n]); printf("\n"); } } ExecuteCommand () { int n; switch(RX_COMMAND) { case CMD_SYS_BAT_READ: store_bat(); break; case CMD_SYS_I_AM_AWAKE: i_am_awake(); break; } } // we got something we need to reply to ExecuteReply() { int n; switch(RX_COMMAND) { case CMD_EEPROM_READ_16: write_readings(); break; } } main (int argc, char **argv) { int fd, n; unsigned char byte; int flushcounter=0; char tmpname[256]; if(argc != 2) { printf("talktobase error! arg: filebasename\n"); exit(1); } // catch a signal and exit cleanly signal(SIGHUP, sigcatch); // open port initialise_coms("/dev/ttyS4", B9600, "/home/km/incoming/basecoms.log"); // this is where we copy every byte we get for posterity! sprintf(tmpname, "%s.bin",argv[1]); storefile = fopen (tmpname, "a"); if( storefile == NULL){ printf("talktobase error! can't open %s\n",argv[1]); exit(1); } // this is where we write formatted data sprintf(tmpname, "%s.txt",argv[1]); datafile = fopen (tmpname, "a"); if( storefile == NULL){ printf("talktobase error! can't open %s\n",argv[1]); exit(1); } while (1) { byte = getbyte(); fwrite(&byte,1,1,storefile); // flush everything to file every few bytes if(flushcounter >=15){ fflush(storefile); flushcounter=0; } COMINTInterpret (byte); } }