|
| 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 | +} |
0 commit comments