Main Page | Class List | File List | Class Members | File Members

channel.c

Go to the documentation of this file.
00001 #include "standard.h"
00002 #include "channel.h"
00003 #include "clock.h"
00004 #include "input.h"
00005 
00006 #define MAX_RAND 2147483647
00007 
00008 /*
00009  * Define "forward channel" through which data logically flows from the local 
00010  * side to the remote side.
00011  *
00012  * Define "reverse channel" through which data logically flows from the 
00013  * remote side to the local side.
00014  */
00015 
00016 extern int debug;
00017 
00018 #define BUFSIZE 65536
00019 
00020 
00021 void apply_errors(byte *data, channel *chan)
00022 {
00023   int i, j, count=0, num_bits;
00024   float r;
00025   float ber;
00026   byte b=*data;
00027 
00028   chan->bit_count += 8;
00029 
00030   if (chan->error==NoErrors)
00031     return;
00032 
00033   if (chan->error == Random) {
00034     if (chan->bit_error_rate == 0.0)
00035       return;
00036 
00037     if ((chan->bit_count/8) >= chan->error_offset) {
00038       for (j=0; j<8; j++) {
00039         r = (float) random() / MAX_RAND;
00040         if (r < chan->bit_error_rate) {
00041           b ^= (1 << j);
00042           count++;
00043           chan->error_count++;
00044           if (debug >= 2)
00045             printf("apply_errors() r=%e, bit %d flipped. \n", r, j);
00046         }
00047       }
00048     }
00049     else
00050       if (debug>=4) printf("apply_errors() - not applying errors yet\n");
00051   }
00052 
00053   else if (chan->error == File) { 
00054     if (chan->filename==NULL) {
00055       warn("apply_errors","channel's error file name is NULL");
00056       return;
00057     }
00058     if ((chan->bit_count/8) > chan->error_offset) {
00059       if (!chan->file_open) {
00060         chan->error_file = fopen(chan->filename,"r");
00061         if (chan->error_file == NULL) {
00062           error("apply_errors","Can't open error file");
00063         }
00064         chan->file_open = 1;
00065       }
00066 
00067       for (j=0; j<8; j++) {
00068         if (feof(chan->error_file))
00069           fseek(chan->error_file, 0, 0);
00070         if (fgetc(chan->error_file)=='1') {
00071           b ^= (1 << j);
00072           count++;
00073           chan->error_count++;
00074           if (debug >= 4)
00075             printf("apply_errors() bit %d flipped\n", j);
00076         }
00077       }
00078     }
00079     else
00080       if (debug>=4) printf("apply_errors() - not applying errors yet\n");
00081   } 
00082   if (debug >= 4) {
00083     printf("apply_errors() [%s] Applied %d errors to byte\n", 
00084            chan->label, count);
00085   }
00086   if (debug >= 1) {
00087     printf("apply_errors() [%s] Errors %d / %d bits (BER %e)\n",
00088            chan->label,
00089            chan->error_count, chan->bit_count, 
00090            (float) chan->error_count / chan->bit_count);
00091   }
00092 
00093 
00094   /* copy modified byte back to *data.  cheezy way of doing this. */
00095 
00096   *data = b;
00097 
00098   /*
00099    * Figure out the BER for this packet and log it.  
00100    */
00101 
00102 
00103   /* ber = (float) count / (float) num_bits;
00104   log_ber(ber, 0); */
00105 
00106   return;
00107 }
00108 
00109 
00110 int channel_write_indication(channel *one)
00111 /*
00112  * Called by MUX to see if it can write to the channel
00113  * Returns 0 if not ready to write, nonzero if ready to write
00114  *
00115  * The idea is to compare the actual amount of data written to
00116  * the amount of data that we are "allowed" to have written at
00117  * this point, based on the elapsed time and the transmission 
00118  * speed.
00119  */
00120 {
00121   /* int level = (one->transmission_speed * one->transmission_delay) / 8000; */
00122   long int allowed = (one->transmission_speed * get_clock()) / 8000; 
00123   
00124   return (one->write_count < allowed);
00125 }
00126 
00127 
00128 int channel_write(channel *one, byte m)
00129 /*
00130  * Called by MUX to write bytes to the channel.
00131  * 
00132  * Returns 1 if successful, 0 if unsuccessful
00133  */
00134 {
00135   bwrite(one->pdus, &m);
00136   one->write_count++;
00137 }
00138 
00139 
00140 int channel_read_indication(channel *one)
00141 /*
00142  * Called by DEMUX to see if it can read a byte.
00143  * This is the complicated one.
00144  *
00145  * first, check to see if there is any data in the incoming buffer
00146  * second, check to see if the number of bytes that we have already read
00147  * is less than the amount we are "allowed" to have read at this point,
00148  * based on elapsed time, transmission delay, and transmission speed
00149  */
00150 {
00151 /*  long int pos = ((get_clock() * one->transmission_speed) / 8000) - one->transmission_delay; */
00152   long int allowed = ((get_clock() - one->transmission_delay) * one->transmission_speed) / 8000;
00153 
00154   if (blevel(one->pdus) > 0)
00155         return (one->read_count < allowed);
00156   else 
00157         return 0;
00158 }
00159 
00160 
00161 byte channel_read(channel *one)
00162 /*
00163  * Called by DEMUX to read a byte from the channel.  
00164  */
00165 {
00166   static byte b;
00167 
00168   bread(one->pdus, &b);
00169 
00170   apply_errors(&b, one);
00171 
00172   one->read_count++;
00173 
00174   return(b);
00175 }
00176 
00177 
00178 channel *new_channel(char *name)
00179 {
00180   char s[256];
00181   int x;
00182 
00183   channel *one = malloc(sizeof(channel));
00184   if (one != NULL) {
00185     strcpy(one->label, name);
00186     one->transmission_speed = DEF_CHANNEL_SPEED;
00187     one->transmission_delay = DEF_CHANNEL_DELAY;
00188     one->error = DEF_CHANNEL_ERROR;
00189     one->bit_error_rate = DEF_CHANNEL_BER;
00190     strcpy(one->filename, DEF_CHANNEL_FILE);
00191     one->pdus = mkbuffer(BUFSIZE, sizeof(byte));
00192     one->error_count = 0;
00193     one->bit_count = 0;
00194     one->write_count=0;
00195     one->read_count=0;
00196     one->error_offset=0;
00197     one->file_open=0;
00198     one->error_file=NULL;
00199   }
00200   else
00201     error("new_channel","Can't malloc new channel");
00202   return (one);
00203 }
00204 
00205 void close_channel(channel *c)
00206 {
00207   if (debug) {
00208     fprintf(stdout,"Channel %s:\n",c->label);
00209     fprintf(stdout,"Number of errors: %d\nNumber of bits:   %d\n",c->error_count,
00210             c->bit_count);
00211     fprintf(stdout,"BER:              %f\n", (float) c->error_count/c->bit_count);
00212   }
00213   if (c->error_file!=NULL)
00214     fclose(c->error_file);
00215   closebuffer(c->pdus);
00216   free(c);
00217 }
00218 

Generated on Sun Jul 16 16:27:45 2006 by  doxygen 1.3.9.1