Guest User

osccal.c

a guest
Oct 9th, 2014
459
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 6.93 KB | None | 0 0
  1. /* Имя: osccal.c
  2.  * Автор: Christian Starkjohann
  3.  * Перевод: microsin.ru
  4.  * Дата создания: 2008-04-10
  5.  * Табуляция: 4
  6.  * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
  7.  * Лицензия: GNU GPL v2 (см. License.txt) или проприетарная (CommercialLicense.txt)
  8.  * Ревизия: $Id: osccal.c 553 2008-04-17 19:00:20Z cs $
  9.  */
  10.  
  11. #include <avr/io.h>
  12. #include "usbdrv.h"
  13. #include <avr/eeprom.h>
  14.  
  15.  
  16. #ifdef OSC_CAL_OLD
  17. /* ------------------------------------------------------------------------- */
  18. /* -------------------- Калибровка тактового генератора -------------------- */
  19. /* ------------------------------------------------------------------------- */
  20.  
  21. /* Функция калибрует RC-генератор. Наш опорный источник точного времени -
  22.  *  сигнал SOF, Start Of Frame (один бит SE0), повторяющийся каждую милисекунду
  23.  *  сразу после состояния USB RESET. Мы сначала делаем двоичный поиск величины
  24.  *  OSCCAL, и затем оптимизируем эту величину поиском соседних значений.
  25.  *  Этот алгоритм может также использоваться для калибровки RC-генератора напрямую
  26.  *  до 12 MHz (не вовлекается ФАПЧ, таким образом эту технику можно использовать
  27.  *  почти на ВСЕХ AVR), но это слишком вне спецификации величины OSCCAL и необходимой
  28.  *  точности для тактов на 12 МГц! Используйте RC-генератор, калиброванный на 12 МГц
  29.  *  только для экспериментов!
  30.  */
  31. void    calibrateOscillator(void)
  32. {
  33.     uint8_t     step = 128;
  34.     uint8_t     trialValue = 0, optimumValue;
  35.     int         x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
  36.  
  37.     /* делаем двоичный поиск: */
  38.     do{
  39.         OSCCAL = trialValue + step;
  40.         x = usbMeasureFrameLength();    /* пропорционально текущей реальной частоте */
  41.         if(x < targetValue)             /* частота еще слишком низкая */
  42.             trialValue += step;
  43.         step >>= 1;
  44.     }while(step > 0);
  45.     /* Здесь мы имеем точность +/- 1 от оптимального OSCCAL */
  46.     /*  теперь ищем соседнее значение для оптимальной величины */
  47.     optimumValue = trialValue;
  48.     optimumDev = x; /* это конечно очень далеко от оптимума */
  49.     for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
  50.         x = usbMeasureFrameLength() - targetValue;
  51.         if(x < 0) x = -x;
  52.         if(x < optimumDev)
  53.         {
  54.             optimumDev = x;
  55.             optimumValue = OSCCAL;
  56.         }
  57.     }
  58.     OSCCAL = optimumValue;
  59. }
  60. /*
  61. Замечание: Этот алгоритм калибровки может пробовать
  62. величины OSCCAL до 192, даже если оптимальная величина далеко меньше 192.
  63. Таким образом, может быть превышена допустимая тактовая частота CPU в разработках
  64. с низковольтным питанием! Вы можете заменить этот алгоритм поиска любым другим
  65. алгоритмом по Вашему желанию, если Вы имеете дополнительные ограничения как,
  66. например, максимальная частота CPU.
  67. Для RC-генераторов версий 5.x (у которых диапазон регулировки склеен из 2x128
  68. шагов, например ATTiny25, ATTiny45, ATTiny85), может быть полезно искать оптимум
  69. в обеих областях.
  70. */
  71.  
  72. #endif /* OSC_CAL_OLD */
  73.  
  74.  
  75. /*****************************************************************************/
  76. #define OSC_CAL
  77. #ifdef  OSC_CAL
  78. /* ------------------------------------------------------------------------- */
  79. /* ------------------------ Oscillator Calibration ------------------------- */
  80. /* ------------------------------------------------------------------------- */
  81.  
  82. /* Calibrate the RC oscillator to 8.25 MHz. The core clock of 16.5 MHz is
  83.  * derived from the 66 MHz peripheral clock by dividing. Our timing reference
  84.  * is the Start Of Frame signal (a single SE0 bit) available immediately after
  85.  * a USB RESET. We first do a binary search for the OSCCAL value and then
  86.  * optimize this value with a neighboorhod search.
  87.  * This algorithm may also be used to calibrate the RC oscillator directly to
  88.  * 12 MHz (no PLL involved, can therefore be used on almost ALL AVRs), but this
  89.  * is wide outside the spec for the OSCCAL value and the required precision for
  90.  * the 12 MHz clock! Use the RC oscillator calibrated to 12 MHz for
  91.  * experimental purposes only!
  92.  */
  93. static void calibrateOscillator(void)
  94. {
  95. uchar       step = 128;
  96. uchar       trialValue = 0, optimumValue;
  97. int         x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
  98.  
  99.     /* do a binary search: */
  100.     do{
  101.         OSCCAL = trialValue + step;
  102.         x = usbMeasureFrameLength();    /* proportional to current real frequency */
  103.         if(x < targetValue)             /* frequency still too low */
  104.             trialValue += step;
  105.         step >>= 1;
  106.     }while(step > 0);
  107.     /* We have a precision of +/- 1 for optimum OSCCAL here */
  108.     /* now do a neighborhood search for optimum value */
  109.     optimumValue = trialValue;
  110.     optimumDev = x; /* this is certainly far away from optimum */
  111.     for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
  112.         x = usbMeasureFrameLength() - targetValue;
  113.         if(x < 0)
  114.             x = -x;
  115.         if(x < optimumDev){
  116.             optimumDev = x;
  117.             optimumValue = OSCCAL;
  118.         }
  119.     }
  120.     OSCCAL = optimumValue;
  121. }
  122. /*
  123. Note: This calibration algorithm may try OSCCAL values of up to 192 even if
  124. the optimum value is far below 192. It may therefore exceed the allowed clock
  125. frequency of the CPU in low voltage designs!
  126. You may replace this search algorithm with any other algorithm you like if
  127. you have additional constraints such as a maximum CPU clock.
  128. For version 5.x RC oscillators (those with a split range of 2x128 steps, e.g.
  129. ATTiny25, ATTiny45, ATTiny85), it may be useful to search for the optimum in
  130. both regions.
  131. */
  132.  
  133. void usbEventResetReady(void)
  134. {
  135.     calibrateOscillator();
  136.     eeprom_write_byte(0, OSCCAL);   /* store the calibrated value in EEPROM */
  137. }
  138.  
  139. #endif /* OSC_CAL */
  140. /*****************************************************************************/
Advertisement
Add Comment
Please, Sign In to add comment