Skip to content

Instantly share code, notes, and snippets.

@andy-shev
Last active July 1, 2021 14:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andy-shev/06b084488b3629898121 to your computer and use it in GitHub Desktop.
Save andy-shev/06b084488b3629898121 to your computer and use it in GitHub Desktop.
Quark SoC SPI baudrate calculator
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# vim: ts=4 sw=4 et ai si
import sys
import os
import operator
import math
import fractions
__author__ = "Andy Shevchenko"
__license__ = "GPL v2"
PROG = os.path.basename(sys.argv[0])
FSYS = 200000000
#
# Fssp = Fsys * DDS_CLK_RATE / 2**24
# Baud rate = Fsclk = Fssp / (2 * (SCR + 1))
#
# DDS_CLK_RATE either 2^n or 2^n / 5.
# SCR is in range 0 .. 255
#
# Divisor = 5^i * 2^j * 2 * k
# i = [0, 1] i = 1 iff j = 0 or j > 3
# j = [0, 23] j = 0 iff i = 1
# k = [1, 256]
# Special case: j = 0, i = 1: Divisor = 2 / 5
#
# Baud rate, DDS_CLK_RATE, SCR
TABLE = [
[50000000, 8388608, 0],
[40020000, -1, -1],
[40000000, 6710886, 0],
[39980000, -1, -1],
[25000000, 4194304, 0],
[20000000, 6710886, 1],
[16667000, 8388608, 2],
[13333000, 6710886, 2],
[12500000, 2097152, 0],
[10000000, 8388608, 4],
[8000000, 6710886, 4],
[6250000, 4194304, 3],
[5000000, 4194304, 4],
[4350000, -1, -1],
[4000000, 6710886, 9],
[3333000, -1, -1],
[3140500, 524288, -1],
[3125000, 524288, 0],
[3109500, 524288, -1],
[2500000, 4194304, 9],
[2000000, 6710886, 19],
[1563000, 262144, 0],
[1250000, 2097152, 9],
[1006000, -1, -1],
[1000000, 4194304, 24],
[994000, -1, -1],
[800000, 6710886, 49],
[781250, 131072, 0],
[625000, 2097152, 19],
[500000, 4194304, 49],
[400000, 6710886, 99],
[390625, 65536, 0],
[250000, 4194304, 99],
[205313, 32768, -1],
[200000, 6710886, 199],
[195313, 32768, 0],
[185313, 32768, -1],
[125000, 1048576, 49],
[100700, -1, -1],
[100000, 2097152, 124],
[99300, -1, -1],
[50000, 1048576, 124],
[25000, 524288, 124],
[10066, 131072, -1],
[10016, 131072, 77],
[9966, 131072, -1],
[5065, 131072, -1],
[5040, 131072, 154],
[5015, 131072, -1],
[1007, 32768, -1],
[1002, 32768, 194],
[997, 32768, -1],
[69, -1, -1],
[7, -1, -1],
[2, -1, -1],
[1, -1, -1],
]
def idiv(a, b):
return int(a // b)
def go(fref, baud):
fr1 = idiv(fref, 2)
fr2 = idiv(fref * 2, 5)
q1 = idiv(fr1 + baud - 1, baud)
q2 = idiv(fr2 + baud - 1, baud)
q12 = q1
q3 = idiv(fref + baud - 1, baud)
dds12 = 2 ** 23
if q12 > 256:
# Use fls()
shift = int(math.ceil(math.log(q12, 2)))
if shift > 9:
q12 >>= shift - 9
dds12 >>= shift - 9
if q12 % 2:
q12 += 1
# Use ffs()
while q12 % 2 == 0:
q12 >>= 1
dds12 >>= 1
arate1 = idiv(fr1, q1)
r1 = abs(baud - arate1)
dds2 = idiv(2 ** 24 * 2, 5)
arate2 = idiv(fr2, q2)
r2 = abs(baud - arate2)
div = 23 - int(math.log(dds12, 2))
arate12 = idiv(fr1 >> div, q12)
r12 = abs(baud - arate12)
dds3 = idiv(2 ** 24, q3)
arate3 = idiv(fref * dds3, 2 ** 24)
r3 = abs(baud - arate3)
c1 = '%d, %d' % (q1, r1)
c12 = '%d, %d' % (q12, r12)
c2 = ''
c3 = ''
# if (r2 == 0 and r12 == 0 and dds2 > dds12) or (r2 and r2 >= r12) or q2 > 256:
if r2 >= r12 or q2 > 256:
arate = arate12
dds = dds12
q = q12
r = r12
else:
arate = arate2
dds = dds2
q = q2
r = r2
if q2 <= 256:
c2 = '%d, %d' % (q2, r2)
if fref / 80 >= baud:
if r3 < r:
arate = arate3
dds = dds3
q = 1
r = r3
c3 = '%d, %d' % (q3, r3)
choice = ' -> %06x, %d, %d' % (dds, q, r)
print("%8d(%8d): c1: %-12s c12: %-12s c2: %-12s c3: %-12s %s" % (baud, arate, c1, c12, c2, c3, choice))
def usage():
sys.stdout.write("Usage %s [CUSTOM_BAUD_RATE]\n" % PROG)
def toint(value):
try:
return int(value)
except ValueError:
usage()
raise SystemExit("Invalid argument")
def main(argv):
fref = FSYS / 2
if len(argv) > 1:
custom = toint(argv[1])
go(fref, custom)
else:
for item in TABLE:
go(fref, operator.itemgetter(0)(item))
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