SDRAngel  4.11.5
Developer docs for <a href="https://github.com/f4exb/sdrangel">SDRangel<\a>, an Open Source Qt5 / OpenGL 3.0+ SDR and signal analyzer frontend to various hardware.
rdsdecoder.cpp
Go to the documentation of this file.
1 // Copyright (C) 2015 F4EXB //
3 // written by Edouard Griffiths //
4 // //
5 // This program is free software; you can redistribute it and/or modify //
6 // it under the terms of the GNU General Public License as published by //
7 // the Free Software Foundation as version 3 of the License, or //
8 // (at your option) any later version. //
9 // //
10 // This program is distributed in the hope that it will be useful, //
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
13 // GNU General Public License V3 for more details. //
14 // //
15 // You should have received a copy of the GNU General Public License //
16 // along with this program. If not, see <http://www.gnu.org/licenses/>. //
18 
19 #include "rdsdecoder.h"
20 
21 #include <QDebug>
22 #include <string.h>
23 
24 const unsigned int RDSDecoder::offset_pos[5] = {0,1,2,3,2};
25 const unsigned int RDSDecoder::offset_word[5] = {252,408,360,436,848};
26 const unsigned int RDSDecoder::syndrome[5] = {383,14,303,663,748};
27 
29 {
30  m_reg = 0;
31  m_presync = false;
33  m_bitCounter = 0;
34  m_lastseenOffset = 0;
35  m_blocksCounter = 0;
37  m_blockNumber = 0;
38  m_groupAssemblyStarted = false;
39  m_sync = SYNC;
42  m_goodBlock = false;
43  m_qua = 0.0f;
44  memset(m_group, 0, 4*sizeof(int));
45 }
46 
48 {
49 }
50 
51 bool RDSDecoder::frameSync(bool bit)
52 {
53  bool group_ready = false;
54  unsigned int reg_syndrome;
55  unsigned long bit_distance, block_distance;
56  unsigned int block_calculated_crc, block_received_crc, checkword, dataword;
57 
58  m_reg = (m_reg<<1) | bit;
59 
60  switch (m_sync)
61  {
62  case NO_SYNC:
63  reg_syndrome = calc_syndrome(m_reg,26);
64 
65  for (int j = 0; j < 5; j++)
66  {
67  if (reg_syndrome == syndrome[j])
68  {
69  if (!m_presync)
70  {
71  m_lastseenOffset = j;
73  m_presync=true;
74  }
75  else
76  {
77  bit_distance = m_bitCounter - m_lastseenOffsetCounter;
78 
80  {
81  block_distance = offset_pos[j] + 4 - offset_pos[m_lastseenOffset];
82  }
83  else
84  {
85  block_distance = offset_pos[j] - offset_pos[m_lastseenOffset];
86  }
87 
88  if ((block_distance*26)!=bit_distance)
89  {
90  m_presync = false;
91  }
92  else
93  {
94  //qDebug("RDSDecoder::frameSync: Sync State Detected");
95  enter_sync(j);
96  }
97  }
98 
99  break; //syndrome found, no more cycles
100  }
101  }
102  break;
103 
104  case SYNC:
105  // wait until 26 bits enter the buffer
106  if (m_blockBitCounter < 25)
107  {
109  }
110  else
111  {
112  m_goodBlock = false;
113  dataword = (m_reg>>10) & 0xffff;
114  block_calculated_crc = calc_syndrome(dataword, 16);
115  checkword = m_reg & 0x3ff;
116 
117  // manage special case of C or C' offset word
118  if (m_blockNumber == 2)
119  {
120  block_received_crc = checkword ^ offset_word[m_blockNumber];
121 
122  if (block_received_crc==block_calculated_crc)
123  {
124  m_goodBlock = true;
125  }
126  else
127  {
128  block_received_crc=checkword^offset_word[4];
129 
130  if (block_received_crc==block_calculated_crc)
131  {
132  m_goodBlock = true;
133  }
134  else
135  {
137  m_goodBlock = false;
138  }
139  }
140  }
141  else
142  {
143  block_received_crc = checkword ^ offset_word[m_blockNumber];
144 
145  if (block_received_crc==block_calculated_crc)
146  {
147  m_goodBlock = true;
148  }
149  else
150  {
152  m_goodBlock = false;
153  }
154  }
155 
156  //done checking CRC
157  if (m_blockNumber == 0 && m_goodBlock)
158  {
159  m_groupAssemblyStarted = true;
161  }
162 
164  {
165  if (!m_goodBlock)
166  {
167  m_groupAssemblyStarted = false;
168  }
169  else
170  {
171  m_group[m_blockNumber] = dataword;
173  }
174 
175  if (m_groupGoodBlocksCounter == 5)
176  {
177  group_ready = true; //decode_group(group); pass on to the group parser
178  }
179  }
180 
181  m_blockBitCounter = 0;
182  m_blockNumber = (m_blockNumber + 1) % 4;
183  m_blocksCounter++;
184 
185  // 1187.5 bps / 104 bits = 11.4 groups/sec, or 45.7 blocks/sec
186  if (m_blocksCounter == 50)
187  {
188  if (m_wrongBlocksCounter > 35)
189  {
190  /*
191  qDebug() << "RDSDecoder::frameSync: Lost Sync (Got " << m_wrongBlocksCounter
192  << " bad blocks on " << m_blocksCounter
193  << " total)";*/
194  enter_no_sync();
195  }
196  else
197  {
198  /*
199  qDebug() << "RDSDecoder::frameSync: Still Sync-ed (Got " << m_wrongBlocksCounter
200  << " bad blocks on " << m_blocksCounter
201  << " total)";*/
202  }
203 
204  m_qua = 2.0 * (50 - m_wrongBlocksCounter);
205  m_blocksCounter = 0;
207  }
208  }
209  break;
210  default:
211  break;
212  }
213 
214  m_bitCounter++;
215 
216  return group_ready;
217 }
218 
220 
221 void RDSDecoder::enter_sync(unsigned int sync_block_number)
222 {
224  m_blocksCounter = 0;
225  m_blockBitCounter = 0;
226  m_blockNumber = (sync_block_number + 1) % 4;
227  m_groupAssemblyStarted = false;
228  m_sync = SYNC;
229 }
230 
232 {
233  m_presync = false;
234  m_sync = NO_SYNC;
235 }
236 
240 unsigned int RDSDecoder::calc_syndrome(unsigned long message, unsigned char mlen)
241 {
242  unsigned long reg = 0;
243  unsigned int i;
244  const unsigned long poly = 0x5B9;
245  const unsigned char plen = 10;
246 
247  for (i = mlen; i > 0; i--)
248  {
249  reg = (reg << 1) | ((message >> (i-1)) & 0x01);
250  if (reg & (1 << plen)) reg = reg ^ poly;
251  }
252 
253  for (i = plen; i > 0; i--)
254  {
255  reg = reg << 1;
256  if (reg & (1<<plen)) {
257  reg = reg ^ poly;
258  }
259  }
260 
261  return (reg & ((1<<plen)-1)); // select the bottom plen bits of reg
262 }
263 
bool m_goodBlock
Definition: rdsdecoder.h:52
static const unsigned int offset_word[5]
Definition: rdsdecoder.h:58
unsigned int m_group[4]
Definition: rdsdecoder.h:53
void enter_no_sync()
Definition: rdsdecoder.cpp:231
bool m_groupAssemblyStarted
Definition: rdsdecoder.h:51
enum RDSDecoder::@0 m_sync
bool m_presync
Definition: rdsdecoder.h:42
unsigned long m_bitCounter
Definition: rdsdecoder.h:44
int32_t i
Definition: decimators.h:244
unsigned long m_lastseenOffsetCounter
Definition: rdsdecoder.h:43
unsigned int m_blockBitCounter
Definition: rdsdecoder.h:46
static const unsigned int offset_pos[5]
Definition: rdsdecoder.h:57
unsigned int m_blocksCounter
Definition: rdsdecoder.h:48
unsigned char m_blockNumber
Definition: rdsdecoder.h:50
unsigned int m_groupGoodBlocksCounter
Definition: rdsdecoder.h:49
bool frameSync(bool bit)
Definition: rdsdecoder.cpp:51
float m_qua
Definition: rdsdecoder.h:32
void enter_sync(unsigned int sync_block_number)
Definition: rdsdecoder.cpp:221
static const unsigned int syndrome[5]
Definition: rdsdecoder.h:59
unsigned int m_wrongBlocksCounter
Definition: rdsdecoder.h:47
unsigned int calc_syndrome(unsigned long message, unsigned char mlen)
Definition: rdsdecoder.cpp:240
unsigned long m_reg
Definition: rdsdecoder.h:40
unsigned char m_lastseenOffset
Definition: rdsdecoder.h:45