9aa5083056187f2a336f1c8d857f7aa4f7b6d4a1
[bertos.git] / bertos / net / afsk_test.c
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 2009 Develer S.r.l. (http://www.develer.com/)
30  *
31  * -->
32  *
33  * \brief AFSK demodulator test.
34  *
35  * \version $Id$
36  * \author Francesco Sacchi <batt@develer.com>
37  * $test$: cp bertos/cfg/cfg_ax25.h $cfgdir/
38  * $test$: echo "#undef AX25_LOG_LEVEL" >> $cfgdir/cfg_ax25.h
39  * $test$: echo "#define AX25_LOG_LEVEL LOG_LVL_INFO" >> $cfgdir/cfg_ax25.h
40  * $test$: cp bertos/cfg/cfg_afsk.h $cfgdir/
41  * $test$: echo "#undef CONFIG_AFSK_TX_BUFLEN" >> $cfgdir/cfg_afsk.h
42  * $test$: echo "#define CONFIG_AFSK_TX_BUFLEN 512" >> $cfgdir/cfg_afsk.h
43  */
44
45
46 #include "afsk.h"
47 #include "cfg/cfg_afsk.h"
48
49 #include <drv/timer.h>
50 #include <net/ax25.h>
51
52 #include <cfg/test.h>
53 #include <cfg/debug.h>
54
55 #include <cpu/byteorder.h>
56
57 #include <stdio.h>
58 #include <string.h>
59
60 FILE *fp_adc;
61 FILE *fp_dac;
62 uint32_t data_size;
63 uint32_t data_written;
64 Afsk afsk_fd;
65 AX25Ctx ax25;
66
67 int msg_cnt;
68 static void message_hook(UNUSED_ARG(struct AX25Msg *, msg))
69 {
70         msg_cnt++;
71 }
72
73 static FILE *afsk_fileOpen(const char *name)
74 {
75         FILE *fp = 0;
76         #if CPU_AVR
77                 (void)name;
78                 #warning TODO: open the file?
79         #else
80                 fp = fopen(name, "rb");
81         #endif
82         ASSERT(fp);
83
84         char snd[5];
85         ASSERT(fread(snd, 1, 4, fp) == 4);
86         snd[4] = 0;
87         ASSERT(strcmp(snd, ".snd") == 0);
88
89         uint32_t offset;
90         ASSERT(fread(&offset, 1, sizeof(offset), fp) == sizeof(offset));
91         offset = be32_to_cpu(offset);
92         kprintf("AU file offset: %ld\n", (long)offset);
93         ASSERT(offset >= 24);
94
95         ASSERT(fread(&data_size, 1, sizeof(data_size), fp) == sizeof(data_size));
96         data_size = be32_to_cpu(data_size);
97         kprintf("AU file data_size: %ld\n", (long)data_size);
98         ASSERT(data_size);
99
100         uint32_t encoding;
101         ASSERT(fread(&encoding, 1, sizeof(encoding), fp) == sizeof(encoding));
102         encoding = be32_to_cpu(encoding);
103         kprintf("AU file encoding: %ld\n", (long)encoding);
104         ASSERT(encoding == 2); // 8 bit linear PCM
105
106         uint32_t sample_rate;
107         ASSERT(fread(&sample_rate, 1, sizeof(sample_rate), fp) == sizeof(sample_rate));
108         sample_rate = be32_to_cpu(sample_rate);
109         kprintf("AU file sample_rate: %ld\n", (long)sample_rate);
110         ASSERT(sample_rate == 9600);
111
112         uint32_t channels;
113         ASSERT(fread(&channels, 1, sizeof(channels), fp) == sizeof(channels));
114         channels = be32_to_cpu(channels);
115         kprintf("AU file channels: %ld\n", (long)channels);
116         ASSERT(channels == 1);
117
118         #if CPU_AVR
119                 #warning TODO: fseek?
120         #else
121                 ASSERT(fseek(fp, offset, SEEK_SET) == 0);
122         #endif
123         return fp;
124 }
125
126 int afsk_testSetup(void)
127 {
128         kdbg_init();
129         fp_adc = afsk_fileOpen("test/afsk_test.au");
130         #if CPU_AVR
131                 #warning TODO: open the file?
132         #else
133                 fp_dac = fopen("test/afsk_test_out.au", "w+b");
134         #endif
135         ASSERT(fp_dac);
136         #define FS_HH (((uint32_t)CONFIG_AFSK_DAC_SAMPLERATE) >> 24)
137         #define FS_HL ((((uint32_t)CONFIG_AFSK_DAC_SAMPLERATE) >> 16) & 0xff)
138         #define FS_LH ((((uint32_t)CONFIG_AFSK_DAC_SAMPLERATE) >> 8) & 0xff)
139         #define FS_LL (((uint32_t)CONFIG_AFSK_DAC_SAMPLERATE) & 0xff)
140
141         uint8_t snd_header[] = { '.','s','n','d', 0,0,0,24, 0,0,0,0, 0,0,0,2, FS_HH,FS_HL,FS_LH,FS_LL, 0,0,0,1};
142
143         ASSERT(fwrite(snd_header, 1, sizeof(snd_header), fp_dac) == sizeof(snd_header));
144
145         timer_init();
146         afsk_init(&afsk_fd, 0 ,0);
147         ax25_init(&ax25, &afsk_fd.fd, message_hook);
148         return 0;
149 }
150
151
152 static void messageout_hook(struct AX25Msg *msg)
153 {
154         ASSERT(strncmp(msg->dst.call, "ABCDEF", 6) == 0);
155         ASSERT(strncmp(msg->src.call, "123456", 6) == 0);
156         ASSERT(msg->src.ssid == 1);
157         ASSERT(msg->dst.ssid == 0);
158         ASSERT(msg->ctrl == AX25_CTRL_UI);
159         ASSERT(msg->pid == AX25_PID_NOLAYER3);
160         ASSERT(msg->len == 256);
161         for (int i = 0; i < 256; i++)
162                 ASSERT(msg->info[i] == i);
163 }
164
165 int afsk_testRun(void)
166 {
167         int c;
168         while ((c = fgetc(fp_adc)) != EOF)
169         {
170                 afsk_adc_isr(&afsk_fd, (int8_t)c);
171
172                 ax25_poll(&ax25);
173         }
174         kprintf("Messages correctly received: %d\n", msg_cnt);
175         ASSERT(msg_cnt >= 15);
176
177         char buf[256];
178         for (unsigned i = 0; i < sizeof(buf); i++)
179                 buf[i] = i;
180
181         ax25_send(&ax25, AX25_CALL("abcdef", 0), AX25_CALL("123456", 1), buf, sizeof(buf));
182
183         do
184         {
185                 int8_t val = afsk_dac_isr(&afsk_fd) - 128;
186                 ASSERT(fwrite(&val, 1, sizeof(val), fp_dac) == sizeof(val));
187                 data_written++;
188         }
189         while (afsk_fd.sending);
190
191         #define SND_DATASIZE_OFF 8
192         #if CPU_AVR
193                 #warning TODO: fseek?
194         #else
195                 ASSERT(fseek(fp_dac, SND_DATASIZE_OFF, SEEK_SET) == 0);
196         #endif
197         data_written = cpu_to_be32(data_written);
198         ASSERT(fwrite(&data_written, 1, sizeof(data_written), fp_dac) == sizeof(data_written));
199         ASSERT(fclose(fp_adc) + fclose(fp_dac) == 0);
200
201         fp_adc = afsk_fileOpen("test/afsk_test_out.au");
202         ax25_init(&ax25, &afsk_fd.fd, messageout_hook);
203
204         while ((c = fgetc(fp_adc)) != EOF)
205         {
206                 afsk_adc_isr(&afsk_fd, (int8_t)c);
207
208                 ax25_poll(&ax25);
209         }
210
211         return 0;
212 }
213
214 int afsk_testTearDown(void)
215 {
216         return fclose(fp_adc);
217 }
218
219 TEST_MAIN(afsk);