Go Down

Topic: Need help modifying timer/counter PPM code (Read 211 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
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy