comparison spandsp-0.0.6pre17/src/async.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * async.c - Asynchronous serial bit stream encoding and decoding
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2003 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: async.c,v 1.19 2009/04/23 14:12:34 steveu Exp $
26 */
27
28 /*! \file */
29
30 #if defined(HAVE_CONFIG_H)
31 #include "config.h"
32 #endif
33
34 #include <inttypes.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <assert.h>
38
39 #include "spandsp/telephony.h"
40 #include "spandsp/async.h"
41
42 #include "spandsp/private/async.h"
43
44 SPAN_DECLARE(const char *) signal_status_to_str(int status)
45 {
46 switch (status)
47 {
48 case SIG_STATUS_CARRIER_DOWN:
49 return "Carrier down";
50 case SIG_STATUS_CARRIER_UP:
51 return "Carrier up";
52 case SIG_STATUS_TRAINING_IN_PROGRESS:
53 return "Training in progress";
54 case SIG_STATUS_TRAINING_SUCCEEDED:
55 return "Training succeeded";
56 case SIG_STATUS_TRAINING_FAILED:
57 return "Training failed";
58 case SIG_STATUS_FRAMING_OK:
59 return "Framing OK";
60 case SIG_STATUS_END_OF_DATA:
61 return "End of data";
62 case SIG_STATUS_ABORT:
63 return "Abort";
64 case SIG_STATUS_BREAK:
65 return "Break";
66 case SIG_STATUS_SHUTDOWN_COMPLETE:
67 return "Shutdown complete";
68 case SIG_STATUS_OCTET_REPORT:
69 return "Octet report";
70 case SIG_STATUS_POOR_SIGNAL_QUALITY:
71 return "Poor signal quality";
72 case SIG_STATUS_MODEM_RETRAIN_OCCURRED:
73 return "Modem retrain occurred";
74 }
75 return "???";
76 }
77 /*- End of function --------------------------------------------------------*/
78
79 SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s,
80 int data_bits,
81 int parity,
82 int stop_bits,
83 int use_v14,
84 put_byte_func_t put_byte,
85 void *user_data)
86 {
87 if (s == NULL)
88 {
89 if ((s = (async_rx_state_t *) malloc(sizeof(*s))) == NULL)
90 return NULL;
91 }
92 s->data_bits = data_bits;
93 s->parity = parity;
94 s->stop_bits = stop_bits;
95 s->use_v14 = use_v14;
96
97 s->put_byte = put_byte;
98 s->user_data = user_data;
99
100 s->byte_in_progress = 0;
101 s->bitpos = 0;
102 s->parity_bit = 0;
103
104 s->parity_errors = 0;
105 s->framing_errors = 0;
106 return s;
107 }
108 /*- End of function --------------------------------------------------------*/
109
110 SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s)
111 {
112 return 0;
113 }
114 /*- End of function --------------------------------------------------------*/
115
116 SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s)
117 {
118 free(s);
119 return 0;
120 }
121 /*- End of function --------------------------------------------------------*/
122
123 SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit)
124 {
125 async_rx_state_t *s;
126
127 s = (async_rx_state_t *) user_data;
128 if (bit < 0)
129 {
130 /* Special conditions */
131 switch (bit)
132 {
133 case SIG_STATUS_CARRIER_UP:
134 case SIG_STATUS_CARRIER_DOWN:
135 case SIG_STATUS_TRAINING_IN_PROGRESS:
136 case SIG_STATUS_TRAINING_SUCCEEDED:
137 case SIG_STATUS_TRAINING_FAILED:
138 case SIG_STATUS_END_OF_DATA:
139 s->put_byte(s->user_data, bit);
140 s->bitpos = 0;
141 s->byte_in_progress = 0;
142 break;
143 default:
144 //printf("Eh!\n");
145 break;
146 }
147 return;
148 }
149 if (s->bitpos == 0)
150 {
151 /* Search for the start bit */
152 s->bitpos += (bit ^ 1);
153 s->parity_bit = 0;
154 s->byte_in_progress = 0;
155 }
156 else if (s->bitpos <= s->data_bits)
157 {
158 s->byte_in_progress = (s->byte_in_progress >> 1) | (bit << 7);
159 s->parity_bit ^= bit;
160 s->bitpos++;
161 }
162 else if (s->parity && s->bitpos == s->data_bits + 1)
163 {
164 if (s->parity == ASYNC_PARITY_ODD)
165 s->parity_bit ^= 1;
166
167 if (s->parity_bit != bit)
168 s->parity_errors++;
169 s->bitpos++;
170 }
171 else
172 {
173 /* Stop bit */
174 if (bit == 1)
175 {
176 /* Align the received value */
177 if (s->data_bits < 8)
178 s->byte_in_progress >>= (8 - s->data_bits);
179 s->put_byte(s->user_data, s->byte_in_progress);
180 s->bitpos = 0;
181 }
182 else if (s->use_v14)
183 {
184 /* This is actually the start bit for the next character, and
185 the stop bit has been dropped from the stream. This is the
186 rate adaption specified in V.14 */
187 /* Align the received value */
188 if (s->data_bits < 8)
189 s->byte_in_progress >>= (8 - s->data_bits);
190 s->put_byte(s->user_data, s->byte_in_progress);
191 s->bitpos = 1;
192 s->parity_bit = 0;
193 s->byte_in_progress = 0;
194 }
195 else
196 {
197 s->framing_errors++;
198 s->bitpos = 0;
199 }
200 }
201 }
202 /*- End of function --------------------------------------------------------*/
203
204 SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s,
205 int data_bits,
206 int parity,
207 int stop_bits,
208 int use_v14,
209 get_byte_func_t get_byte,
210 void *user_data)
211 {
212 if (s == NULL)
213 {
214 if ((s = (async_tx_state_t *) malloc(sizeof(*s))) == NULL)
215 return NULL;
216 }
217 /* We have a use_v14 parameter for completeness, but right now V.14 only
218 applies to the receive side. We are unlikely to have an application where
219 flow control does not exist, so V.14 stuffing is not needed. */
220 s->data_bits = data_bits;
221 s->parity = parity;
222 s->stop_bits = stop_bits;
223 if (parity != ASYNC_PARITY_NONE)
224 s->stop_bits++;
225
226 s->get_byte = get_byte;
227 s->user_data = user_data;
228
229 s->byte_in_progress = 0;
230 s->bitpos = 0;
231 s->parity_bit = 0;
232 return s;
233 }
234 /*- End of function --------------------------------------------------------*/
235
236 SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s)
237 {
238 return 0;
239 }
240 /*- End of function --------------------------------------------------------*/
241
242 SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s)
243 {
244 free(s);
245 return 0;
246 }
247 /*- End of function --------------------------------------------------------*/
248
249 SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data)
250 {
251 async_tx_state_t *s;
252 int bit;
253
254 s = (async_tx_state_t *) user_data;
255 if (s->bitpos == 0)
256 {
257 if ((s->byte_in_progress = s->get_byte(s->user_data)) < 0)
258 {
259 /* No more data */
260 bit = SIG_STATUS_END_OF_DATA;
261 }
262 else
263 {
264 /* Start bit */
265 bit = 0;
266 s->parity_bit = 0;
267 s->bitpos++;
268 }
269 }
270 else if (s->bitpos <= s->data_bits)
271 {
272 bit = s->byte_in_progress & 1;
273 s->byte_in_progress >>= 1;
274 s->parity_bit ^= bit;
275 s->bitpos++;
276 }
277 else if (s->parity && s->bitpos == s->data_bits + 1)
278 {
279 if (s->parity == ASYNC_PARITY_ODD)
280 s->parity_bit ^= 1;
281 bit = s->parity_bit;
282 s->bitpos++;
283 }
284 else
285 {
286 /* Stop bit(s) */
287 bit = 1;
288 if (++s->bitpos > s->data_bits + s->stop_bits)
289 s->bitpos = 0;
290 }
291 return bit;
292 }
293 /*- End of function --------------------------------------------------------*/
294 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.