1 /*---------------------------------------------------------------------------*\
2
3 FILE........: fdmdv_mod.c
4 AUTHOR......: David Rowe
5 DATE CREATED: April 28 2012
6
7 Given an input file of bits outputs a raw file (8kHz, 16 bit shorts)
8 of FDMDV modem samples ready to send over a HF radio channel. The
9 input file is assumed to be arranged as codec frames of 56 bits (7
10 bytes) which we send as two 28 bit modem frames.
11
12 \*---------------------------------------------------------------------------*/
13
14
15 /*
16 Copyright (C) 2012 David Rowe
17
18 All rights reserved.
19
20 This program is free software; you can redistribute it and/or modify
21 it under the terms of the GNU Lesser General Public License version 2.1, as
22 published by the Free Software Foundation. This program is
23 distributed in the hope that it will be useful, but WITHOUT ANY
24 WARRANTY; without even the implied warranty of MERCHANTABILITY or
25 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
26 License for more details.
27
28 You should have received a copy of the GNU Lesser General Public License
29 along with this program; if not, see <http://www.gnu.org/licenses/>.
30 */
31
32 #include <assert.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <math.h>
37 #include <errno.h>
38
39 #include "codec2_fdmdv.h"
40
main(int argc,char * argv[])41 int main(int argc, char *argv[])
42 {
43 FILE *fin, *fout;
44 struct FDMDV *fdmdv;
45 char *packed_bits;
46 int *tx_bits;
47 COMP tx_fdm[2*FDMDV_NOM_SAMPLES_PER_FRAME];
48 short tx_fdm_scaled[2*FDMDV_NOM_SAMPLES_PER_FRAME];
49 int frames;
50 int i, bit, byte;
51 int sync_bit;
52 int bits_per_fdmdv_frame;
53 int bits_per_codec_frame;
54 int bytes_per_codec_frame;
55 int Nc;
56 #ifdef CHANNEL_SIM
57 COMP foff_phase_rect;
58 float foff;
59 #endif
60
61 if (argc < 3) {
62 printf("usage: %s InputBitFile OutputModemRawFile [Nc]\n", argv[0]);
63 printf("e.g %s hts1a.c2 hts1a_fdmdv.raw\n", argv[0]);
64 exit(1);
65 }
66
67 if (strcmp(argv[1], "-") == 0) fin = stdin;
68 else if ( (fin = fopen(argv[1],"rb")) == NULL ) {
69 fprintf(stderr, "Error opening input bit file: %s: %s.\n",
70 argv[1], strerror(errno));
71 exit(1);
72 }
73
74 if (strcmp(argv[2], "-") == 0) fout = stdout;
75 else if ( (fout = fopen(argv[2],"wb")) == NULL ) {
76 fprintf(stderr, "Error opening output modem sample file: %s: %s.\n",
77 argv[2], strerror(errno));
78 exit(1);
79 }
80
81 if (argc == 4) {
82 Nc = atoi(argv[3]);
83
84 if ((Nc < 2) || (Nc > FDMDV_NC_MAX) ) {
85 fprintf(stderr, "Error number of carriers must be btween 2 and %d\n", FDMDV_NC_MAX);
86 exit(1);
87 }
88 }
89 else
90 Nc = FDMDV_NC;
91
92 fdmdv = fdmdv_create(Nc);
93
94 bits_per_fdmdv_frame = fdmdv_bits_per_frame(fdmdv);
95 bits_per_codec_frame = 2*fdmdv_bits_per_frame(fdmdv);
96 bytes_per_codec_frame = (bits_per_codec_frame+7)/8;
97
98 packed_bits = (char*)malloc(bytes_per_codec_frame);
99 assert(packed_bits != NULL);
100 tx_bits = (int*)malloc(sizeof(int)*bits_per_codec_frame);
101 assert(tx_bits != NULL);
102
103 #ifdef CHANNEL_SIM
104 foff = -100;
105 foff_phase_rect.real = 1.0; foff_phase_rect.imag = 0.0;
106 #endif
107
108 frames = 0;
109
110 while(fread(packed_bits, sizeof(char), bytes_per_codec_frame, fin) == bytes_per_codec_frame) {
111 frames++;
112
113 /* unpack bits, MSB first */
114
115 bit = 7; byte = 0;
116 for(i=0; i<bits_per_codec_frame; i++) {
117 tx_bits[i] = (packed_bits[byte] >> bit) & 0x1;
118 bit--;
119 if (bit < 0) {
120 bit = 7;
121 byte++;
122 }
123 }
124
125 /* modulate even and odd frames */
126
127 fdmdv_mod(fdmdv, tx_fdm, tx_bits, &sync_bit);
128 assert(sync_bit == 1);
129
130 fdmdv_mod(fdmdv, &tx_fdm[FDMDV_NOM_SAMPLES_PER_FRAME], &tx_bits[bits_per_fdmdv_frame], &sync_bit);
131 assert(sync_bit == 0);
132
133 #ifdef CHANNEL_SIM
134 /* optional freq shift and channel simulation */
135
136 fdmdv_freq_shift(tx_fdm, tx_fdm, foff, &foff_phase_rect, 2*FDMDV_NOM_SAMPLES_PER_FRAME);
137 fdmdv_simulate_channel(&sig_pwr_av, tx_fdm, 2*FDMDV_NOM_SAMPLES_PER_FRAME, 10.0);
138 #endif
139
140 /* scale and save to disk as shorts */
141
142 for(i=0; i<2*FDMDV_NOM_SAMPLES_PER_FRAME; i++)
143 tx_fdm_scaled[i] = FDMDV_SCALE * tx_fdm[i].real;
144
145 fwrite(tx_fdm_scaled, sizeof(short), 2*FDMDV_NOM_SAMPLES_PER_FRAME, fout);
146
147 /* if this is in a pipeline, we probably don't want the usual
148 buffering to occur */
149
150 if (fout == stdout) fflush(stdout);
151 }
152
153 //fdmdv_dump_osc_mags(fdmdv);
154
155 free(tx_bits);
156 free(packed_bits);
157 fclose(fin);
158 fclose(fout);
159 fdmdv_destroy(fdmdv);
160
161 return 0;
162 }
163