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.
Этот коммит содержится в:
родитель
2f059ac91e
коммит
f7dde33842
2 изменённых файлов: 147 добавлений и 193 удалений
|
@ -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
|
||||
|
|
|
@ -6,196 +6,3 @@
|
|||
// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
|
||||
//
|
||||
package machine
|
||||
|
||||
import (
|
||||
"device/sam"
|
||||
)
|
||||
|
||||
// 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) {
|
||||
if p < 32 {
|
||||
return &sam.PORT.GROUP[0].OUTSET.Reg, 1 << uint8(p)
|
||||
} else {
|
||||
return &sam.PORT.GROUP[1].OUTSET.Reg, 1 << uint8(p-32)
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if p < 32 {
|
||||
return &sam.PORT.GROUP[0].OUTCLR.Reg, 1 << uint8(p)
|
||||
} else {
|
||||
return &sam.PORT.GROUP[1].OUTCLR.Reg, 1 << uint8(p-32)
|
||||
}
|
||||
}
|
||||
|
||||
// Set the pin to high or low.
|
||||
// Warning: only use this on an output pin!
|
||||
func (p Pin) Set(high bool) {
|
||||
if p < 32 {
|
||||
if high {
|
||||
sam.PORT.GROUP[0].OUTSET.Set(1 << uint8(p))
|
||||
} else {
|
||||
sam.PORT.GROUP[0].OUTCLR.Set(1 << uint8(p))
|
||||
}
|
||||
} else {
|
||||
if high {
|
||||
sam.PORT.GROUP[1].OUTSET.Set(1 << uint8(p-32))
|
||||
} else {
|
||||
sam.PORT.GROUP[1].OUTCLR.Set(1 << uint8(p-32))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the current value of a GPIO pin.
|
||||
func (p Pin) Get() bool {
|
||||
if p < 32 {
|
||||
return (sam.PORT.GROUP[0].IN.Get()>>uint8(p))&1 > 0
|
||||
} else {
|
||||
return (sam.PORT.GROUP[1].IN.Get()>>(uint8(p)-32))&1 > 0
|
||||
}
|
||||
}
|
||||
|
||||
// Configure this pin with the given configuration.
|
||||
func (p Pin) Configure(config PinConfig) {
|
||||
switch config.Mode {
|
||||
case PinOutput:
|
||||
if p < 32 {
|
||||
sam.PORT.GROUP[0].DIRSET.Set(1 << uint8(p))
|
||||
// output is also set to input enable so pin can read back its own value
|
||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN)
|
||||
} else {
|
||||
sam.PORT.GROUP[1].DIRSET.Set(1 << uint8(p-32))
|
||||
// output is also set to input enable so pin can read back its own value
|
||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN)
|
||||
}
|
||||
|
||||
case PinInput:
|
||||
if p < 32 {
|
||||
sam.PORT.GROUP[0].DIRCLR.Set(1 << uint8(p))
|
||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN)
|
||||
} else {
|
||||
sam.PORT.GROUP[1].DIRCLR.Set(1 << uint8(p-32))
|
||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN)
|
||||
}
|
||||
|
||||
case PinInputPulldown:
|
||||
if p < 32 {
|
||||
sam.PORT.GROUP[0].DIRCLR.Set(1 << uint8(p))
|
||||
sam.PORT.GROUP[0].OUTCLR.Set(1 << uint8(p))
|
||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)
|
||||
} else {
|
||||
sam.PORT.GROUP[1].DIRCLR.Set(1 << uint8(p-32))
|
||||
sam.PORT.GROUP[1].OUTCLR.Set(1 << uint8(p-32))
|
||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)
|
||||
}
|
||||
|
||||
case PinInputPullup:
|
||||
if p < 32 {
|
||||
sam.PORT.GROUP[0].DIRCLR.Set(1 << uint8(p))
|
||||
sam.PORT.GROUP[0].OUTSET.Set(1 << uint8(p))
|
||||
p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)
|
||||
} else {
|
||||
sam.PORT.GROUP[1].DIRCLR.Set(1 << uint8(p-32))
|
||||
sam.PORT.GROUP[1].OUTSET.Set(1 << uint8(p-32))
|
||||
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 {
|
||||
switch {
|
||||
case p < 32:
|
||||
return sam.PORT.GROUP[0].PMUX[uint8(p)>>1].Get()
|
||||
case p >= 32 && p < 64:
|
||||
return sam.PORT.GROUP[1].PMUX[uint8(p-32)>>1].Get()
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// setPMux sets the value for the correct PMUX register for this pin.
|
||||
func (p Pin) setPMux(val uint8) {
|
||||
switch {
|
||||
case p < 32:
|
||||
sam.PORT.GROUP[0].PMUX[uint8(p)>>1].Set(val)
|
||||
case p >= 32 && p < 64:
|
||||
sam.PORT.GROUP[1].PMUX[uint8(p-32)>>1].Set(val)
|
||||
}
|
||||
}
|
||||
|
||||
// getPinCfg returns the value for the correct PINCFG register for this pin.
|
||||
func (p Pin) getPinCfg() uint8 {
|
||||
switch {
|
||||
case p < 32:
|
||||
return sam.PORT.GROUP[0].PINCFG[p].Get()
|
||||
case p >= 32 && p <= 64:
|
||||
return sam.PORT.GROUP[1].PINCFG[p-32].Get()
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
// setPinCfg sets the value for the correct PINCFG register for this pin.
|
||||
func (p Pin) setPinCfg(val uint8) {
|
||||
switch {
|
||||
case p < 32:
|
||||
sam.PORT.GROUP[0].PINCFG[p].Set(val)
|
||||
case p >= 32 && p <= 64:
|
||||
sam.PORT.GROUP[1].PINCFG[p-32].Set(val)
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче