Wavebubble 2010 Firmware

pll.c

Go to the documentation of this file.
00001 
00007 #include <avr/io.h>
00008 #include <avr/pgmspace.h>
00009 #include "pll.h"
00010 #include "main.h"
00011 #include "serial.h"
00012 
00019 void pll_init(void) {
00020   uint32_t out;
00021 
00022   ADCSRA = _BV(ADSC) | _BV(ADEN) | _BV(ADPS1) | _BV(ADPS2);
00023 
00024   PLLCLK_DDR |= _BV(PLLCLK);
00025   PLLDATA_DDR |= _BV(PLLDATA);
00026   PLLLE_DDR |= _BV(PLLLE);
00027   PLL_IFIN_DDR &= ~_BV(PLL_IFIN);
00028   PLL_RFIN_DDR &= ~_BV(PLL_RFIN);
00029   PLL_IFIN_PORT &= ~_BV(PLL_IFIN);
00030   PLL_RFIN_PORT &= ~_BV(PLL_RFIN);
00031 
00032   pll_tx(0x0, 0x2); // dont use general purpose pins, no fastlock
00033   pll_tx(0x0, 0x5); // dont use general purpose pins, no fastlock
00034 
00035   // setup 1MHz reference clock
00036   out = 3; out <<= 19; out |= (10&0x7FFF);
00037   pll_tx(out, 0x3); // no otherbits set: defaults
00038   out = 3; out <<= 19; out |= (10&0x7FFF);
00039   pll_tx(out, 0x0); // no otherbits set: defaults
00040 }
00041 
00049 void pll_tx(uint32_t data, uint8_t addr) {
00050   uint8_t i;
00051 
00052   if (addr > 5) return;
00053 
00054   data <<= 3;
00055   data |= (addr & 0x7);
00056   data <<= 8;
00057 
00058   PLLLE_PORT &= ~_BV(PLLLE);
00059   PLLDATA_PORT &= ~_BV(PLLDATA);
00060   PLLCLK_PORT &= ~_BV(PLLCLK);
00061 
00062   for (i=0; i<24; i++) {
00063     PLLCLK_PORT &= ~_BV(PLLCLK);
00064     if (data & 0x80000000) {
00065             PLLDATA_PORT |= _BV(PLLDATA);
00066     } else {
00067             PLLDATA_PORT &= ~_BV(PLLDATA);
00068     }
00069     asm volatile ("nop");
00070     asm volatile ("nop");
00071     asm volatile ("nop");
00072     PLLCLK_PORT |= _BV(PLLCLK);
00073     asm volatile ("nop");
00074     asm volatile ("nop");
00075     asm volatile ("nop");
00076     data <<= 1;
00077   }
00078   PLLLE_PORT |= _BV(PLLLE);
00079   asm volatile ("nop");
00080   asm volatile ("nop");
00081   asm volatile ("nop");
00082   PLLLE_PORT &= ~_BV(PLLLE);
00083   PLLDATA_PORT &= ~_BV(PLLDATA);
00084   PLLCLK_PORT &= ~_BV(PLLCLK);
00085 }
00086 
00087 
00094 void pll_set_rcounter(uint16_t rcounter) {
00095   pll_tx((rcounter&0x7FFF), 0x0); // no otherbits set: defaults
00096   pll_tx((rcounter&0x7FFF), 0x3); // no otherbits set: defaults
00097 }
00098 
00099 
00100 void pll_set_freq(uint16_t rf_freq, uint8_t prescaler, uint8_t reg) {
00101   uint16_t N;
00102   uint16_t B, A;
00103   uint32_t out=0;
00104 
00105   if ((prescaler != 8) && (prescaler != 16))
00106     prescaler = 8;
00107 
00108   // Fin = N*fcomp
00109   N = rf_freq; // fcomp = 1MHz
00110   //  N = (P*B) + A
00111   if (prescaler == 8) {
00112     B = N / 8;
00113     A = N % 8;
00114   } else {
00115     B = N / 16;
00116     A = N % 16;
00117   }
00118 
00119   pc_puts_P(PSTR("PLL for RF freq ")); putnum_ud(N);
00120   pc_puts_P(PSTR("MHz & prescaler ")); putnum_ud(prescaler);
00121   pc_puts_P(PSTR(": B=")); putnum_ud(B);
00122   pc_puts_P(PSTR(" A=")); putnum_ud(A);
00123   pc_putc('\n');
00124 
00125   if (prescaler == 16)
00126     out = 1; // 16 prescale
00127   out <<= 15;
00128   out |= B; out<<= 4;
00129   out |= A&0xF;
00130   pll_tx(out, reg);
00131 }
00132 
00142 uint8_t tune_rf(uint16_t freq) {
00143   uint16_t i=0, low, high;
00144 
00145   pll_set_rf(freq, 8);
00146 
00147   set_resistor(BANDWADJ1_RES, 0);
00148   POWERCTL1_PORT |= _BV(POWERCTL1); // turn on vco
00149 
00150   OCR1A = 0;
00151   delay_ms(500);
00152 
00153   if (PLL_RFIN_PIN & _BV(PLL_RFIN)) {   // we cant tune any lower...???
00154     pc_puts_P(PSTR("RF VCO range is too high!\n"));
00155     return 0;
00156   }
00157   OCR1A = 4095;
00158   delay_ms(500);
00159 
00160   if (! (PLL_RFIN_PIN & _BV(PLL_RFIN))) {   // we cant tune any higher...???
00161     pc_puts_P(PSTR("RF VCO range is too low!\n"));
00162     return 0;
00163   }
00164 
00165   pc_puts_P(PSTR("midpoint @ "));
00166   low = 0;
00167   high = 4095;
00168   while ((low + 2) <= high) {
00169     //putnum_ud(low); uart_putchar('/'); putnum_ud(high); uart_putchar('\t');
00170     i = ((uint16_t)low+(uint16_t)high)/2;
00171     OCR1A = i;
00172     //putnum_ud(OCR1A); pc_puts(", ");
00173     delay_ms(500);
00174     if (PLL_RFIN_PIN & _BV(PLL_RFIN)) {
00175       delay_ms(1);
00176       if (PLL_RFIN_PIN & _BV(PLL_RFIN)) {
00177         high = i;
00178       }
00179     } else {
00180       low = i;
00181     }
00182   }
00183   putnum_ud(i); pc_putc('\n');
00184   return i;
00185 }
00186 
00196 uint8_t tune_if(uint16_t freq) {
00197   uint16_t i=0, low, high;
00198 
00199   pll_set_if(freq, 8);
00200 
00201   set_resistor(BANDWADJ2_RES, 0);
00202   POWERCTL2_PORT |= _BV(POWERCTL2); // turn on vco
00203 
00204   OCR1B = 0;
00205   delay_ms(500);
00206 
00207   if (PLL_IFIN_PIN & _BV(PLL_IFIN)) {   // we cant tune any lower...???
00208     pc_puts_P(PSTR("IF VCO range is too high!\n"));
00209     return 0;
00210   }
00211 
00212   OCR1B = 4095;
00213   delay_ms(500);
00214 
00215   if (! (PLL_IFIN_PIN & _BV(PLL_IFIN))) {   // we cant tune any higher...???
00216     pc_puts_P(PSTR("IF VCO range is too low!\n"));
00217     return 0;
00218   }
00219 
00220   pc_puts_P(PSTR("midpoint @ "));
00221   low = 0;
00222   high = 4095;
00223   while ((low + 2) <= high) {
00224     i = ((uint16_t)low+(uint16_t)high)/2;
00225     OCR1B = i;
00226     //putnum_ud(OCR1B); pc_puts(", ");
00227     delay_ms(500);
00228     if (PLL_IFIN_PIN & _BV(PLL_IFIN)) {
00229       delay_ms(1);
00230       if (PLL_IFIN_PIN & _BV(PLL_IFIN)) {
00231         high = i;
00232       }
00233     } else {
00234       low = i;
00235     }
00236   }
00237   putnum_ud(i); pc_putc('\n');
00238   return i;
00239 }
00240 
00250 uint8_t tune_rf_band(uint16_t min, uint16_t max, uint8_t vco_num) {
00251   uint16_t threshhold, midpt;
00252   uint32_t avg;
00253   uint8_t i=0, j, low, high;
00254 
00255   // Check and correct possible frequency mismatch
00256   if (min > max) {
00257     midpt = max;
00258     max = min;
00259     min = midpt;
00260   }
00261 
00262   // Check for single frequency
00263   if( min == max)
00264     midpt = min;
00265   else
00266     midpt = (min+max)/2;
00267 
00268   if (vco_num == 0)
00269     midpt = tune_rf(midpt);
00270   else
00271     midpt = tune_if(midpt);
00272 
00273   if ((midpt == 0) || (min == max)) // start in the middle
00274     return 0;
00275 
00276   pc_puts_P(PSTR("\nbandwidth tuning...\n"));
00277 
00278   if (vco_num==0)
00279     pll_set_rf(min, 8)
00280   else
00281     pll_set_if(min, 8);
00282 
00283   set_sawtooth_low();
00284 
00285   // get high vals?
00286   if (vco_num == 0) {
00287     set_resistor(BANDWADJ1_RES, 0);
00288     ADMUX = 0;
00289   } else {
00290     set_resistor(BANDWADJ2_RES, 0);
00291     ADMUX = 5;
00292   }
00293   delay_ms(100);
00294   avg = 0;
00295   for (j = 0; j < 127; j++) {
00296     ADCSRA |=  _BV(ADSC);
00297     while (ADCSRA & _BV(ADSC)); // wait for conversion to finish;
00298     avg += ADC;
00299     //putnum_ud(t); pc_putc(' ');
00300   }
00301   avg /= 128;
00302   threshhold = avg;
00303   //pc_puts("thres = "); putnum_ud(threshhold); pc_putc('\n');
00304 
00305   low = 0;
00306   high = 255;
00307   while ((low + 2) <= high) {
00308     i = ((uint16_t)low+(uint16_t)high)/2;
00309     // set the bandwidth
00310     if (vco_num == 0)
00311       set_resistor(BANDWADJ1_RES, i);
00312     else
00313       set_resistor(BANDWADJ2_RES, i);
00314     //putnum_ud(i); pc_puts(", ");
00315     delay_ms(500);
00316 
00317     // read ADC
00318 
00319     if (vco_num == 0)
00320       ADMUX = 0;
00321     else
00322       ADMUX = 5;
00323 
00324     avg = 0;
00325     for (j = 0; j < 127; j++) {
00326       ADCSRA |=  _BV(ADSC);
00327       while (ADCSRA & _BV(ADSC)); // wait for conversion to finish;
00328       avg += ADC;
00329       //putnum_ud(t); uart_putchar(' ');
00330     }
00331     avg /= 128;
00332     //putnum_ud(avg); pc_putc('\n');
00333     if (avg < (threshhold-10)) {
00334       high = i;
00335     } else {
00336       low = i;
00337     }
00338   }
00339   putnum_ud(i);
00340   pc_puts_P(PSTR(" done!\n"));
00341   set_sawtooth_high();
00342   return i;
00343 }