machine/atsamd51: pin method cleanup (#659)

* machine/samd51: pin method cleanups.
- Use bit-math to select the group in Pin methods.
- Move Pin methods to atsamd51. They are not chip-specific, they apply to the whole atsamd51 family.
- Move the group/pin-id calculation into a helper method.
- Add a Pin.Toggle() method.
This commit is contained in:
Infinoid
2019-10-27 16:37:52 -04:00
committed by Ron Evans
parent 2f059ac91e
commit f7dde33842
2 changed files with 147 additions and 193 deletions
+147
View File
@@ -110,6 +110,153 @@ const (
PB31 Pin = 63
)
// Return the register and mask to enable a given GPIO pin. This can be used to
// implement bit-banged drivers.
func (p Pin) PortMaskSet() (*uint32, uint32) {
group, pin_in_group := p.getPinGrouping()
return &sam.PORT.GROUP[group].OUTSET.Reg, 1 << pin_in_group
}
// Return the register and mask to disable a given port. This can be used to
// implement bit-banged drivers.
func (p Pin) PortMaskClear() (*uint32, uint32) {
group, pin_in_group := p.getPinGrouping()
return &sam.PORT.GROUP[group].OUTCLR.Reg, 1 << pin_in_group
}
// Set the pin to high or low.
// Warning: only use this on an output pin!
func (p Pin) Set(high bool) {
group, pin_in_group := p.getPinGrouping()
if high {
sam.PORT.GROUP[group].OUTSET.Set(1 << pin_in_group)
} else {
sam.PORT.GROUP[group].OUTCLR.Set(1 << pin_in_group)
}
}
// Get returns the current value of a GPIO pin.
func (p Pin) Get() bool {
group, pin_in_group := p.getPinGrouping()
return (sam.PORT.GROUP[group].IN.Get()>>pin_in_group)&1 > 0
}
// Toggle switches an output pin from low to high or from high to low.
// Warning: only use this on an output pin!
func (p Pin) Toggle() {
group, pin_in_group := p.getPinGrouping()
sam.PORT.GROUP[group].OUTTGL.Set(1 << pin_in_group)
}
// Configure this pin with the given configuration.
func (p Pin) Configure(config PinConfig) {
group, pin_in_group := p.getPinGrouping()
switch config.Mode {
case PinOutput:
sam.PORT.GROUP[group].DIRSET.Set(1 << pin_in_group)
// output is also set to input enable so pin can read back its own value
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN)
case PinInput:
sam.PORT.GROUP[group].DIRCLR.Set(1 << pin_in_group)
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN)
case PinInputPulldown:
sam.PORT.GROUP[group].DIRCLR.Set(1 << pin_in_group)
sam.PORT.GROUP[group].OUTCLR.Set(1 << pin_in_group)
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)
case PinInputPullup:
sam.PORT.GROUP[group].DIRCLR.Set(1 << pin_in_group)
sam.PORT.GROUP[group].OUTSET.Set(1 << pin_in_group)
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)
case PinSERCOM:
if p&1 > 0 {
// odd pin, so save the even pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
} else {
// even pin, so save the odd pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
}
// enable port config
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR | sam.PORT_GROUP_PINCFG_INEN)
case PinSERCOMAlt:
if p&1 > 0 {
// odd pin, so save the even pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
} else {
// even pin, so save the odd pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
}
// enable port config
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)
case PinCom:
if p&1 > 0 {
// odd pin, so save the even pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
p.setPMux(val | (uint8(PinCom) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
} else {
// even pin, so save the odd pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
p.setPMux(val | (uint8(PinCom) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
}
// enable port config
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)
case PinAnalog:
if p&1 > 0 {
// odd pin, so save the even pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
} else {
// even pin, so save the odd pins
val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
p.setPMux(val | (uint8(PinAnalog) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
}
// enable port config
p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)
}
}
// getPMux returns the value for the correct PMUX register for this pin.
func (p Pin) getPMux() uint8 {
group, pin_in_group := p.getPinGrouping()
return sam.PORT.GROUP[group].PMUX[pin_in_group>>1].Get()
}
// setPMux sets the value for the correct PMUX register for this pin.
func (p Pin) setPMux(val uint8) {
group, pin_in_group := p.getPinGrouping()
sam.PORT.GROUP[group].PMUX[pin_in_group>>1].Set(val)
}
// getPinCfg returns the value for the correct PINCFG register for this pin.
func (p Pin) getPinCfg() uint8 {
group, pin_in_group := p.getPinGrouping()
return sam.PORT.GROUP[group].PINCFG[pin_in_group].Get()
}
// setPinCfg sets the value for the correct PINCFG register for this pin.
func (p Pin) setPinCfg(val uint8) {
group, pin_in_group := p.getPinGrouping()
sam.PORT.GROUP[group].PINCFG[pin_in_group].Set(val)
}
// getPinGrouping calculates the gpio group and pin id from the pin number.
// Pins are split into groups of 32, and each group has its own set of
// control registers.
func (p Pin) getPinGrouping() (uint8, uint8) {
group := uint8(p) >> 5
pin_in_group := uint8(p) & 0x1f
return group, pin_in_group
}
// InitADC initializes the ADC.
func InitADC() {
// ADC Bias Calibration