mbed code for Farrari board

Dependencies:   DDRO_Farrari mbed

Fork of DDRO_Farrari by Liangzhen Lai

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers pll.cpp Source File

pll.cpp

00001 #include "pll.h"
00002 
00003 unsigned long long calc_pll_freqs(unsigned int prediv, unsigned int multint_upper, unsigned int multint, 
00004                             unsigned int range_upper, unsigned int rangea, unsigned int rangeb){
00005 
00006     if(prediv < 1 || prediv > 32){
00007         pc.printf("Prediv out of 1-32 range\r\n");
00008     }
00009     if(multint_upper < 1 || multint_upper > 4){
00010         pc.printf("Multint_upper out of 1-4 range\r\n");
00011     }
00012     if(multint < 1 || multint > 255){
00013         pc.printf("Multint out of 1-255 range\r\n");
00014     }
00015     if(multint_upper * multint > 255){
00016         pc.printf("Multint_upper * Multint out of 1-255 range\r\n");
00017     }
00018     if(!(range_upper == 1 || range_upper == 2 || range_upper == 4)){
00019         pc.printf("Range_upper out of 1,2,4 range\r\n");
00020     }
00021     if(rangea < 1 || rangea > 32){
00022         pc.printf("RangeA out of 1-32 range\r\n");
00023     }
00024     if(rangeb < 1 || rangeb > 32){
00025         pc.printf("RangeB out of 1-32 range\r\n");
00026     }
00027     
00028     int dco = (PLL_REF / prediv) * multint_upper * multint;
00029     if(dco < 2500000 || dco > 5000000){
00030         pc.printf("Dco=%d out of 2.5G-5G range\r\n",dco);
00031     }
00032     int internal = dco / multint_upper;
00033     if(internal < 9800 || internal > 3200000){
00034        pc.printf("internal=%d out of 9.8M-3.2G range\r\n",internal);
00035     }
00036     int prescale_dco = dco / range_upper;
00037     if(prescale_dco > 3200000){
00038        pc.printf("Prescale DCO out of 0-3.2G range\r\n");
00039     }
00040     int out_a = prescale_dco / rangea;
00041     if(out_a < 20000 || out_a > 3000000){
00042         pc.printf("Out A out of 20M-3.0G range\r\n");
00043     }
00044     int out_b = prescale_dco / rangeb;
00045     if(out_b < 20000 || out_b > 3000000){
00046         pc.printf("Out B out of 20M-3.0G range\r\n");
00047     }
00048     
00049     return out_a;
00050 }
00051 
00052 int get_binline_by_num(char* filename, int linenum){
00053     char value[30];
00054     
00055     //pc.printf("Opening %s File\r\n", filename);
00056     FILE *fp = fopen(filename, "r");
00057     if(!fp){
00058         pc.printf("ERROR: %s not found\r\n", filename);
00059     }
00060     //pc.printf("%s Open\r\n", filename);
00061         
00062     int i=1;
00063     char lineval[255];
00064     while (!feof(fp)) {
00065         fscanf(fp, "%s", lineval);
00066         if(i == linenum){
00067             strcpy(value, lineval);
00068             break;
00069         }
00070         i++;
00071     }
00072             
00073     //pc.printf("Closing %s File\r\n", filename);
00074     fclose(fp);
00075     //pc.printf("File %s Closed\r\n", filename);
00076     
00077     return strtol(value, NULL, 2);
00078 }
00079 
00080 void scan_pll(unsigned int prediv, unsigned int multint_upper, unsigned int multint, 
00081               unsigned int range_upper, unsigned int rangea, unsigned int rangeb){
00082     
00083     prediv        = get_binline_by_num("/local/Pprediv.txt",  prediv);
00084     multint_upper = get_binline_by_num("/local/Pmultup.txt",  multint_upper);
00085     multint       = get_binline_by_num("/local/Pmultint.txt", multint);
00086     range_upper   = get_binline_by_num("/local/Prangeup.txt", range_upper);
00087     rangea        = get_binline_by_num("/local/Prange.txt",   rangea);
00088     rangeb        = get_binline_by_num("/local/Prange.txt",   rangeb);
00089     
00090     set_scan_bits("PLL_CE1CCB",   1);
00091     set_scan_bits("PLL_CE1MPGC1", 1);
00092     set_scan_bits("PLL_FFTUNE",   fftune(0));
00093     set_scan_bits("PLL_LFTUNE",   lftune()); // @@@ Fix this. Scan doesn't support more than 32 bits
00094     set_scan_bits("PLL_INTFBK",   1);
00095     set_scan_bits("PLL_PREDIV",   prediv);
00096     set_scan_bits("PLL_MULTINT",  multint_upper << 8 | multint);
00097     set_scan_bits("PLL_RANGEA",   range_upper << 5 | rangea);
00098     set_scan_bits("PLL_RANGEB",   range_upper << 5 | rangeb);
00099 }
00100 
00101 void jtag_pll(JTAG &jtag, unsigned int prediv, unsigned int multint_upper, unsigned int multint, 
00102               unsigned int range_upper, unsigned int rangea, unsigned int rangeb){
00103     
00104     prediv        = get_binline_by_num("/local/Pprediv.txt",  prediv);
00105     multint_upper = get_binline_by_num("/local/Pmultup.txt",  multint_upper);
00106     multint       = get_binline_by_num("/local/Pmultint.txt", multint);
00107     range_upper   = get_binline_by_num("/local/Prangeup.txt", range_upper);
00108     rangea        = get_binline_by_num("/local/Prange.txt",   rangea);
00109     rangeb        = get_binline_by_num("/local/Prange.txt",   rangeb);
00110     jtag.writeMemory(PLL_CE1CCB,   1);
00111     jtag.writeMemory(PLL_CE1MPGC1, 1);
00112     jtag.writeMemory(PLL_FFTUNE,   fftune(0));
00113     jtag.writeMemory(PLL_LFTUNE_32_0,   lftune_lo());
00114     jtag.writeMemory(PLL_LFTUNE_40_32,   lftune_hi());
00115     jtag.writeMemory(PLL_INTFBK,   1);
00116     jtag.writeMemory(PLL_PREDIV,   prediv);
00117     jtag.writeMemory(PLL_RANGEA,   range_upper << 5 | rangea);
00118     jtag.writeMemory(PLL_RANGEB,   range_upper << 5 | rangeb);
00119     jtag.writeMemory(PLL_MULTINT,  multint_upper << 8 | multint);
00120 }
00121 
00122 
00123 unsigned int fftune(bool change_rangeab){
00124     if(change_rangeab){
00125         return 0x0120;
00126     }else{
00127         return 0x0100;
00128     }
00129 }
00130 
00131 unsigned int lftune_hi(){
00132     return 0x00000050;
00133 }
00134 
00135 unsigned int lftune_lo(){
00136     return 0x40100000;
00137 }
00138 
00139 unsigned long long lftune(){
00140     // 41 bits
00141     return 0x05040100000L;
00142 }
00143 
00144 /*
00145 unsigned long long calc_pll_freqs(unsigned int prediv, unsigned int multint_upper, unsigned int multint, 
00146                             unsigned int range_upper, unsigned int rangea, unsigned int rangeb)
00147                             dco = (PLL_REF / prediv) * multint_upper * multint;
00148                             prescale_dco = dco / range_upper;
00149                             out_a = prescale_dco / rangea;
00150 */
00151 int set_pll_frequency (int fMHz, JTAG &jtag) {
00152   jtag.writeMemory(intclk_source, 0);
00153   int counter = fMHz / 5;
00154   int frequency = counter * 5;
00155   if (frequency >= 625) {
00156     pc.printf("Frequency > 625 MHz out of range!\r\nClock source changed to HCLK_EXT\r\n");
00157     return 1;
00158   } /*
00159   else if (frequency >= 625) {
00160     //counter between 125 and 200
00161     // 20*125/4=625
00162     // 20*200/4=1G 
00163     jtag_pll(jtag, 1, 1, counter, 1, 4, 4);
00164     calculated_f = calc_pll_freqs(1, 1, counter, 1, 4, 4)/1000;
00165     if (calculated_f != frequency) {
00166         pc.printf("PLL frequency not match!\r\n");
00167     }
00168   } */ 
00169   else if (frequency >= 325) {
00170     //counter between 65 and 125
00171     // 20*2*65/8=325
00172     // 20*2*125/8=625
00173     jtag_pll(jtag, 1, 2, counter, 1, 8, 8);
00174   } else if (frequency >= 210) {
00175     //counter between 42 and 65 
00176     // 20*3*42/12=210
00177     // 20*3*65/12=325
00178     jtag_pll(jtag, 1, 3, counter, 1, 12, 12);
00179   } else if (frequency >= 105) {
00180     //counter between 21 and 42 
00181     // 20*6*21/24=125
00182     // 20*6*42/24=210
00183     jtag_pll(jtag, 1, 3, 2*counter, 1, 24, 24);
00184   } else {
00185     pc.printf("Frequency < 105M out of range!\r\nClock source changed to HCLK_EXT\r\n");
00186     return 1;
00187   }
00188   jtag.writeMemory(PLL_RESET, 1);
00189   wait_us(10);
00190   jtag.writeMemory(PLL_RESET, 0);
00191   wait_us(10);
00192   if(jtag.readMemory(PLL_PLLLOCK)==0) {
00193     pc.printf("PLL lock failed!\r\nClock source changed to HCLK_EXT\r\n");
00194     return 1;
00195   } else {
00196     jtag.writeMemory(intclk_source, 2);
00197     return 0;
00198   }
00199 }