obdev/v-usb — pull request #4 by cpldcpu (2013-11-04 13:16:03+00:00)
Title: Optimized RC oscillator calibration

In the meantime I rewrote the entire oscillator calibration in assembler, saving 90 bytes in total. All changes reside in "libs-device" now, the usb-driver does not have to be altered.

Original text:

I spent some time optimizing calibrateOscillator(void). The new implementation has been debugged on an ATtiny 85 and was confirmed to converge to the same osccal value as the previous implementation. If desired, I can also supply some debug data. I used a SPI connection to monitor the new implementation in real time.

One thing that is still lacking is a separate define for USB_CFG_HAVE_MEASURE_FRAME_LENGTH to chose only the new implementation of usbMeasureFrameLength.
Benefits:

Codesize reduced by 90 bytes.
Improved robustness due to removing timeout from frame length measurement and inserted NOP after OSCCAL writes.

Changes:

The new routine performs a combined binary and neighborhood search in a single loop. Note that the neighborhood search is necessary due to the quasi-monotonic nature of OSCCAL. (See Atmel application note AVR054).
Inserted NOP after writes to OSCCAL to avoid CPU errors during oscillator stabilization.
Implemented new routine to measure frame time "usbMeasureFrameLengthDecreasing". This routine takes the target time as a parameter and returns the deviation.
usbMeasureFrameLengthDecreasing measures in multiples of 5 cycles and is thus slighly more accurate.
usbMeasureFrameLengthDecreasing does not support time out anymore. The original implementation returned zero in case of time out, which would have caused the old calibrateOscillator() implementation to increase OSSCAL to 255, effictively overclocking and most likely crashing the CPU. The new implementation will enter an infinite loop when no USB activity is encountered. The user program should use the watchdog to escape from situations like this.