Factor out hdlc context, add some documentation.
[bertos.git] / bertos / net / afsk.h
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2008 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \brief AFSK1200 modem.
34  *
35  * \version $Id$
36  * \author Francesco Sacchi <asterix@develer.com>
37  *
38  * $WIZ$ module_name = "afsk"
39  * $WIZ$ module_configuration = "bertos/cfg/cfg_afsk.h"
40  * $WIZ$ module_depends = "timer", "kfile"
41  * $WIZ$ module_hw = "bertos/hw/hw_afsk.h"
42  */
43
44 #ifndef DRV_AFSK_H
45 #define DRV_AFSK_H
46
47 #include "cfg/cfg_afsk.h"
48 #include "hw/hw_afsk.h"
49
50 #include <kern/kfile.h>
51 #include <cfg/compiler.h>
52 #include <struct/fifobuf.h>
53
54
55 // Demodulator constants
56 #define SAMPLERATE 9600
57 #define BITRATE    1200
58
59 #define SAMPLEPERBIT (SAMPLERATE / BITRATE)
60
61 /**
62  * HDLC (High-Level Data Link Control) context.
63  * Maybe to be moved in a separate HDLC module one day.
64  */
65 typedef struct Hdlc
66 {
67         uint8_t demod_bits; ///< Bitstream from the demodulator.
68         uint8_t bit_idx;    ///< Current received bit.
69         uint8_t currchar;   ///< Current received character.
70         bool rxstart;       ///< True if an HDLC_FLAG char has been found in the bitstream.
71 } Hdlc;
72
73
74 /**
75  * AFSK1200 modem context.
76  */
77 typedef struct Afsk
78 {
79         /** Base "class" */
80         KFile fd;
81
82         /** ADC channel to be used by the demodulator */
83         int adc_ch;
84
85         /** DAC channel to be used by the modulator */
86         int dac_ch;
87
88         /** Current sample of bit for output data. */
89         uint8_t sample_count;
90
91         /** Current character to be modulated */
92         uint8_t curr_out;
93
94         /** Mask of current modulated bit */
95         uint8_t tx_bit;
96
97         /** True if bit stuff is allowed, false otherwise */
98         bool bit_stuff;
99
100         /** Counter for bit stuffing */
101         uint8_t stuff_cnt;
102         /**
103          * DDS phase accumulator for generating modulated data.
104          */
105         uint16_t phase_acc;
106
107         /** Current phase increment for current modulated bit */
108         uint16_t phase_inc;
109
110         /** Delay line used to delay samples by (SAMPLEPERBIT / 2) */
111         FIFOBuffer delay_fifo;
112
113         /**
114          * Buffer for delay FIFO.
115          * The 1 is added because the FIFO macros need
116          * 1 byte more to handle a buffer (SAMPLEPERBIT / 2) bytes long.
117          */
118         int8_t delay_buf[SAMPLEPERBIT / 2 + 1];
119
120         /** FIFO for received data */
121         FIFOBuffer rx_fifo;
122
123         /** FIFO rx buffer */
124         uint8_t rx_buf[CONFIG_AFSK_RX_BUFLEN];
125
126         /** FIFO for transmitted data */
127         FIFOBuffer tx_fifo;
128
129         /** FIFO tx buffer */
130         uint8_t tx_buf[CONFIG_AFSK_TX_BUFLEN];
131
132         /** IIR filter X cells, used to filter sampled data by the demodulator */
133         int16_t iir_x[2];
134
135         /** IIR filter Y cells, used to filter sampled data by the demodulator */
136         int16_t iir_y[2];
137
138         /**
139          * Bits sampled by the demodulator are here.
140          * Since ADC samplerate is higher than the bitrate, the bits here are
141          * SAMPLEPERBIT times the bitrate.
142          */
143         uint8_t sampled_bits;
144
145         /**
146          * Current phase, needed to know when the bitstream at ADC speed
147          * should be sampled.
148          */
149         int8_t curr_phase;
150
151         /** Bits found by the demodulator at the correct bitrate speed. */
152         uint8_t found_bits;
153
154         /** True while modem sends data */
155         volatile bool sending;
156
157         /** Hdlc context */
158         Hdlc hdlc;
159
160         /**
161          * Preamble length.
162          * When the AFSK modem wants to send data, before sending the actual data,
163          * shifts out preamble_len HDLC_FLAG characters.
164          * This helps to synchronize the demodulator filters on the receiver side.
165          */
166         uint16_t preamble_len;
167
168         /**
169          * Preamble length.
170          * After sending the actual data, the AFSK shifts out
171          * trailer_len HDLC_FLAG characters.
172          * This helps to synchronize the demodulator filters on the receiver side.
173          */
174         uint16_t trailer_len;
175 } Afsk;
176
177 #define KFT_AFSK MAKE_ID('A', 'F', 'S', 'K')
178
179 INLINE Afsk *AFSK_CAST(KFile *fd)
180 {
181   ASSERT(fd->_type == KFT_AFSK);
182   return (Afsk *)fd;
183 }
184
185 void afsk_adc_isr(Afsk *af, int8_t curr_sample);
186 void afsk_dac_isr(Afsk *af);
187 void afsk_init(Afsk *af, int adc_ch, int dac_ch);
188
189
190 /**
191  * \name afsk filter type
192  * $WIZ$ afsk_filter_list = "AFSK_BUTTERWORTH", "AFSK_CHEBYSHEV"
193  * \{
194  */
195 #define AFSK_BUTTERWORTH  0
196 #define AFSK_CHEBYSHEV    1
197 /* \} */
198
199 int afsk_testSetup(void);
200 int afsk_testRun(void);
201 int afsk_testTearDown(void);
202
203 #endif