Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members | Related Pages

kernel/lnp-logical.c

Go to the documentation of this file.
00001 
00006 /*
00007  *  The contents of this file are subject to the Mozilla Public License
00008  *  Version 1.0 (the "License"); you may not use this file except in
00009  *  compliance with the License. You may obtain a copy of the License at
00010  *  http://www.mozilla.org/MPL/
00011  *
00012  *  Software distributed under the License is distributed on an "AS IS"
00013  *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
00014  *  License for the specific language governing rights and limitations
00015  *  under the License.
00016  *
00017  *  The Original Code is legOS code, released October 17, 1999.
00018  *
00019  *  The Initial Developer of the Original Code is Markus L. Noga.
00020  *  Portions created by Markus L. Noga are Copyright (C) 1999
00021  *  Markus L. Noga. All Rights Reserved.
00022  *
00023  *  Contributor(s): Markus L. Noga <markus@noga.de>
00024  *                  Chris Dearman <chris@algor.co.uk>
00025  *                  Martin Cornelius <Martin.Cornelius@t-online.de>
00026  */
00027 
00028 #include <sys/lnp-logical.h>
00029 
00030 #ifdef CONF_LNP
00031 
00032 #include <sys/lnp.h>
00033 
00034 #include <sys/h8.h>
00035 #include <sys/irq.h>
00036 
00037 #ifdef CONF_AUTOSHUTOFF
00038 #include <sys/timeout.h>
00039 #endif
00040 
00041 #include <time.h>
00042 #include <mem.h>
00043 #include <semaphore.h>
00044 #include <unistd.h>
00045 
00046 #include <rom/registers.h>
00047 
00049 //
00050 // Variables
00051 //
00053 
00054 static const unsigned char *tx_ptr; 
00055 static const unsigned char *tx_verify;  
00056 static const unsigned char *tx_end; 
00057 
00058 volatile signed char tx_state;    
00059 
00061 
00066 static time_t allow_tx;                 
00067 
00068 #ifdef CONF_TM
00069 static sem_t tx_sem;                
00070 #endif
00071 
00073 //
00074 // Functions
00075 //
00077 
00078 #ifdef CONF_RCX_COMPILER
00079 static void rx_handler(void) __attribute__ ((rcx_interrupt));
00080 static void rxerror_handler(void) __attribute__ ((rcx_interrupt));
00081 static void tx_handler(void) __attribute__ ((rcx_interrupt));
00082        void txend_handler(void) __attribute__ ((rcx_interrupt));
00083 #else
00084 void rx_handler(void);
00085 void rxerror_handler(void);
00086 void tx_handler(void);
00087 void txend_handler(void);
00088 #endif
00089 
00090 
00092 extern inline void carrier_init(void) {
00093   T1_CR  =0x9;
00094   T1_CSR =0x13;
00095   T1_CORA=0x1a;
00096 }
00097 
00099 extern inline void carrier_shutdown(void) {
00100   T1_CR  =0;
00101   T1_CSR =0;
00102 }
00103 
00105 //
00106 #ifdef CONF_RCX_COMPILER
00107 static void rx_handler(void) {
00108 #else
00109 HANDLER_WRAPPER("rx_handler","rx_core");
00110 void rx_core(void) {
00111 #endif
00112   time_t new_tx;
00113   lnp_timeout_reset();
00114   if(tx_state<TX_ACTIVE) {
00115     // foreign bytes
00116     //
00117     new_tx = get_system_up_time()+LNP_BYTE_SAFE;
00118     if (new_tx > allow_tx) allow_tx = new_tx;
00119     lnp_integrity_byte(S_RDR);
00120   } else {
00121     // echos of own bytes -> collision detection
00122     //
00123     if(S_RDR!=*tx_verify) {
00124       txend_handler();
00125       tx_state=TX_COLL;
00126     } else if( tx_end <= ++tx_verify ) {
00127       // let transmission end handler handle things
00128       //
00129       tx_state=TX_IDLE;
00130     }
00131   }
00132 
00133   // suppress volatile modifier to generate bit instruction.
00134   //
00135   *((char*) &S_SR) &=~SSR_RECV_FULL;
00136 }
00137 
00139 //
00140 #ifdef CONF_RCX_COMPILER
00141 static void rxerror_handler(void) {
00142 #else
00143 HANDLER_WRAPPER("rxerror_handler","rxerror_core");
00144 void rxerror_core(void) {
00145 #endif
00146   time_t new_tx;
00147   if(tx_state<TX_ACTIVE) {
00148     lnp_integrity_reset();
00149     new_tx = get_system_up_time()+LNP_BYTE_SAFE;
00150     if (new_tx > allow_tx) allow_tx = new_tx;
00151   } else {
00152     txend_handler();
00153     tx_state=TX_COLL;
00154   }
00155 
00156   S_SR&=~SSR_ERRORS;
00157 }
00158 
00160 //
00161 #ifdef CONF_RCX_COMPILER
00162 void txend_handler(void) {
00163 #else
00164 HANDLER_WRAPPER("txend_handler","txend_core");
00165 void txend_core(void) {
00166 #endif
00167   // shutdown transmit and irqs, clear status flags
00168   //
00169   S_CR&=~(SCR_TX_IRQ | SCR_TRANSMIT | SCR_TE_IRQ);
00170   S_SR&=~(SSR_TRANS_EMPTY | SSR_TRANS_END);
00171 }
00172 
00174 
00176 #ifdef CONF_RCX_COMPILER
00177 static void tx_handler(void) {
00178 #else
00179 HANDLER_WRAPPER("tx_handler","tx_core");
00180 void tx_core(void) {
00181 #endif
00182   if(tx_ptr<tx_end) {
00183     // transmit next byte
00184     //
00185     S_TDR = *(tx_ptr++);
00186     *((char*) &S_SR)&=~SSR_TRANS_EMPTY;
00187   } else {
00188     // disable transmission interrupt
00189     //
00190     S_CR&=~SCR_TX_IRQ;
00191   }
00192 }
00193 
00195 void lnp_logical_shutdown(void) {
00196   S_CR =0;        // everything off
00197   carrier_shutdown();
00198   lnp_logical_range(0);
00199 
00200   tx_state=TX_IDLE;
00201   allow_tx=0;
00202 
00203 #ifdef CONF_TM
00204   sem_destroy(&tx_sem);
00205 #endif
00206 }
00207 
00209 
00211 void lnp_logical_init(void) {
00212   // safe initial state.
00213   //
00214   lnp_logical_shutdown();
00215 
00216 #ifdef CONF_TM
00217   sem_init(&tx_sem,0,1);
00218 #endif
00219 
00220   // serial setup according to CONF_LNP_FAST / lnp_logical.h
00221   // was 8N1 fixed, now parity is also set.
00222   //
00223   S_MR =LNP_LOGICAL_PARITY;
00224   S_BRR=LNP_LOGICAL_BAUD_RATE;
00225   S_SR =0;
00226 
00227   // carrier setup
00228   //
00229   rom_port4_ddr |= 1;     // port 4 bit 0 output
00230   PORT4_DDR = rom_port4_ddr;
00231   carrier_init();
00232   rom_port5_ddr = 4;      // init p5ddr, for now
00233   PORT5_DDR = rom_port5_ddr;
00234 
00235   // IRQ handler setup
00236   //
00237   eri_vector=&rxerror_handler;
00238   rxi_vector=&rx_handler;
00239   txi_vector=&tx_handler;
00240   tei_vector=&txend_handler;
00241 
00242   // enable receiver and IRQs
00243   //
00244   S_CR=SCR_RECEIVE | SCR_RX_IRQ;
00245 }
00246 
00247 
00248 static wakeup_t write_allow(wakeup_t data) {
00249   return get_system_up_time() >= *((volatile time_t*)&allow_tx);
00250 }
00251 
00252 static wakeup_t write_complete(wakeup_t data) {
00253   return *((volatile signed char*)&tx_state)<TX_ACTIVE;
00254 }
00255 
00257 
00261 int lnp_logical_write(const void* buf,size_t len) {
00262   unsigned char tmp;
00263 
00264 #ifdef CONF_TM
00265   if (sem_wait(&tx_sem) == -1)
00266         return tx_state;
00267 #endif
00268 
00269 #ifdef CONF_AUTOSHUTOFF
00270   shutoff_restart();
00271 #endif
00272 
00273         if (wait_event(write_allow,0) != 0)
00274         {
00275           lnp_timeout_reset();
00276 
00277         tx_verify=tx_ptr=buf;                 // what to transmit
00278           tx_end=buf+len;
00279 
00280           tx_state=TX_ACTIVE;
00281           S_SR&=~(SSR_TRANS_EMPTY | SSR_TRANS_END); // clear flags
00282           S_CR|=SCR_TRANSMIT | SCR_TX_IRQ | SCR_TE_IRQ; // enable transmit & irqs
00283 
00284           wait_event(write_complete,0);
00285 
00286           // determine delay before next transmission
00287           //
00288           if(tx_state==TX_IDLE)
00289             tmp=LNP_WAIT_TXOK;
00290           else
00291             tmp=LNP_WAIT_COLL + ( ((unsigned char) 0x0f) &
00292                 ( ((unsigned char) len)+
00293                   ((unsigned char*)buf)[len-1]+
00294                   ((unsigned char) get_system_up_time())    ) );
00295           allow_tx=get_system_up_time()+tmp;
00296         }
00297 
00298 #ifdef CONF_TM
00299   sem_post(&tx_sem);
00300 #endif
00301 
00302   return tx_state;
00303 }
00304 
00305 #endif  // CONF_LNP

brickOS is released under the Mozilla Public License.
Original code copyright 1998-2002 by the authors.

Generated on Mon Feb 16 21:02:10 2004 for brickOS Kernel Developer by doxygen 1.3.5