00001
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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
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
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
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
00122
00123 if(S_RDR!=*tx_verify) {
00124 txend_handler();
00125 tx_state=TX_COLL;
00126 } else if( tx_end <= ++tx_verify ) {
00127
00128
00129 tx_state=TX_IDLE;
00130 }
00131 }
00132
00133
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
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
00184
00185 S_TDR = *(tx_ptr++);
00186 *((char*) &S_SR)&=~SSR_TRANS_EMPTY;
00187 } else {
00188
00189
00190 S_CR&=~SCR_TX_IRQ;
00191 }
00192 }
00193
00195 void lnp_logical_shutdown(void) {
00196 S_CR =0;
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
00213
00214 lnp_logical_shutdown();
00215
00216 #ifdef CONF_TM
00217 sem_init(&tx_sem,0,1);
00218 #endif
00219
00220
00221
00222
00223 S_MR =LNP_LOGICAL_PARITY;
00224 S_BRR=LNP_LOGICAL_BAUD_RATE;
00225 S_SR =0;
00226
00227
00228
00229 rom_port4_ddr |= 1;
00230 PORT4_DDR = rom_port4_ddr;
00231 carrier_init();
00232 rom_port5_ddr = 4;
00233 PORT5_DDR = rom_port5_ddr;
00234
00235
00236
00237 eri_vector=&rxerror_handler;
00238 rxi_vector=&rx_handler;
00239 txi_vector=&tx_handler;
00240 tei_vector=&txend_handler;
00241
00242
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;
00278 tx_end=buf+len;
00279
00280 tx_state=TX_ACTIVE;
00281 S_SR&=~(SSR_TRANS_EMPTY | SSR_TRANS_END);
00282 S_CR|=SCR_TRANSMIT | SCR_TX_IRQ | SCR_TE_IRQ;
00283
00284 wait_event(write_complete,0);
00285
00286
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