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
CRYSTAL_INTERNAL_LOAD_CAPACITANCE = 183
FANOUT_ENABLE = 187
)
const (
@@ -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
View File
@@ -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)
}
+19 -16
View File
@@ -5,12 +5,13 @@ package st7735 // import "tinygo.org/x/drivers/st7735"
import (
"image/color"
"machine"
"time"
"errors"
"tinygo.org/x/drivers"
"tinygo.org/x/drivers/internal/legacy"
"tinygo.org/x/drivers/internal/pin"
"tinygo.org/x/drivers/pixel"
)
@@ -39,10 +40,10 @@ type Device = DeviceOf[pixel.RGB565BE]
// formats.
type DeviceOf[T Color] struct {
bus drivers.SPI
dcPin machine.Pin
resetPin machine.Pin
csPin machine.Pin
blPin machine.Pin
dcPin pin.OutputFunc
resetPin pin.OutputFunc
csPin pin.OutputFunc
blPin pin.OutputFunc
width int16
height int16
columnOffset int16
@@ -65,23 +66,25 @@ type Config struct {
}
// 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)
}
// NewOf creates a new ST7735 connection with a particular pixel format. The SPI
// wire must already be configured.
func NewOf[T Color](bus drivers.SPI, resetPin, dcPin, csPin, blPin machine.Pin) DeviceOf[T] {
dcPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
resetPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
csPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
blPin.Configure(machine.PinConfig{Mode: machine.PinOutput})
func NewOf[T Color](bus drivers.SPI, resetPin, dcPin, csPin, blPin pin.Output) DeviceOf[T] {
// IMPORTANT: pin configuration should really be done outside of this driver,
// but for backwards compatibility with existing code, we do it here.
legacy.ConfigurePinOut(dcPin)
legacy.ConfigurePinOut(resetPin)
legacy.ConfigurePinOut(csPin)
legacy.ConfigurePinOut(blPin)
return DeviceOf[T]{
bus: bus,
dcPin: dcPin,
resetPin: resetPin,
csPin: csPin,
blPin: blPin,
dcPin: dcPin.Set,
resetPin: resetPin.Set,
csPin: csPin.Set,
blPin: blPin.Set,
}
}
@@ -423,7 +426,7 @@ func (d *DeviceOf[T]) Data(data uint8) {
// Tx sends data to the display
func (d *DeviceOf[T]) Tx(data []byte, isCommand bool) {
d.dcPin.Set(!isCommand)
d.dcPin(!isCommand)
d.bus.Tx(data, nil)
}