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
|
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.
|
// InitADC initializes the ADC.
|
||||||
func InitADC() {
|
func InitADC() {
|
||||||
// ADC Bias Calibration
|
// ADC Bias Calibration
|
||||||
|
|
|
@ -6,196 +6,3 @@
|
||||||
// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
|
// http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
|
||||||
//
|
//
|
||||||
package machine
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче