edt_si570.c

00001 /* #pragma ident "@(#)set_ss_vco.c      1.17 01/17/05 EDT" */
00002 
00003 #include <stdio.h>
00004 #include <math.h>
00005 
00006 #include <string.h>
00007 
00008 #include <stdlib.h>
00009 
00010 #include "edtinc.h"
00011 
00012 #include <stddef.h>
00013 
00014 #include "edt_si570.h"
00015 
00016 
00017 EdtRegisterDescriptor si570regs_map[] = {
00018     {7,5,3,"hs_div"},
00019     {7,6,7,"n1"},
00020     {8,4,10,"rfreq_int"},
00021     {9,0,28,"rfreq_frac"},
00022     {135,7,1,"reset"},
00023     {135,6,1,"newfreq"},
00024     {135,0,1,"recall"},
00025     {137,4,1,"freeze"},
00026     {0,0,0,0}
00027 };
00028 
00029 int
00030 edt_set_out_clk_si570(EdtDev *edt_p, EdtSI570 *sip)
00031 
00032 {
00033     return 0;
00034 }
00035 
00036 
00037 /* return valid bwsel */
00038 /* return 0 if not OK */
00039 
00040 
00041 void
00042 edt_si570_read_values(EdtDev *edt_p, 
00043                       u_int base_desc, 
00044                       u_int device, 
00045                       EdtSI570 *sip)
00046 
00047 {
00048     sip->hs_div = edt_get_two_wire_value(edt_p, 
00049         si570regs_map,
00050         base_desc, 
00051         device);
00052 
00053     sip->n1 = edt_get_two_wire_value(edt_p,
00054         si570regs_map+1,
00055         base_desc, 
00056         device);
00057 
00058     sip->rfreq_hi = edt_get_two_wire_value(edt_p,
00059         si570regs_map+2,
00060         base_desc, 
00061         device);
00062 
00063     sip->rfreq_fraction = edt_get_two_wire_value(edt_p,
00064         si570regs_map+3,
00065         base_desc, 
00066         device);
00067 }
00068 
00069 void
00070 edt_si570_reset(EdtDev *edt_p, u_int base_desc, u_int device)
00071 
00072 {
00073     int r;
00074     int t;
00075     
00076     edt_set_two_wire_value(edt_p, si570regs_map + 4, base_desc, device, 1);
00077 
00078     t = 0;
00079     while (r = edt_get_two_wire_value(edt_p, si570regs_map+4, base_desc, device))
00080     {
00081         edt_msleep(50);
00082         t += 50;
00083     }
00084 
00085     edt_msleep(100);
00086 }
00087 
00088 void
00089 edt_si570_write_values(EdtDev *edt_p, 
00090                        u_int base_desc, 
00091                        u_int device, 
00092                        EdtSI570 *sip)
00093 
00094 {
00095     /* freeze */
00096     edt_set_two_wire_value(edt_p, si570regs_map + 7, base_desc, device, 1);
00097 
00098     edt_set_two_wire_value(edt_p, si570regs_map, base_desc, device, sip->hs_div);
00099     edt_set_two_wire_value(edt_p, si570regs_map+1, base_desc, device, sip->n1);
00100     edt_set_two_wire_value(edt_p, si570regs_map+2, base_desc, device, sip->rfreq_hi);
00101     edt_set_two_wire_value(edt_p, si570regs_map+3, base_desc, device, sip->rfreq_fraction);
00102 
00103     /* unfreeze */
00104     edt_set_two_wire_value(edt_p, si570regs_map + 7, base_desc, device, 0);
00105     /* assert new freq */
00106     edt_set_two_wire_value(edt_p, si570regs_map + 5, base_desc, device, 1);
00107    
00108 }
00109 
00110 int
00111 edt_si570_dump(EdtDev *edt_p, u_int base_desc, u_int device)
00112 
00113 {
00114     edt_two_wire_reg_dump_raw(edt_p, si570regs_map, base_desc, device);
00115     edt_two_wire_reg_dump(edt_p, si570regs_map, base_desc, device);
00116     return 0;
00117 }
00118 
00119 double
00120 edt_si570_rfreq(u_int freq_hi, u_int freq_fraction)
00121 
00122 {
00123     double scalar = (double) (1 << 28);
00124 
00125     return (double) freq_hi + ((double) freq_fraction)/scalar;
00126 
00127 }
00128 
00129 double edt_si570_fxtal(EdtSI570 *sip, double refclock)
00130 
00131 {
00132     double rfreq = edt_si570_rfreq(sip->rfreq_hi,sip->rfreq_fraction);
00133 
00134     return ((sip->n1 + 1) * (sip->hs_div + 4) * refclock) / rfreq;
00135 
00136 }
00137 
00138 double edt_si570_current_freq(EdtSI570 *sip, double fxtal)
00139 
00140 {
00141     double rfreq = edt_si570_rfreq(sip->rfreq_hi,sip->rfreq_fraction);
00142     double output;
00143 
00144     output = (rfreq * fxtal) / ((sip->hs_div + 4) * (sip->n1 + 1));
00145 
00146     return output;
00147 }
00148 
00149 
00150 void 
00151 edt_si570_print(EdtSI570 *sip, double refclock)
00152 {
00153     double rfreq = edt_si570_rfreq(sip->rfreq_hi,sip->rfreq_fraction);
00154 
00155     printf("n1       = %d\nhs_div    = %d\nrfreq_int = %d\nfraction  = %08x\nrfreq   = %f\n",
00156         sip->n1,
00157         sip->hs_div,
00158         sip->rfreq_hi,
00159         sip->rfreq_fraction,
00160         rfreq);
00161 
00162     printf("\nF1 = %f\n",
00163         ((sip->n1 + 1) * (sip->hs_div + 4) * refclock) / rfreq);
00164 
00165 
00166 }
00167 
00168 #define foscmin 4850000000.0
00169 #define foscmax 5670000000.0
00170 
00171 #define N_HS_DIV_VALUES 6
00172 
00173 static int hs_divs[N_HS_DIV_VALUES] = 
00174 {
00175     4,
00176     5,
00177     6,
00178     7,
00179     9,
00180     11
00181 };
00182 
00183 double edt_vco_si570_compute(double xtal, double target, EdtSI570 *parms)
00184 
00185 {
00186     double actual = target;
00187     double fxtal = edt_si570_fxtal(parms, xtal);
00188     int best_hdiv = -1;
00189     int best_n1;
00190     double best_fosc;
00191     int i;
00192     int n1;
00193     double fosc;
00194     double rfreq;
00195 
00196     for (i=0;i<N_HS_DIV_VALUES;i++)
00197     {
00198         int hs_div = hs_divs[i];
00199 
00200         for (n1=0;n1<128;n1++)
00201         {
00202             if (n1==1 || (n1 & 1) == 0)
00203             {
00204                 fosc = target * hs_div * n1;
00205 
00206                 if (fosc >= foscmin && fosc <= foscmax)
00207                 {
00208                     if (best_hdiv == -1 || (fosc < best_fosc) || (fosc == best_fosc && n1 < best_n1) )
00209                     {
00210                         best_hdiv = hs_div;
00211                         best_n1   = n1;
00212                         best_fosc = fosc;
00213                         edt_msg(EDTLIB_MSG_INFO_1, "Selected fosc = %10f n1 = %d hdiv = %d\n",
00214                             best_fosc,best_n1,best_hdiv);
00215                     } 
00216                     else
00217                         edt_msg(EDTLIB_MSG_INFO_1,"Rejected fosc = %10f n1 = %d hdiv = %d\n",
00218                             fosc,n1,hs_div);
00219                 }
00220             }
00221         }
00222     }
00223 
00224     rfreq = best_fosc / fxtal;
00225 
00226     edt_msg(EDTLIB_MSG_INFO_1,"new rfreq %f\n", rfreq);
00227 
00228     parms->hs_div = best_hdiv - 4;
00229     parms->n1 = best_n1 - 1;
00230     parms->rfreq_fraction = (u_int)((rfreq - floor(rfreq)) * (double) (1 << 28)) ;
00231     parms->rfreq_hi = (u_int) (floor(rfreq));
00232 
00233     return actual;
00234 
00235 }
00236 
00237 int
00238 edt_si570_set_clock(EdtDev *edt_p, u_int base_desc, u_int device,
00239                     double nominal, double target, EdtSI570 *parms)
00240 
00241 {
00242 
00243     EdtSI570 *sip;
00244     EdtSI570 localparms;
00245 
00246     if (base_desc < 0x100)
00247         base_desc |= 0x01010000;
00248 
00249     if (parms)
00250         sip = parms;
00251     else
00252         sip = &localparms;
00253 
00254     edt_si570_reset(edt_p, base_desc, device);
00255 
00256     edt_si570_read_values(edt_p, base_desc, device, sip);
00257 
00258     edt_vco_si570_compute(nominal, target, sip);
00259 
00260     edt_si570_write_values(edt_p, base_desc, device, sip);
00261 
00262     return 0;
00263 }
00264 
00265 /* somewhat complicated method to read current output - without making any
00266    assumption aboout calibrated value */
00267 
00268 double 
00269 edt_si570_get_clock(EdtDev *edt_p, u_int base_desc, u_int device, double nominal, 
00270                     EdtSI570 *parms)
00271 
00272 {
00273     EdtSI570 *sip;
00274     EdtSI570 localparms;
00275     EdtSI570 storeparms;
00276     double fxtal;
00277     double output;
00278 
00279     if (parms)
00280         sip = parms;
00281     else
00282         sip = &storeparms;
00283 
00284 
00285     edt_si570_read_values(edt_p, base_desc, device, sip);
00286 
00287 
00288     /* return to factory state */
00289 
00290     edt_si570_reset(edt_p, base_desc, device);
00291 
00292     edt_si570_read_values(edt_p, base_desc, device, &localparms);
00293 
00294     /* compute the correct internal clock */
00295 
00296     fxtal = edt_si570_fxtal(&localparms, nominal);
00297 
00298     output = edt_si570_current_freq(sip,  fxtal);
00299 
00300     edt_si570_write_values(edt_p, base_desc, device, sip);
00301 
00302     return output;
00303 }
00304 
00305 
00306 
00307 
00308 

Generated on 19 Jun 2015 by  doxygen 1.4.7