0
\$\begingroup\$

While writing a time critical piece of code for an Attiny13, I figured I could use the rising edge of an input as a trigger to read in some self clocking data. However, the number of clock cycles needed to go into the interrupt routine differs depending on the instruction being executed at the moment.

  • How can I ensure the time from rising edge interrupt until start of the interrupt routine is always the same number of clock cycles?

Except for the interrupt routine there's no code running at the moment, so maybe there's a way to loop with a single instruction in the main code?

\$\endgroup\$
  • \$\begingroup\$ Personally, I'd do all I can to avoid the strategy entirely. I'd clock the data into a shift register, and then shift it out at leisure. \$\endgroup\$ – Scott Seidman Apr 9 '15 at 15:58
2
\$\begingroup\$

One option would be to have two triggers, the first causes the code to jump into a loop waiting for the signal to go low and then back high. As soon as the signal has gone back high, then start clocking the data.

Something like:

while(PINREG & (1<<PORTBIT)); //wait for low
while(!(PINREG & (1<<PORTBIT))); //wait for next high
//Clock in your data here...

In that code, the two while loops should simplify to branch when bit in register is set (or clear), which means that every 2 clock cycles it would check the trigger bit, and once the second edge was found, it would start with a predictable latency.

The latency would however be +/-1 cycle depending on where the rising edge occurred with relation to the clock, but this would be the case in all scenarios as the signals go through a clock synchronised in the I/O chain.

If your data symbol rate I less than ~F_CPU/4, then minor variation in latency of the above shouldn't be an issue. Any faster than that and you probably wouldn't be able to process in anyway - no time to actually do anything with the data as you clock it in.

\$\endgroup\$
0
\$\begingroup\$

Maybe you can flag readiness to accept an interrupt from within your code. This then clocks a D type flip flop and if the D input was set (meaning a pending interrupt) then the output from the D type becomes the "new" interrupt edge. It all depends on your ability to flag readiness.

\$\endgroup\$
0
\$\begingroup\$

I think you can spin in an infinite RJMP loop waiting for the interrupt. RJMP always takes 2 cycles, so you should have less than 2 cycles of jitter between the pin change and the entrance into the ISR.

To kick out of the RJMP loop, the ISR can pop the return address off the stack and then jump to the next state. You could also use the Timer to generate an interrupt to time out of the RJMP loop.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.