00001 /* src_experimental/net/rsm.c 00002 CubeOS Version 0.4.90 experimental 00003 Copyright (C) 1999,2000 Holger Kenn 00004 00005 CubeOS is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or any later version. 00009 00010 CubeOS is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 */ 00016 // 00017 // Radio State machine for CubeOS 00018 // 00019 00024 #include <rsm.h> 00025 #include <rdio.h> 00026 #include <cubeos.h> 00027 //#include <conio.h> 00028 #include <stdio.h> 00029 #include <ttyio.h> 00030 00031 // 00032 // A frame for the RSM looks like this: 00033 // 00034 // 00 ff 00 ff ... 00 ff SOH E1 E2 E1 E2 E1 E2 ... E1 E2 C1 C2 00035 // 00036 // There are exactly RMS_FRAMELEN E1/E2 pairs, each one encoding one byte 00037 // The C1/C2 bytes represent the encoded 8-bit checksum of the frame 00038 // 00039 // At the moment, no escaping of the SOH byte is done, so the protocol 00040 // may get stuck. 00041 // 00042 00043 // States of the RSM 00044 00045 #define RSM_OFF 0 00046 #define RSM_IDLE 1 00047 #define RSM_INFRAME1 2 00048 #define RSM_INFRAME2 3 00049 #define RSM_CHECKSUM1 4 00050 #define RSM_CHECKSUM2 5 00051 00052 // Start of Header 00053 #define RSM_SOH 0xA5 00054 00055 #define RSM_PREHEADER 6 //Number of 0x00 0xff in preheader 00056 00057 //#define RSM_DEBUG 00058 00059 // variables 00060 00061 // buffers 00062 char _RSM_buffer0[RSM_FRAMELEN]; 00063 char _RSM_buffer1[RSM_FRAMELEN]; 00064 00065 // internal 00066 unsigned char _RSM_state = 0; 00067 //unsigned char _RSM_enabled = 0; 00068 short _RSM_count; 00069 char RSM_new; 00070 char *_RSM_writebuf; 00071 char *RSM_getbuf; 00072 unsigned char _RSM_checksum; 00073 unsigned char _RSM_charcount; 00074 00075 // statistics 00076 int RSM_good; 00077 int _RSM_bad; 00078 int _RSM_ugly; 00079 int _RSM_bytes; 00080 int _RSM_uglycount; 00081 00082 // function prototypes: user interface 00083 00084 int RSM_init_rx (); 00085 int RSM_init_tx (); 00086 int RSM_getframe (unsigned char *buffer); 00087 int RSM_send_frame (unsigned char *buffer); 00088 00089 00090 // function prototypes: for internal use only 00091 00092 void _RSM_doutchar (unsigned char c); 00093 void _RSM_douthex (unsigned char c); 00094 void RSM_process (unsigned char c); 00095 void RSM_tty_rdioput_block (char byte); 00096 unsigned char *RSM_rxframe (unsigned char *frame); 00097 00098 00099 // function implementations 00100 00105 int RSM_init_rx () 00106 { 00107 #ifdef DUART_BASE 00108 _RSM_writebuf = _RSM_buffer0; 00109 RSM_getbuf = _RSM_buffer1; 00110 _RSM_state = RSM_IDLE; 00111 RSM_good = 0; 00112 _RSM_bad = 0; 00113 _RSM_ugly = 0; 00114 _RSM_bytes = 0; 00115 _RSM_uglycount = 0; 00116 RSM_new = 0; 00117 _RSM_charcount = 0; 00118 // _RSM_enabled = 1; /* redirect to RSM_process() */ 00119 TTY_tty[1].char_process = RSM_process; /* enable char processor */ 00120 clearRTXSEL (); /* disable transmitter */ 00121 setRRXSEL (); /* enable receiver */ 00122 RSM_rdio_enable_rx (); /* Enable reception IRQ */ 00123 return 0; 00124 #else 00125 return -1; 00126 #endif 00127 } 00128 00129 00134 int RSM_deinitrx () 00135 { 00136 #ifdef DUART_BASE 00137 clearRRXSEL (); /* disable receiver */ 00138 // _RSM_enabled = 0; /* redirect to RSM_process() */ 00139 TTY_tty[1].char_process = NULL; /* disable char processor */ 00140 _RSM_state = RSM_IDLE; /* back to idle state */ 00141 RSM_rdio_disable_rx (); /* disable reception IRQ */ 00142 return 0; 00143 #else 00144 return -1; 00145 #endif 00146 } 00147 00152 int RSM_init_tx () 00153 { 00154 #ifdef DUART_BASE 00155 clearRRXSEL (); /* disable receiver */ 00156 setRTXSEL (); /* enable transmitter */ 00157 RSM_rdio_disable_rx (); /* disable RX ISR */ 00158 // _RSM_enabled = 0; /* and redirect to rdio queue */ 00159 TTY_tty[1].char_process = NULL; /* disable char processor */ 00160 00161 return 0; 00162 #else 00163 return -1; 00164 #endif 00165 } 00166 00171 int RSM_deinittx () 00172 { 00173 #ifdef DUART_BASE 00174 RSM_rdio_flush (); 00175 clearRTXSEL (); /* disable transmitter */ 00176 return 0; 00177 #else 00178 return -1; 00179 #endif 00180 } 00181 00182 #ifdef RSM_DEBUG 00183 00188 void _RSM_doutchar (unsigned char c) 00189 { 00190 iTTY_outchar (c); 00191 } 00192 00197 void _RSM_douthex (unsigned char c) 00198 { 00199 char l; 00200 char h; 00201 00202 h = (c & 0xf0) >> 4; 00203 if (h < 10) { 00204 _RSM_doutchar ('0' + h); 00205 } else { 00206 _RSM_doutchar ('A' + h - 10); 00207 } 00208 l = (c & 0x0f); 00209 if (l < 10) { 00210 _RSM_doutchar ('0' + l); 00211 } else { 00212 _RSM_doutchar ('A' + l - 10); 00213 } 00214 } 00215 00216 #else 00217 void _RSM_doutchar (unsigned char c) 00218 { 00219 } 00220 void _RSM_douthex (unsigned char c) 00221 { 00222 } 00223 00224 #endif 00225 00226 #ifdef DUART_BASE 00227 00232 void RSM_process (unsigned char c) 00233 { /* this is called from the duart irq */ 00234 static unsigned char save; 00235 unsigned char cx; 00236 00237 _RSM_bytes++; // byte statistics 00238 00239 switch (_RSM_state) { 00240 case RSM_IDLE: 00241 if (c == RSM_SOH) { 00242 _RSM_state = RSM_INFRAME1; 00243 _RSM_count = 0; 00244 _RSM_checksum = 0; 00245 _RSM_doutchar ('X'); 00246 } 00247 break; 00248 00249 case RSM_INFRAME1: 00250 if ((c & 0xAA) != ((~((c << 1) | 0x55)) & 0xff)) { 00251 _RSM_state = RSM_IDLE; 00252 _RSM_uglycount = _RSM_count; 00253 _RSM_ugly++; 00254 _RSM_doutchar ('u'); 00255 break; 00256 } 00257 save = c; 00258 _RSM_state = RSM_INFRAME2; 00259 break; 00260 00261 case RSM_INFRAME2: 00262 if ((c & 0xAA) != ((~((c << 1) | 0x55)) & 0xff)) { 00263 _RSM_state = RSM_IDLE; 00264 _RSM_uglycount = _RSM_count; 00265 _RSM_ugly++; 00266 _RSM_doutchar ('U'); 00267 break; 00268 } 00269 cx = ((save & 0xAA) | (c & 0x55)); 00270 _RSM_writebuf[_RSM_count++] = cx; 00271 _RSM_checksum += cx; 00272 00273 if (_RSM_count >= RSM_FRAMELEN) { 00274 _RSM_state = RSM_CHECKSUM1; 00275 break; 00276 } 00277 _RSM_state = RSM_INFRAME1; 00278 break; 00279 00280 case RSM_CHECKSUM1: 00281 save = c; 00282 _RSM_state = RSM_CHECKSUM2; 00283 break; 00284 00285 case RSM_CHECKSUM2: 00286 if ( 00287 ((save & 0xAA) != ((~((save << 1) | 0x55)) & 0xff)) || 00288 ((c & 0xAA) != ((~((c << 1) | 0x55)) & 0xff)) 00289 ) { 00290 _RSM_state = RSM_IDLE; 00291 _RSM_uglycount = _RSM_count; 00292 _RSM_ugly++; 00293 _RSM_doutchar ('U'); 00294 _RSM_doutchar ('c'); 00295 break; 00296 } 00297 cx = ((save & 0xAA) | (c & 0x55)); 00298 if (cx == _RSM_checksum) { 00299 _RSM_doutchar ('G'); 00300 _RSM_douthex (cx); 00301 _RSM_doutchar ('\n'); 00302 RSM_good++; 00303 00304 // bufsave = RSM_getbuf; 00305 // RSM_getbuf = _RSM_writebuf; 00306 // _RSM_writebuf = bufsave; 00307 // RSM_new = 1; 00308 _RSM_writebuf = RSM_rxframe (_RSM_writebuf); 00309 if (_RSM_writebuf == NULL) { /* we did not get a new buffer, so we 00310 disable the reception */ 00311 RSM_rdio_disable_rx (); 00312 _RSM_doutchar ('N'); 00313 } 00314 } else { 00315 _RSM_bad++; 00316 _RSM_doutchar ('B'); 00317 _RSM_douthex (cx); 00318 _RSM_doutchar ('e'); 00319 _RSM_douthex (_RSM_checksum); 00320 _RSM_doutchar ('\n'); 00321 } 00322 _RSM_state = RSM_IDLE; 00323 } 00324 } 00325 00326 00327 // this implements a simple double buffer scheme. One gets written, the other 00328 // can be read 00329 #endif 00330 00331 00336 unsigned char *RSM_rxframe (unsigned char *rxframebuf) 00337 { 00338 unsigned char *bufsave; 00339 00340 bufsave = RSM_getbuf; 00341 RSM_getbuf = rxframebuf; // this is the pointer to the frame just received 00342 00343 RSM_new = 1; // new frame available 00344 00345 return (bufsave); // we return the previous getbuf 00346 00347 } 00348 00353 int RSM_getframe (unsigned char *buffer) 00354 { 00355 int i; 00356 00357 if (!RSM_new) 00358 return (-1); 00359 disable (); 00360 for (i = 0; i < RSM_FRAMELEN; i++) 00361 buffer[i] = RSM_getbuf[i]; 00362 RSM_new = 0; 00363 enable (); 00364 00365 return (0); 00366 00367 } 00368 00374 unsigned char *RSM_encode (unsigned char c) 00375 { 00376 static unsigned char buf[2]; 00377 00378 unsigned char t, hi, lo; 00379 00380 t = (c & 0xaa); 00381 hi = t | ((~(t >> 1)) & 0x55); 00382 t = (c & 0x55); 00383 lo = t | ((~(t << 1)) & 0xaa); 00384 *buf = hi; 00385 *(buf + 1) = lo; 00386 return buf; 00387 00388 } 00389 00395 void RSM_tty_rdioput_block (char c) 00396 { 00397 #ifdef DUART_BASE 00398 int i; 00399 i = 0; 00400 while (TTY_rdioput (c)) { 00401 i++; 00402 if (i > 1000) { 00403 //_RSM_doutchar('B'); 00404 } 00405 } 00406 #endif 00407 00408 } 00409 00414 int RSM_send_frame (unsigned char *buffer) 00415 { 00416 00417 unsigned char *buf; 00418 int i; 00419 unsigned char checksum; 00420 00421 00422 for (i = 1; i < RSM_PREHEADER; i++); 00423 { 00424 RSM_tty_rdioput_block (0x00); 00425 RSM_tty_rdioput_block (0xff); 00426 } 00427 00428 checksum = 0; 00429 00430 RSM_tty_rdioput_block (RSM_SOH); 00431 00432 for (i = 0; i < RSM_FRAMELEN; i++) { 00433 buf = RSM_encode (buffer[i]); 00434 RSM_tty_rdioput_block (buf[0]); 00435 RSM_tty_rdioput_block (buf[1]); 00436 checksum += buffer[i]; 00437 } 00438 00439 buf = RSM_encode (checksum); 00440 00441 RSM_tty_rdioput_block (buf[0]); 00442 RSM_tty_rdioput_block (buf[1]); 00443 return (0); 00444 00445 }