Compare commits

...

2 Commits

Author SHA1 Message Date
deadprogram e472cf88c8 si5351: additional functions needed for more advanced and power saving usage scenarios
Signed-off-by: deadprogram <ron@hybridgroup.com>
2025-12-28 20:52:10 +01:00
Yurii Soldak 2a42fa7cbb st7735: remove dependency on the machine package 2025-12-22 08:59:05 +00:00
3 changed files with 222 additions and 16 deletions
+43
View File
@@ -28,6 +28,8 @@ const (
PLL_RESET = 177 PLL_RESET = 177
CRYSTAL_INTERNAL_LOAD_CAPACITANCE = 183 CRYSTAL_INTERNAL_LOAD_CAPACITANCE = 183
FANOUT_ENABLE = 187
) )
const ( const (
@@ -77,3 +79,44 @@ const (
const ( const (
SI5351_PLL_C_MAX = 1048575 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
View File
@@ -627,3 +627,163 @@ func (d *Device) GetFreqStep(pll uint8) uint64 {
return pllFreq / SI5351_PLL_C_MAX 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)
}
+19 -16
View File
@@ -5,12 +5,13 @@ package st7735 // import "tinygo.org/x/drivers/st7735"
import ( import (
"image/color" "image/color"
"machine"
"time" "time"
"errors" "errors"
"tinygo.org/x/drivers" "tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
"tinygo.org/x/drivers/internal/pin"
"tinygo.org/x/drivers/pixel" "tinygo.org/x/drivers/pixel"
) )
@@ -39,10 +40,10 @@ type Device = DeviceOf[pixel.RGB565BE]
// formats. // formats.
type DeviceOf[T Color] struct { type DeviceOf[T Color] struct {
bus drivers.SPI bus drivers.SPI
dcPin machine.Pin dcPin pin.OutputFunc
resetPin machine.Pin resetPin pin.OutputFunc
csPin machine.Pin csPin pin.OutputFunc
blPin machine.Pin blPin pin.OutputFunc
width int16 width int16
height int16 height int16
columnOffset int16 columnOffset int16
@@ -65,23 +66,25 @@ type Config struct {
} }
// New creates a new ST7735 connection. The SPI wire must already be configured. // New creates a new ST7735 connection. The SPI wire must already be configured.
func New(bus drivers.SPI, resetPin, dcPin, csPin, blPin machine.Pin) Device { func New(bus drivers.SPI, resetPin, dcPin, csPin, blPin pin.Output) Device {
return NewOf[pixel.RGB565BE](bus, resetPin, dcPin, csPin, blPin) return NewOf[pixel.RGB565BE](bus, resetPin, dcPin, csPin, blPin)
} }
// NewOf creates a new ST7735 connection with a particular pixel format. The SPI // NewOf creates a new ST7735 connection with a particular pixel format. The SPI
// wire must already be configured. // wire must already be configured.
func NewOf[T Color](bus drivers.SPI, resetPin, dcPin, csPin, blPin machine.Pin) DeviceOf[T] { func NewOf[T Color](bus drivers.SPI, resetPin, dcPin, csPin, blPin pin.Output) DeviceOf[T] {
dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) // IMPORTANT: pin configuration should really be done outside of this driver,
resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) // but for backwards compatibility with existing code, we do it here.
csPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) legacy.ConfigurePinOut(dcPin)
blPin.Configure(machine.PinConfig{Mode: machine.PinOutput}) legacy.ConfigurePinOut(resetPin)
legacy.ConfigurePinOut(csPin)
legacy.ConfigurePinOut(blPin)
return DeviceOf[T]{ return DeviceOf[T]{
bus: bus, bus: bus,
dcPin: dcPin, dcPin: dcPin.Set,
resetPin: resetPin, resetPin: resetPin.Set,
csPin: csPin, csPin: csPin.Set,
blPin: blPin, blPin: blPin.Set,
} }
} }
@@ -423,7 +426,7 @@ func (d *DeviceOf[T]) Data(data uint8) {
// Tx sends data to the display // Tx sends data to the display
func (d *DeviceOf[T]) Tx(data []byte, isCommand bool) { func (d *DeviceOf[T]) Tx(data []byte, isCommand bool) {
d.dcPin.Set(!isCommand) d.dcPin(!isCommand)
d.bus.Tx(data, nil) d.bus.Tx(data, nil)
} }