Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add PWM interrupt functionality for RP2040 #2684

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from
Draft
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
55 changes: 47 additions & 8 deletions src/machine/machine_rp2040_pwm.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ type pwmGroup struct {
TOP volatile.Register32
}

type pwmBlock struct {
EN volatile.Register32
INTR volatile.Register32
INTE volatile.Register32
INTF volatile.Register32
INTS volatile.Register32
}

// Equivalent of
// var pwmSlice []pwmGroup = (*[8]pwmGroup)(unsafe.Pointer(rp.PWM))[:]
// return &pwmSlice[index]
Expand All @@ -52,6 +60,11 @@ func getPWMGroup(index uintptr) *pwmGroup {
return (*pwmGroup)(unsafe.Pointer(uintptr(unsafe.Pointer(rp.PWM)) + 0x14*index))
}

func getPWMHW() *pwmBlock {
const offset = 0xa0 // EN register offset
return (*pwmBlock)(unsafe.Pointer(uintptr(unsafe.Pointer(rp.PWM)) + offset))
}

// Hardware Pulse Width Modulation (PWM) API
// PWM peripherals available on RP2040. Each peripheral has 2 pins available for
// a total of 16 available PWM outputs. Some pins may not be available on some boards.
Expand All @@ -68,14 +81,15 @@ func getPWMGroup(index uintptr) *pwmGroup {
// immediately wrap to 0. PWM slices also offer a phase-correct mode, where the counter starts to count downward after
// reaching TOP, until it reaches 0 again.
var (
PWM0 = getPWMGroup(0)
PWM1 = getPWMGroup(1)
PWM2 = getPWMGroup(2)
PWM3 = getPWMGroup(3)
PWM4 = getPWMGroup(4)
PWM5 = getPWMGroup(5)
PWM6 = getPWMGroup(6)
PWM7 = getPWMGroup(7)
pwmHW = getPWMHW()
PWM0 = getPWMGroup(0)
PWM1 = getPWMGroup(1)
PWM2 = getPWMGroup(2)
PWM3 = getPWMGroup(3)
PWM4 = getPWMGroup(4)
PWM5 = getPWMGroup(5)
PWM6 = getPWMGroup(6)
PWM7 = getPWMGroup(7)
)

// Configure enables and configures this PWM.
Expand Down Expand Up @@ -391,6 +405,31 @@ func (pwm *pwmGroup) getClockDiv() (Int, frac uint8) {
return uint8((div & rp.PWM_CH0_DIV_INT_Msk) >> rp.PWM_CH0_DIV_INT_Pos), uint8((div & rp.PWM_CH0_DIV_FRAC_Msk) >> rp.PWM_CH0_DIV_FRAC_Pos)
}

// SetIRQ enables or disables PWM instance interrupt request functionality.
func (pwm *pwmGroup) SetIRQ(enabled bool) {
p := pwm.peripheral()
if enabled {
pwmHW.INTE.SetBits(1 << p)
} else {
pwmHW.INTE.ClearBits(1 << p)
}
}

// ClearIRQ clears the current PWM's channel interrupt
func (pwm *pwmGroup) ClearIRQ() {
pwmHW.INTR.Set(1 << pwm.peripheral())
}

// ForceIRQ forces an interrupt request for the given PWM.
func (pwm *pwmGroup) ForceIRQ() {
pwmHW.INTF.Set(1 << pwm.peripheral())
}

// IRQStatus returns true if interrupt functionality is enabled for the pwmGroup.
func (pwm *pwmGroup) IsIRQSet() bool {
return pwmHW.INTS.Get()&(1<<pwm.peripheral()) != 0
}

// pwmGPIOToSlice Determine the PWM channel that is attached to the specified GPIO.
// gpio must be less than 30. Returns the PWM slice number that controls the specified GPIO.
func pwmGPIOToSlice(gpio Pin) (slicenum uint8) {
Expand Down