~ubuntu-branches/debian/jessie/linpsk/jessie

« back to all changes in this revision

Viewing changes to src/rttydemodulator.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Hamish Moffatt
  • Date: 2005-04-10 18:17:27 UTC
  • mfrom: (1.1.1 upstream) (2.1.1 warty)
  • Revision ID: james.westby@ubuntu.com-20050410181727-3l9dnfg0sp7bhk13
Tags: 0.8.1-1
* New upstream release 0.8.1
  * Modified upstream configure.in to support FHS-compliant Qt
    installation! (ie /usr/include/qt3, not /usr/lib/qt3/include) :-(
  * Re-autotools with autoconf2.59 and automake-1.9
* linpsk is no longer a Debian-native package (dsc/tar.gz)
* Now maintained by the debian-hams group
* Switch to debhelper 4

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
 ***************************************************************************/
 
16
 
 
17
#include "rttydemodulator.h"
 
18
#include "firfilter.h"
 
19
#include "constants.h"
 
20
 
 
21
//#define CC1 0.9491 //   0.875 0.125 0.9125 0.0875 0.2 0.8
 
22
//#define CC3 0.05518// 0.9 0.02
 
23
//#define B1 0.932
 
24
#define CC1 0.95    /// 1. 0.1 0.7 , 0.775 0.1 0.7 , 0.8 0.08 0.575
 
25
#define CC3 0.15     /// 0.975 0.05 0.55 , 0.95 0.06 0.4 , 0.975 0.2 0.625
 
26
#define B1  0.625
 
27
#define DOWN 2
 
28
#define HoldLimit 3
 
29
RTTYDemodulator::RTTYDemodulator():FSKDemodulator(2)
 
30
{
 
31
ShiftOn = false;
 
32
BufferPointer=0;
 
33
BufferCount=0;
 
34
StopBit1Length=0;
 
35
RxFrequency=0.0; // Will be set correctly in setFrequency !
 
36
//Initialize ExtraParameter
 
37
extraParameter.stopbits=Onepoint5;
 
38
extraParameter.parity=None;
 
39
extraParameter.reverse=true;
 
40
extraParameter.offset=170;
 
41
 
 
42
C1=CC1;
 
43
C3=CC3;
 
44
}
 
45
RTTYDemodulator::~RTTYDemodulator()
 
46
{
 
47
 /**
 
48
 if (Lp0 != 0)
 
49
  delete Lp0;
 
50
 if (Lp1 != 0)
 
51
  delete Lp1;
 
52
 if (Lp2 != 0)
 
53
  delete Lp2;
 
54
 
 
55
 Lp0=0;
 
56
 Lp1=0;
 
57
 Lp2=0;
 
58
 **/
 
59
}
 
60
/** returns the asci char corresponding to the baudot code */
 
61
char RTTYDemodulator::baudot_code(char data)
 
62
{
 
63
/** Table of letters */
 
64
 
 
65
static const char letters[32] = {0x00,'E','\r','A',' ','S','I','U',
 
66
                                 '\n','D','R','J','N','F','C','K',
 
67
                                 'T','Z','L','W','H','Y','P','Q',
 
68
                                 'O','B','G','^','M','X','V','^'};
 
69
 
 
70
 
 
71
/** Table of symbols */
 
72
static const char symbols[32] = {0x00,'3','\r','-',' ','\'','8','7',
 
73
                                  '\n','$','4','#',',','!',':','(',
 
74
                                   '5','"',')','2','#','6','0','1',
 
75
                                   '9','?','&','^','.','/',';','^'};
 
76
 
 
77
char c;
 
78
 
 
79
 switch (data)
 
80
 {
 
81
  case 0x1f :
 
82
   ShiftOn = false;  //LTRS
 
83
   c = 0;
 
84
   break;
 
85
  case 0x1b :
 
86
   ShiftOn = true;   //FIGS
 
87
   c = 0;
 
88
   break;
 
89
  default:
 
90
   if (!ShiftOn)
 
91
    c=letters[(int) data];
 
92
   else
 
93
    c=symbols[(int) data];
 
94
    break;
 
95
 }
 
96
 
 
97
 
 
98
if ( c == ' ')  // Unshift on Space
 
99
 ShiftOn =false;        
 
100
 
 
101
return c;
 
102
}
 
103
 
 
104
bool RTTYDemodulator::Init(double FS,int NumberofSamples)
 
105
{
 
106
 double coeffs[NumberofProbes], x0;
 
107
 int i;
 
108
FSKDemodulator::Init(FS,NumberofSamples);
 
109
Baudrate=45.45;
 
110
NumberOfBits=5;
 
111
SymbolLength=int (FS/Baudrate+0.5);
 
112
Status = WaitingForMark;
 
113
FrequencyChanged = false;
 
114
ave1=0.5;
 
115
ave2=0.0;
 
116
setFilter(Baudrate,SymbolLength,Distance);
 
117
setRxFrequency(1000.);
 
118
DisplayPointer=0;
 
119
 
 
120
x0 = PI2*85./(11025./Distance);
 
121
for(i=0; i < NumberofProbes; i++)
 
122
 {
 
123
  if( i != (NumberofProbes-1)/2 )
 
124
   coeffs[i]=sin(x0*(i-(NumberofProbes-1)/2))/(i-(NumberofProbes-1)/2);
 
125
  else
 
126
   coeffs[i]=x0;
 
127
  coeffs[i] *=(0.42-0.5*cos((PI2*i)/(NumberofProbes-1))
 
128
                +0.08*cos((PI2*(i+i))/(NumberofProbes-1)));
 
129
 }
 
130
  // Normalize for unity at DC
 
131
  x0=0.;
 
132
  for(i=0;i<NumberofProbes;i++) 
 
133
   x0 +=coeffs[i];
 
134
  for(i=0;i<NumberofProbes;i++) 
 
135
   coeffs[i] /=x0;
 
136
DiscriminatorThreshold=0.;
 
137
MarkMax=0.05;
 
138
SpaceMax=0.05;
 
139
holdCount1=0;
 
140
holdCount2=0;
 
141
return true;
 
142
}
 
143
 
 
144
void RTTYDemodulator::ProcessInput(double *input, double *)
 
145
{
 
146
char c1;
 
147
int i,j,count;
 
148
int StartBitCount,StopBit2Length, StartBitLength;
 
149
int StopBit2Count;
 
150
int actSample;
 
151
int SamplestoProcess;
 
152
actSample = 0;
 
153
double F0in[MaxSamplestoProcess], F1in[MaxSamplestoProcess];
 
154
 //, F0out[MaxSamplestoProcess], F1out[MaxSamplestoProcess];
 
155
//double ThresholdInput[MaxSamplestoProcess],ThresholdOutput[MaxSamplestoProcess];
 
156
 
 
157
float xx,xSum,StartBitValue, StopBit2Value;
 
158
 
 
159
mixer(input);
 
160
SamplestoProcess=lpDownSample();
 
161
for(i=0;i <SamplestoProcess;i++)
 
162
{
 
163
 F0in[i]=abs(FilterOutput[0][i]);
 
164
 F1in[i]=abs(FilterOutput[1][i]); 
 
165
}
 
166
 
 
167
 
 
168
while ( actSample < SamplestoProcess )
 
169
{
 
170
 if( (BufferCount < SampleBufferLength ) )
 
171
 { 
 
172
  while ( (BufferCount < SampleBufferLength ) && ( actSample < SamplestoProcess ) )
 
173
  {
 
174
    BufferCount++;
 
175
 
 
176
    ellipseDisplay[DisplayPointer]=complex<float>(0.,5.);
 
177
    DisplayPointer = (DisplayPointer +1 )% 512;
 
178
    if (extraParameter.reverse)
 
179
    {
 
180
     MarkBuffer[BufferPointer]=F1in[actSample];
 
181
     SpaceBuffer[BufferPointer]=F0in[actSample];
 
182
    } 
 
183
    else
 
184
    { 
 
185
     MarkBuffer[BufferPointer]=F0in[actSample];
 
186
     SpaceBuffer[BufferPointer]=F1in[actSample];
 
187
    } 
 
188
    if(MarkMax < MarkBuffer[BufferPointer] )
 
189
    {
 
190
     MarkMax = MarkMax + C1 * ( MarkBuffer[BufferPointer]-MarkMax);
 
191
     holdCount1=0;
 
192
    }
 
193
    else
 
194
    {
 
195
     if ( holdCount1 == HoldLimit )
 
196
      MarkMax = MarkMax - C3 * ( MarkMax -MarkBuffer[BufferPointer]);
 
197
     else
 
198
      holdCount1++;
 
199
    }
 
200
    if(SpaceMax < SpaceBuffer[BufferPointer] )
 
201
    {
 
202
     SpaceMax = SpaceMax + C1 * ( SpaceBuffer[BufferPointer]-SpaceMax);
 
203
     holdCount2=0;
 
204
    }
 
205
    else
 
206
    {
 
207
     if ( holdCount2 == HoldLimit )
 
208
      SpaceMax = SpaceMax - C3 * ( SpaceMax -SpaceBuffer[BufferPointer]);
 
209
     else
 
210
      holdCount2++; 
 
211
    }
 
212
    MarkBuffer[BufferPointer] -= MarkMax/2;
 
213
    SpaceBuffer[BufferPointer] -= SpaceMax/2;
 
214
    
 
215
    CharacterData[BufferPointer]=MarkBuffer[BufferPointer]-SpaceBuffer[BufferPointer];
 
216
    BufferPointer++;
 
217
    BufferPointer=BufferPointer%SampleBufferLength;
 
218
    actSample ++;
 
219
  } // End of filling CharacterData
 
220
 }
 
221
 while (BufferCount == SampleBufferLength)
 
222
 {  
 
223
  switch (Status)  // Now let's analyze the data
 
224
  {
 
225
   case WaitingForMark:        // Waiting for Stopbit, previous state undefined 
 
226
 
 
227
    switch(extraParameter.stopbits)
 
228
    {
 
229
     case One:
 
230
      StopBit1Length=NumberofProbes;
 
231
      break;
 
232
     case Onepoint5:
 
233
      StopBit1Length =(3*NumberofProbes)/2;
 
234
      break;
 
235
      
 
236
     case Two:
 
237
      StopBit1Length=2*NumberofProbes;
 
238
      break;  
 
239
    }
 
240
    // Check, if we are possibly at the beginning of a stop bit
 
241
    
 
242
    i = 0;
 
243
    while ( (i < BufferCount ) && (CharacterData[(BufferPointer + i) % SampleBufferLength] <= DiscriminatorThreshold ) )
 
244
     i++;
 
245
    if ( i == 0 ) // At the beginning
 
246
    {
 
247
     StopBit1Count=0;
 
248
     xSum=0.;
 
249
     StopBit1Value=0.;
 
250
     while ( i < StopBit1Length )
 
251
     {
 
252
      if (CharacterData[(BufferPointer + i) % SampleBufferLength] > DiscriminatorThreshold )
 
253
       StopBit1Count++;
 
254
      StopBit1Value +=MarkBuffer[(BufferPointer + i) % SampleBufferLength];
 
255
      xSum += CharacterData[(BufferPointer + i) % SampleBufferLength];
 
256
      i++;
 
257
     }
 
258
     StopBit1Value= StopBit1Value/StopBit1Length;
 
259
     xSum = xSum / StopBit1Length;
 
260
     if ( xSum > DiscriminatorThreshold  ) 
 
261
      Status = WaitingForSpace;
 
262
     else
 
263
      BufferCount -= StopBit1Count;
 
264
    }
 
265
    else         // Refill the buffer
 
266
     BufferCount -=i;
 
267
   break;
 
268
    
 
269
    case WaitingForSpace:      // Stopbit seems to be found, now waiting for transition
 
270
    
 
271
     i = StopBit1Length  ;
 
272
     while( (i < SampleBufferLength) && (CharacterData[(BufferPointer + i) % SampleBufferLength ]
 
273
                                         > DiscriminatorThreshold ) )
 
274
      i++;
 
275
     if (i == SampleBufferLength )
 
276
     {
 
277
      BufferCount= StopBit1Length;   // No Space found, keep only StopBit1Length Samples
 
278
      DiscriminatorThreshold /=DOWN;
 
279
      CalcQuality((float)0.);
 
280
     }
 
281
     else
 
282
     {
 
283
      Status=CheckingStartBit;
 
284
      i = i - StopBit1Length; 
 
285
      BufferCount -=i;              // Refill buffer
 
286
     }
 
287
     break;
 
288
     
 
289
    case CheckingStartBit:
 
290
     
 
291
     j = StopBit1Length + BufferPointer;
 
292
     xSum =0.;
 
293
     StartBitValue = 0.;
 
294
     StartBitCount=0;
 
295
     StartBitLength = NumberofProbes;
 
296
     for ( i= 0; i < NumberofProbes; i++)
 
297
     { 
 
298
      if (CharacterData[( i + j ) % SampleBufferLength]  < DiscriminatorThreshold )
 
299
       StartBitCount++;
 
300
      StartBitValue += SpaceBuffer[( i + j ) % SampleBufferLength];
 
301
      xSum += CharacterData[( i + j ) % SampleBufferLength];
 
302
     }
 
303
     
 
304
     StartBitValue= StartBitValue / StartBitLength; 
 
305
     xSum = xSum/StartBitLength;
 
306
     if ( xSum < DiscriminatorThreshold ) // Super, Startbit fits very well
 
307
     {
 
308
      Status = CheckingStopBits;
 
309
      DiscriminatorThreshold = B1 * DiscriminatorThreshold + (1.-B1) * (StopBit1Value - StartBitValue ) /2; 
 
310
     if(abs(xSum) > 0.01)
 
311
      CalcQuality(abs(StartBitValue/xSum));
 
312
     else
 
313
      CalcQuality(abs(xSum));
 
314
     }
 
315
     else
 
316
     {
 
317
       Status = WaitingForMark;           // Was'nt the correct start bit, neither number nor value fits
 
318
       BufferCount -= StopBit1Length;
 
319
       CalcQuality((float)0.);
 
320
     } 
 
321
     
 
322
     break;
 
323
     
 
324
     case CollectingByte:
 
325
      c1=0;
 
326
      for(i=0;i < NumberOfBits; i++)  
 
327
      {
 
328
       j=(BufferPointer + StopBit1Length + StartBitLength + i * NumberofProbes ) % SampleBufferLength;
 
329
       xx =0.;
 
330
       count = 0;
 
331
       for(int j1=j;j1 <j + NumberofProbes; j1++)
 
332
        xx += CharacterData[j1];
 
333
       xx /= NumberofProbes;
 
334
       
 
335
       if ( xx > DiscriminatorThreshold )
 
336
       {
 
337
        c1 |= ( 1 << i);
 
338
        DiscriminatorThreshold =B1 * DiscriminatorThreshold + (1.-B1) * (xx - StopBit1Value)/2 ;
 
339
        StopBit1Value=xx;
 
340
       }
 
341
       else 
 
342
       {
 
343
        DiscriminatorThreshold =B1 * DiscriminatorThreshold + (1.-B1) * (StartBitValue-xx)/2 ;
 
344
        StartBitValue=xx;
 
345
       }
 
346
      }  
 
347
      if ( (c1 > 0 ) && (!Squelch || (Squelch && ( (unsigned int)(100.*ave1)>CDemodulator::Threshold))))
 
348
      {
 
349
       c1 = baudot_code(c1);
 
350
       if ( c1 > 0)           // FIGS or LTRS result in c1 = 0 !
 
351
        emit newSymbol( c1 );
 
352
      } 
 
353
     
 
354
      if (extraParameter.parity != None)
 
355
       Status = CheckingParity;
 
356
      else
 
357
      {
 
358
       if ( xSum > DiscriminatorThreshold ) //|| (StopBit2Value > DiscriminatorThreshold) )
 
359
        Status = WaitingForSpace;
 
360
       else
 
361
        Status=WaitingForMark;
 
362
       BufferCount -= (StopBit1Length + StartBitLength + 5*NumberofProbes  );
 
363
       StopBit1Length=StopBit2Length;
 
364
       StopBit1Count=StopBit2Count;
 
365
       StopBit1Value=StopBit2Value;
 
366
      }
 
367
     break;
 
368
      
 
369
     case CheckingParity: // Here we need BitsInData
 
370
     break;
 
371
      
 
372
     case CheckingStopBits:
 
373
      switch(extraParameter.stopbits)
 
374
      {
 
375
       case One:
 
376
        StopBit2Length=NumberofProbes;
 
377
        break;
 
378
       case Onepoint5:
 
379
        StopBit2Length =(3*NumberofProbes)/2;
 
380
        break;
 
381
        
 
382
       case Two:
 
383
        StopBit2Length=2*NumberofProbes;
 
384
        break;  
 
385
      }
 
386
      
 
387
      xSum=0.;
 
388
      StopBit2Count=0;
 
389
      StopBit2Value=0.;
 
390
      j = BufferPointer+StopBit1Length + StartBitLength + NumberOfBits*NumberofProbes;
 
391
      for ( i=0; i < StopBit2Length;i++)
 
392
      { 
 
393
       xx = CharacterData[(j+i)%SampleBufferLength];
 
394
       StopBit2Value += MarkBuffer[(j+i)%SampleBufferLength];
 
395
       if ( xx > DiscriminatorThreshold)
 
396
        StopBit2Count++;
 
397
       xSum +=xx;
 
398
      }
 
399
      StopBit2Value = StopBit2Value/StopBit2Length; 
 
400
      xSum /= StopBit2Length;
 
401
      if ( xSum > DiscriminatorThreshold ) //|| ( StopBit2avgThreshold > DiscriminatorThreshold ) )
 
402
       Status = CollectingByte; 
 
403
      else
 
404
      {
 
405
       if (StartBitValue < DiscriminatorThreshold ) 
 
406
       {
 
407
        
 
408
       Status = CollectingByte; 
 
409
       }
 
410
       else
 
411
       {
 
412
       // StartBit was not Ok, can we correct ?
 
413
        Status = WaitingForMark;
 
414
        BufferCount -= (StopBit1Length+ StartBitLength/2);
 
415
       }
 
416
      }
 
417
     break; 
 
418
  }  // end of switch
 
419
 }
 
420
 }
 
421
}
 
422
void RTTYDemodulator::setRxFrequency(double freq)
 
423
{
 
424
 if ( freq != RxFrequency)
 
425
 {
 
426
  RxFrequency=freq; 
 
427
  mixerfreqinc[0]=PI2*(RxFrequency)/SampleRate;
 
428
  mixerfreqinc[1]=PI2*(RxFrequency+extraParameter.offset)/SampleRate;
 
429
 }
 
430
}
 
431
void RTTYDemodulator::CalcQuality(float x)
 
432
{
 
433
 ave2=ave1;
 
434
 ave1=0.3*ave1 + 0.15 *ave2 + 0.55 * x;
 
435
// ave1 = 0.4899*ave1 + 0.9165 *ave2 + 0.916572 *x;
 
436
}
 
437
void RTTYDemodulator::CalcQuality(int pointer)
 
438
{
 
439
ave2=ave1;
 
440
float sum,diff;
 
441
pointer = pointer % SampleBufferLength;
 
442
diff=abs(CharacterData[pointer]);
 
443
sum=MarkBuffer[pointer]+SpaceBuffer[pointer];
 
444
 
 
445
//if ( sum > 0.1 )
 
446
 ave1=0.7*ave1 + 0.25 * ave2 + 0.05 * diff/sum;
 
447
//else
 
448
// ave1 = 0.5*ave1 + 0.3 *ave2;
 
449
}
 
450
 
 
451
int RTTYDemodulator::getSquelchValue()
 
452
{
 
453
return (int)(100.*ave1);
 
454
}
 
455
 
 
456
double RTTYDemodulator::get2RxFrequency()
 
457
{
 
458
 return RxFrequency+extraParameter.offset;
 
459
 
 
460
}
 
461
void RTTYDemodulator::setParameter(RxTxParameterType Type,void *Value)
 
462
{
 
463
switch (Type)
 
464
 {
 
465
 case Reverse:
 
466
        extraParameter.reverse =  * (bool *) Value;
 
467
        break;
 
468
 case Offset:
 
469
        extraParameter.offset = * (int *) Value;
 
470
        break;
 
471
case Parity:
 
472
        extraParameter.parity = * (Paritaet *) Value;
 
473
        break;
 
474
case Extra:
 
475
       extraParameter = * (ExtraParameter *) Value;
 
476
       break; 
 
477
 default:
 
478
        break;
 
479
 }
 
480
}
 
481
void *RTTYDemodulator::getParameter(RxTxParameterType Type)
 
482
{
 
483
switch (Type)
 
484
 {
 
485
 case Reverse:
 
486
        return (void *) &extraParameter.reverse; 
 
487
        break;
 
488
 case Offset:
 
489
        return (void *) &extraParameter.offset;
 
490
        break;
 
491
case Parity:
 
492
        return (void *) &extraParameter.parity;
 
493
        break;
 
494
case Extra:
 
495
        return (void *) &extraParameter;
 
496
        break;        
 
497
 default:
 
498
        return 0;
 
499
        break;
 
500
  }      
 
501
}
 
502
void *RTTYDemodulator::getBuffer()
 
503
{
 
504
return (void *) ellipseDisplay;
 
505
}
 
506
AfcMode RTTYDemodulator::AfcProperties()
 
507
{
 
508
return Off;
 
509
}