#include "serial_communications.h" /** @name top-level.c This file contains functions in the highest layer. @author Daniel Storey, UWA, 1998 @version 1.0 */ /*@{*/ /*************************************************************************/ /** Initiate the communications system. Set all channel variables, initiate the serial port. @param my_address string, which contains the address of this station. @param next_address string, which contains the address of the next station in the control loop. @return Channel, the variable containing the characteristics of the link. */ /*************************************************************************/ Channel initiate_serial_communications(char* my_address, char* next_address, char* broadcast_address, int baudrate, bool wireless, bool master) { Channel channel; /* set baud rate */ channel.baudrate = baudrate; /* Initialise packet vairables */ channel.last_packet_number = 36; /* Initialise Addresses */ strncpy(&channel.my_address[0], my_address, ADDRESS_LEN); channel.my_address[ADDRESS_LEN] = '\0'; strncpy(&channel.next_address[0], next_address, ADDRESS_LEN); channel.next_address[ADDRESS_LEN] = '\0'; strncpy(&channel.broadcast_address[0], broadcast_address, ADDRESS_LEN); channel.broadcast_address[ADDRESS_LEN] = '\0'; /* write the preamble */ write_preamble(&channel); /* Initialise the recent received frame data queue */ initialise_recframe_queue(&channel.recframe_queue); /* Initialise Special Sending Queue */ initialise_special_queue(&channel.special_sending); /* Initialise Receive Queue */ initialise_string_queue(&channel.string_receiving); /* Initialise Send Queue */ initialise_queue(&channel.sending); /* initialise error queue */ initialise_queue(&channel.error); /* Initialise token status */ channel.token = FALSE; /* Initialise physical link */ initalise_serial_port(channel); /* Set the wireless */ channel.wireless = wireless; /* Set the transceiver to receive mode */ tx_receive(); /* Set the raw frame status */ channel.raw_valid=FALSE; channel.raw_length=0; /* Set the number of timeouts to 0 */ channel.timeout=0; /* Allow a send if master */ if(master==TRUE) { channel.master = TRUE; force_send(&channel); } else channel.master = FALSE; return channel; } /*************************************************************************/ /** Allow the station to send without a token. Set the relevant part of the communications channel. @param channel Channel, the communication link variable. @return void. */ /*************************************************************************/ void force_send(Channel *channel) { channel->token = TRUE; } /*************************************************************************/ /** Send a string. Send a string to the station indicated over the channel indicated. @param array char*, the string/array to be sent. @param address string, the address of the station to send to. @param length int, the length of the string/array to be sent. @param channel Channel, the communication link variable. @return int, 0 if sucessful, -1 if unsucessful. */ /*************************************************************************/ int comms_send(const char* array, char* address, int length, Channel *channel) { char packet_type[3], string[MAXIMUM_DATA_LENGTH]; Packet packet; /* Check the queue length */ if(queue_length(&channel->sending)>=QUEUE_ELEMENTS) return FALSE; /* Check packet length, return error information if packet too long */ if (length > MAXIMUM_DATA_LENGTH) { LCDPrintf("Comms Error:\nLongPacket Length\n"); return FALSE; } /* Encode the packet */ convert_to_comms_string(string, array, length); /* Find the length of the encoded string */ length = string_length(string); /* Generate Packet type information */ int_2_packet_length(packet_type, length); /* Generate Packet */ packet = generate_packet(packet, address, packet_type, string, channel); /* Add to send Queue */ enqueue(&channel->sending, packet); /* Send o.k. */ return TRUE; } /*************************************************************************/ /** Send a string. Send a string to the station indicated over the channel indicated. @param channel Channel, the communication link variable. @param string string, the string that has been received. @return int, 0 if sucessful, -1 if unsucessful. */ /*************************************************************************/ int comms_receive(char *array, char *address, Channel *channel) { char string[MAXIMUM_DATA_LENGTH]; /* Read next packet from receive queue */ if(string_queue_length(&channel->string_receiving)==0) { string[0] = '\0'; return -1; } /* Dequeue next string */ string_dequeue(&channel->string_receiving, string, address); /* Decode the string */ decipher_comms_string(array, string); /* Return ok */ return 0; } /*************************************************************************/ /** Return the number of packets in the receive queue. Access the appropriate queue and return the number of strings in the q. @param channel Channel, the communication link variable. @return int, the number of packets in the queue. */ /*************************************************************************/ int receive_queue(Channel *channel) { return string_queue_length(&channel->string_receiving); } /*************************************************************************/ /** Return the number of packets in the error queue. Return the number of strings have been sent but for which there has been no reply confirming recipt. @param string string, the string variable to be written to. @param channel Channel, the communication link variable. @return int, the number of errors in the queue. */ /*************************************************************************/ char* comms_error(char* string, Channel *channel) { int length; Packet packet; /* Read next packet from error queue */ if(!empty(&channel->error)) packet = dequeue(&channel->error); else { string[0] = '\0'; }; /* Copy data to string */ length = packet_length(packet.type); strcpy(&string[0], &packet.start[0]); /* Return pointer to the string */ return &string[0]; } /*************************************************************************/ /** Return the number of packets in the output error queue. Return the number of packets in the error queue (o/p of comms). @param channel Channel, the communication link variable. @return int, the number of errors in the output queue. */ /*************************************************************************/ int error_queue(Channel *channel) { return queue_length(&channel->error); } /*************************************************************************/ /** Map special characters. Take a character in an array and process it to return the mapped character. @param character char, the character that is to be encoded. @return char, the character that has been encoded. */ /*************************************************************************/ char map_char(const char character) { switch (character) { case '\0': return 'A'; break; case COMMS_STRING_SPECIAL_CHARACTER_INDICATOR: return 'B'; break; case PACKET_START: return 'C'; break; case PACKET_END: return 'D'; break; default: return character; } } /*************************************************************************/ /** Un-map special characters. Take a character in a string and process it to return the un-mapped character. @param character char, the character that is to be decoded. @return char, the character that has been decoded. */ /*************************************************************************/ char unmap_char(const char character) { switch (character) { case 'A': return '\0'; break; case 'B': return COMMS_STRING_SPECIAL_CHARACTER_INDICATOR; case 'C': return PACKET_START; break; case 'D': return PACKET_END; break; default: return character; } } /*************************************************************************/ /** Convert an array to a communications string. Take an array, and map the characters so it can be transmitted. @param string string, the output string that has been encoded. @param array char*, the array that is to be encoded. @param length int, the length of the array to be encoded. @return void. */ /*************************************************************************/ void convert_to_comms_string(char* string, const char* array, int length) { int i = 0, j = 0, flag = 0; char c; for(i=0; i