diff --git a/src/machine/machine_rp2040_pwm.go b/src/machine/machine_rp2040_pwm.go index a355be4c8b..4fececc9e7 100644 --- a/src/machine/machine_rp2040_pwm.go +++ b/src/machine/machine_rp2040_pwm.go @@ -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] @@ -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. @@ -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. @@ -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<