From 819ce8ac705e9a336cb60fdb6f525a17cbc9dcb3 Mon Sep 17 00:00:00 2001 From: cpldcpu Date: Mon, 4 Nov 2013 04:43:26 +0100 Subject: further size optimization in calibrateoscillator. 1976 bytes --- firmware/libs-device/osccal.c | 64 +++++++++++++++++++++++++++++++++++++++++++ firmware/libs-device/osccal.h | 5 ++-- 2 files changed, 67 insertions(+), 2 deletions(-) (limited to 'firmware/libs-device') 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 +#include #ifndef uchar #define uchar unsigned char #endif @@ -57,6 +58,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; 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 // 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 -- cgit v1.2.3