Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions si5351/registers.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ const (
PLL_RESET = 177

CRYSTAL_INTERNAL_LOAD_CAPACITANCE = 183

FANOUT_ENABLE = 187
)

const (
Expand Down Expand Up @@ -77,3 +79,44 @@ const (
const (
SI5351_PLL_C_MAX = 1048575
)

// Bit masks for FANOUT_ENABLE register
const (
CLKIN_ENABLE = (1 << 7)
XTAL_ENABLE = (1 << 6)
MULTISYNTH_ENABLE = (1 << 4)
)

const (
FANOUT_CLKIN = iota
FANOUT_XO
FANOUT_MS
)

// Clock source selection masks for CLKx_CONTROL registers
const (
CLK_INPUT_MASK = 0x3 // Bits 0 and 1
CLK_INPUT_XTAL = 0x0
CLK_INPUT_CLKIN = 0x1
CLK_INPUT_MULTISYNTH_0_4 = 0x2
CLK_INPUT_MULTISYNTH_N = 0x3
)

// Clock source selection
const (
CLK_SRC_XTAL = iota
CLK_SRC_CLKIN
CLK_SRC_MS0
CLK_SRC_MS
)

const (
CLK_INVERT = 1 << 4
)

const (
CLK_DRIVE_STRENGTH_2MA = 0
CLK_DRIVE_STRENGTH_4MA = 1
CLK_DRIVE_STRENGTH_6MA = 2
CLK_DRIVE_STRENGTH_8MA = 3
)
160 changes: 160 additions & 0 deletions si5351/si5351.go
Original file line number Diff line number Diff line change
Expand Up @@ -627,3 +627,163 @@ func (d *Device) GetFreqStep(pll uint8) uint64 {

return pllFreq / SI5351_PLL_C_MAX
}

// SetClockFanout enables or disables the specified clock fanout.
// fanout - The fanout to configure, which must be one of:
// - FANOUT_CLKIN
// - FANOUT_XO
// - FANOUT_MS
//
// enable - true to enable the fanout, false to disable it.
func (d *Device) SetClockFanout(fanout int, enable bool) error {
if !d.initialised {
return ErrNotInitialised
}

// Read the current value of the FANOUT_ENABLE register
regVal, err := d.rw.Read8(FANOUT_ENABLE)
if err != nil {
return err
}
// Modify regVal based on fanout and enable
switch fanout {
case FANOUT_CLKIN:
if enable {
regVal |= CLKIN_ENABLE
} else {
regVal &^= CLKIN_ENABLE
}
case FANOUT_XO:
if enable {
regVal |= XTAL_ENABLE
} else {
regVal &^= XTAL_ENABLE
}
case FANOUT_MS:
if enable {
regVal |= MULTISYNTH_ENABLE
} else {
regVal &^= MULTISYNTH_ENABLE
}
default:
return ErrInvalidParameter
}

return d.rw.Write8(FANOUT_ENABLE, regVal)
}

// SetClockSource sets the clock source for a multisynth output.
// clk - Clock output (0..7)
// src - Clock source (see constants below)
func (d *Device) SetClockSource(clk uint8, src uint8) error {
if !d.initialised {
return ErrNotInitialised
}

clkReg := CLK0_CONTROL + clk
regVal, err := d.rw.Read8(clkReg)
if err != nil {
return err
}

// Clear the input source bits
regVal &^= CLK_INPUT_MASK

switch src {
case CLK_SRC_XTAL:
regVal |= CLK_INPUT_XTAL
case CLK_SRC_CLKIN:
regVal |= CLK_INPUT_CLKIN
case CLK_SRC_MS0:
if clk == 0 {
return nil // MS0 not valid for CLK0
}
regVal |= CLK_INPUT_MULTISYNTH_0_4
case CLK_SRC_MS:
regVal |= CLK_INPUT_MULTISYNTH_N
default:
return ErrInvalidParameter
}

return d.rw.Write8(clkReg, regVal)
}

// SetClockInvert enables or disables inversion of the clock output waveform.
// clk - Clock output (0..7)
// invert - true to enable inversion, false to disable
func (d *Device) SetClockInvert(clk uint8, invert bool) error {
if !d.initialised {
return ErrNotInitialised
}

clkReg := CLK0_CONTROL + clk
regVal, err := d.rw.Read8(clkReg)
if err != nil {
return err
}

if invert {
regVal |= CLK_INVERT
} else {
regVal &^= CLK_INVERT
}

return d.rw.Write8(clkReg, regVal)
}

// SetDriveStrength sets the drive strength of the specified clock output.
// clk - Clock output (0..7)
// drive - Desired drive level (use SI5351_CLK_DRIVE_STRENGTH_* constants)
func (d *Device) SetDriveStrength(clk uint8, drive uint8) error {
if !d.initialised {
return ErrNotInitialised
}

const mask = 0x03
clkReg := CLK0_CONTROL + clk
regVal, err := d.rw.Read8(clkReg)
if err != nil {
return err
}

// Clear drive strength bits
regVal &^= mask

switch drive {
case CLK_DRIVE_STRENGTH_2MA:
regVal |= 0x00
case CLK_DRIVE_STRENGTH_4MA:
regVal |= 0x01
case CLK_DRIVE_STRENGTH_6MA:
regVal |= 0x02
case CLK_DRIVE_STRENGTH_8MA:
regVal |= 0x03
default:
return ErrInvalidParameter
}

return d.rw.Write8(clkReg, regVal)
}

// SetClockPower enables or disables power to a clock output (power saving).
// clk - Clock output (0..7)
// enable - true to enable power, false to disable (power down)
func (d *Device) SetClockPower(clk uint8, enable bool) error {
if !d.initialised {
return ErrNotInitialised
}

clkReg := CLK0_CONTROL + clk
regVal, err := d.rw.Read8(clkReg)
if err != nil {
return err
}

if enable {
regVal &^= 0x80 // Clear bit 7 to enable power
} else {
regVal |= 0x80 // Set bit 7 to disable power (power down)
}

return d.rw.Write8(clkReg, regVal)
}