Mercurial > hg > audiostuff
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spandsp-0.0.6pre17/src/async.c Fri Jun 25 15:50:58 2010 +0200 @@ -0,0 +1,294 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * async.c - Asynchronous serial bit stream encoding and decoding + * + * Written by Steve Underwood <steveu@coppice.org> + * + * Copyright (C) 2003 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: async.c,v 1.19 2009/04/23 14:12:34 steveu Exp $ + */ + +/*! \file */ + +#if defined(HAVE_CONFIG_H) +#include "config.h" +#endif + +#include <inttypes.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include "spandsp/telephony.h" +#include "spandsp/async.h" + +#include "spandsp/private/async.h" + +SPAN_DECLARE(const char *) signal_status_to_str(int status) +{ + switch (status) + { + case SIG_STATUS_CARRIER_DOWN: + return "Carrier down"; + case SIG_STATUS_CARRIER_UP: + return "Carrier up"; + case SIG_STATUS_TRAINING_IN_PROGRESS: + return "Training in progress"; + case SIG_STATUS_TRAINING_SUCCEEDED: + return "Training succeeded"; + case SIG_STATUS_TRAINING_FAILED: + return "Training failed"; + case SIG_STATUS_FRAMING_OK: + return "Framing OK"; + case SIG_STATUS_END_OF_DATA: + return "End of data"; + case SIG_STATUS_ABORT: + return "Abort"; + case SIG_STATUS_BREAK: + return "Break"; + case SIG_STATUS_SHUTDOWN_COMPLETE: + return "Shutdown complete"; + case SIG_STATUS_OCTET_REPORT: + return "Octet report"; + case SIG_STATUS_POOR_SIGNAL_QUALITY: + return "Poor signal quality"; + case SIG_STATUS_MODEM_RETRAIN_OCCURRED: + return "Modem retrain occurred"; + } + return "???"; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(async_rx_state_t *) async_rx_init(async_rx_state_t *s, + int data_bits, + int parity, + int stop_bits, + int use_v14, + put_byte_func_t put_byte, + void *user_data) +{ + if (s == NULL) + { + if ((s = (async_rx_state_t *) malloc(sizeof(*s))) == NULL) + return NULL; + } + s->data_bits = data_bits; + s->parity = parity; + s->stop_bits = stop_bits; + s->use_v14 = use_v14; + + s->put_byte = put_byte; + s->user_data = user_data; + + s->byte_in_progress = 0; + s->bitpos = 0; + s->parity_bit = 0; + + s->parity_errors = 0; + s->framing_errors = 0; + return s; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) async_rx_release(async_rx_state_t *s) +{ + return 0; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) async_rx_free(async_rx_state_t *s) +{ + free(s); + return 0; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE_NONSTD(void) async_rx_put_bit(void *user_data, int bit) +{ + async_rx_state_t *s; + + s = (async_rx_state_t *) user_data; + if (bit < 0) + { + /* Special conditions */ + switch (bit) + { + case SIG_STATUS_CARRIER_UP: + case SIG_STATUS_CARRIER_DOWN: + case SIG_STATUS_TRAINING_IN_PROGRESS: + case SIG_STATUS_TRAINING_SUCCEEDED: + case SIG_STATUS_TRAINING_FAILED: + case SIG_STATUS_END_OF_DATA: + s->put_byte(s->user_data, bit); + s->bitpos = 0; + s->byte_in_progress = 0; + break; + default: + //printf("Eh!\n"); + break; + } + return; + } + if (s->bitpos == 0) + { + /* Search for the start bit */ + s->bitpos += (bit ^ 1); + s->parity_bit = 0; + s->byte_in_progress = 0; + } + else if (s->bitpos <= s->data_bits) + { + s->byte_in_progress = (s->byte_in_progress >> 1) | (bit << 7); + s->parity_bit ^= bit; + s->bitpos++; + } + else if (s->parity && s->bitpos == s->data_bits + 1) + { + if (s->parity == ASYNC_PARITY_ODD) + s->parity_bit ^= 1; + + if (s->parity_bit != bit) + s->parity_errors++; + s->bitpos++; + } + else + { + /* Stop bit */ + if (bit == 1) + { + /* Align the received value */ + if (s->data_bits < 8) + s->byte_in_progress >>= (8 - s->data_bits); + s->put_byte(s->user_data, s->byte_in_progress); + s->bitpos = 0; + } + else if (s->use_v14) + { + /* This is actually the start bit for the next character, and + the stop bit has been dropped from the stream. This is the + rate adaption specified in V.14 */ + /* Align the received value */ + if (s->data_bits < 8) + s->byte_in_progress >>= (8 - s->data_bits); + s->put_byte(s->user_data, s->byte_in_progress); + s->bitpos = 1; + s->parity_bit = 0; + s->byte_in_progress = 0; + } + else + { + s->framing_errors++; + s->bitpos = 0; + } + } +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(async_tx_state_t *) async_tx_init(async_tx_state_t *s, + int data_bits, + int parity, + int stop_bits, + int use_v14, + get_byte_func_t get_byte, + void *user_data) +{ + if (s == NULL) + { + if ((s = (async_tx_state_t *) malloc(sizeof(*s))) == NULL) + return NULL; + } + /* We have a use_v14 parameter for completeness, but right now V.14 only + applies to the receive side. We are unlikely to have an application where + flow control does not exist, so V.14 stuffing is not needed. */ + s->data_bits = data_bits; + s->parity = parity; + s->stop_bits = stop_bits; + if (parity != ASYNC_PARITY_NONE) + s->stop_bits++; + + s->get_byte = get_byte; + s->user_data = user_data; + + s->byte_in_progress = 0; + s->bitpos = 0; + s->parity_bit = 0; + return s; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) async_tx_release(async_tx_state_t *s) +{ + return 0; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE(int) async_tx_free(async_tx_state_t *s) +{ + free(s); + return 0; +} +/*- End of function --------------------------------------------------------*/ + +SPAN_DECLARE_NONSTD(int) async_tx_get_bit(void *user_data) +{ + async_tx_state_t *s; + int bit; + + s = (async_tx_state_t *) user_data; + if (s->bitpos == 0) + { + if ((s->byte_in_progress = s->get_byte(s->user_data)) < 0) + { + /* No more data */ + bit = SIG_STATUS_END_OF_DATA; + } + else + { + /* Start bit */ + bit = 0; + s->parity_bit = 0; + s->bitpos++; + } + } + else if (s->bitpos <= s->data_bits) + { + bit = s->byte_in_progress & 1; + s->byte_in_progress >>= 1; + s->parity_bit ^= bit; + s->bitpos++; + } + else if (s->parity && s->bitpos == s->data_bits + 1) + { + if (s->parity == ASYNC_PARITY_ODD) + s->parity_bit ^= 1; + bit = s->parity_bit; + s->bitpos++; + } + else + { + /* Stop bit(s) */ + bit = 1; + if (++s->bitpos > s->data_bits + s->stop_bits) + s->bitpos = 0; + } + return bit; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/