/*
 * SpanDSP - a series of DSP components for telephony
 *
 * async.h - 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 General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU 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.h,v 1.2 2005/11/25 14:52:00 steveu Exp $
 */

/*! \file */

/*! \page async_page Asynchronous bit stream processing
\section async_page_sec_1 What does it do?
The asynchronous serial bit stream processing module provides
generation and decoding facilities for most asynchronous data
formats. It supports:
 - 1 or 2 stop bits.
 - Odd, even or no parity.
 - 5, 6, 7, or 8 bit characters.
 - V.14 rate adaption.
The input to this module is a bit stream. This means any symbol synchronisation
and decoding must occur before data is fed to this module.

\section async_page_sec_2 The transmitter
???.

\section async_page_sec_3 The receiver
???.
*/

#if !defined(_ASYNC_H_)
#define _ASYNC_H_

/* Special "bit" values for the put and get bit functions */
enum
{
    PUTBIT_CARRIER_DOWN = -1,
    PUTBIT_CARRIER_UP = -2,
    PUTBIT_TRAINING_SUCCEEDED = -3,
    PUTBIT_TRAINING_FAILED = -4,
    PUTBIT_FRAMING_OK = -5,
    PUTBIT_END_OF_DATA = -6
};

/*! Message put function for data pumps */
typedef void (*put_msg_func_t)(void *user_data, const uint8_t *msg, int len);

/*! Message get function for data pumps */
typedef int (*get_msg_func_t)(void *user_data, uint8_t *msg, int max_len);

/*! Byte put function for data pumps */
typedef void (*put_byte_func_t)(void *user_data, int byte);

/*! Byte get function for data pumps */
typedef int (*get_byte_func_t)(void *user_data);

/*! Bit put function for data pumps */
typedef void (*put_bit_func_t)(void *user_data, int bit);

/*! Bit get function for data pumps */
typedef int (*get_bit_func_t)(void *user_data);

/*! No parity bit should be used */
#define ASYNC_PARITY_NONE   0
/*! An even parity bit will exist, after the data bits */
#define ASYNC_PARITY_EVEN   1
/*! An odd parity bit will exist, after the data bits */
#define ASYNC_PARITY_ODD    2

/*!
    Asynchronous data transmit descriptor. This defines the state of a single
    working instance of a byte to asynchronous serial converter, for use
    in FSK modems.
*/
typedef struct
{
    /*! \brief The number of data bits per character. */
    int data_bits;
    /*! \brief The type of parity. */
    int parity;
    /*! \brief The number of stop bits per character. */
    int stop_bits;
    /*! \brief A pointer to the callback routine used to get characters to be transmitted. */
    get_byte_func_t get_byte;
    /*! \brief An opaque pointer passed when calling get_byte. */
    void *user_data;

    /*! \brief A current, partially transmitted, character. */
    int byte_in_progress;
    /*! \brief The current bit position within a partially transmitted character. */
    int bitpos;
    int parity_bit;
} async_tx_state_t;

/*!
    Asynchronous data receive descriptor. This defines the state of a single
    working instance of an asynchronous serial to byte converter, for use
    in FSK modems.
*/
typedef struct
{
    /*! \brief The number of data bits per character. */
    int data_bits;
    /*! \brief The type of parity. */
    int parity;
    /*! \brief The number of stop bits per character. */
    int stop_bits;
    /*! \brief TRUE if V.14 rate adaption processing should be performed. */
    int use_v14;
    /*! \brief A pointer to the callback routine used to handle received characters. */
    put_byte_func_t put_byte;
    /*! \brief An opaque pointer passed when calling put_byte. */
    void *user_data;

    /*! \brief A current, partially complete, character. */
    int byte_in_progress;
    /*! \brief The current bit position within a partially complete character. */
    int bitpos;
    int parity_bit;

    int parity_errors;
    int framing_errors;
} async_rx_state_t;

#ifdef __cplusplus
extern "C" {
#endif

/*! Initialise an asynchronous data transmit context.
    \brief Initialise an asynchronous data transmit context.
    \param s The transmitter context.
    \param data_bits The number of data bit.
    \param parity_bits The type of parity.
    \param stop_bits The number of stop bits.
    \param use_v14 TRUE if V.14 rate adaption processing should be used.
    \param get_byte The callback routine used to get the data to be transmitted.
    \param user_data An opaque pointer. */
void async_tx_init(async_tx_state_t *s,
                   int data_bits,
                   int parity_bits,
                   int stop_bits,
                   int use_v14,
                   get_byte_func_t get_byte,
                   void *user_data);

/*! Get the next bit of a transmitted serial bit stream.
    \brief Get the next bit of a transmitted serial bit stream.
    \param user_data An opaque point which must point to a transmitter context.
    \return the next bit, or PUTBIT_END_OF_DATA to indicate the data stream has ended. */
int async_tx_bit(void *user_data);

/*! Initialise an asynchronous data receiver context.
    \brief Initialise an asynchronous data receiver context.
    \param s The receiver context.
    \param data_bits The number of data bits.
    \param parity_bits The type of parity.
    \param stop_bits The number of stop bits.
    \param use_v14 TRUE if V.14 rate adaption processing should be used.
    \param put_byte The callback routine used to put the received data.
    \param user_data An opaque pointer. */
void async_rx_init(async_rx_state_t *s,
                   int data_bits,
                   int parity_bits,
                   int stop_bits,
                   int use_v14,
                   put_byte_func_t put_byte,
                   void *user_data);

/*! Accept a bit from a received serial bit stream
    \brief Accept a bit from a received serial bit stream
    \param user_data An opaque point which must point to a receiver context.
    \param bit The new bit. Some special values are supported for this field.
        - PUTBIT_CARRIER_UP
        - PUTBIT_CARRIER_DOWN
        - PUTBIT_TRAINING_SUCCEEDED
        - PUTBIT_TRAINING_FAILED
        - PUTBIT_END_OF_DATA */
void async_rx_bit(void *user_data, int bit);

#ifdef __cplusplus
}
#endif

#endif
/*- End of file ------------------------------------------------------------*/
