The PRU is pretty cool. Just had to simulate a dozen eCAP devices and its just a few lines of code. An eCAP records the period (in ticks) of a signal on an input pin. It can be triggered on a rising or falling signal, and can record absolute ticks or the number of ticks since the last trigger (differential mode). Here's the main loop:
while (1)
{
uint32_t sample = __R31;
uint32_t change = sample ^ pEcap->sample;
if (change)
{
// Calculate which bits have seen a desired edge (it changed, and we trigger on that change)
uint32_t edge = change & trigger;
if (edge)
{
uint32_t ts = ReadTimestamp();
int bit = 1;
int iBit = 0;
while (iBit < 30)
{
if (edge & bit)
{
// Store the ts (or the difference in ts) into the capture table for this bit
// and increment the slot index (aICap)
pEcap->ECAP[iBit][pEcap->aICap[iBit]++] = (pEcap->differential & bit)? (ts - tsLast[iBit]) :ts;
pEcap->aICap[iBit] %= 4;
// Next time we calculate the difference from this time
tsLast[iBit] = ts;
}
iBit++;
bit <<= 1;
}
pEcap->edgeDetected |= edge;
}
pEcap->sample = sample;
trigger = sample ^ pEcap->edgeUpDown;
}
}
It detects an edge within a few dozen nanoseconds (low jitter). A while loop like this would kill a main processor thread; and it would have terrible latency when other threads were scheduled during a trigger event.
And it detects edges on 30 pins in parallel! I could work on the "which pin had a trigger" code to reduce the period calculation from X30 to log(30) but I have no need for that fine latency in my current application.
And it detects edges on 30 pins in parallel! I could work on the "which pin had a trigger" code to reduce the period calculation from X30 to log(30) but I have no need for that fine latency in my current application.