PDB settings on Teensy 3.6 - MOD and IDLY values

Status
Not open for further replies.

maelh

Member
Sorry for the many questions in a row, I hope that's the last one ;)

I have been reading through the source code employing the PDB, and I noticed that they all set PDB0_MOD to a value that is one less than I would expect.
Using an oscilloscope I did various tests that indeed this is the right thing to do to get the desired frequency.
I wonder however if there is anything that indicates why to do this. In the documentation of the Teensy 3.6 chip, they suggest that this is a modulo value that resets the PDB counter to 0. So if you want 10 counts 0..9 you would use 10 as modulus in normal math.

To get specific, the documentation says:
PDB Modulus

Specifies the period of the counter. When the counter reaches this value, it will be reset back to zero. If the
PDB is in Continuous mode, the count begins anew. Reading this field returns the value of the internal
register that is effective for the current cycle of PDB.
So in our example, you would set PDB0_MOD to 9 because you want to count from 0 to 9 (inclusive) and learned that you have to use the actual modulus -1.
According to the the doc excerpt above however you would have to set it to 10, because if you set it to 9 it would already reset to 0, which would be one too early.

How did you find out that you need to use modulo - 1? Is that documented somewhere?
This may seem like a very academical question. The reason I ask is that I would have very likely missed this subtelty if I hadn't noticed it in Teensy's source code. So maybe I read something wrong in the docs or missed something, that might be useful in similar situations.


The other question is: why is PDB0_IDLY set to 1 in many places?
If I understand correctly PDB0_MOD sets the maximum counter value, and PDB0_IDLY sets when inside this period (period = 0 to max counter value) the interrupt/DMA request is actually raised. In other words, you can delay the interrupt to happen later in the period, instead of just on the start.

Is this for synchronizing the DAC with the ADC. But in this case, why do both have the same delay?
 
I am talking about the DAC and ADC code of teensy. Does nobody have an insight on why PDB0_IDLY is 1 and not 0?
 
I am talking about the DAC and ADC code of teensy. Does nobody have an insight on why PDB0_IDLY is 1 and not 0?
In my program, I simply copied it from cores. I would try it with 0 and see if ADC/DAC is working, I even believe that you can trigger with one PDB phase shifted conversions on both ADCs.

Concerning the other question, my interpretation is that for a sequence of 10 counts starting from 0 (0,...,9) the highest number is 9 and it is this number you put in.
The counter decreases then to 0 and afterwards flips back to 9 (-1+10).
 
In my program, I simply copied it from cores. I would try it with 0 and see if ADC/DAC is working, I even believe that you can trigger with one PDB phase shifted conversions on both ADCs.
For a simple PDB that should just generate interrupts at a certain frequency it works perfeclty, not matter what I set IDLY to.
That's why I was wondering about its purpose in the ADC converters.
 
The other question is: why is PDB0_IDLY set to 1 in many places?
If I understand correctly PDB0_MOD sets the maximum counter value, and PDB0_IDLY sets when inside this period (period = 0 to max counter value) the interrupt/DMA request is actually raised. In other words, you can delay the interrupt to happen later in the period, instead of just on the start.

Is this for synchronizing the DAC with the ADC. But in this case, why do both have the same delay?
To show a couple concrete examples:

from AudioInputAnalog::init() in input_adc.cpp:
Code:
// set the programmable delay block to trigger the ADC at 44.1 kHz
#if defined(KINETISK)
	if (!(SIM_SCGC6 & SIM_SCGC6_PDB)
	  || (PDB0_SC & PDB_CONFIG) != PDB_CONFIG
	  || PDB0_MOD != PDB_PERIOD
	  || PDB0_IDLY != 1
	  || PDB0_CH0C1 != 0x0101) {
		SIM_SCGC6 |= SIM_SCGC6_PDB;
		[B]PDB0_IDLY = 1;[/B]
		PDB0_MOD = PDB_PERIOD;
		PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
		PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;
		PDB0_CH0C1 = 0x0101;
	}
#endif

from AudioOutputAnalog::begin() in output_dac.cpp:
Code:
	// set the programmable delay block to trigger DMA requests
	if (!(SIM_SCGC6 & SIM_SCGC6_PDB)
	  || (PDB0_SC & PDB_CONFIG) != PDB_CONFIG
	  || PDB0_MOD != PDB_PERIOD
	  || PDB0_IDLY != 1
	  || PDB0_CH0C1 != 0x0101) {
		SIM_SCGC6 |= SIM_SCGC6_PDB;
		[B]PDB0_IDLY = 1;[/B]
		PDB0_MOD = PDB_PERIOD;
		PDB0_SC = PDB_CONFIG | PDB_SC_LDOK;
		PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;
		PDB0_CH0C1 = 0x0101;
	}

and finally in Servo::attach() from Servo.cpp:
Code:
if (!(SIM_SCGC6 & SIM_SCGC6_PDB)) {
	SIM_SCGC6 |= SIM_SCGC6_PDB; // TODO: use bitband for atomic bitset
	PDB0_MOD = 0xFFFF;
	PDB0_CNT = 0;
	[B]PDB0_IDLY[/B] = 0;
	PDB0_SC = PDB_CONFIG;
	// TODO: maybe this should be a higher priority than most
	// other interrupts (init all to some default?)
	PDB0_SC = PDB_CONFIG | PDB_SC_SWTRIG;
	NVIC_SET_PRIORITY(IRQ_PDB, 32);
}

And as mentioned above, I noticed no effect when using the PDB to just generate "calls" to pdb_isr() at regular intervals, no matter what PDB0_IDLY was set to.

So, why PDB0_IDLY = 1 and not some other number. I don't see how one cycle is enough to synchronize, and why both, DAC and ADC are delayed by one.
 
Status
Not open for further replies.
Back
Top