Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 30 Jun 2015 06:22:14 -0700
From:      Leonardo Fogel <leonardofogel@yahoo.com.br>
To:        freebsd-arm@freebsd.org
Subject:   Improvement to am335x_lcd_calc_divisor()
Message-ID:  <1435670534.33073.YahooMailBasic@web120806.mail.ne1.yahoo.com>

next in thread | raw e-mail | index | archive | help
Hello.

Given a reference frequency (R) and a target frequency (F), am335x_lcd_calc=
_divisor(R,F) calculates the divisor (d) such that abs(R/d - F) is the mini=
mum; ideally R/d =3D=3D F.

https://svnweb.freebsd.org/base/head/sys/arm/ti/am335x/am335x_lcd.c?revisio=
n=3D284534&view=3Dmarkup#l234

The function does a brute-force search; it tests d=3D2,...,255. I would lik=
e to propose a simpler (and faster) implementation.

Let r be the real number R/F, such that R/r =3D=3D F. The integer d that pr=
oduces the minimum abs(R/d - F) also produces the minimum abs(r - d). The t=
rivial solution is d =3D lround(r) (rounds to the nearest integer).

We do not need floating point arithmetic. Let f be the fractional part of r=
, namely, the real number (R%F)/F. If f >=3D 0.5, then lround(r) rounds up.=
 Otherwise, it rounds down. We can test whether 10*f >=3D 5. Here is the pr=
oposal:

=09if (freq =3D=3D 0) /* there is a bug somewhere. */
=09=09return (255);

=09/* The fractional part of the real number reference/freq, times 10. */
=09fraction_x10 =3D 10*(reference%freq)/freq;
=09if (fraction_x10 >=3D 5)
=09=09div =3D reference/freq + 1; /* rounds up   */
=09else
=09=09div =3D reference/freq ;    /* rounds down */

=09/* Raster mode case: divisors are in range from 2 to 255 */
=09if (div < 2)
=09=09div =3D 2;
=09else if (div > 255)
=09=09dir =3D 255;

=09return (div);

If you think it is worth, I'll be glad to submit a path. I just can not tes=
t it, though.
Thank you.
Leonardo



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1435670534.33073.YahooMailBasic>