Go Down

Topic: Need help modifying timer/counter PPM code (Read 105 times) previous topic - next topic

stratosfear

The code in reply #10 generates PPM on the Due's D2 pin.  To work with a shield I've designed, I need PPM on pin D11.  Going through the (convoluted) data sheet, I've made these changes:

TC0 to TC2
PIOB to PIOD
TIOA0 to TIOA8
pin 25 to 7

The following code compiles and uploads without error.  D11 goes high , but the interrupt function never runs.  Can anyone figure out what I've missed? 

Code: [Select]
//Modified from original for PPM output on pin D11

// timer is clocked at 42MHz, so 42 ticks per us

//See Table 37-4 (sheet 872) for PD7 (Arduino pin D11):
//Instance    Signal        I/O line    Peripheral
//TC0         TIOA0         PB25        B          (original sketch that works)
//TC2         TIOA8         PD7         B          (my sketch that doesn't work)


uint32_t periods[] = {1000 * 42, 1000 * 42, 1000 * 42, 1000 * 42, 1000 * 42, 1000 * 42, 1000 * 42, 1000 * 42, 1000 * 42};
uint32_t num_periods = 8 + 1;  // number of channels +1

int ppm_channels[8];
long Frame;
long Sum;
int val = 1;

void TC2_Handler()
{
  long dummy = REG_TC2_SR0;  // vital - reading this clears some flag, 37.7.17
  // otherwise you get infinite interrupts
  static int i = 0;
  REG_TC2_RC0 = periods[i++];  //37.7.16
  if (i >= num_periods)i = 0;
  //Serial.println("interrupt"); 
}

void setup() {

  //Serial.begin(115200);

  //This does not work...
  pinMode(11, OUTPUT);          // port D pin 7
  analogWrite(11, 255);         // sets up some other registers I haven't worked out yet
  REG_PIOD_WPMR = 0x50494F00;  // enable write to register, 32.7.42 
  REG_PIOD_PDR  = 1 << 7;     // disable PIO, enable peripheral      see Section 32.7.2
  REG_PIOD_ABSR = 1 << 7;     // select peripheral B (TIOA8) TC2, 32.7.24
  REG_TC2_WPMR  = 0x54494D00;  // enable write to registers, 37.7.9

  REG_TC2_CMR0  = 0b00000000000010011100010000000000; // set channel mode register (see 37.7.11)
  //REG_TC2_CMR0  = 0b00000000000001101100010000000000; // alternative CMR for inverted output
  REG_TC2_RC0   = 100000000;   // counter period, 37.7.16
  REG_TC2_CCR0  = 0b101;       // start counter, 37.7.3
  REG_TC2_IER0  = 0b00010000;  // enable interrupt on counter = rc, 37.7.18
  REG_TC2_IDR0  = 0b11101111;  // disable other interrupts, 37.7.19

  REG_TC2_RA0   = 0.5 * 1000 * 42; // Pulse length     = .5ms, 37.7.14
  Frame         = 22 * 1000 * 42; // ppm frame length = 22ms

  ppm_channels[0] = 0;         // channel 1 from 0 to 255
  ppm_channels[1] = 0;         // channel 2 from 0 to 255
  ppm_channels[2] = 255;       // channel 3 from 0 to 255
  ppm_channels[3] = 0;         // channel 4 from 0 to 255
  ppm_channels[4] = 0;         // channel 5 from 0 to 255
  ppm_channels[5] = 0;         // channel 6 from 0 to 255
  ppm_channels[6] = 0;         // channel 7 from 0 to 255
  ppm_channels[7] = 0;         // channel 8 from 0 to 255


  NVIC_EnableIRQ(TC2_IRQn);    // enable TC2 interrupts
}

void loop() {

  // 1. Setup 8 channels (changing only channel 1 here just for fun)
  ppm_channels[0] = ppm_channels[0] + val;
  if (ppm_channels[0] >= 255) {
    val = -1;
  }
  if (ppm_channels[0] <= 0)  {
    val = 1;
  }
  //delay(25);

  // 2. Calculate the 8 channels
  Sum = 0;
  for (int i = 0; i < 8; i++)  {
    periods[i] = map(ppm_channels[i], 0, 255, 1000 * 42, 2000 * 42);
    Sum = Sum + periods[i];
  }
  // 3. Calculate the sync frame
  periods[8] = Frame - Sum;
 
  //Serial.println("loop");
}




Jon

Go Up