From 95ca3f5bd696b5450820929e1b1a444d02f0bd1e Mon Sep 17 00:00:00 2001 From: Christian Starkjohann Date: Thu, 17 Apr 2008 19:00:20 +0000 Subject: - imported new files into project --- libs-device/Readme.txt | 16 +++++++++++++ libs-device/osccal.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++ libs-device/osccal.h | 53 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) create mode 100644 libs-device/Readme.txt create mode 100644 libs-device/osccal.c create mode 100644 libs-device/osccal.h (limited to 'libs-device') diff --git a/libs-device/Readme.txt b/libs-device/Readme.txt new file mode 100644 index 0000000..7c0e311 --- /dev/null +++ b/libs-device/Readme.txt @@ -0,0 +1,16 @@ +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. + + +---------------------------------------------------------------------------- +(c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH. +http://www.obdev.at/ diff --git a/libs-device/osccal.c b/libs-device/osccal.c new file mode 100644 index 0000000..5734a84 --- /dev/null +++ b/libs-device/osccal.c @@ -0,0 +1,64 @@ +/* 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) or proprietary (CommercialLicense.txt) + * This Revision: $Id$ + */ + +#include + +/* ------------------------------------------------------------------------- */ +/* ------------------------ 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. + * This algorithm may also be used to calibrate the RC oscillator directly to + * 12 MHz (no PLL involved, can therefore be used on almost ALL AVRs), but this + * is wide outside the spec for the OSCCAL value and the required precision for + * the 12 MHz clock! Use the RC oscillator calibrated to 12 MHz for + * experimental purposes only! + */ +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/libs-device/osccal.h b/libs-device/osccal.h new file mode 100644 index 0000000..8bd0209 --- /dev/null +++ b/libs-device/osccal.h @@ -0,0 +1,53 @@ +/* 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) or proprietary (CommercialLicense.txt) + * This Revision: $Id$ + */ + +/* +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. + +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 16.5 MHz version +of AVR-USB (with built-in receiver PLL) can tolerate this deviation! All other +frequency modules require at least 0.3% 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__ */ -- cgit v1.2.3