#include "serial_communications.h" /** @name user.c This file contains functions that will be used by any programming accessing the communciations system. @author Daniel Storey, UWA, 1998 @version 1.0 */ /*@{*/ /** Global Variable for storing channel information */ Channel radio_channel; /** Global semaphore */ int radio_sema; /** Global indicators of transmission state */ bool radio_send; bool radio_begin_send; /*************************************************************************/ /** Initiate the communications system. Called by the user to initiate the communications system. @param baudrate int, the baud rate of the link. @param next_address char, the address of the next machine in the control loop. @return int, 0 if the transmission was sucessful. */ /*************************************************************************/ int RadioInit(char number) { char my_address[2], n_a[2], broadcast_address[2]; int next_address, baudrate = SER9600, wireless = TRUE; bool master = FALSE; /* Use robot identification number as address */ my_address[0] = (char) OSMachineID(); my_address[1] = '\0'; /* Check station status. ID = 1 -> Master station */ if(my_address[0]==1) master = TRUE; /* Set next address */ if(my_address[0]==(char) number) next_address = 1; else next_address = my_address[0] + 1; /* offset address for easy reading */ my_address[0] += 48; /* move to ASCII Number range */ LCDPrintf("My add = %c\n", my_address[0]); /* Write next address */ n_a[0] = next_address + 48; /* move to ASCII Number range */ n_a[1] = '\0'; /* Write to broadcast address */ broadcast_address[0] = 0 + 48; /* ASCII zero */ broadcast_address[1] = '\0'; radio_channel = initiate_serial_communications(my_address, n_a, broadcast_address, baudrate, wireless, master); #if DEBUG LCDPrintf("Initialise\n"); #endif if(master==TRUE) { #if DEBUG LCDPrintf("Master\n"); #endif tx_send(); OSWait(2); LOWSEND(); write_serial_data(EYEBOT_SERIAL_PORT); while(OSCheckOutRS232(EYEBOT_SERIAL_PORT)!=0);/* is o/p buffer empty? */ OSWait(1); tx_receive(); OSWait(2); } else { #if DEBUG LCDPrintf("Slave\n"); #endif } radio_send = FALSE; radio_begin_send = FALSE; radio_sema = FALSE; OSAttachTimer(10, RadioCheck); return 0; } /*************************************************************************/ /** Transmit a message. Called by the user to transmit a data array. @param id int, the number of the station to send to. @param message *char, the message to be sent. @param length int, the length of the message to be sent. @return int, 0 if the transmission was sucessful, -1 if not. */ /*************************************************************************/ int RadioTx(char id, char *message, int length) { char address[2]; int a; radio_sema = TRUE; address[0] = id + 48; address[1] = '\0'; a = comms_send(message, address, length, &radio_channel); radio_sema = FALSE; return a; } /*************************************************************************/ /** Receive a message (Non-blocking). Check the incoming queue for a message. If there are no messages, return -1. @param message char*, The received message. @return int, the sender ID, or -1 for an error. */ /*************************************************************************/ int RadioRx(char *message) { int a = 0; char address[2]; radio_sema=TRUE; a = comms_receive(message, address, &radio_channel); radio_sema=FALSE; /* No Packet present */ if(a==-1) return -1; /* Return the address */ return (int) (address[1] - 48); } /*************************************************************************/ /** Receive a message (Blocking). Wait until there is a message in the receive queue, then get it. @param message char*, The received message. @return int, the sender ID. */ /*************************************************************************/ int RadioRxB(char *message) { char address[2]; while(RadioRx(message)==-1) OSWait(10); /* Wait for some action */ /* Return the address */ return (int) (address[1] - 48); } /*************************************************************************/ /** Low level send & receive. Send and receive at the lowest level. This is a multitasking routine that is to be run in the background. Its priority represents the speed at which data will be transmitted through the network as well as the amount of processing resources it will consume. @param void. @return void.*/ /*************************************************************************/ void RadioCheck() { #if TIMERS LCDPrintf("Radio Check\n"); #endif BufferCheck(); /* Check to see if the transmitter must be switched */ if(radio_send==TRUE) { if(OSCheckOutRS232(EYEBOT_SERIAL_PORT)==0) { /* is o/p buffer empty? */ WL_RECV(); radio_send = FALSE; } return; } /* Return if the channel variable is in use */ if(radio_sema==TRUE) return; /* Check if we need to switch to transmit mode */ if((can_send(&radio_channel))&&(radio_begin_send==TRUE)) { WL_SEND(); radio_begin_send=FALSE; return; } /* Check if we can send */ if((can_send(&radio_channel))&&(radio_begin_send==FALSE)) { LOWSEND(); write_serial_data(EYEBOT_SERIAL_PORT); radio_send = TRUE; return; } /* If we can't do any of these things, read serial port data */ LOWRECEIVE(); /* Change mode if a token has been received */ if(can_send(&radio_channel)) { radio_begin_send=TRUE; } return; } /*************************************************************************/ /** Low level send. Explicitly call a low level send. @param void. @return void.*/ /*************************************************************************/ void LOWSEND() { low_send(&radio_channel); } /*************************************************************************/ /** Low level receive. Explicitly call a low level receive. @param void. @return void.*/ /*************************************************************************/ void LOWRECEIVE() { low_receive(&radio_channel); } void BufferCheck() { read_serial_data(EYEBOT_SERIAL_PORT); }