Looking at the RISC part of the CPU

The RISC software flow

Having looked at the CISC core it is the turn of the RISC. Alot less flexible than the CISC core and really only able to add and subtract with any efficiency but on the otherhand twice as rapid as the CISC core.

The RISC Core Software

The RISC engine in this MCU is based upon interrupt actions. An interrupt is generated, the interrupt handler decides which function is to be the handler, the handler runs to completion, the the RISC engine awaits the next IRQ. For maximum speed all RISC functions run from RAM

The XGATE (RISC engine) is also set up via a function triggered by the CISC CPU at start up, the symbol sample are loaded in the RISC RAM, the data set is loaded into shared CISC/RICS RAM, RISC functions are loaded into RAM, ADC clock is configured and started with default pilot clock sample values, the IRQ table defined. On the first pilot sample the RDS engine is begun and handled here:

interrupt void Timer_Handler(DataType* __restrict pData) 
{
  //  This handles the periodic timer to read the ATD. The time is 2.92uS
  //  Reset the timer IRQ flag
  ECT_TFLG1 = 1;                     // Reset interrupt request flag

We pass through the SDPLL on each ADC sample by placing the sample in a 32bit lock register, adjusting the ADC clock time to maintain lock. Obviously there is a short start up time until phase lock is achieved with the pilot. By displacing the comparision register we can have an orthoganal phase lock if required.

Next we recover a sample from the register of DAC levels by first looking up the sample in the data set. The data set is packed with 4 symbols per word. So here we extract the symbol_code for dataset0 (up to 4 data sets are available), symbol_element increments 0,,3 to cover the 4 posible symbol positions in the word:

//  Obtain the next symbol start point. The data setalready has the 
//  symbol to use. There are +ve and -ve profiles in the same array
switch (symbol_element) 
{
  case 3:
    symbol_code = (word)dataset0[dataset_position];
    break;
  case 2:
    symbol_code = (word)(dataset0[dataset_position] >> 4);
    break;
  case 1:
    symbol_code = (word)(dataset0[dataset_position] >> 8);
    break;
  case 0:
    symbol_code = (word)(dataset0[dataset_position] >> 12);
    break;
  default:
    symbol_code = (word)dataset0[dataset_position];
    break;
}

Next we extract the DAC level from the signalled sample of the symbol being acted upon, where _symbol_code is the symbol being sent and symbol_position is the position of the sample in the symbol information register:

_symbol_code = symbol_code & 0x000F;
switch (_symbol_code) 
{
  case 0:
    //  Upper part of symbol P0_P1 = P1
    symbol = ((word)_P0_P1[symbol_position] >> 8);
    break;
  case 1:
    //  Upper part of symbol P4_P5 = P5
    symbol = ((word)_P4_P5[symbol_position] >> 8);
    break;
  case 2:
    //  Lower part of symbol P2_P3 = P2
    symbol = (word)_P2_P3[symbol_position];
    break;
  case 3:
    //  Lower part of symbol P6_P7 = P6
    symbol = (word)_P6_P7[symbol_position];
    break;
  case 4:
    //  Upper part of symbol P6_P7 = P7
    symbol = ((word)_P6_P7[symbol_position] >> 8);
    break;
  case 5:
    //  Upper part of symbol P2_P3 = P3
    symbol = ((word)_P2_P3[symbol_position] >> 8);
    break;
  case 6:
    //  Lower part of symbol P4_P5 = P4
    symbol = (word)_P4_P5[symbol_position];
    break;
  case 7:
    //  Lower part of symbol P0_P1 = P0
    symbol = (word)_P0_P1[symbol_position];
    break;
  default:
    //  Upper part of symbol P0_P1 = P1
    symbol = ((word)_P0_P1[symbol_position] >> 8);
    break;
}

The symbol_element is incremented 0..3 to extract each symbol from a dataset word. The symbol_position increments 0..287 through the data set. The sequence then repeats through the dataset ad-infinitum.

However there are exceptions when there is a change to the data set eg: time data synchronisation, traffic anouncement, rich text change. We can do this by flipping from one dataset to another or by dynamically changing the active data set. To do this we need to know the progress of the dataset transmission and we do this by using RISC/CISC semaphores in the XGSEM register.

//  There are 4 symbol codes per word in modulation data and 288 samples per symbol
symbol_position++;
if(symbol_position > 287)  //  This is the symbol sample length
{
  symbol_position = 0;
  symbol_element++;
  if(symbol_element > 3) 
  {
    symbol_element = 0;
    //  Move to next dataset word, a new symbol pair
    dataset_position++;
    //  Set semaphore 4 on upper cycle of data set
    if(dataset_position == HALF_DATA_SET_SIZE) XGSEM = 0x1010;
    //  If the end of the modulation array is reached we re-cycle to the start
    if(dataset_position >= DATA_SET_SIZE)   // dataset_length) 
    {
      dataset_position = 0;
      if(XGSEM & 0x0002) XGSEM = 0x0101;
      else XGSEM = 0x0100; // Move outside so reset after 4 symbols
      //  Always set semaphore 4 to 0 at data set end
      XGSEM = 0x1000;
    }
  }
}