summaryrefslogtreecommitdiffstats
path: root/firmware/libs-device/osctune.h
diff options
context:
space:
mode:
authorJenna Fox <a@creativepony.com>2012-09-23 16:09:28 +1000
committerJenna Fox <a@creativepony.com>2012-09-23 16:09:28 +1000
commit824c303782a62b57b6525875b3c2dee81056baa4 (patch)
tree03ce927f2481dd43e8531abaa4abef159b73db75 /firmware/libs-device/osctune.h
downloadmicronucleus-824c303782a62b57b6525875b3c2dee81056baa4.tar.gz
micronucleus-824c303782a62b57b6525875b3c2dee81056baa4.tar.bz2
micronucleus-824c303782a62b57b6525875b3c2dee81056baa4.zip
Begin work to convert embedded-creations USBaspLoader-tiny85 port to bootloadHID
Diffstat (limited to 'firmware/libs-device/osctune.h')
-rw-r--r--firmware/libs-device/osctune.h88
1 files changed, 88 insertions, 0 deletions
diff --git a/firmware/libs-device/osctune.h b/firmware/libs-device/osctune.h
new file mode 100644
index 0000000..c751648
--- /dev/null
+++ b/firmware/libs-device/osctune.h
@@ -0,0 +1,88 @@
+/* Name: osctune.h
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-10-18
+ * Tabsize: 4
+ * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
+ * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
+ * This Revision: $Id: osctune.h 692 2008-11-07 15:07:40Z cs $
+ */
+
+/*
+General Description:
+This file is declared as C-header file although it is mostly documentation
+how the RC oscillator can be kept in sync to the USB frame rate. The code
+shown here must be added to usbconfig.h or this header file is included from
+there. This code works only if D- is wired to the interrupt, not D+!!!
+
+This is an alternative to the osccal routine in osccal.c. It has the advantage
+that the synchronization is done continuously and that it has more compact
+code size. The disadvantages are slow synchronization (it may take a while
+until the driver works), that messages immediately after the SOF pulse may be
+lost (and need to be retried by the host) and that the interrupt is on D-
+contrary to most examples.
+
+You may want to store a good calibration value in EEPROM for the next startup.
+You know that the calibration value is good when the first USB message is
+received. Do not store the value on every received message because the EEPROM
+has a limited endurance.
+
+Notes:
+(*) You must declare the global character variable "lastTimer0Value" in your
+main code.
+
+(*) Timer 0 must be free running (not written by your code) and the prescaling
+must be consistent with the TIMER0_PRESCALING define.
+
+(*) Good values for Timer 0 prescaling depend on how precise the clock must
+be tuned and how far away from the default clock rate the target clock is.
+For precise tuning, choose a low prescaler factor, for a broad range of tuning
+choose a high one. A prescaler factor of 64 is good for the entire OSCCAL
+range and allows a precision of better than +/-1%. A prescaler factor of 8
+allows tuning to slightly more than +/-6% of the default frequency and is
+more precise than one step of OSCCAL. It is therefore not suitable to tune an
+8 MHz oscillator to 12.5 MHz.
+
+Thanks to Henrik Haftmann for the idea to this routine!
+*/
+
+#define TIMER0_PRESCALING 64 /* must match the configuration for TIMER0 in main */
+#define TOLERATED_DEVIATION_PPT 5 /* max clock deviation before we tune in 1/10 % */
+/* derived constants: */
+#define EXPECTED_TIMER0_INCREMENT ((F_CPU / (1000 * TIMER0_PRESCALING)) & 0xff)
+#define TOLERATED_DEVIATION (TOLERATED_DEVIATION_PPT * F_CPU / (1000000 * TIMER0_PRESCALING))
+
+#ifdef __ASSEMBLER__
+macro tuneOsccal
+ push YH ;[0]
+ in YL, TCNT0 ;[2]
+ lds YH, lastTimer0Value ;[3]
+ sts lastTimer0Value, YL ;[5]
+ sub YL, YH ;[7] time passed since last frame
+ subi YL, EXPECTED_TIMER0_INCREMENT ;[8]
+#if OSCCAL > 0x3f /* outside I/O addressable range */
+ lds YH, OSCCAL ;[6]
+#else
+ in YH, OSCCAL ;[6] assembler modle uses __SFR_OFFSET == 0
+#endif
+ cpi YL, TOLERATED_DEVIATION + 1 ;[10]
+ brmi notTooHigh ;[11]
+ subi YH, 1 ;[12] clock rate was too high
+; brcs tuningOverflow ; optionally check for overflow
+ rjmp osctuneDone ;[13]
+notTooHigh:
+ cpi YL, -TOLERATED_DEVIATION ;[13]
+ brpl osctuneDone ;[14] not too low
+ inc YH ;[15] clock rate was too low
+; breq tuningOverflow ; optionally check for overflow
+osctuneDone:
+#if OSCCAL > 0x3f /* outside I/O addressable range */
+ sts OSCCAL, YH ;[12-13] store tuned value
+#else
+ out OSCCAL, YH ;[12-13] store tuned value
+#endif
+tuningOverflow:
+ pop YH ;[17]
+ endm ;[19] max number of cycles
+#endif
+
+#define USB_SOF_HOOK tuneOsccal