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.