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?
//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