/*! \file lnp-logical.c \brief Implementation: link networking protocol logical layer \author Markus L. Noga */ /* * The contents of this file are subject to the Mozilla Public License * Version 1.0 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * * The Original Code is legOS code, released October 17, 1999. * * The Initial Developer of the Original Code is Markus L. Noga. * Portions created by Markus L. Noga are Copyright (C) 1999 * Markus L. Noga. All Rights Reserved. * * Contributor(s): Markus L. Noga * Chris Dearman * Martin Cornelius */ #include #ifdef CONF_LNP #include #include #include #ifdef CONF_AUTOSHUTOFF #include #endif #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// // // Variables // /////////////////////////////////////////////////////////////////////////////// static const unsigned char *tx_ptr; //!< ptr to next byte to transmit static const unsigned char *tx_verify; //!< ptr to next byte to verify static const unsigned char *tx_end; //!< ptr to byte after last volatile signed char tx_state; //!< flag: transmission state //! when to allow next transmission /*! transmit OK -> wait some time to grant others bus access collision -> wait some more, plus "random" amount. receive -> reset timeout to default value. */ static time_t allow_tx; //!< time to allow new transmission #ifdef CONF_TM static sem_t tx_sem; //!< transmitter access semaphore #endif /////////////////////////////////////////////////////////////////////////////// // // Functions // /////////////////////////////////////////////////////////////////////////////// #ifdef CONF_RCX_COMPILER static void rx_handler(void) __attribute__ ((rcx_interrupt)); static void rxerror_handler(void) __attribute__ ((rcx_interrupt)); static void tx_handler(void) __attribute__ ((rcx_interrupt)); void txend_handler(void) __attribute__ ((rcx_interrupt)); #else void rx_handler(void); void rxerror_handler(void); void tx_handler(void); void txend_handler(void); #endif //! enable IR carrier frequency. extern inline void carrier_init(void) { T1_CR =0x9; T1_CSR =0x13; T1_CORA=0x1a; } //! disable IR carrier frequency. extern inline void carrier_shutdown(void) { T1_CR =0; T1_CSR =0; } //! the byte received interrupt handler // #ifdef CONF_RCX_COMPILER static void rx_handler(void) { #else HANDLER_WRAPPER("rx_handler","rx_core"); void rx_core(void) { #endif time_t new_tx; lnp_timeout_reset(); if(tx_state allow_tx) allow_tx = new_tx; lnp_integrity_byte(S_RDR); } else { // echos of own bytes -> collision detection // if(S_RDR!=*tx_verify) { txend_handler(); tx_state=TX_COLL; } else if( tx_end <= ++tx_verify ) { // let transmission end handler handle things // tx_state=TX_IDLE; } } // suppress volatile modifier to generate bit instruction. // *((char*) &S_SR) &=~SSR_RECV_FULL; } //! the receive error interrupt handler // #ifdef CONF_RCX_COMPILER static void rxerror_handler(void) { #else HANDLER_WRAPPER("rxerror_handler","rxerror_core"); void rxerror_core(void) { #endif time_t new_tx; if(tx_state allow_tx) allow_tx = new_tx; } else { txend_handler(); tx_state=TX_COLL; } S_SR&=~SSR_ERRORS; } //! the end-of-transmission interrupt handler // #ifdef CONF_RCX_COMPILER void txend_handler(void) { #else HANDLER_WRAPPER("txend_handler","txend_core"); void txend_core(void) { #endif // shutdown transmit and irqs, clear status flags // S_CR&=~(SCR_TX_IRQ | SCR_TRANSMIT | SCR_TE_IRQ); S_SR&=~(SSR_TRANS_EMPTY | SSR_TRANS_END); } //! the transmit byte interrupt handler /*! write next byte if there's one left, otherwise unhook irq. */ #ifdef CONF_RCX_COMPILER static void tx_handler(void) { #else HANDLER_WRAPPER("tx_handler","tx_core"); void tx_core(void) { #endif if(tx_ptr= *((volatile time_t*)&allow_tx); } static wakeup_t write_complete(wakeup_t data) { return *((volatile signed char*)&tx_state)