lnp-logical.c
Go to the documentation of this file.
1 
6 /*
7  * The contents of this file are subject to the Mozilla Public License
8  * Version 1.0 (the "License"); you may not use this file except in
9  * compliance with the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS"
13  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
14  * License for the specific language governing rights and limitations
15  * under the License.
16  *
17  * The Original Code is legOS code, released October 17, 1999.
18  *
19  * The Initial Developer of the Original Code is Markus L. Noga.
20  * Portions created by Markus L. Noga are Copyright (C) 1999
21  * Markus L. Noga. All Rights Reserved.
22  *
23  * Contributor(s): Markus L. Noga <markus@noga.de>
24  * Chris Dearman <chris@algor.co.uk>
25  * Martin Cornelius <Martin.Cornelius@t-online.de>
26  */
27 
28 #include <sys/lnp-logical.h>
29 
30 #ifdef CONF_LNP
31 
32 #include <sys/lnp.h>
33 
34 #include <sys/h8.h>
35 #include <sys/irq.h>
36 
37 #ifdef CONF_AUTOSHUTOFF
38 #include <sys/timeout.h>
39 #endif
40 
41 #include <time.h>
42 #include <mem.h>
43 #include <semaphore.h>
44 #include <unistd.h>
45 
46 #include <rom/registers.h>
47 
49 //
50 // Variables
51 //
53 
54 static const unsigned char *tx_ptr;
55 static const unsigned char *tx_verify;
56 static const unsigned char *tx_end;
57 
58 volatile signed char tx_state;
59 
61 
66 static time_t allow_tx;
67 
68 #ifdef CONF_TM
69 static sem_t tx_sem;
70 #endif
71 
73 //
74 // Functions
75 //
77 
78 #ifdef CONF_RCX_COMPILER
79 static void rx_handler(void) __attribute__ ((rcx_interrupt));
80 static void rxerror_handler(void) __attribute__ ((rcx_interrupt));
81 static void tx_handler(void) __attribute__ ((rcx_interrupt));
82  void txend_handler(void) __attribute__ ((rcx_interrupt));
83 #else
84 void rx_handler(void);
85 void rxerror_handler(void);
86 void tx_handler(void);
87 void txend_handler(void);
88 #endif
89 
90 
92 extern inline void carrier_init(void) {
93  T1_CR =0x9;
94  T1_CSR =0x13;
95  T1_CORA=0x1a;
96 }
97 
99 extern inline void carrier_shutdown(void) {
100  T1_CR =0;
101  T1_CSR =0;
102 }
103 
105 //
106 #ifdef CONF_RCX_COMPILER
107 static void rx_handler(void) {
108 #else
109 HANDLER_WRAPPER("rx_handler","rx_core");
110 void rx_core(void) {
111 #endif
112  time_t new_tx;
114  if(tx_state<TX_ACTIVE) {
115  // foreign bytes
116  //
118  if (new_tx > allow_tx) allow_tx = new_tx;
120  } else {
121  // echos of own bytes -> collision detection
122  //
123  if(S_RDR!=*tx_verify) {
124  txend_handler();
126  } else if( tx_end <= ++tx_verify ) {
127  // let transmission end handler handle things
128  //
130  }
131  }
132 
133  // suppress volatile modifier to generate bit instruction.
134  //
135  *((char*) &S_SR) &=~SSR_RECV_FULL;
136 }
137 
139 //
140 #ifdef CONF_RCX_COMPILER
141 static void rxerror_handler(void) {
142 #else
143 HANDLER_WRAPPER("rxerror_handler","rxerror_core");
144 void rxerror_core(void) {
145 #endif
146  time_t new_tx;
147  if(tx_state<TX_ACTIVE) {
150  if (new_tx > allow_tx) allow_tx = new_tx;
151  } else {
152  txend_handler();
154  }
155 
156  S_SR&=~SSR_ERRORS;
157 }
158 
160 //
161 #ifdef CONF_RCX_COMPILER
162 void txend_handler(void) {
163 #else
164 HANDLER_WRAPPER("txend_handler","txend_core");
165 void txend_core(void) {
166 #endif
167  // shutdown transmit and irqs, clear status flags
168  //
171 }
172 
174 
176 #ifdef CONF_RCX_COMPILER
177 static void tx_handler(void) {
178 #else
179 HANDLER_WRAPPER("tx_handler","tx_core");
180 void tx_core(void) {
181 #endif
182  if(tx_ptr<tx_end) {
183  // transmit next byte
184  //
185  S_TDR = *(tx_ptr++);
186  *((char*) &S_SR)&=~SSR_TRANS_EMPTY;
187  } else {
188  // disable transmission interrupt
189  //
190  S_CR&=~SCR_TX_IRQ;
191  }
192 }
193 
195 void lnp_logical_shutdown(void) {
196  S_CR =0; // everything off
197  carrier_shutdown();
199 
201  allow_tx=0;
202 
203 #ifdef CONF_TM
204  sem_destroy(&tx_sem);
205 #endif
206 }
207 
209 
211 void lnp_logical_init(void) {
212  // safe initial state.
213  //
215 
216 #ifdef CONF_TM
217  sem_init(&tx_sem,0,1);
218 #endif
219 
220  // serial setup according to CONF_LNP_FAST / lnp_logical.h
221  // was 8N1 fixed, now parity is also set.
222  //
225  S_SR =0;
226 
227  // carrier setup
228  //
229  rom_port4_ddr |= 1; // port 4 bit 0 output
231  carrier_init();
232  rom_port5_ddr = 4; // init p5ddr, for now
234 
235  // IRQ handler setup
236  //
237  eri_vector=&rxerror_handler;
238  rxi_vector=&rx_handler;
239  txi_vector=&tx_handler;
241 
242  // enable receiver and IRQs
243  //
245 }
246 
247 
248 static wakeup_t write_allow(wakeup_t data) {
249  return get_system_up_time() >= *((volatile time_t*)&allow_tx);
250 }
251 
252 static wakeup_t write_complete(wakeup_t data) {
253  return *((volatile signed char*)&tx_state)<TX_ACTIVE;
254 }
255 
257 
261 int lnp_logical_write(const void* buf,size_t len) {
262  unsigned char tmp;
263 
264 #ifdef CONF_TM
265  if (sem_wait(&tx_sem) == -1)
266  return tx_state;
267 #endif
268 
269 #ifdef CONF_AUTOSHUTOFF
270  shutoff_restart();
271 #endif
272 
273  if (wait_event(write_allow,0) != 0)
274  {
276 
277  tx_verify=tx_ptr=buf; // what to transmit
278  tx_end=buf+len;
279 
281  S_SR&=~(SSR_TRANS_EMPTY | SSR_TRANS_END); // clear flags
282  S_CR|=SCR_TRANSMIT | SCR_TX_IRQ | SCR_TE_IRQ; // enable transmit & irqs
283 
284  wait_event(write_complete,0);
285 
286  // determine delay before next transmission
287  //
288  if(tx_state==TX_IDLE)
289  tmp=LNP_WAIT_TXOK;
290  else
291  tmp=LNP_WAIT_COLL + ( ((unsigned char) 0x0f) &
292  ( ((unsigned char) len)+
293  ((unsigned char*)buf)[len-1]+
294  ((unsigned char) get_system_up_time()) ) );
295  allow_tx=get_system_up_time()+tmp;
296  }
297 
298 #ifdef CONF_TM
299  sem_post(&tx_sem);
300 #endif
301 
302  return tx_state;
303 }
304 
305 #endif // CONF_LNP
volatile unsigned char S_SR
serial status register
void lnp_timeout_reset(void)
reset the inter-byte timeout counter.
#define SSR_TRANS_EMPTY
Definition: h8.h:248
Internal Interface: H8/3297 processor registers.
Interface: memory data types.
void shutoff_restart(void)
void * tei_vector
TEI interrupt vector.
unsigned char T1_CORA
timer 1 constant A register
volatile unsigned char S_RDR
serial receive data register
ROM Interface: RCX registers cached by ROM functions.
Internal Interface: Powerdown Timer Routines.
int sem_wait(sem_t *sem)
Wait for semaphore (blocking)
int sem_destroy(sem_t *sem)
We're done with the semaphore, destroy it.
Definition: semaphore.h:147
unsigned char PORT5_DDR
port 5 data direction register
Internal LNP Interface: link networking protocol logical layer.
time_t get_system_up_time(void)
retrieve the current system time
unsigned char S_BRR
serial baud rate register
void * txi_vector
TXI interrupt vector.
#define SCR_RECEIVE
Definition: h8.h:240
#define SSR_RECV_FULL
Definition: h8.h:249
void lnp_integrity_byte(unsigned char b)
receive a byte from the physical layer, decoding integrity layer packets.
unsigned char PORT4_DDR
port 4 data direction register
volatile unsigned char T1_CSR
timer 1 control / status register
#define LNP_LOGICAL_PARITY
parity
Definition: lnp-logical.h:55
atomic_t sem_t
the semaphore data-type
Definition: semaphore.h:46
void * rxi_vector
RXI interrupt vector.
void lnp_logical_init(void)
Initialize the logical layer (IR port)
Interface: reduced UNIX standard library.
void txend_handler(void)
Callback: end of transmission.
unsigned char rom_port5_ddr
ROM shadow of port 5 DDR.
#define SCR_TX_IRQ
Definition: h8.h:237
HANDLER_WRAPPER("lcd_refresh_next_byte","lcd_refresh_next_byte_core")
lcd refresh handler, called from system timer interrupt
unsigned char rom_port4_ddr
ROM shadow of port 4 DDR.
#define SCR_TE_IRQ
Definition: h8.h:242
unsigned char S_MR
serial mode register
unsigned long wakeup_t
wakeup data area type
Definition: tm.h:57
#define SCR_TRANSMIT
Definition: h8.h:239
#define LNP_WAIT_COLL
delay after collision
Definition: lnp-logical.h:63
void lnp_logical_range(int far)
Set the IR transmitter range.
Definition: lnp-logical.h:62
Interface: POSIX 1003.1b semaphores for task synchronization.
unsigned char T1_CR
timer 1 control register
unsigned long time_t
time type
Definition: time.h:50
volatile signed char tx_state
transmit status
#define SSR_TRANS_END
Definition: h8.h:254
#define TX_COLL
not transmitting, last xmit was collision
Definition: lnp-logical.h:66
int sem_post(sem_t *sem)
Post a semaphore.
Definition: semaphore.h:123
void lnp_logical_shutdown(void)
Shutdown the logical layer (IR port)
#define LNP_LOGICAL_BAUD_RATE
baud rate
Definition: lnp-logical.h:54
Internal LNP Interface: RCX redirected IRQ vectors.
#define TX_IDLE
not transmitting, last xmit OK
Definition: lnp-logical.h:67
#define LNP_WAIT_TXOK
delay after good transmit
Definition: lnp-logical.h:62
void * eri_vector
ERI interrupt vector.
unsigned char S_TDR
serial transmit data register
#define LNP_BYTE_SAFE
delay before transmitting a byte
Definition: lnp-logical.h:60
Internal LNP Interface: link networking protocol.
int lnp_logical_write(const void *buf, size_t len)
Write buffer to IR port.
wakeup_t wait_event(wakeup_t(*wakeup)(wakeup_t), wakeup_t data)
#define TX_ACTIVE
currently transmitting
Definition: lnp-logical.h:68
#define SSR_ERRORS
Definition: h8.h:253
void lnp_integrity_reset(void)
reset the integrity layer on error or timeout.
unsigned char S_CR
serial control register
int sem_init(sem_t *sem, int pshared, unsigned int value)
Initialize a semaphore.
Definition: semaphore.h:64
#define SCR_RX_IRQ
Definition: h8.h:238

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

Generated for brickOS Kernel Developer by doxygen 1.8.9.1