summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorcpldcpu <cpldcpu@gmail.com>2013-11-04 04:43:26 +0100
committercpldcpu <cpldcpu@gmail.com>2013-11-04 04:43:26 +0100
commit819ce8ac705e9a336cb60fdb6f525a17cbc9dcb3 (patch)
tree18f8069c3fc5cddab675b874ca9d63a65eba648b
parent97c24d7b6ab9fb4436308a9423810b54eed54a51 (diff)
downloadmicronucleus-819ce8ac705e9a336cb60fdb6f525a17cbc9dcb3.tar.gz
micronucleus-819ce8ac705e9a336cb60fdb6f525a17cbc9dcb3.tar.bz2
micronucleus-819ce8ac705e9a336cb60fdb6f525a17cbc9dcb3.zip
further size optimization in calibrateoscillator.
1976 bytes
-rw-r--r--firmware/libs-device/osccal.c64
-rw-r--r--firmware/libs-device/osccal.h5
2 files changed, 67 insertions, 2 deletions
diff --git a/firmware/libs-device/osccal.c b/firmware/libs-device/osccal.c
index b8d1bb5..8debe49 100644
--- a/firmware/libs-device/osccal.c
+++ b/firmware/libs-device/osccal.c
@@ -8,6 +8,7 @@
*/
#include <avr/io.h>
+#include <avr/interrupt.h>
#ifndef uchar
#define uchar unsigned char
#endif
@@ -59,6 +60,69 @@ int usbMeasureFrameLengthDecreasing(int);
void calibrateOscillator(void)
{
uchar step, trialValue, optimumValue;
+ int x, targetValue;
+ uchar optimumDev;
+ uchar i,xl;
+
+ targetValue = (unsigned)((double)F_CPU * 999e-6 / 5.0 + 0.5); /* Time is measured in multiples of 5 cycles. Target is 0.999µs */
+ optimumDev = 0xff;
+ // optimumValue = OSCCAL;
+ step=64;
+ trialValue = 128;
+
+ cli(); // disable interrupts
+
+ /*
+ Performs seven iterations of a binary search (stepwidth decreasing9
+ with three additional steps of a neighborhood search (step=1, trialvalue will oscillate around target value to find optimum)
+ */
+
+ for(i=0; i<10; i++){
+ OSCCAL = trialValue;
+ asm volatile(" NOP");
+
+ x = usbMeasureFrameLengthDecreasing(targetValue);
+
+ if(x < 0) /* frequency too high */
+ {
+ trialValue -= step;
+ xl=(uchar)-x;
+ }
+ else /* frequency too low */
+ {
+ trialValue += step;
+ xl=(uchar)x;
+ }
+
+ /*
+ Halve stepwidth to perform binary search. Logical oring with 1 to ensure step is never equal to zero.
+ This results in a neighborhood search with stepwidth 1 after binary search is finished.
+ Once the neighbourhood search stage is reached, x will be smaller than +-255, hence more code can be
+ saved by only working with the lower 8 bits.
+ */
+
+ step >>= 1;
+
+ if (step==0)
+ {
+ step=1;
+ if(xl <= optimumDev){
+ optimumDev = xl;
+ optimumValue = OSCCAL;
+ }
+ }
+
+ }
+
+ OSCCAL = optimumValue;
+ asm volatile(" NOP");
+
+ sei(); // enable interrupts
+}
+
+void calibrateOscillator_old(void)
+{
+ uchar step, trialValue, optimumValue;
int x, optimumDev, targetValue;
uchar i;
diff --git a/firmware/libs-device/osccal.h b/firmware/libs-device/osccal.h
index 710ce05..6f443a5 100644
--- a/firmware/libs-device/osccal.h
+++ b/firmware/libs-device/osccal.h
@@ -22,10 +22,11 @@ calibrateOscillator() from the reset hook in usbconfig.h:
*/
#ifndef __ASSEMBLER__
-#include <avr/interrupt.h> // for sei()
extern void calibrateOscillator(void);
+//extern void calibrateOscillatorASM(void);
#endif
-#define USB_RESET_HOOK(resetStarts) if(!resetStarts){cli(); calibrateOscillator(); sei();}
+#define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillator(); }
+//#define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillatorASM(); }
/*
This routine is an alternative to the continuous synchronization described