Instantly share code, notes, and snippets.

Embed
What would you like to do?
Fractional divider calculator for Synopsys DesignWare UART (8250) v4.00a and newer
#!/usr/bin/python -tt
# -*- coding: UTF-8 -*-
# vim: ts=4 sw=4 et ai si
from __future__ import print_function
import sys
import os
import math
__author__ = "Andy Shevchenko"
__license__ = "GPL v2"
PROG = os.path.basename(sys.argv[0])
BAUDRATES = [
# Group 0
110,
134,
# Group 1
50,
75,
150,
200,
300,
600,
1200,
1800,
2400,
4800,
9600,
19200,
38400,
57600,
115200,
230400,
460800,
921600,
1843200,
# Group 2
576000,
1152000,
# Group 3
500000,
1000000,
1500000,
2000000,
2500000,
3000000,
3500000,
4000000,
]
XTAL = 38400000
BAUD = 115200
DFL = 64
#
# Fuart = XTAL / (BRDi + BRDf)
# uartclk = Fuart * 16
# baud = uartclk / DLAB
#
def go(xtal, baud, dfl):
bb = baud * 16
# mathematical (br1 == baud)
div1 = xtal * 1.0 * dfl / bb
br1 = (xtal * 1.0 / (div1 / dfl)) / 16
# algorithm in the driver
quot = xtal // bb
rem = xtal % bb
# DIV_ROUND_CLOSEST(rem * dfl, bb)
frac = int(round((rem * dfl) * 1.0 / bb))
div2 = quot * dfl + frac
br2 = ((xtal * dfl) // div2) // 16
return div1, br1, div2, br2
def usage():
sys.stdout.write("Usage %s [XTAL [DFL [BAUD]]]\n" % PROG)
def toint(value):
try:
return int(value)
except ValueError:
usage()
raise SystemExit("Invalid argument")
def main(argv):
if len(argv) > 1:
xtal = toint(argv[1])
else:
xtal = XTAL
if len(argv) > 2:
dfl = toint(argv[2])
else:
dfl = DFL
if len(argv) > 3:
baud = toint(argv[3])
bauds = (baud, )
else:
baud = BAUD
bauds = sorted(BAUDRATES)
for b in bauds:
div1, br1, div2, br2 = go(xtal, b, dfl)
ds = math.copysign(1, br2 - br1)
dv = abs(br2 - br1) * 100.0 / b
if dv < 0.005 and dv > -0.005:
sdv = ""
else:
sdv = "%+2.2f" % (dv * ds)
print("%-8d %-8.3f\t%-8.0f %-10d %-10d %s" % (b, div1, br1, div2, br2, sdv))
if __name__ == "__main__":
sys.exit(main(sys.argv))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment