The RDS data stream is generated as a series of bytes. This has to be converted to a stream of sysmbols, that in turn decide the information to be sent to the DAC.
The differential encoding consists of taking bit pairs and generating a change or no change of state. The result is placed back into the same bit as the later of the bits pair
void EncodeDifferential(void)
{
// Take the payload and differential encode into differential_encoded_payload.
// Works at bit level
// There is a maximum PAYLOAD_SIZE of bytes and payload.part.frame_count of active frames
// Between bytes and last bit last byte wrap
// Prime the start
word size = (payload.part.frame_count * 13);
byte value = 0;
byte shift = 0;
int i = 0;
byte b_next = 0x00;
// At the start the previous bit is unknown could have been 0 or 1. We try 0 first
byte b_previous = 0;
// Empty the differental array
for(i = 0; i < size; i++) differential_encoded_payload[i] = 0x00;
for(i = 0; i < size; i++)
{
// Run along the bytes. The shift is offset by 1
value = payload.frame_byte[i];
for(shift = 8; shift > 0; shift--)
{
// Run along the bits
b_next = (byte)((value >> (shift - 1)) & 0x01);
// Encode
// If the bit is set place the bit
if(b_previous != b_next)
{
switch (shift)
{
case 8:
differential_encoded_payload[i] |= 0x80;
break;
case 7:
differential_encoded_payload[i] |= 0x40;
break;
case 6:
differential_encoded_payload[i] |= 0x20;
break;
case 5:
differential_encoded_payload[i] |= 0x10;
break;
case 4:
differential_encoded_payload[i] |= 0x08;
break;
case 3:
differential_encoded_payload[i] |= 0x04;
break;
case 2:
differential_encoded_payload[i] |= 0x02;
break;
case 1:
differential_encoded_payload[i] |= 0x01;
break;
}
b_previous = 1;
} // End of bit set
else b_previous = 0; // Update previous to current output
}
}
}
The encoding must form a consistent circle, with the last bit (n = 0-1) unknown when the encoding starts.
There are 8 possible symbols (P0..P7) as per a window of three differentially encoded bits.
void EncodeModulationSymbols(byte set)
{
// Takes the differential_encoded_payload and converts to symbols in modulation_data
// P0 u d u d u d == 1 1 1
// P1 d u d u d u == 0 0 0
// P2 d u u d d u == 0 1 0
// P3 u d d u u d == 1 0 1
// P4 u d u d d u == 1 1 0
// P5 d u d u u d == 0 0 1
// P6 d u u d u d == 0 1 1
// P7 u d d u d u == 1 0 0
// Three bits are required to decide on each symbol
// Initialise with last bit of sequence, first bit of sequence
word i = 0; // The symbol
byte j = 6; // The bit position in the byte
word k = 0; // The payload byte
word l = 0; // modulation_data position
word number_of_symbols = 0;
word symbol = 0;
// bytes are assigned to the bit value
byte bLast = (differential_encoded_payload[((payload.part.frame_count * 13) - 1)] & 0x01);
byte bFirst = (differential_encoded_payload[0] & 0x80);
byte bNext = 0;
byte bActual = bFirst;
byte bPrevious = bLast;
byte symbol_place_mark = 0;
// The first symbol to next to last
// The number of symbols is calculated from payload.part.frame_count
number_of_symbols = payload.part.frame_count * 13 * 8;
for(i = 0; i < number_of_symbols; i++)
{
symbol = 0x0000;
// Special case on last symbol, this overlaps into the first element
if(i == (number_of_symbols - 1)) bNext = bFirst;
else
{
if(j == 0) bNext = (differential_encoded_payload[k] & 0x01);
else if (j == 1) bNext = (differential_encoded_payload[k] & 0x02);
else if (j == 2) bNext = (differential_encoded_payload[k] & 0x04);
else if (j == 3) bNext = (differential_encoded_payload[k] & 0x08);
else if (j == 4) bNext = (differential_encoded_payload[k] & 0x10);
else if (j == 5) bNext = (differential_encoded_payload[k] & 0x20);
else if (j == 6) bNext = (differential_encoded_payload[k] & 0x40);
else if (j == 7) bNext = (differential_encoded_payload[k] & 0x80);
if(j == 0)
{
k++; // Go to next payload byte and msbit
j = 7;
}
else j--;
}
if(bPrevious) symbol |= 0x0004;
if(bActual) symbol |= 0x0002;
if(bNext) symbol |= 0x0001;
// The symbol code has been obtained. There are 4 symbols per word
if(set == 0)
{
switch (symbol_place_mark)
{
case 3:
current_data_set[l] |= (word)((word)symbol & 0x000F);
l++; // Increment for next data position
break;
case 2:
current_data_set[l] |= (word)(((word)symbol << 4) & 0x00F0);
break;
case 1:
current_data_set[l] |= (word)(((word)symbol << 8) & 0x0F00);
break;
case 0:
current_data_set[l] = (word)(((word)symbol << 12) & 0xF000);
break;
}
}
// Shift elements
bPrevious = bActual;
bActual = bNext;
symbol_place_mark++;
if(symbol_place_mark > 3) symbol_place_mark = 0;
}
// Modulation_data is now encoded in symbol codes, 4 per modulation_data element
// 1 x symbol = 1 x bit. 1 x word = 4 x bit, 1664 x words = 832 x bytes. 832 x bytes = 64 x frame. 1 x frame = 13 bytes.
}
First a window of three bits is defined. This bit sequence gives the symbol 000 ... 0111
Then the symbols are packed 4 per word (this is a word based CPU .
With this information the modulator determines the symbol to be transmitted.