OpenModem/bertos/net/afsk.h

227 lines
5.6 KiB
C

/**
* \file
* <!--
* This file is part of BeRTOS.
*
* Bertos 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* As a special exception, you may use this file as part of a free software
* library without restriction. Specifically, if other files instantiate
* templates or use macros or inline functions from this file, or you compile
* this file and link it with other files to produce an executable, this
* file does not by itself cause the resulting executable to be covered by
* the GNU General Public License. This exception does not however
* invalidate any other reasons why the executable file might be covered by
* the GNU General Public License.
*
* Copyright 2008 Develer S.r.l. (http://www.develer.com/)
*
* -->
*
* \brief AFSK1200 modem.
*
* \author Francesco Sacchi <batt@develer.com>
*
* $WIZ$ module_name = "afsk"
* $WIZ$ module_configuration = "bertos/cfg/cfg_afsk.h"
* $WIZ$ module_depends = "timer", "kfile"
* $WIZ$ module_hw = "bertos/hw/hw_afsk.h"
*/
#ifndef NET_AFSK_H
#define NET_AFSK_H
#include "cfg/cfg_afsk.h"
#include "hw/hw_afsk.h"
#include <cfg/compiler.h>
#include <io/kfile.h>
#include <struct/fifobuf.h>
/**
* ADC sample rate.
* The demodulator filters are designed to work at this frequency.
* If you need to change this remember to update afsk_adc_isr().
*/
#define SAMPLERATE 9600
/**
* Bitrate of the received/transmitted data.
* The demodulator filters and decoderes are designed to work at this frequency.
* If you need to change this remember to update afsk_adc_isr().
*/
#define BITRATE 1200
#define SAMPLEPERBIT (SAMPLERATE / BITRATE)
/**
* HDLC (High-Level Data Link Control) context.
* Maybe to be moved in a separate HDLC module one day.
*/
typedef struct Hdlc
{
uint8_t demod_bits; ///< Bitstream from the demodulator.
uint8_t bit_idx; ///< Current received bit.
uint8_t currchar; ///< Current received character.
bool rxstart; ///< True if an HDLC_FLAG char has been found in the bitstream.
} Hdlc;
/**
* RX FIFO buffer full error.
*/
#define AFSK_RXFIFO_OVERRUN BV(0)
/**
* AFSK1200 modem context.
*/
typedef struct Afsk
{
/** Base "class" */
KFile fd;
/** ADC channel to be used by the demodulator */
int adc_ch;
/** DAC channel to be used by the modulator */
int dac_ch;
/** Current sample of bit for output data. */
uint8_t sample_count;
/** Current character to be modulated */
uint8_t curr_out;
/** Mask of current modulated bit */
uint8_t tx_bit;
/** True if bit stuff is allowed, false otherwise */
bool bit_stuff;
/** Counter for bit stuffing */
uint8_t stuff_cnt;
/**
* DDS phase accumulator for generating modulated data.
*/
uint16_t phase_acc;
/** Current phase increment for current modulated bit */
uint16_t phase_inc;
/** Delay line used to delay samples by (SAMPLEPERBIT / 2) */
FIFOBuffer delay_fifo;
/**
* Buffer for delay FIFO.
* The 1 is added because the FIFO macros need
* 1 byte more to handle a buffer (SAMPLEPERBIT / 2) bytes long.
*/
int8_t delay_buf[SAMPLEPERBIT / 2 + 1];
/** FIFO for received data */
FIFOBuffer rx_fifo;
/** FIFO rx buffer */
uint8_t rx_buf[CONFIG_AFSK_RX_BUFLEN];
/** FIFO for transmitted data */
FIFOBuffer tx_fifo;
/** FIFO tx buffer */
uint8_t tx_buf[CONFIG_AFSK_TX_BUFLEN];
/** IIR filter X cells, used to filter sampled data by the demodulator */
int16_t iir_x[2];
/** IIR filter Y cells, used to filter sampled data by the demodulator */
int16_t iir_y[2];
/**
* Bits sampled by the demodulator are here.
* Since ADC samplerate is higher than the bitrate, the bits here are
* SAMPLEPERBIT times the bitrate.
*/
uint8_t sampled_bits;
/**
* Current phase, needed to know when the bitstream at ADC speed
* should be sampled.
*/
int8_t curr_phase;
/** Bits found by the demodulator at the correct bitrate speed. */
uint8_t found_bits;
/** True while modem sends data */
volatile bool sending;
/**
* AFSK modem status.
* If 0 all is ok, otherwise errors are present.
*/
volatile int status;
/** Hdlc context */
Hdlc hdlc;
/**
* Preamble length.
* When the AFSK modem wants to send data, before sending the actual data,
* shifts out preamble_len HDLC_FLAG characters.
* This helps to synchronize the demodulator filters on the receiver side.
*/
uint16_t preamble_len;
/**
* Trailer length.
* After sending the actual data, the AFSK shifts out
* trailer_len HDLC_FLAG characters.
* This helps to synchronize the demodulator filters on the receiver side.
*/
uint16_t trailer_len;
} Afsk;
#define KFT_AFSK MAKE_ID('A', 'F', 'S', 'K')
INLINE Afsk *AFSK_CAST(KFile *fd)
{
ASSERT(fd->_type == KFT_AFSK);
return (Afsk *)fd;
}
void afsk_adc_isr(Afsk *af, int8_t sample);
uint8_t afsk_dac_isr(Afsk *af);
void afsk_init(Afsk *af, int adc_ch, int dac_ch);
/**
* \name Afsk filter types.
* $WIZ$ afsk_filter_list = "AFSK_BUTTERWORTH", "AFSK_CHEBYSHEV"
* \{
*/
#define AFSK_BUTTERWORTH 0
#define AFSK_CHEBYSHEV 1
/* \} */
int afsk_testSetup(void);
int afsk_testRun(void);
int afsk_testTearDown(void);
#endif /* NET_AFSK_H */