OpenModem/Modem/afsk.h

186 lines
4.0 KiB
C
Raw Normal View History

2014-04-03 14:21:37 -06:00
#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 */