Skip to content

Commit d681a27

Browse files
committed
si5351: add support for si5351
Adds support for the si5351 I2C programmable clock generator using code from @chiefMarlin which used code from @conotto which somehow never got merged. Thank you everyone! Signed-off-by: deadprogram <ron@hybridgroup.com>
1 parent bd88b70 commit d681a27

File tree

4 files changed

+663
-0
lines changed

4 files changed

+663
-0
lines changed

examples/si5351/main.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package main
2+
3+
import (
4+
"machine"
5+
"time"
6+
7+
"tinygo.org/x/drivers/si5351"
8+
)
9+
10+
// Simple demo of the SI5351 clock generator.
11+
// This is like the Arduino library example:
12+
// https://github.com/adafruit/Adafruit_Si5351_Library/blob/master/examples/si5351/si5351.ino
13+
// Which will configure the chip with:
14+
// - PLL A at 900mhz
15+
// - PLL B at 616.66667mhz
16+
// - Clock 0 at 112.5mhz, using PLL A as a source divided by 8
17+
// - Clock 1 at 13.5531mhz, using PLL B as a source divided by 45.5
18+
// - Clock 2 at 10.76khz, using PLL B as a source divided by 900 and further divided with an R divider of 64.
19+
20+
func main() {
21+
time.Sleep(5 * time.Second)
22+
23+
println("Si5351 Clockgen Test")
24+
println()
25+
26+
// Configure I2C bus
27+
machine.I2C0.Configure(machine.I2CConfig{})
28+
29+
// Create driver instance
30+
clockgen := si5351.New(machine.I2C0)
31+
32+
// Verify device wired properly
33+
connected, err := clockgen.Connected()
34+
if err != nil {
35+
println("Unable to read device status")
36+
time.Sleep(time.Second)
37+
}
38+
if !connected {
39+
for {
40+
println("Unable to detect si5351 device")
41+
time.Sleep(time.Second)
42+
}
43+
}
44+
45+
// Initialise device
46+
clockgen.Configure()
47+
48+
// Now configue the PLLs and clock outputs.
49+
// The PLLs can be configured with a multiplier and division of the on-board
50+
// 25mhz reference crystal. For example configure PLL A to 900mhz by multiplying
51+
// by 36. This uses an integer multiplier which is more accurate over time
52+
// but allows less of a range of frequencies compared to a fractional
53+
// multiplier shown next.
54+
clockgen.ConfigurePLL(si5351.PLL_A, 36, 0, 1) // Multiply 25mhz by 36
55+
println("PLL A frequency: 900mhz")
56+
57+
// And next configure PLL B to 616.6667mhz by multiplying 25mhz by 24.667 using
58+
// the fractional multiplier configuration. Notice you specify the integer
59+
// multiplier and then a numerator and denominator as separate values, i.e.
60+
// numerator 2 and denominator 3 means 2/3 or 0.667. This fractional
61+
// configuration is susceptible to some jitter over time but can set a larger
62+
// range of frequencies.
63+
clockgen.ConfigurePLL(si5351.PLL_B, 24, 2, 3) // Multiply 25mhz by 24.667 (24 2/3)
64+
println("PLL B frequency: 616.6667mhz")
65+
66+
// Now configure the clock outputs. Each is driven by a PLL frequency as input
67+
// and then further divides that down to a specific frequency.
68+
// Configure clock 0 output to be driven by PLL A divided by 8, so an output
69+
// of 112.5mhz (900mhz / 8). Again this uses the most precise integer division
70+
// but can't set as wide a range of values.
71+
clockgen.ConfigureMultisynth(0, si5351.PLL_A, 8, 0, 1) // Divide by 8 (8 0/1)
72+
println("Clock 0: 112.5mhz")
73+
74+
// Next configure clock 1 to be driven by PLL B divided by 45.5 to get
75+
// 13.5531mhz (616.6667mhz / 45.5). This uses fractional division and again
76+
// notice the numerator and denominator are explicitly specified. This is less
77+
// precise but allows a large range of frequencies.
78+
clockgen.ConfigureMultisynth(1, si5351.PLL_B, 45, 1, 2) // Divide by 45.5 (45 1/2)
79+
println("Clock 1: 13.5531mhz")
80+
81+
// Finally configure clock 2 to be driven by PLL B divided once by 900 to get
82+
// down to 685.15 khz and then further divided by a special R divider that
83+
// divides 685.15 khz by 64 to get a final output of 10.706khz.
84+
clockgen.ConfigureMultisynth(2, si5351.PLL_B, 900, 0, 1) // Divide by 900 (900 0/1)
85+
// Set the R divider, this can be a value of:
86+
// - R_DIV_1: divider of 1
87+
// - R_DIV_2: divider of 2
88+
// - R_DIV_4: divider of 4
89+
// - R_DIV_8: divider of 8
90+
// - R_DIV_16: divider of 16
91+
// - R_DIV_32: divider of 32
92+
// - R_DIV_64: divider of 64
93+
// - R_DIV_128: divider of 128
94+
clockgen.ConfigureRdiv(2, si5351.R_DIV_64)
95+
println("Clock 2: 10.706khz")
96+
97+
// After configuring PLLs and clocks, enable the outputs.
98+
clockgen.EnableOutputs()
99+
100+
for {
101+
time.Sleep(5 * time.Second)
102+
println()
103+
println("Clock 0: 112.5mhz")
104+
println("Clock 1: 13.5531mhz")
105+
println("Clock 2: 10.706khz")
106+
}
107+
}

si5351/registers.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package si5351
2+
3+
// The I2C address which this device listens to.
4+
const AddressDefault = 0x60 // Assumes ADDR pin is low
5+
const AddressAlternative = 0x61 // Assumes ADDR pin is high
6+
7+
const (
8+
OUTPUT_ENABLE_CONTROL = 3
9+
10+
CLK0_CONTROL = 16
11+
CLK1_CONTROL = 17
12+
CLK2_CONTROL = 18
13+
CLK3_CONTROL = 19
14+
CLK4_CONTROL = 20
15+
CLK5_CONTROL = 21
16+
CLK6_CONTROL = 22
17+
CLK7_CONTROL = 23
18+
19+
MULTISYNTH0_PARAMETERS_1 = 42
20+
MULTISYNTH0_PARAMETERS_3 = 44
21+
MULTISYNTH1_PARAMETERS_1 = 50
22+
MULTISYNTH1_PARAMETERS_3 = 52
23+
MULTISYNTH2_PARAMETERS_1 = 58
24+
MULTISYNTH2_PARAMETERS_3 = 60
25+
26+
SPREAD_SPECTRUM_PARAMETERS = 149
27+
28+
PLL_RESET = 177
29+
30+
CRYSTAL_INTERNAL_LOAD_CAPACITANCE = 183
31+
)
32+
33+
const (
34+
CRYSTAL_LOAD_6PF = (1 << 6)
35+
CRYSTAL_LOAD_8PF = (2 << 6)
36+
CRYSTAL_LOAD_10PF = (3 << 6)
37+
)
38+
39+
const (
40+
CRYSTAL_FREQ_25MHZ = 25000000
41+
CRYSTAL_FREQ_27MHZ = 27000000
42+
)
43+
44+
const (
45+
PLL_A = iota
46+
PLL_B
47+
)
48+
49+
const (
50+
R_DIV_1 = iota
51+
R_DIV_2
52+
R_DIV_4
53+
R_DIV_8
54+
R_DIV_16
55+
R_DIV_32
56+
R_DIV_64
57+
R_DIV_128
58+
)
59+
60+
const (
61+
MULTISYNTH_DIV_4 = 4
62+
MULTISYNTH_DIV_6 = 6
63+
MULTISYNTH_DIV_8 = 8
64+
)

0 commit comments

Comments
 (0)