summaryrefslogtreecommitdiffstats
path: root/firmware/osccalASM.S
diff options
context:
space:
mode:
authorcpldcpu <cpldcpu@gmail.com>2014-01-05 12:09:34 +0100
committercpldcpu <cpldcpu@gmail.com>2014-01-05 12:09:34 +0100
commita1a11ed4888bfd84f2215321489b25944404b6ab (patch)
tree0ff67bd7f5f96267e103c38fc24b11cee4364f8b /firmware/osccalASM.S
parentc4907c6896943eb3ff778cb007a9891ac7b68248 (diff)
downloadmicronucleus-a1a11ed4888bfd84f2215321489b25944404b6ab.tar.gz
micronucleus-a1a11ed4888bfd84f2215321489b25944404b6ab.tar.bz2
micronucleus-a1a11ed4888bfd84f2215321489b25944404b6ab.zip
firmware: first working version with polled usb
Diffstat (limited to 'firmware/osccalASM.S')
-rw-r--r--firmware/osccalASM.S70
1 files changed, 40 insertions, 30 deletions
diff --git a/firmware/osccalASM.S b/firmware/osccalASM.S
index c0c8803..9c3b45a 100644
--- a/firmware/osccalASM.S
+++ b/firmware/osccalASM.S
@@ -1,6 +1,8 @@
-/* Name: osccalASM.S
+/* Name: osccalASM.S v1.1
* Author: cpldcpu@gmail.com
* Creation Date: 2013-11-3
+ * Update : 2014-01-4
+ *
* Tabsize: 4
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
@@ -11,28 +13,34 @@
*
*
* Benefits:
- * - Codesize reduced by 90 bytes.
+ * - Codesize reduced by 90 bytes.
* - Improved robustness due to removing timeout from frame length measurement and
- * inserted NOP after OSCCAL writes.
+ * 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
+ * - 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
+ * 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
+ * an infinite loop when no USB activity is encountered. The user program should
* use the watchdog to escape from situations like this.
- *
+ * Update 2014-01-4
+ * - Added an initial sync-state, which will discard the first delay measurement.
+ * This allows to call this routine before or during the SE0 bus reset without
+ * corrupting OSCCAL.
+ * - Removed CLI/SEI to allow more flexibility.
+ *
+ *
* This routine will work both on controllers with and without split OSCCAL range.
* The first trial value is 128 which is the lowest value of the upper OSCCAL range
* on Attiny85 and will effectively limit the search to the upper range, unless the
@@ -90,20 +98,19 @@
.global calibrateOscillatorASM
calibrateOscillatorASM:
-; cli
- ldi opD, 255
+ ldi opD, 255
- ldi try, 128 ; calibration start value
- ldi stp, 64 ; initial step width
- ldi i, 10 ; 10 iterations
+ ldi try, 128 ; calibration start value
+ ldi stp, 0 ; initial step width=0 for sync phase (first delay is discarded)
+ ldi i, 11 ; 11 iterations (1x sync, 7x binary search, 3x neighbourhood)
usbCOloop:
- out OSCCAL, try
- nop
+ out OSCCAL, try
+ nop
- ; Delay values = F_CPU * 999e-6 / 5 + 0.5
-
+ ; Delay values = F_CPU * 999e-6 / 5 + 0.5
+
#if (F_CPU == 16500000)
ldi cnt16L, lo8(3297)
ldi cnt16H, hi8(3297)
@@ -115,9 +122,9 @@ usbCOloop:
ldi cnt16H, hi8(2398)
#elif (F_CPU == 16000000)
ldi cnt16L, lo8(3197)
- ldi cnt16H, hi8(3197)
+ ldi cnt16H, hi8(3197)
#else
- #error "calibrateOscillatorASM: no delayvalues defined for this F_CPU setting"
+ #error "calibrateOscillatorASM: no delayvalues defined for this F_CPU setting"
#endif
usbCOWaitStrobe: ; first wait for D- == 0 (idle strobe)
@@ -139,21 +146,26 @@ usbCOWaitLoop:
usbCOclocktoolow:
add try, stp
usbCOclocktoohigh:
- lsr stp
- brne usbCOnoneighborhoodsearch
+ lsr stp ; stp = 0 in first iteration (sync)
+ ; stp = 2^x (x=0..6) during binary search,
+ ; stp = 1 during neighbourhood search
+
+ brne usbCObinarysearch
+ ldi stp, 64 ; stp=64 to initiate binary search.
+ ; If we are in neighbourhood search (c=1), it is changed to 1 below
+ brcc usbCObinarysearch
cp opD, cnt16L
brcs usbCOnoimprovement
in opV, OSCCAL
mov opD, cnt16L
usbCOnoimprovement:
- ldi stp, 1
-usbCOnoneighborhoodsearch:
+ ldi stp, 1 ; stp=1 to continue with neighbourhood search
+usbCObinarysearch:
subi i, 1
brne usbCOloop
out OSCCAL, opV
nop
-; sei
ret
#undef i
@@ -227,8 +239,6 @@ void calibrateOscillator(void)
}
OSCCAL = optimumValue;
- asm volatile(" NOP");
-
- sei(); // enable interrupts
+ asm volatile(" NOP");
}
#endif \ No newline at end of file