summaryrefslogtreecommitdiffstats
path: root/firmware/libs-device
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
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')
-rw-r--r--firmware/libs-device/Readme.txt22
-rw-r--r--firmware/libs-device/osccal.c63
-rw-r--r--firmware/libs-device/osccal.c.lst102
-rw-r--r--firmware/libs-device/osccal.h65
-rw-r--r--firmware/libs-device/osccal.obin0 -> 956 bytes
-rw-r--r--firmware/libs-device/osctune.h88
6 files changed, 340 insertions, 0 deletions
diff --git a/firmware/libs-device/Readme.txt b/firmware/libs-device/Readme.txt
new file mode 100644
index 0000000..76518dc
--- /dev/null
+++ b/firmware/libs-device/Readme.txt
@@ -0,0 +1,22 @@
+This is the Readme file for the libs-device directory. This directory contains
+code snippets which may be useful for USB device firmware.
+
+
+WHAT IS INCLUDED IN THIS DIRECTORY?
+===================================
+
+osccal.c and osccal.h
+ This module contains a function which calibrates the AVR's built-in RC
+ oscillator based on the USB frame clock. See osccal.h for a documentation
+ of the API.
+
+osctune.h
+ This header file contains a code snippet for usbconfig.h. With this code,
+ you can keep the AVR's internal RC oscillator in sync with the USB frame
+ clock. This is a continuous synchronization, not a single calibration at
+ USB reset as with osccal.c above. Please note that this code works only
+ if D- is wired to the interrupt, not D+.
+
+----------------------------------------------------------------------------
+(c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH.
+http://www.obdev.at/
diff --git a/firmware/libs-device/osccal.c b/firmware/libs-device/osccal.c
new file mode 100644
index 0000000..939d5c3
--- /dev/null
+++ b/firmware/libs-device/osccal.c
@@ -0,0 +1,63 @@
+/* Name: osccal.c
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-10
+ * 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: osccal.c 762 2009-08-12 17:10:30Z cs $
+ */
+
+#include <avr/io.h>
+
+#ifndef uchar
+#define uchar unsigned char
+#endif
+
+/* ------------------------------------------------------------------------- */
+/* ------------------------ Oscillator Calibration ------------------------- */
+/* ------------------------------------------------------------------------- */
+
+/* Calibrate the RC oscillator. Our timing reference is the Start Of Frame
+ * signal (a single SE0 bit) repeating every millisecond immediately after
+ * a USB RESET. We first do a binary search for the OSCCAL value and then
+ * optimize this value with a neighboorhod search.
+ */
+void calibrateOscillator(void)
+{
+uchar step = 128;
+uchar trialValue = 0, optimumValue;
+int x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
+
+ /* do a binary search: */
+ do{
+ OSCCAL = trialValue + step;
+ x = usbMeasureFrameLength(); /* proportional to current real frequency */
+ if(x < targetValue) /* frequency still too low */
+ trialValue += step;
+ step >>= 1;
+ }while(step > 0);
+ /* We have a precision of +/- 1 for optimum OSCCAL here */
+ /* now do a neighborhood search for optimum value */
+ optimumValue = trialValue;
+ optimumDev = x; /* this is certainly far away from optimum */
+ for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
+ x = usbMeasureFrameLength() - targetValue;
+ if(x < 0)
+ x = -x;
+ if(x < optimumDev){
+ optimumDev = x;
+ optimumValue = OSCCAL;
+ }
+ }
+ OSCCAL = optimumValue;
+}
+/*
+Note: This calibration algorithm may try OSCCAL values of up to 192 even if
+the optimum value is far below 192. It may therefore exceed the allowed clock
+frequency of the CPU in low voltage designs!
+You may replace this search algorithm with any other algorithm you like if
+you have additional constraints such as a maximum CPU clock.
+For version 5.x RC oscillators (those with a split range of 2x128 steps, e.g.
+ATTiny25, ATTiny45, ATTiny85), it may be useful to search for the optimum in
+both regions.
+*/
diff --git a/firmware/libs-device/osccal.c.lst b/firmware/libs-device/osccal.c.lst
new file mode 100644
index 0000000..25eda0a
--- /dev/null
+++ b/firmware/libs-device/osccal.c.lst
@@ -0,0 +1,102 @@
+GAS LISTING /var/folders/nd/dq8cd7_x03d_z3x899kwf__80000gn/T//ccgky3fN.s page 1
+
+
+ 1 .file "osccal.c"
+ 2 __SREG__ = 0x3f
+ 3 __SP_H__ = 0x3e
+ 4 __SP_L__ = 0x3d
+ 5 __CCP__ = 0x34
+ 6 __tmp_reg__ = 0
+ 7 __zero_reg__ = 1
+ 8 .text
+ 9 .global calibrateOscillator
+ 10 .type calibrateOscillator, @function
+ 11 calibrateOscillator:
+ 12 0000 FF92 push r15
+ 13 0002 0F93 push r16
+ 14 0004 1F93 push r17
+ 15 0006 CF93 push r28
+ 16 0008 DF93 push r29
+ 17 /* prologue: function */
+ 18 /* frame size = 0 */
+ 19 /* stack size = 5 */
+ 20 .L__stack_usage = 5
+ 21 000a C8E0 ldi r28,lo8(8)
+ 22 000c D0E0 ldi r29,hi8(8)
+ 23 000e 10E0 ldi r17,lo8(0)
+ 24 0010 00E8 ldi r16,lo8(-128)
+ 25 .L3:
+ 26 0012 F12E mov r15,r17
+ 27 0014 F00E add r15,r16
+ 28 0016 F1BE out 81-32,r15
+ 29 0018 00D0 rcall usbMeasureFrameLength
+ 30 001a 29E0 ldi r18,hi8(2356)
+ 31 001c 8433 cpi r24,lo8(2356)
+ 32 001e 9207 cpc r25,r18
+ 33 0020 04F4 brge .L2
+ 34 0022 1F2D mov r17,r15
+ 35 .L2:
+ 36 0024 0695 lsr r16
+ 37 0026 2197 sbiw r28,1
+ 38 0028 01F4 brne .L3
+ 39 002a 212F mov r18,r17
+ 40 002c 2150 subi r18,lo8(-(-1))
+ 41 002e 21BF out 81-32,r18
+ 42 0030 EC01 movw r28,r24
+ 43 0032 012F mov r16,r17
+ 44 0034 00C0 rjmp .L4
+ 45 .L7:
+ 46 0036 00D0 rcall usbMeasureFrameLength
+ 47 0038 8453 subi r24,lo8(-(-2356))
+ 48 003a 9940 sbci r25,hi8(-(-2356))
+ 49 003c 97FF sbrs r25,7
+ 50 003e 00C0 rjmp .L5
+ 51 0040 9095 com r25
+ 52 0042 8195 neg r24
+ 53 0044 9F4F sbci r25,lo8(-1)
+ 54 .L5:
+ 55 0046 8C17 cp r24,r28
+ 56 0048 9D07 cpc r25,r29
+ 57 004a 04F4 brge .L6
+ GAS LISTING /var/folders/nd/dq8cd7_x03d_z3x899kwf__80000gn/T//ccgky3fN.s page 2
+
+
+ 58 004c 01B7 in r16,81-32
+ 59 004e EC01 movw r28,r24
+ 60 .L6:
+ 61 0050 81B7 in r24,81-32
+ 62 0052 8F5F subi r24,lo8(-(1))
+ 63 0054 81BF out 81-32,r24
+ 64 .L4:
+ 65 0056 21B7 in r18,81-32
+ 66 0058 30E0 ldi r19,lo8(0)
+ 67 005a 812F mov r24,r17
+ 68 005c 90E0 ldi r25,lo8(0)
+ 69 005e 0196 adiw r24,1
+ 70 0060 8217 cp r24,r18
+ 71 0062 9307 cpc r25,r19
+ 72 0064 04F4 brge .L7
+ 73 0066 01BF out 81-32,r16
+ 74 /* epilogue start */
+ 75 0068 DF91 pop r29
+ 76 006a CF91 pop r28
+ 77 006c 1F91 pop r17
+ 78 006e 0F91 pop r16
+ 79 0070 FF90 pop r15
+ 80 0072 0895 ret
+ 81 .size calibrateOscillator, .-calibrateOscillator
+ GAS LISTING /var/folders/nd/dq8cd7_x03d_z3x899kwf__80000gn/T//ccgky3fN.s page 3
+
+
+DEFINED SYMBOLS
+ *ABS*:00000000 osccal.c
+/var/folders/nd/dq8cd7_x03d_z3x899kwf__80000gn/T//ccgky3fN.s:2 *ABS*:0000003f __SREG__
+/var/folders/nd/dq8cd7_x03d_z3x899kwf__80000gn/T//ccgky3fN.s:3 *ABS*:0000003e __SP_H__
+/var/folders/nd/dq8cd7_x03d_z3x899kwf__80000gn/T//ccgky3fN.s:4 *ABS*:0000003d __SP_L__
+/var/folders/nd/dq8cd7_x03d_z3x899kwf__80000gn/T//ccgky3fN.s:5 *ABS*:00000034 __CCP__
+/var/folders/nd/dq8cd7_x03d_z3x899kwf__80000gn/T//ccgky3fN.s:6 *ABS*:00000000 __tmp_reg__
+/var/folders/nd/dq8cd7_x03d_z3x899kwf__80000gn/T//ccgky3fN.s:7 *ABS*:00000001 __zero_reg__
+/var/folders/nd/dq8cd7_x03d_z3x899kwf__80000gn/T//ccgky3fN.s:11 .text:00000000 calibrateOscillator
+
+UNDEFINED SYMBOLS
+usbMeasureFrameLength
diff --git a/firmware/libs-device/osccal.h b/firmware/libs-device/osccal.h
new file mode 100644
index 0000000..710ce05
--- /dev/null
+++ b/firmware/libs-device/osccal.h
@@ -0,0 +1,65 @@
+/* Name: osccal.h
+ * Author: Christian Starkjohann
+ * Creation Date: 2008-04-10
+ * 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: osccal.h 762 2009-08-12 17:10:30Z cs $
+ */
+
+/*
+General Description:
+This module contains a function which calibrates the AVR's internal RC
+oscillator so that the CPU runs at F_CPU (F_CPU is a macro which must be
+defined when the module is compiled, best passed in the compiler command
+line). The time reference is the USB frame clock of 1 kHz available
+immediately after a USB RESET condition. Timing is done by counting CPU
+cycles, so all interrupts must be disabled while the calibration runs. For
+low level timing measurements, usbMeasureFrameLength() is called. This
+function must be enabled in usbconfig.h by defining
+USB_CFG_HAVE_MEASURE_FRAME_LENGTH to 1. It is recommended to call
+calibrateOscillator() from the reset hook in usbconfig.h:
+*/
+
+#ifndef __ASSEMBLER__
+#include <avr/interrupt.h> // for sei()
+extern void calibrateOscillator(void);
+#endif
+#define USB_RESET_HOOK(resetStarts) if(!resetStarts){cli(); calibrateOscillator(); sei();}
+
+/*
+This routine is an alternative to the continuous synchronization described
+in osctune.h.
+
+Algorithm used:
+calibrateOscillator() first does a binary search in the OSCCAL register for
+the best matching oscillator frequency. Then it does a next neighbor search
+to find the value with the lowest clock rate deviation. It is guaranteed to
+find the best match among neighboring values, but for version 5 oscillators
+(which have a discontinuous relationship between OSCCAL and frequency) a
+better match might be available in another OSCCAL region.
+
+Limitations:
+This calibration algorithm may try OSCCAL values of up to 192 even if the
+optimum value is far below 192. It may therefore exceed the allowed clock
+frequency of the CPU in low voltage designs!
+Precision depends on the OSCCAL vs. frequency dependency of the oscillator.
+Typical precision for an ATMega168 (derived from the OSCCAL vs. F_RC diagram
+in the data sheet) should be in the range of 0.4%. Only the 12.8 MHz and
+16.5 MHz versions of V-USB (with built-in receiver PLL) can tolerate this
+deviation! All other frequency modules require at least 0.2% precision.
+*/
+
+#ifndef __OSCCAL_H_INCLUDED__
+#define __OSCCAL_H_INCLUDED__
+
+//void calibrateOscillator(void);
+/* This function calibrates the RC oscillator so that the CPU runs at F_CPU.
+ * It MUST be called immediately after the end of a USB RESET condition!
+ * Disable all interrupts during the call!
+ * It is recommended that you store the resulting value in EEPROM so that a
+ * good guess value is available after the next reset.
+ */
+
+
+#endif /* __OSCCAL_H_INCLUDED__ */
diff --git a/firmware/libs-device/osccal.o b/firmware/libs-device/osccal.o
new file mode 100644
index 0000000..79622f1
--- /dev/null
+++ b/firmware/libs-device/osccal.o
Binary files differ
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