rllib  1
rl3964r.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  rl3964r.cpp - description
3  -------------------
4  begin : Wed Jan 14 2004
5  copyright : (C) 2004 by R. Lehrig
6  email : lehrig@t-online.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This library is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as *
13  * published by the Free Software Foundation *
14  * *
15  ***************************************************************************/
16 #include <stdio.h>
17 #include <stdarg.h>
18 #include <string.h>
19 #include "rlcutil.h"
20 #include "rl3964r.h"
21 #define STX 2
22 #define ETX 3
23 #define ENQ 5
24 #define EOT 4
25 #define ETB 23
26 #define DLE 16
27 #define NAK 21
28 #define ACK 6
29 
30 enum State
31 {
32  IDLE = 0,
33  SENDING = 1,
34  RECEIVING = 2,
37 };
38 
39 static const char *statestr[] = {"idle","sending","receiving","want_to_send","want_to_receive"};
40 
41 static void *receiverThread(void *arg)
42 {
43  THREAD_PARAM *p = (THREAD_PARAM *) arg;
44  rl3964R *d = (rl3964R *) p->user;
45  unsigned char c;
46  int ret,send_retry;
47 
48  send_retry = 0;
49  while(d->run)
50  {
51  c = 0x0ff;
52  ret = d->tty.select(1000);
53  if(ret == 1) c = d->tty.readChar();
54  p->thread->lock();
55 
56  d->dprintf("receiverThread: c=%d state=%s\n",c,statestr[d->state]);
57  if(c==STX && d->state==IDLE)
58  {
59  d->dprintf("STX IDLE\n");
60  d->state = RECEIVING;
61  d->dprintf("write DLE\n");
62  d->tty.writeChar(DLE);
63  d->dprintf("call receive\n");
64  d->receive();
65  d->dprintf("after receive\n");
66  d->state = IDLE;
67  }
68  else if(c==STX && d->state==WANT_TO_SEND && d->priority==rl3964R::lowPriority)
69  {
70  d->dprintf("receiverThread: STX WANT_TO_SEND lowPriority\n");
71  d->state = RECEIVING;
72  d->tty.writeChar(DLE);
73  d->receive();
74  d->state = WANT_TO_SEND;
75  }
76  else if(c==STX && d->state==WANT_TO_SEND && d->priority==rl3964R::highPriority)
77  {
78  d->dprintf("receiverThread: STX WANT_TO_SEND highPriority\n");
79  d->tty.writeChar(NAK);
80  d->tty.writeChar(STX);
81  }
82  else if(c==DLE && d->state==WANT_TO_SEND)
83  {
84  d->dprintf("receiverThread: DLE WANT_TO_SEND\n");
85  d->send();
86  d->state = IDLE;
88  }
89  else if(c==NAK)
90  {
91  d->dprintf("receiverThread: NAK\n");
92  }
93  else if(d->state==WANT_TO_SEND)
94  {
95  if(send_retry < 1)
96  {
97  }
98  else if(send_retry < 3)
99  {
100  d->tty.writeChar(STX);
101  send_retry++;
102  d->dprintf("receiverThread: WANT_TO_SEND send=STX retry=%d\n",send_retry+1);
103  }
104  else
105  {
106  send_retry = 0;
107  d->dprintf("receiverThread: WANT_TO_SEND failed after 3 retries\n");
108  d->state = IDLE;
110  }
111  }
112  else
113  {
114  d->dprintf("receiverThread: IDLE\n");
115  d->state = IDLE;
116  }
117 
118  p->thread->unlock();
119  }
120 
121  return NULL;
122 }
123 
124 rl3964R::rl3964R(int _priority)
125 {
126  priority = _priority;
127  readCallback = NULL;
128  debug = 0;
129  isOpen = 0;
130  state = IDLE;
131  send_result = 0;
133 }
134 
136 {
137  close();
138 }
139 
140 int rl3964R::open(const char *devicename, int _baudrate)
141 {
142  int ret;
143 
144  if(isOpen == 0)
145  {
146  //int openDevice(const char *devicename, int speed=B9600, int block=1, int rtscts=1, int bits=8, int stopbits=1, int parity=NONE);
147  ret = tty.openDevice(devicename,_baudrate,1,0,8,1,rlSerial::EVEN);
148  if(ret >= 0)
149  {
150  isOpen = 1;
151  run = 1;
153  }
154  return ret;
155  }
156  return -1;
157 }
158 
160 {
161  if(isOpen == 1)
162  {
163  isOpen = 0;
164  run = 0;
165  dprintf("close(): cancel\n");
166  receiver.cancel();
167  dprintf("close(): closeDevice\n");
168  tty.closeDevice();
169  dprintf("close(): return\n");
170  return 0;
171  }
172  isOpen = 0;
173  return -1;
174 }
175 
176 int rl3964R::setReadCallback( void (*_readCallback)(const unsigned char *buf, int len))
177 {
178  readCallback = _readCallback;
179  return 0;
180 }
181 
182 int rl3964R::write(const unsigned char *buf, int len)
183 {
184  dprintf("write() len=%d\n",len);
185  if(len >= (int) sizeof(tel_send)) return -1;
186  receiver.lock();
187  tel_send_length = len;
188  memcpy(tel_send,buf,len);
190  dprintf("write() STX\n");
191  tty.writeChar(STX);
192  dprintf("write() unlock\n");
193  receiver.unlock();
194  dprintf("write() waitSemaphore\n");
196  dprintf("write() return len=%d\n",len);
197  if(send_result < 0) return -1;
198  return len;
199 }
200 
202 {
203  int i,bcc,c,ret;
204 
205  dprintf("send()");
206  //bcc = STX;
207  bcc = 0;
208  for(i=0; i<tel_send_length; i++)
209  {
210  switch(tel_send[i])
211  {
212  case DLE:
213  tty.writeChar(DLE);
214  tty.writeChar(DLE);
215  bcc = bcc ^ DLE;
216  bcc = bcc ^ DLE;
217  break;
218  default:
219  tty.writeChar(tel_send[i]);
220  bcc = bcc ^ tel_send[i];
221  break;
222  }
223  }
224  tty.writeChar(DLE);
225  bcc = bcc ^ DLE;
226  tty.writeChar(ETX);
227  bcc = bcc ^ ETX;
228  tty.writeChar(bcc);
229  ret = tty.select(1000);
230  if(ret == 1) c = tty.readChar();
231  else
232  {
233  send_result = -1;
234  dprintf("send(): partner was sending nothing\n");
235  return -1;
236  }
237  if(c == DLE)
238  {
239  send_result = 0;
240  dprintf(" success\n");
241  return tel_send_length;
242  }
243  send_result = -1;
244  dprintf(" failure\n");
245  return -1;
246 }
247 
249 {
250  int i,c,c2,bcc,received_bcc,ret;
251 
252  dprintf("receive()\n");
253  //bcc = STX;
254  bcc = 0;
255  i = received_bcc = 0;
256  tel_receive[i++] = c = STX;
257  while(c > 0 && i < (int) sizeof(tel_receive))
258  {
259  ret = tty.select(1000);
260  if(ret == 1) c = tty.readChar();
261  else
262  {
263  dprintf("receive(): partner was sending nothing\n");
264  return -1;
265  }
266  dprintf(" %x\n",c);
267  switch(c)
268  {
269  case -1:
270  case -2:
271  return -1;
272  case DLE:
273  bcc = bcc ^ c;
274  c2 = tty.readChar();
275  dprintf(" %x\n",c2);
276  bcc = bcc ^ c2;
277  if(c2 < 0) return -1;
278  tel_receive[i++] = c2;
279  if(c2 == ETX)
280  {
281  c2 = tty.readChar();
282  dprintf(" %x\n",c2);
283  if(c2 < 0) return -1;
284  tel_receive[i++] = c2; // bcc
285  received_bcc = c2;
286  dprintf(" bcc=%d received_bcc=%d\n",bcc,received_bcc);
287  c = -1;
288  }
289  break;
290  default:
291  bcc = bcc ^ c;
292  tel_receive[i++] = c;
293  break;
294  }
295  }
296  tel_receive_length = i;
297 
298  if(bcc == received_bcc)
299  {
300  tty.writeChar(DLE);
301  dprintf(" success\n");
303  return tel_receive_length-3;
304  }
305  tty.writeChar(NAK);
306  dprintf(" failure\n");
307  return -1;
308 }
309 
310 int rl3964R::dprintf(const char *format, ...)
311 {
312  char message[rl_PRINTF_LENGTH]; // should be big enough
313  int ret;
314 
315  if(debug != 1) return 0;
316  va_list ap;
317  va_start(ap,format);
318  ret = rlvsnprintf(message, rl_PRINTF_LENGTH - 1, format, ap);
319  va_end(ap);
320  printf("%s",message);
321  return ret;
322 }
323 
static const char * statestr[]
Definition: rl3964r.cpp:39
int receive()
Definition: rl3964r.cpp:248
int closeDevice()
Definition: rlserial.cpp:763
rl3964R(int _priority=highPriority)
Definition: rl3964r.cpp:124
int cancel()
Definition: rlthread.cpp:78
void * user
Definition: rlthread.h:30
int send()
Definition: rl3964r.cpp:201
rlThread * thread
Definition: rlthread.h:29
virtual ~rl3964R()
Definition: rl3964r.cpp:135
int waitSemaphore()
Definition: rlthread.cpp:57
int unlock()
Definition: rlthread.cpp:52
#define ETX
Definition: rl3964r.cpp:22
rlSerial tty
Definition: rl3964r.h:46
int write(const unsigned char *buf, int len)
Definition: rl3964r.cpp:182
#define STX
Definition: rl3964r.cpp:21
int create(void *(*func)(void *), void *argument)
Definition: rlthread.cpp:35
int setReadCallback(void(*_readCallback)(const unsigned char *buf, int len))
Definition: rl3964r.cpp:176
#define rl_PRINTF_LENGTH
Definition: rldefine.h:71
Definition: rl3964r.cpp:32
rlThread receiver
Definition: rl3964r.h:45
int writeChar(unsigned char uchar)
Definition: rlserial.cpp:454
#define DLE
Definition: rl3964r.cpp:26
int select(int timeout=500)
Definition: rlserial.cpp:719
int rlvsnprintf(char *text, int len, const char *format, va_list ap)
Definition: rlcutil.cpp:197
int close()
Definition: rl3964r.cpp:159
int send_result
Definition: rl3964r.h:59
int dprintf(const char *format,...)
Definition: rl3964r.cpp:310
unsigned char tel_send[512]
Definition: rl3964r.h:54
int openDevice(const char *devicename, int speed=B9600, int block=1, int rtscts=1, int bits=8, int stopbits=1, int parity=rlSerial::NONE)
Definition: rlserial.cpp:100
int run
Definition: rl3964r.h:49
int readChar()
Definition: rlserial.cpp:405
#define NAK
Definition: rl3964r.cpp:27
int isOpen
Definition: rl3964r.h:58
int incrementSemaphore()
Definition: rlthread.cpp:62
int open(const char *devicename, int _baudrate=B9600)
Definition: rl3964r.cpp:140
int state
Definition: rl3964r.h:47
State
Definition: rl3964r.cpp:30
int tel_receive_length
Definition: rl3964r.h:57
int priority
Definition: rl3964r.h:48
static void * receiverThread(void *arg)
Definition: rl3964r.cpp:41
int debug
Definition: rl3964r.h:50
unsigned char tel_receive[512]
Definition: rl3964r.h:55
int tel_send_length
Definition: rl3964r.h:56
int lock()
Definition: rlthread.cpp:47
void(* readCallback)(const unsigned char *buf, int len)
Definition: rl3964r.h:53