Closed mattgilbertnet closed 10 years ago
On 2013.12.17 01:23 , mattgilbertnet wrote:
This is really a feature request more than an "issue".
This is surely a low priority, if it's even a concern for anyone other than me, but is there any chance of a tws_delayMicroseconds() being implemented?
delaymicroseconds is a bit tricky to implement, especially if you want it to be accurate see: https://github.com/rambo/arduino-tiny/blob/master/hardware/tiny/cores/tiny/wiring.c#L155
Doing function calls like TinyWireS_stop_check() there will completely mess up the delicate timing (as will any callbacks the stop_check may or may not trigger...)
You could do a naive implementation that looks something like this:
tws_delayMicroseconds_inaccurate(uint16_t usec) { uint16_t start = (uint16_t)micros(); while ((uint16_t)((uint16_t)micros() - start) < usec) { TinyWireS_stop_check(); } }
but it will be wildly inaccurate, the overhead per iteration is going to be many cycles, which means several microseconds even if there is no STOP condition, if there is a STOP then your timing will be totally blown out of the water since the function call to the callback alone will mess this up, and whatever the callback spends time on is added as well.
So if you need microsecond timing you're better off disabling interrupts and using delayMicroseconds() and perhaps using a separate io-line to tell the master that you're busy.
/Rambo
Thanks! This looks pretty straightforward, and since precise timing is less important for my application than having some range of timing on the scale of microseconds, I think this will do the trick.
This is just a nit, but wouldn't the naive loop be better written precalculating the end time?:
tws_delayMicroseconds_inaccurate(uint16_t usec)
{
uint16_t stopMicros = (uint16_t)micros() + usec;
while (((uint16_t)micros()) < stopMicros)
{
TinyWireS_stop_check();
}
}
@jockm: Please don't use "(((uint16_t)micros()) < stopMicros)
", because that leads to occasional difficult-to-debug glitches when TinyWireS_stop_check() takes more than 1 microsecond. For example, if we try to delay usec = 9 microseconds, and the first micros() call gives us 0xFFF6, this code sets "stopMicros" to 0xFFFF, and TinyWireS_stop_check() plus the loop overhead takes 2 microseconds, then this precalculating approach ends up stuck in the loop for over 65,000 microseconds (possibly forever), which is not what we wanted. The "((uint16_t)((uint16_t)micros() - start) < usec)
" properly handles rollover even with TinyWireS_stop_check(); taking anywhere from practically 0 to nearly 16,000 microseconds. See https://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover and https://stackoverflow.com/questions/61443/rollover-safe-timer-tick-comparisons and https://www.baldengineer.com/arduino-how-do-you-reset-millis.html for more details.
@carycode Fair point, but you should note that I was just copying rambo's style from above. This comment is better addressed there
This is really a feature request more than an "issue".
This is surely a low priority, if it's even a concern for anyone other than me, but is there any chance of a tws_delayMicroseconds() being implemented?