Example #1
0
/* Calibrate the RC oscillator to 8.25 MHz. The core clock of 16.5 MHz is
 * derived from the 66 MHz peripheral clock by dividing. Our timing reference
 * is the Start Of Frame signal (a single SE0 bit) available 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!
 */
static 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;
}
Example #2
0
/* Calibrate the RC oscillator to 8.25 MHz. The core clock of 16.5 MHz is
 * derived from the 66 MHz peripheral clock by dividing. Our timing reference
 * is the Start Of Frame signal (a single SE0 bit) available 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!
 * 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.
 */
void calibrateOscillator(void) {
  uchar step = 128;
  uchar trialValue = 0;
  uchar optimumValue;
  int x;
  int optimumDev;
  int 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, now do a neighbourhood
   * search for the 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;
}
Example #3
0
File: main.c Project: jbowes/nespad
// Called by V-USB after device reset
void hadUsbReset() {
    int frameLength, targetLength = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
    int bestDeviation = 9999;
    uchar bestCal = 0;
    uchar trialCal;
    uchar step;
    uchar region;

    // do a binary search in regions 0-127 and 128-255 to get optimum OSCCAL
    for(region = 0; region <= 1; region++) {
        frameLength = 0;
        trialCal = (region == 0) ? 0 : 128;

        for(step = 64; step > 0; step >>= 1) {
            if(frameLength < targetLength) // true for initial iteration
                trialCal += step; // frequency too low
            else
                trialCal -= step; // frequency too high

            OSCCAL = trialCal;
            frameLength = usbMeasureFrameLength();

            if(abs(frameLength-targetLength) < bestDeviation) {
                bestCal = trialCal; // new optimum found
                bestDeviation = abs(frameLength -targetLength);
            }
        }
    }

    OSCCAL = bestCal;
}
Example #4
0
File: main.c Project: mmitch/tasta
/* Calibrate the RC oscillator to 8.25 MHz. The core clock of 16.5 MHz is
 * derived from the 66 MHz peripheral clock by dividing. Our timing reference
 * is the Start Of Frame signal (a single SE0 bit) available immediately after
 * a USB RESET.
 */
static void calibrateOscillator(void)
{
	int frameLength, targetLength = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
	int bestDeviation = 9999;
	uchar trialCal, bestCal, step, region;

	/* do a binary search in regions 0-127 and 128-255 to get optimum OSCCAL */
	for (region = 0; region <= 1; region++)
	{
		frameLength = 0;
		trialCal = (region == 0) ? 0 : 128;
        
		for (step = 64; step > 0; step >>= 1)
		{
			if (frameLength < targetLength) /* true for initial iteration */
			{
				trialCal += step; /* frequency too low */
			}
			else
			{
				trialCal -= step; /* frequency too high */
			}
                
			OSCCAL = trialCal;
			frameLength = usbMeasureFrameLength();
			
			if (abs(frameLength-targetLength) < bestDeviation)
			{
				bestCal = trialCal; /* new optimum found */
				bestDeviation = abs(frameLength -targetLength);
			}
		}
	}

	OSCCAL = bestCal;
}