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 ------------------------------------------------------------*/

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