File: mt63tx.cc

package info (click to toggle)
hf 0.7.3-4etch1
  • links: PTS
  • area: main
  • in suites: etch
  • size: 3,684 kB
  • ctags: 3,156
  • sloc: ansic: 26,447; cpp: 4,909; sh: 3,785; makefile: 309
file content (309 lines) | stat: -rw-r--r-- 9,983 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
/*
 *    mt63tx.cc  --  The MT63ASC transmitter in C++ for LINUX,
 *                   written to be compatible with the
 *                   MT63ASC.ASM modem for the EVM56K/DSPCARD4.
 *
 *    Copyright (C) 1999-2004 Pawel Jalocha, SP9VRC
 *
 *    This file is part of MT63.
 *
 *    MT63 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.
 *
 *    MT63 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 MT63; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

// Date: 08-NOV-1999

#include <stdio.h>

#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>

#include "dsp.h"
#include "mt63.h"
#include "sound.h"

#include "stdinr.h"

// ============================================================================

char DevName[32]=""; 	// the name of the sound device
char UseDevice=0;

int ReqRate=8000;	// we request 8000 Hz sampling
float DevRate=0;	// the device gives us a possibly different rate
float UserRate=0.0;	// user provided rate (overrides the DevRate)

int SaveToFile=0;	// save audio to a file
char *SaveFile=NULL;	// file to save audio

int SendTextFile=0;	// send text from a file
char *TextFile=NULL;

int Bandwidth=1000;	// 500, 1000 or 2000 Hz bandwidth
int Interleave=0;	// short/long interleave

char *CW_ID=NULL;	// CW identification to be transmitted along the digital signal

// ============================================================================

MT63tx Tx;		// MT63 encoder

RateConvBL RateConv;	// rate converter to adjust the sampling rate
int UseRateConv=1;

s16_buff OutBuff;	// S16 buffer

SoundDevice TxDev;	// sound device to output audio

// ============================================================================

int main(int argc, char *argv[])
{ int len,err,i,arg; char ch;
  float ValueF; int ValueI;
  int End; int InpFile;

printf("\n\
Multitone MT63 modem for Linux - transmitter, (c) 1999 Pawel Jalocha, SP9VRC\n\
Made to be compatible with the MT63ASC for the EVM56K/DSPCARD4\n\
\n");

if(argc<=1)
{ printf("\
Usage: mt63tx <options>\n\
 the options:\n\
	 -d<device> the output dsp device number or name [default = none]\n\
		    -d => /dev/dsp, -d1 => /dev/dsp1, etc.\n\
		    or: -d/dev/dsp, -d/dev/dsp1, etc.\n\
	 -s<file>   save audio to a file\n\
	 -r<rate>   request given sampling rate from device [8000 Hz]\n\
	 -R<rate>   the true sampling rate (if you know it already)\n\
	 -t<file>   send text from <file> [default = send from keyboard]\n\
	 -B<band>   select bandwidth: 500, 1000 or 2000 Hz [1000Hz]\n\
	 -i         use the long interleave [default = short]\n\
	 -C<CW_ID>  transmit the <CW_ID> identifier along the signal\n\
                    put underscores into the message instead of spaces\n\
Examples:\n\
  mt63tx -d0      => default settings, send audio to /dev/dsp0\n\
  mt63tx -d0 -i   => use the double interleave (64 symbols)\n\
  mt63tx -tmsg.txt -smsg.raw => transmit message from msg.txt but save audio\n\
				to a file in a raw signed 16-bit format\n\
");
goto Error; }

for(err=0,arg=1; arg<argc; arg++)
{ if(argv[arg][0]!='-')
  { printf("Unknown option %s\n",argv[arg]); err+=1; continue; }
  switch(argv[arg][1])
  {
  case 'd':
    if(argv[arg][2]=='\0')
    { strcpy(DevName,"/dev/dsp"); UseDevice=1; }
    else if(isdigit(argv[arg][2]))
    { strcpy(DevName,"/dev/dsp"); strcat(DevName,argv[arg]+2); UseDevice=1; }
    else if(argv[arg][2]=='/')
    { strcpy(DevName,argv[arg]+2); UseDevice=1; }
    else
    { printf("Bad device number/name in %s\n",argv[arg]); err+=1; }
    break;
  case 'r':
    if(sscanf(argv[arg]+2,"%d",&ValueI)!=1)
      { printf("Invalid decimal number in %s\n",argv[arg]); err+=1; }
    else ReqRate=ValueI;
    break;
  case 'R':
    if(sscanf(argv[arg]+2,"%f",&ValueF)!=1)
      { printf("Invalid floating point number in %s\n",argv[arg]); err+=1; }
    else UserRate=ValueF;
    break;
  case 's':
    SaveToFile=1; SaveFile=argv[arg]+2; break;
  case 't':
    SendTextFile=1; TextFile=argv[arg]+2; break;
  case 'C':
    CW_ID=argv[arg]+2; break;
  case 'i':
    Interleave=1;
    break;
  case 'B':
    if(sscanf(argv[arg]+2,"%d",&ValueI)!=1)
      { printf("Invalid decimal number in %s\n",argv[arg]); err+=1; }
    else
    { switch(ValueI)
      { case 500:
	case 1000:
	case 2000:
	  Bandwidth=ValueI; break;
	default:
	  { printf("The modem bandwidth can only be 500, 1000 or 2000 Hz\n"); err+=1; }
      }
    } break;
  default:
    printf("Unknown option %s\n",argv[arg]); err+=1;
  }
}

if(err) goto Error;

if((UseDevice==0)&&(SaveToFile==0))
{ printf("No audio device selected nor a file to save audio\n"); goto Error; }

if(UseDevice) printf("Audio device for output is %s\n",DevName);
else printf("No audio device selected\n");

if(SaveToFile)
{ if(UseDevice)
  { err=TxDev.OpenFileForWrite(SaveFile,ReqRate,DevName);
    if(err<0)
    { printf("Can't open %s or %s to write audio to, errno => %s\n",
	     SaveFile,DevName,strerror(errno)); goto Error; }
    printf("We save the audio to %s and play it via %s\n",
	    SaveFile,DevName);
  } else
  { err=TxDev.OpenFileForWrite(SaveFile,ReqRate);
    if(err<0)
    { printf("Can't open %s to write audio to, errno => %s\n",
	     SaveFile,strerror(errno)); goto Error; }
    printf("We write the audio to %s\n",SaveFile);
  }
} else
{ err=TxDev.OpenForWrite(DevName,ReqRate);
  if(err<0) { printf("Can't open %s to write audio to: errno => %s\n",
		   DevName,strerror(errno)); goto Error; }
}
DevRate=TxDev.Rate;
printf("Requested rate = %d Hz, device reported rate = %1.0f Hz\n",
       ReqRate,DevRate);
if(UserRate>0.0)
{ printf("You say the true device rate is %4.2f Hz.\n",UserRate);
  DevRate=UserRate; }
UseRateConv=(DevRate!=8000.0);

if(UseRateConv)
{ err=RateConv.Preset(16,NULL,64);
  if(err)
  { printf("Can't preset the rate converter - not enough RAM ?!\n"); goto Error; }
  err=RateConv.ComputeShape(0.0,0.75*M_PI,WindowBlackman2);
  if(err)
  { printf("Can't compute the shape for the rate converter - not enough RAM ?!\n"); goto Error; }
  RateConv.SetOutVsInp(DevRate/8000.0);
}
printf("Modem bandwidth is %d Hz with %s interleave\n",
	Bandwidth,Interleave ? "DOUBLE (64)" : "SINGLE (32)");

if(CW_ID!=NULL)
{ for(i=0; CW_ID[i]; i++) if(CW_ID[i]=='_') CW_ID[i]=' ';
  printf("CW message \"%s\" is transmitted along the digital signal\n",CW_ID); }

err=Tx.Preset(Bandwidth,Interleave,CW_ID);
if(err)
{ printf("Can't preset the MT63tx module - not enough RAM ?!\n"); goto Error; }

if(SendTextFile)
{
  InpFile=open(TextFile,O_RDONLY,0);
  if(InpFile<0) { printf("Can't open %s to read text from\n",TextFile); goto Stop; }
  printf("MT63 transmitting text from %s ...\n",TextFile);
// the following code is to debug the Tx.SendTune()
/*  for(i=0; i<20; i++) // send tuning, just to test the SendTune()
  { Tx.SendTune();
    if(UseRateConv)
    { RateConv.ProcessLinI(&Tx.Comb.Output);
      ConvFloatToS16(&RateConv.Output,&OutBuff);
    } else ConvFloatToS16(&Tx.Comb.Output,&OutBuff);
    len=TxDev.Write(OutBuff.Data,OutBuff.Len);
    printf("tuning...");
    if(len!=OutBuff.Len)
    { printf("Error while sending out audio, errno => %s\n",strerror(errno));
      goto Stop; }
  }
*/
  for(End=0; !End; )
  { err=read(InpFile,&ch,1); if(err!=1) { close(InpFile); break; }
    printf("%c",ch); fflush(stdout);
    if(ch=='\n') ch='\r'; Tx.SendChar(ch);
    if(UseRateConv)
    { RateConv.ProcessLinI(&Tx.Comb.Output);
      ConvFloatToS16(&RateConv.Output,&OutBuff);
    } else ConvFloatToS16(&Tx.Comb.Output,&OutBuff);

    len=TxDev.Write(OutBuff.Data,OutBuff.Len);
    if(len!=OutBuff.Len)
    { printf("Error while sending out audio, errno => %s\n",strerror(errno));
      close(InpFile); goto Stop; }
  } close(InpFile);
}
else
{ printf("MT63 transmiting: type your text, press Ctrl-D to stop\n");

  err=StdinSetRaw();
  if(err) { printf("Can't set STDIN into the raw mode\n"); goto Error; }
  for(End=0; !End; )
  { ch=StdinRead(); Tx.SendChar(ch); if(ch==0x04) End=1;
    if(ch) { printf("%c",ch);
	   if(ch=='\r') printf("\n"); fflush(stdout); }

    if(UseRateConv)
    { RateConv.ProcessLinI(&Tx.Comb.Output);
      ConvFloatToS16(&RateConv.Output,&OutBuff);
    } else ConvFloatToS16(&Tx.Comb.Output,&OutBuff);

    len=TxDev.Write(OutBuff.Data,OutBuff.Len);
    if(len!=OutBuff.Len)
    { printf("Error while sending out audio, errno => %s\n",strerror(errno));
      StdinRestore(); goto Stop; }
  } StdinRestore(); 
}

printf("\nFlushing data interleaver ...\n");
for(i=0; i<Tx.DataInterleave; i++)
{ Tx.SendChar('\0');
  if(UseRateConv)
  { RateConv.ProcessLinI(&Tx.Comb.Output);
    ConvFloatToS16(&RateConv.Output,&OutBuff);
  } else ConvFloatToS16(&Tx.Comb.Output,&OutBuff);
  len=TxDev.Write(OutBuff.Data,OutBuff.Len);
  if(len!=OutBuff.Len)
  { printf("Error while sending out audio, errno => %s\n",strerror(errno));
    goto Stop; }
}

printf("Sending jamming waveform ...\n");
for(i=0; i<20; i++)
{ Tx.SendJam();
  if(UseRateConv)
  { RateConv.ProcessLinI(&Tx.Comb.Output);
    ConvFloatToS16(&RateConv.Output,&OutBuff);
  } else ConvFloatToS16(&Tx.Comb.Output,&OutBuff);
  len=TxDev.Write(OutBuff.Data,OutBuff.Len);
  if(len!=OutBuff.Len)
  { printf("Error while sending out audio, errno => %s\n",strerror(errno));
    goto Stop; }
}

Stop:
 printf("\nClosing audio device ...\n");
 TxDev.Close();
 printf("Stopped OK.\n");
 printf("%ld samples sent out = %3.1f sec\n",
     TxDev.TotalWritten,TxDev.TotalWritten/DevRate);
 return 0;

Error:
 TxDev.Close();
 return 1;

}