> -----Original Message----- > From: Richard Cochran [mailto:richardcoch...@gmail.com] > Sent: Wednesday, November 23, 2016 11:03 PM > To: Andrei Pistirica - M16132 > Cc: netdev@vger.kernel.org; linux-ker...@vger.kernel.org; linux-arm- > ker...@lists.infradead.org; da...@davemloft.net; > nicolas.fe...@atmel.com; harinikatakamli...@gmail.com; > harini.kata...@xilinx.com; punn...@xilinx.com; mich...@xilinx.com; > anir...@xilinx.com; boris.brezil...@free-electrons.com; > alexandre.bell...@free-electrons.com; tbul...@pixelsurmer.com > Subject: Re: [RFC PATCH v2 1/2] macb: Add 1588 support in Cadence GEM. > > On Wed, Nov 23, 2016 at 02:34:03PM +0100, Andrei Pistirica wrote: > > From what I understand, your suggestion is: > > (ns | frac) * ppb = (total_ns | total_frac) (total_ns | total_frac) / > > 10^9 = (adj_ns | adj_frac) This is correct iff total_ns/10^9 >= 1, but > > the problem is that there are missed fractions due to the following > > approximation: > > frac*ppb =~ > > (ns*ppb+frac*ppb*2^16)*2^16-10^9*2^16*flor(ns*ppb+frac*ppb*2^16, > > 10^9). > > -ENOPARSE; > > > An example which uses values from a real test: > > let ppb=4891, ns=12 and frac=3158 > > That is a very strange example for nominal frequency. The clock period is > 12.048187255859375 nanoseconds, and so the frequency is > 83000037.99 Hz. > > But hey, let's go with it... > > > - using suggested algorithm, yields: adj_ns = 0 and adj_frac = 0 > > - using in-place algorithm, yields: adj_ns = 0, adj_frac = 4 You can > > check the calculus. > > The test program, below, shows you what I meant. (Of course, you should > adjust this to fit the adjfine() method.) > > Unfortunately, this device has a very coarse frequency resolution. > Using a nominal period of ns=12 as an example, the resolution is > 2^-16 / 12 or 1.27 ppm. The 24 bit device is much better in this repect. > > The output using your example numbers is: > > $ ./a.out 12 3158 4891 > ns=12 frac=3158 > ns=12 frac=3162 > > $ ./a.out 12 3158 -4891 > ns=12 frac=3158 > ns=12 frac=3154 > > See how you get a result of +/- 4 with just one division? > > Thanks, > Richard > > --- > #include <stdint.h> > #include <stdio.h> > #include <stdlib.h> > > static void adjfreq(uint32_t ns, uint32_t frac, int32_t ppb) { > uint64_t adj; > uint32_t diff, word; > int neg_adj = 0; > > printf("ns=%u frac=%u\n", ns, frac); > > if (ppb < 0) { > neg_adj = 1; > ppb = -ppb; > } > word = (ns << 16) + frac; > adj = word; > adj *= ppb; > adj += 500000000UL; > diff = adj / 1000000000UL; > > word = neg_adj ? word - diff : word + diff; > printf("ns=%u frac=%u\n", word >> 16, word & 0xffff); } > > int main(int argc, char *argv[]) > { > uint32_t ns, frac; > int32_t ppb; > > if (argc != 4) { > puts("need ns, frac, and ppb"); > return -1; > } > ns = atoi(argv[1]); > frac = atoi(argv[2]); > ppb = atoi(argv[3]); > adjfreq(ns, frac, ppb); > return 0; > }
Ok, thanks. I will use this one then. Regards, Andrei