~ubuntu-branches/ubuntu/quantal/linpsk/quantal

« back to all changes in this revision

Viewing changes to linpsk/rttydemodulator.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bruce Walker
  • Date: 2002-02-06 11:43:38 UTC
  • Revision ID: james.westby@ubuntu.com-20020206114338-xqmjmhh01lpjm0g4
Tags: upstream-0.6.2
Import upstream version 0.6.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
                          rttydemodulator.cpp  -  description
 
3
                             -------------------
 
4
    begin                : Mon Jun 4 2001
 
5
    copyright            : (C) 2001 by Volker Schroer
 
6
    email                : dl1ksv@gmx.de
 
7
 ***************************************************************************/
 
8
 
 
9
/***************************************************************************
 
10
 *                                                                         *
 
11
 *   This program is free software; you can redistribute it and/or modify  *
 
12
 *   it under the terms of the GNU General Public License as published by  *
 
13
 *   the Free Software Foundation; either version 2 of the License, or     *
 
14
 *   (at your option) any later version.                                   *
 
15
 *    based on the work of  Moe Wheatly, AE4JY                             *  
 
16
 ***************************************************************************/
 
17
 
 
18
#include "rttydemodulator.h"
 
19
 
 
20
RTTYDemodulator::RTTYDemodulator():CDemodulator()
 
21
{
 
22
ShiftOn = false;
 
23
NumberOfStopBits = 2;
 
24
parity = 0;
 
25
x1=0;
 
26
 
 
27
NxSamples = 0;
 
28
 
 
29
twiddles = NULL;
 
30
bins = NULL;
 
31
history = NULL;
 
32
FrequencyNumber = NULL;
 
33
// Disable PhaseDisplay
 
34
 
 
35
}
 
36
RTTYDemodulator::~RTTYDemodulator()
 
37
{
 
38
if (twiddles != NULL)
 
39
  delete twiddles;
 
40
 
 
41
if (bins != NULL)
 
42
        delete bins;
 
43
 
 
44
if (history != NULL )
 
45
        delete history;
 
46
if (FrequencyNumber != NULL)
 
47
        delete FrequencyNumber;
 
48
}
 
49
/** returns the asci char corresponding to the baudot code */
 
50
char RTTYDemodulator::baudot_code(char data)
 
51
{
 
52
/** Table of letters */
 
53
 
 
54
static const char letters[32] = {0x00,'E','\n','A',' ','S','I','U',
 
55
                                                                 '\n','D','R','J','N','F','C','K',
 
56
                                                                 'T','Z','L','W','H','Y','P','Q',
 
57
                                                                 'O','B','G','^','M','X','V','^'};
 
58
 
 
59
 
 
60
/** Table of symbols */
 
61
static const char symbols[32] = {0x00,'3','\n','-',' ',',','8','7',
 
62
 '\n','$','4','#',',','�',':','(',
 
63
 '5','+',')','2','�','6','0','1',
 
64
'9','7','�','^','.','/','=','^'};
 
65
 
 
66
char c;
 
67
 
 
68
        switch (data)
 
69
         {
 
70
                case 0x1f :
 
71
                                ShiftOn = false;  //LTRS
 
72
                                c = 0;
 
73
                                break;
 
74
                case 0x1b :
 
75
                                ShiftOn = true;   //FIGS
 
76
                                c = 0;
 
77
                        break;
 
78
                default:        if (!ShiftOn)
 
79
                                                                c=letters[data];
 
80
                                                         else
 
81
                                                         c=symbols[data];
 
82
                                                 break;
 
83
                }
 
84
 
 
85
 
 
86
if ( c == ' ')                          // Unshift on Space
 
87
        ShiftOn =false; 
 
88
 
 
89
return c;
 
90
}
 
91
 
 
92
bool RTTYDemodulator::Init(double FS,int NumberOfSamples)
 
93
{
 
94
 
 
95
int i;
 
96
float x;
 
97
 
 
98
Baudrate=45;
 
99
NumberOfBits=5;
 
100
NxSamples=NumberOfSamples;
 
101
SamplesPerBit=int (FS/Baudrate+0.5);
 
102
SampleRate=FS;
 
103
Status = WaitingForMark;
 
104
actSample=0;
 
105
data=0;
 
106
BitsInData=0;
 
107
bitcounter=0;
 
108
c=0;
 
109
count=0;
 
110
 
 
111
FrequencyChanged = false;
 
112
 
 
113
 
 
114
ave1=0.0;
 
115
ave2=0.0;
 
116
 
 
117
 
 
118
 
 
119
if ( (twiddles = new float_complex [SamplesPerBit]) == NULL )
 
120
        return false;
 
121
 
 
122
if ( (bins = new float_complex[NumberofTones]) == NULL )
 
123
        return false;
 
124
 
 
125
if ( (history = new float[SamplesPerBit] ) == NULL )
 
126
        return false;
 
127
if ( (FrequencyNumber=new int[NumberofTones]) == NULL )
 
128
        return false;
 
129
ptr = 0;
 
130
 
 
131
setRxFrequency(1000.);
 
132
 
 
133
// Initialize the coefficients for the slfft
 
134
 
 
135
for (i=0;i < SamplesPerBit; i++)
 
136
        {
 
137
                x =2*i * M_PI*Baudrate/FS;
 
138
                twiddles[i] = float_complex( cos(x), sin(x) ) ;
 
139
        }
 
140
 
 
141
for (i=0;i<SamplesPerBit; i++)
 
142
{
 
143
history[i]= 0.;
 
144
}
 
145
for(i=0;i<NumberofTones;i++)
 
146
                bins[i]= float_complex(0.,0.);
 
147
return true;
 
148
}
 
149
 
 
150
void RTTYDemodulator::ProcessInput(double *input)
 
151
{
 
152
 
 
153
 
 
154
 
 
155
 
 
156
 
 
157
char c1;
 
158
 
 
159
bool bit;
 
160
 
 
161
DataAvailable = true;   // Just read the data
 
162
actSample = 0;                          // Start processing, counter will be incremented while processing
 
163
                                                                                        // the next value
 
164
data=input;     
 
165
while (DataAvailable)
 
166
        {
 
167
                switch (Status)
 
168
                        {
 
169
                                case WaitingForMark:
 
170
                                                while ( DataAvailable )                                 // Waiting for Mark
 
171
                                                        if (ProcessNextSample() > 0)
 
172
                                                        {
 
173
                                                                Status = WaitingForSpace;   // We seem to have found Mark, so we can wait for
 
174
                                                                break;                     // Space
 
175
                                                        }
 
176
                                break;
 
177
                                
 
178
                                case WaitingForSpace:                      // Mark seems to be found, now waiting for transition                                                                                                                                                                                                                                                                
 
179
                                                while ( DataAvailable )                                  // Waiting for transition
 
180
                                                        if (ProcessNextSample() < 0 )           
 
181
                                                        {
 
182
                                                                Status  = CheckingStartBit;  // Transition seems to be found    
 
183
                                                                bitcounter = SamplesPerBit/2;
 
184
                                                                CalcQuality();
 
185
                                                                break;
 
186
                                                        }
 
187
                                                break;                          
 
188
                                                        
 
189
                                case CheckingStartBit:
 
190
 
 
191
                                        while ( DataAvailable  )
 
192
                                                        if ( --bitcounter > 0)
 
193
                                                                ProcessNextSample();
 
194
                                                        else
 
195
                                        if ( ProcessNextSample() > 0 )          // 0.5 bit processed
 
196
                                                        {
 
197
                                                                Status  = WaitingForSpace; // Was'nt the correct start bit, as we found Mark
 
198
                                                                break;                     // here , so go and look for another Space
 
199
                                                        }       
 
200
                                                else
 
201
                                                        {               
 
202
///                                                             Status = SkipRestOfStartBit;   // We are tight behind the midle of the Startbit
 
203
                                                                Status = CollectingByte;   // We are tight behind the midle of the Startbit
 
204
 
 
205
///                                                     bitcounter = SamplesPerBit/4;
 
206
///                                                             bitcounter =1;
 
207
///                CalcQuality();
 
208
                                                                Frequencykor = 0;
 
209
                                                                bitcounter =5;
 
210
                CalcQuality();
 
211
                reset();
 
212
                                                                break;
 
213
                                                        }
 
214
                                                
 
215
                                        break;                          // We've reached the end of the available data or completed Status
 
216
 
 
217
        case SkipRestOfStartBit:
 
218
                                        while ( DataAvailable && (--bitcounter > 0) )
 
219
                                                if  ( ProcessNextSample() > 0 )         // Oops, already Mark
 
220
                                                        {
 
221
                                                                Status = CollectingByte;
 
222
                                                                bitcounter = 5;
 
223
                                                                reset();
 
224
                                                                count = 10;                                                                             // This is only aguess
 
225
                                                                break;
 
226
                                                        }
 
227
                                        if ( bitcounter == 0 )                  // Normal end of skip
 
228
                                                {
 
229
                                                                Status = CollectingByte;
 
230
                                                                bitcounter = 5;
 
231
                                                                reset();
 
232
                                                                break;
 
233
                                                }
 
234
                                        break;
 
235
                                case CollectingByte:
 
236
                                        while( DataAvailable && (bitcounter > 0) )
 
237
                                                {
 
238
                                                        bit=get_next_bit();                                                     
 
239
                                                        if ( DataAvailable )
 
240
                                                                {
 
241
                                                                        if (bit)
 
242
                                                                                BitsInData++;
 
243
                                                                        bitcounter--;
 
244
                                                                        c >>=1;
 
245
                                                                        if (bit)
 
246
                                                                                c |= 128;
 
247
                                                                }                                                                       
 
248
                                                        else
 
249
                                                                break;                  // No more data to be processed at the moment   
 
250
                                                        
 
251
                                                }
 
252
                                        if ( bitcounter == 0 ) // Data 'byte' completed
 
253
                                                {
 
254
                                                        c >>= (8- NumberOfBits);
 
255
                                                        Status = CheckingParity;
 
256
                                                        c1=c;
 
257
                                                        c1 = baudot_code(c1);  // FIGS or LTRS result in c1 = 0 !
 
258
                                                        if ( c1 > 0 )
 
259
                                                                emit newSymbol( c1 );
 
260
                                                }       
 
261
                                                        
 
262
                                        break;  
 
263
                                        
 
264
                                case CheckingParity:
 
265
 
 
266
                                        if (parity)
 
267
                                                {
 
268
                                                        bit=get_next_bit();
 
269
                                                        if (    DataAvailable )
 
270
                                                                {
 
271
                                                                        if (bit)
 
272
                                                                                BitsInData++;
 
273
                                                                        if (parity == 1 ) // even
 
274
                                                                                {
 
275
                                                                                if ( BitsInData & 1)    // error                                                
 
276
                                                                                        {
 
277
                                                                                        emit newSymbol('<');
 
278
                                                                                        emit newSymbol('P');
 
279
                                                                                        emit newSymbol('>');
 
280
                                                                                        }
 
281
                                                                                }
 
282
                                                                        else                                                    // odd
 
283
                                                                                {
 
284
                                                                                if (! (BitsInData & 1)) // error                                                
 
285
                                                                                        {
 
286
                                                                                        emit newSymbol('<');
 
287
                                                                                        emit newSymbol('P');
 
288
                                                                                        emit newSymbol('>');
 
289
                                                                                        }
 
290
                                                                                }
 
291
                                                                        
 
292
                                                                        }
 
293
                                                                        else
 
294
                                                                                break;
 
295
                                                                }       
 
296
                                                                Status =WaitingForStopBits;
 
297
                                                                BitsInData = 0;
 
298
//                                                              bitcounter=NumberOfStopBits;
 
299
                                                                bitcounter =1;
 
300
                                                        
 
301
                                break;  
 
302
                                                                        
 
303
                                case WaitingForStopBits:
 
304
                                        while ( DataAvailable && bitcounter >0 )
 
305
                                                {
 
306
                                                bit = get_next_bit();
 
307
                                                if ( DataAvailable)             // We've got a bit
 
308
                                                        {
 
309
                                                                bitcounter --;
 
310
                                                                if  (!bit)              // Framing Error
 
311
                                                                        {
 
312
                                                                        emit newSymbol('<');
 
313
                                                                        emit newSymbol('F');
 
314
                                                                        emit newSymbol('>');
 
315
                                                Status = CollectingByte;   // Lets try whether this was already the start bit
 
316
///                                                                     Status = WaitingForMark;
 
317
                                                                        bitcounter=NumberOfBits;
 
318
                                                                        c=0;
 
319
                                                                        if ( (Frequencykor != 0) && UseAfc && (ave1 > 0.35))
 
320
                                                                        {
 
321
                                                                                emit rxFrequencyChanged( RxFrequency + Frequencykor);
 
322
                    setRxFrequency ( RxFrequency + Frequencykor);
 
323
                                                                                Frequencykor =0;
 
324
                                                                        }
 
325
                                    break;
 
326
                                                                        }
 
327
                                                                else
 
328
                                                        {
 
329
                                                                                
 
330
                                                                c=0;
 
331
///                                                             Status=WaitingForSpace;
 
332
                                                                Status=WaitingForMark;
 
333
 
 
334
                                                                if ( ( Frequencykor != 0) && UseAfc && ( ave1 >0.35 ))
 
335
                                                                        {
 
336
                                                                                emit rxFrequencyChanged( RxFrequency + Frequencykor);
 
337
                    setRxFrequency ( RxFrequency + Frequencykor);
 
338
                                                                                Frequencykor =0;
 
339
                  }
 
340
                                                                break;
 
341
                                                        }       
 
342
 
 
343
                                                        }
 
344
                                                }
 
345
                                
 
346
                                break;
 
347
                                
 
348
                                case ThrowHalfBit:
 
349
                                        while ( DataAvailable && --bitcounter > 0)
 
350
                                                ProcessNextSample();
 
351
                                        if ( bitcounter == 0 )
 
352
                                                Status = WaitingForMark;
 
353
                                break;                  
 
354
                                                
 
355
                }       // End switch   
 
356
        }       // End While
 
357
}
 
358
 
 
359
int RTTYDemodulator::ProcessNextSample()
 
360
{
 
361
float x;
 
362
float z[NumberofTones];
 
363
int i,index;
 
364
if ( actSample<NxSamples )
 
365
        {
 
366
        DataAvailable = true;
 
367
        x= (float) data[actSample];
 
368
        actSample++;
 
369
  slfft(x);
 
370
        for (i=0;i < NumberofTones; i++)
 
371
                z[i] = abs(bins[i]);
 
372
 
 
373
index=0;
 
374
x= z[0];
 
375
for (i=1;i <NumberofTones;i++)
 
376
        {
 
377
        if (z[i]> x)
 
378
                {
 
379
                        index = i;
 
380
                        x = z[i];
 
381
                }
 
382
        }
 
383
        if ( index > 3)
 
384
                return 1;
 
385
        else
 
386
                return -1;
 
387
        }
 
388
else
 
389
        DataAvailable = false;
 
390
        
 
391
return 0;               
 
392
}
 
393
 
 
394
 
 
395
 
 
396
bool RTTYDemodulator::get_next_bit()
 
397
{
 
398
 
 
399
int x;
 
400
float z[NumberofTones],y;
 
401
int i, index;
 
402
 
 
403
/*while (DataAvailable)
 
404
        {
 
405
        if (count != SamplesPerBit )
 
406
                        {
 
407
                                if ( actSample<NxSamples )
 
408
                                {
 
409
                                        z= (float) data[actSample];
 
410
                                        count++;
 
411
                                        actSample++;
 
412
                                slfft(z);
 
413
                                }
 
414
                                else
 
415
                                        DataAvailable = false;
 
416
                                x = 0;
 
417
                        }
 
418
        else
 
419
                {
 
420
                        x = ProcessNextSample();
 
421
                        CalcQuality();
 
422
      reset();
 
423
                        break;
 
424
        }
 
425
        }*/
 
426
while (DataAvailable)
 
427
        {
 
428
        if ( actSample < NxSamples)
 
429
                {
 
430
                        y= (float) data[actSample];
 
431
                        count++;
 
432
                        actSample++;
 
433
                        slfft(y);
 
434
                        if ( count == SamplesPerBit)
 
435
                                {
 
436
                                        if (UseAfc)
 
437
                                                {
 
438
                                                        for (i=0;i < NumberofTones; i++)
 
439
                                                                z[i] = abs(bins[i]);
 
440
 
 
441
                                                        index=0;
 
442
                                                        y       = z[0];
 
443
                                                        for (i=1;i <NumberofTones;i++)
 
444
                                                                {
 
445
                                                                        if (z[i]> y)
 
446
                                                                        {
 
447
                                                                                index = i;
 
448
                                                                                y = z[i];
 
449
                                                                        }
 
450
                                                                }
 
451
                                                        if ( z[1] > z[5] )
 
452
                                                                x = -1;
 
453
                                                        else
 
454
                                                                x =1;
 
455
                                                        switch (index)
 
456
                                                                {
 
457
                                                                        case 1:       // Frequency is ok
 
458
                                                                        case 5:
 
459
                                                                                break;
 
460
                                                                        case 0:                         // Frequency is too high
 
461
                                                                        case 4:
 
462
                                                                                Frequencykor -= 1;
 
463
                                                                                break;
 
464
                                                                        case 2:                         // Frequency is too low
 
465
                                                                        case 6:
 
466
                                                                                Frequencykor += 1;
 
467
                                                                                break;
 
468
                                                                        default:
 
469
                                                                                break;
 
470
                                                                }       
 
471
                                                                        
 
472
                                                }
 
473
                                        else
 
474
                                                if ( abs(bins[1]) > abs(bins[5]) )
 
475
                                                        x= -1;
 
476
                                                else
 
477
                                                        x =1;
 
478
          CalcQuality();
 
479
                                        reset();
 
480
                                        break;
 
481
                                }
 
482
                }
 
483
         else
 
484
                {
 
485
                        DataAvailable = false;
 
486
                        x = 0;
 
487
                }
 
488
        }
 
489
return ( (x > 0 ) ? true : false) ;     
 
490
}
 
491
 
 
492
void RTTYDemodulator::slfft(float x)
 
493
{
 
494
float old;
 
495
 
 
496
///old = x - history[ptr];
 
497
old = history[ptr];
 
498
 
 
499
history[ptr] = x;
 
500
ptr = (ptr +1) % SamplesPerBit;
 
501
 
 
502
for (int i=0; i <NumberofTones;i++)
 
503
        bins[i] = bins[i]*twiddles[FrequencyNumber[i]] +x - old;
 
504
        
 
505
}
 
506
 
 
507
void RTTYDemodulator::setRxFrequency(double freq)
 
508
{
 
509
int i;
 
510
if ( freq != RxFrequency)
 
511
        {
 
512
                RxFrequency=freq;
 
513
                for(i=0; i < NumberofTones; i++)
 
514
                        bins[i]=float_complex(0.0,0.0);
 
515
 
 
516
                FrequencyNumber[1]= (RxFrequency*SamplesPerBit)/SampleRate+0.5;
 
517
                FrequencyNumber[0] = FrequencyNumber[1] - 1;
 
518
                FrequencyNumber[2] = FrequencyNumber[1] + 1;
 
519
                FrequencyNumber[3] = FrequencyNumber[2] + 1;
 
520
                FrequencyNumber[5]= ( (RxFrequency+170) *SamplesPerBit)/SampleRate+0.5;
 
521
                FrequencyNumber[4] = FrequencyNumber[5] - 1;
 
522
                FrequencyNumber[6] = FrequencyNumber[5] + 1;
 
523
   }
 
524
}
 
525
 
 
526
void RTTYDemodulator::CalcQuality()
 
527
{
 
528
ave2=ave1;
 
529
float sum,diff;
 
530
sum=abs(bins[1])+abs(bins[5]);
 
531
diff=abs( abs(bins[1])-abs(bins[5]));
 
532
//ave1=0.8*ave1 + 0.2 * abs(y0-y1)/(y0+y1);
 
533
if ( sum > 0.5 )
 
534
        ave1=0.7*ave1 + 0.25 * ave2 + 0.05 * diff/sum;
 
535
else
 
536
        ave1 = 0.5*ave1 + 0.3 *ave2;
 
537
emit setSquelchValue((int)(100*ave1));
 
538
}
 
539
 
 
540
 
 
541
 
 
542
 
 
543
void RTTYDemodulator::reset()
 
544
{
 
545
int i;
 
546
 
 
547
for(i=0;i<NumberofTones;i++)
 
548
                        bins[i]=float_complex(0.0,0.0);
 
549
for(i=0;i < SamplesPerBit; i++) 
 
550
                        history[i]=0.;
 
551
count =0;
 
552
x1=0;
 
553
 
 
554
}