accept configuration struct for ADC parameters (#1533)
Этот коммит содержится в:
родитель
3d6921b0e1
коммит
06f231468d
8 изменённых файлов: 371 добавлений и 64 удалений
|
@ -15,7 +15,7 @@ func main() {
|
||||||
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
led.Configure(machine.PinConfig{Mode: machine.PinOutput})
|
||||||
|
|
||||||
sensor := machine.ADC{machine.ADC2}
|
sensor := machine.ADC{machine.ADC2}
|
||||||
sensor.Configure()
|
sensor.Configure(machine.ADCConfig{})
|
||||||
|
|
||||||
for {
|
for {
|
||||||
val := sensor.Get()
|
val := sensor.Get()
|
||||||
|
|
12
src/machine/adc.go
Обычный файл
12
src/machine/adc.go
Обычный файл
|
@ -0,0 +1,12 @@
|
||||||
|
package machine
|
||||||
|
|
||||||
|
// Hardware abstraction layer for the analog-to-digital conversion (ADC)
|
||||||
|
// peripheral.
|
||||||
|
|
||||||
|
// ADCConfig holds ADC configuration parameters. If left unspecified, the zero
|
||||||
|
// value of each parameter will use the peripheral's default settings.
|
||||||
|
type ADCConfig struct {
|
||||||
|
Reference uint32 // analog reference voltage (AREF) in millivolts
|
||||||
|
Resolution uint32 // number of bits for a single conversion (e.g., 8, 10, 12)
|
||||||
|
Samples uint32 // number of samples for a single conversion (e.g., 4, 8, 16, 32)
|
||||||
|
}
|
|
@ -307,13 +307,30 @@ func InitADC() {
|
||||||
|
|
||||||
// set calibration
|
// set calibration
|
||||||
sam.ADC.CALIB.Set((bias << 8) | linearity)
|
sam.ADC.CALIB.Set((bias << 8) | linearity)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure configures a ADC pin to be able to be used to read data.
|
||||||
|
func (a ADC) Configure(config ADCConfig) {
|
||||||
|
|
||||||
// Wait for synchronization
|
// Wait for synchronization
|
||||||
waitADCSync()
|
waitADCSync()
|
||||||
|
|
||||||
|
var resolution uint32
|
||||||
|
switch config.Resolution {
|
||||||
|
case 8:
|
||||||
|
resolution = sam.ADC_CTRLB_RESSEL_8BIT
|
||||||
|
case 10:
|
||||||
|
resolution = sam.ADC_CTRLB_RESSEL_10BIT
|
||||||
|
case 12:
|
||||||
|
resolution = sam.ADC_CTRLB_RESSEL_12BIT
|
||||||
|
case 16:
|
||||||
|
resolution = sam.ADC_CTRLB_RESSEL_16BIT
|
||||||
|
default:
|
||||||
|
resolution = sam.ADC_CTRLB_RESSEL_12BIT
|
||||||
|
}
|
||||||
// Divide Clock by 32 with 12 bits resolution as default
|
// Divide Clock by 32 with 12 bits resolution as default
|
||||||
sam.ADC.CTRLB.Set((sam.ADC_CTRLB_PRESCALER_DIV32 << sam.ADC_CTRLB_PRESCALER_Pos) |
|
sam.ADC.CTRLB.Set((sam.ADC_CTRLB_PRESCALER_DIV32 << sam.ADC_CTRLB_PRESCALER_Pos) |
|
||||||
(sam.ADC_CTRLB_RESSEL_12BIT << sam.ADC_CTRLB_RESSEL_Pos))
|
uint16(resolution<<sam.ADC_CTRLB_RESSEL_Pos))
|
||||||
|
|
||||||
// Sampling Time Length
|
// Sampling Time Length
|
||||||
sam.ADC.SAMPCTRL.Set(5)
|
sam.ADC.SAMPCTRL.Set(5)
|
||||||
|
@ -325,18 +342,44 @@ func InitADC() {
|
||||||
sam.ADC.INPUTCTRL.Set(sam.ADC_INPUTCTRL_MUXNEG_GND << sam.ADC_INPUTCTRL_MUXNEG_Pos)
|
sam.ADC.INPUTCTRL.Set(sam.ADC_INPUTCTRL_MUXNEG_GND << sam.ADC_INPUTCTRL_MUXNEG_Pos)
|
||||||
|
|
||||||
// Averaging (see datasheet table in AVGCTRL register description)
|
// Averaging (see datasheet table in AVGCTRL register description)
|
||||||
sam.ADC.AVGCTRL.Set((sam.ADC_AVGCTRL_SAMPLENUM_1 << sam.ADC_AVGCTRL_SAMPLENUM_Pos) |
|
var samples uint32
|
||||||
|
switch config.Resolution {
|
||||||
|
case 1:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_1
|
||||||
|
case 2:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_2
|
||||||
|
case 4:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_4
|
||||||
|
case 8:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_8
|
||||||
|
case 16:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_16
|
||||||
|
case 32:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_32
|
||||||
|
case 64:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_64
|
||||||
|
case 128:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_128
|
||||||
|
case 256:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_256
|
||||||
|
case 512:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_512
|
||||||
|
case 1024:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_1024
|
||||||
|
default:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_1
|
||||||
|
}
|
||||||
|
sam.ADC.AVGCTRL.Set(uint8(samples<<sam.ADC_AVGCTRL_SAMPLENUM_Pos) |
|
||||||
(0x0 << sam.ADC_AVGCTRL_ADJRES_Pos))
|
(0x0 << sam.ADC_AVGCTRL_ADJRES_Pos))
|
||||||
|
|
||||||
|
// TODO: use config.Reference to set AREF level
|
||||||
|
|
||||||
// Analog Reference is AREF pin (3.3v)
|
// Analog Reference is AREF pin (3.3v)
|
||||||
sam.ADC.INPUTCTRL.SetBits(sam.ADC_INPUTCTRL_GAIN_DIV2 << sam.ADC_INPUTCTRL_GAIN_Pos)
|
sam.ADC.INPUTCTRL.SetBits(sam.ADC_INPUTCTRL_GAIN_DIV2 << sam.ADC_INPUTCTRL_GAIN_Pos)
|
||||||
|
|
||||||
// 1/2 VDDANA = 0.5 * 3V3 = 1.65V
|
// 1/2 VDDANA = 0.5 * 3V3 = 1.65V
|
||||||
sam.ADC.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1 << sam.ADC_REFCTRL_REFSEL_Pos)
|
sam.ADC.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1 << sam.ADC_REFCTRL_REFSEL_Pos)
|
||||||
}
|
|
||||||
|
|
||||||
// Configure configures a ADCPin to be able to be used to read data.
|
|
||||||
func (a ADC) Configure() {
|
|
||||||
a.Pin.Configure(PinConfig{Mode: PinAnalog})
|
a.Pin.Configure(PinConfig{Mode: PinAnalog})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -720,65 +720,83 @@ func InitADC() {
|
||||||
|
|
||||||
// calibrate ADC1
|
// calibrate ADC1
|
||||||
sam.ADC1.CALIB.Set(uint16((biascomp | biasr2r | biasref) >> 16))
|
sam.ADC1.CALIB.Set(uint16((biascomp | biasr2r | biasref) >> 16))
|
||||||
|
|
||||||
sam.ADC0.CTRLA.SetBits(sam.ADC_CTRLA_PRESCALER_DIV32 << sam.ADC_CTRLA_PRESCALER_Pos)
|
|
||||||
// adcs[i]->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
|
|
||||||
sam.ADC0.CTRLB.SetBits(sam.ADC_CTRLB_RESSEL_12BIT << sam.ADC_CTRLB_RESSEL_Pos)
|
|
||||||
|
|
||||||
// wait for sync
|
|
||||||
for sam.ADC0.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_CTRLB) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// sampling Time Length
|
|
||||||
sam.ADC0.SAMPCTRL.Set(5)
|
|
||||||
|
|
||||||
// wait for sync
|
|
||||||
for sam.ADC0.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_SAMPCTRL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// No Negative input (Internal Ground)
|
|
||||||
sam.ADC0.INPUTCTRL.Set(sam.ADC_INPUTCTRL_MUXNEG_GND << sam.ADC_INPUTCTRL_MUXNEG_Pos)
|
|
||||||
|
|
||||||
// wait for sync
|
|
||||||
for sam.ADC0.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_INPUTCTRL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Averaging (see datasheet table in AVGCTRL register description)
|
|
||||||
// 1 sample only (no oversampling nor averaging), adjusting result by 0
|
|
||||||
sam.ADC0.AVGCTRL.Set(sam.ADC_AVGCTRL_SAMPLENUM_1 | (0 << sam.ADC_AVGCTRL_ADJRES_Pos))
|
|
||||||
|
|
||||||
// wait for sync
|
|
||||||
for sam.ADC0.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_AVGCTRL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// same for ADC1, as for ADC0
|
|
||||||
sam.ADC1.CTRLA.SetBits(sam.ADC_CTRLA_PRESCALER_DIV32 << sam.ADC_CTRLA_PRESCALER_Pos)
|
|
||||||
sam.ADC1.CTRLB.SetBits(sam.ADC_CTRLB_RESSEL_12BIT << sam.ADC_CTRLB_RESSEL_Pos)
|
|
||||||
for sam.ADC1.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_CTRLB) {
|
|
||||||
}
|
|
||||||
sam.ADC1.SAMPCTRL.Set(5)
|
|
||||||
for sam.ADC1.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_SAMPCTRL) {
|
|
||||||
}
|
|
||||||
sam.ADC1.INPUTCTRL.Set(sam.ADC_INPUTCTRL_MUXNEG_GND << sam.ADC_INPUTCTRL_MUXNEG_Pos)
|
|
||||||
for sam.ADC1.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_INPUTCTRL) {
|
|
||||||
}
|
|
||||||
sam.ADC1.AVGCTRL.Set(sam.ADC_AVGCTRL_SAMPLENUM_1 | (0 << sam.ADC_AVGCTRL_ADJRES_Pos))
|
|
||||||
for sam.ADC1.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_AVGCTRL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// wait for sync
|
|
||||||
for sam.ADC0.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_REFCTRL) {
|
|
||||||
}
|
|
||||||
for sam.ADC1.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_REFCTRL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// default is 3V3 reference voltage
|
|
||||||
sam.ADC0.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1)
|
|
||||||
sam.ADC1.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure configures a ADCPin to be able to be used to read data.
|
// Configure configures a ADCPin to be able to be used to read data.
|
||||||
func (a ADC) Configure() {
|
func (a ADC) Configure(config ADCConfig) {
|
||||||
|
|
||||||
|
for _, adc := range []*sam.ADC_Type{sam.ADC0, sam.ADC1} {
|
||||||
|
|
||||||
|
for adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_CTRLB) {
|
||||||
|
} // wait for sync
|
||||||
|
|
||||||
|
adc.CTRLA.SetBits(sam.ADC_CTRLA_PRESCALER_DIV32 << sam.ADC_CTRLA_PRESCALER_Pos)
|
||||||
|
var resolution uint32
|
||||||
|
switch config.Resolution {
|
||||||
|
case 8:
|
||||||
|
resolution = sam.ADC_CTRLB_RESSEL_8BIT
|
||||||
|
case 10:
|
||||||
|
resolution = sam.ADC_CTRLB_RESSEL_10BIT
|
||||||
|
case 12:
|
||||||
|
resolution = sam.ADC_CTRLB_RESSEL_12BIT
|
||||||
|
case 16:
|
||||||
|
resolution = sam.ADC_CTRLB_RESSEL_16BIT
|
||||||
|
default:
|
||||||
|
resolution = sam.ADC_CTRLB_RESSEL_12BIT
|
||||||
|
}
|
||||||
|
adc.CTRLB.SetBits(uint16(resolution << sam.ADC_CTRLB_RESSEL_Pos))
|
||||||
|
adc.SAMPCTRL.Set(5) // sampling Time Length
|
||||||
|
|
||||||
|
for adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_SAMPCTRL) {
|
||||||
|
} // wait for sync
|
||||||
|
|
||||||
|
// No Negative input (Internal Ground)
|
||||||
|
adc.INPUTCTRL.Set(sam.ADC_INPUTCTRL_MUXNEG_GND << sam.ADC_INPUTCTRL_MUXNEG_Pos)
|
||||||
|
for adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_INPUTCTRL) {
|
||||||
|
} // wait for sync
|
||||||
|
|
||||||
|
// Averaging (see datasheet table in AVGCTRL register description)
|
||||||
|
var samples uint32
|
||||||
|
switch config.Resolution {
|
||||||
|
case 1:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_1
|
||||||
|
case 2:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_2
|
||||||
|
case 4:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_4
|
||||||
|
case 8:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_8
|
||||||
|
case 16:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_16
|
||||||
|
case 32:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_32
|
||||||
|
case 64:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_64
|
||||||
|
case 128:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_128
|
||||||
|
case 256:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_256
|
||||||
|
case 512:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_512
|
||||||
|
case 1024:
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_1024
|
||||||
|
default: // 1 sample only (no oversampling nor averaging), adjusting result by 0
|
||||||
|
samples = sam.ADC_AVGCTRL_SAMPLENUM_1
|
||||||
|
}
|
||||||
|
adc.AVGCTRL.Set(uint8(samples<<sam.ADC_AVGCTRL_SAMPLENUM_Pos) |
|
||||||
|
(0 << sam.ADC_AVGCTRL_ADJRES_Pos))
|
||||||
|
|
||||||
|
for adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_AVGCTRL) {
|
||||||
|
} // wait for sync
|
||||||
|
for adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_REFCTRL) {
|
||||||
|
} // wait for sync
|
||||||
|
|
||||||
|
// TODO: use config.Reference to set AREF level
|
||||||
|
|
||||||
|
// default is 3V3 reference voltage
|
||||||
|
adc.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1)
|
||||||
|
}
|
||||||
|
|
||||||
a.Pin.Configure(PinConfig{Mode: PinAnalog})
|
a.Pin.Configure(PinConfig{Mode: PinAnalog})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,7 @@ func InitADC() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure configures a ADCPin to be able to be used to read data.
|
// Configure configures a ADCPin to be able to be used to read data.
|
||||||
func (a ADC) Configure() {
|
func (a ADC) Configure(ADCConfig) {
|
||||||
return // no pin specific setup on AVR machine.
|
return // no pin specific setup on AVR machine.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ func InitADC() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure configures an ADC pin to be able to be used to read data.
|
// Configure configures an ADC pin to be able to be used to read data.
|
||||||
func (adc ADC) Configure() {
|
func (adc ADC) Configure(ADCConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get reads the current analog value from this ADC peripheral.
|
// Get reads the current analog value from this ADC peripheral.
|
||||||
|
|
|
@ -4,6 +4,7 @@ package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/nrf"
|
"device/nrf"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hardware pins
|
// Hardware pins
|
||||||
|
@ -61,6 +62,122 @@ func (i2c I2C) setPins(scl, sda Pin) {
|
||||||
i2c.Bus.PSELSDA.Set(uint32(sda))
|
i2c.Bus.PSELSDA.Set(uint32(sda))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SPI
|
||||||
|
func (spi SPI) setPins(sck, sdo, sdi Pin) {
|
||||||
|
if sck == 0 {
|
||||||
|
sck = SPI0_SCK_PIN
|
||||||
|
}
|
||||||
|
if sdo == 0 {
|
||||||
|
sdo = SPI0_SDO_PIN
|
||||||
|
}
|
||||||
|
if sdi == 0 {
|
||||||
|
sdi = SPI0_SDI_PIN
|
||||||
|
}
|
||||||
|
spi.Bus.PSEL.SCK.Set(uint32(sck))
|
||||||
|
spi.Bus.PSEL.MOSI.Set(uint32(sdo))
|
||||||
|
spi.Bus.PSEL.MISO.Set(uint32(sdi))
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitADC initializes the registers needed for ADC.
|
||||||
|
func InitADC() {
|
||||||
|
return // no specific setup on nrf52 machine.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure configures an ADC pin to be able to read analog data.
|
||||||
|
func (a ADC) Configure(ADCConfig) {
|
||||||
|
return // no pin specific setup on nrf52 machine.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the current value of a ADC pin in the range 0..0xffff.
|
||||||
|
func (a ADC) Get() uint16 {
|
||||||
|
var pwmPin uint32
|
||||||
|
var value int16
|
||||||
|
|
||||||
|
switch a.Pin {
|
||||||
|
case 2:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3
|
||||||
|
|
||||||
|
case 28:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4
|
||||||
|
|
||||||
|
case 29:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5
|
||||||
|
|
||||||
|
case 30:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6
|
||||||
|
|
||||||
|
case 31:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
nrf.SAADC.RESOLUTION.Set(nrf.SAADC_RESOLUTION_VAL_12bit)
|
||||||
|
|
||||||
|
// Enable ADC.
|
||||||
|
nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Enabled << nrf.SAADC_ENABLE_ENABLE_Pos)
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
nrf.SAADC.CH[i].PSELN.Set(nrf.SAADC_CH_PSELP_PSELP_NC)
|
||||||
|
nrf.SAADC.CH[i].PSELP.Set(nrf.SAADC_CH_PSELP_PSELP_NC)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure ADC.
|
||||||
|
nrf.SAADC.CH[0].CONFIG.Set(((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESP_Pos) & nrf.SAADC_CH_CONFIG_RESP_Msk) |
|
||||||
|
((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESN_Pos) & nrf.SAADC_CH_CONFIG_RESN_Msk) |
|
||||||
|
((nrf.SAADC_CH_CONFIG_GAIN_Gain1_5 << nrf.SAADC_CH_CONFIG_GAIN_Pos) & nrf.SAADC_CH_CONFIG_GAIN_Msk) |
|
||||||
|
((nrf.SAADC_CH_CONFIG_REFSEL_Internal << nrf.SAADC_CH_CONFIG_REFSEL_Pos) & nrf.SAADC_CH_CONFIG_REFSEL_Msk) |
|
||||||
|
((nrf.SAADC_CH_CONFIG_TACQ_3us << nrf.SAADC_CH_CONFIG_TACQ_Pos) & nrf.SAADC_CH_CONFIG_TACQ_Msk) |
|
||||||
|
((nrf.SAADC_CH_CONFIG_MODE_SE << nrf.SAADC_CH_CONFIG_MODE_Pos) & nrf.SAADC_CH_CONFIG_MODE_Msk))
|
||||||
|
|
||||||
|
// Set pin to read.
|
||||||
|
nrf.SAADC.CH[0].PSELN.Set(pwmPin)
|
||||||
|
nrf.SAADC.CH[0].PSELP.Set(pwmPin)
|
||||||
|
|
||||||
|
// Destination for sample result.
|
||||||
|
nrf.SAADC.RESULT.PTR.Set(uint32(uintptr(unsafe.Pointer(&value))))
|
||||||
|
nrf.SAADC.RESULT.MAXCNT.Set(1) // One sample
|
||||||
|
|
||||||
|
// Start tasks.
|
||||||
|
nrf.SAADC.TASKS_START.Set(1)
|
||||||
|
for nrf.SAADC.EVENTS_STARTED.Get() == 0 {
|
||||||
|
}
|
||||||
|
nrf.SAADC.EVENTS_STARTED.Set(0x00)
|
||||||
|
|
||||||
|
// Start the sample task.
|
||||||
|
nrf.SAADC.TASKS_SAMPLE.Set(1)
|
||||||
|
|
||||||
|
// Wait until the sample task is done.
|
||||||
|
for nrf.SAADC.EVENTS_END.Get() == 0 {
|
||||||
|
}
|
||||||
|
nrf.SAADC.EVENTS_END.Set(0x00)
|
||||||
|
|
||||||
|
// Stop the ADC
|
||||||
|
nrf.SAADC.TASKS_STOP.Set(1)
|
||||||
|
for nrf.SAADC.EVENTS_STOPPED.Get() == 0 {
|
||||||
|
}
|
||||||
|
nrf.SAADC.EVENTS_STOPPED.Set(0)
|
||||||
|
|
||||||
|
// Disable the ADC.
|
||||||
|
nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Disabled << nrf.SAADC_ENABLE_ENABLE_Pos)
|
||||||
|
|
||||||
|
if value < 0 {
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return 16-bit result from 12-bit value.
|
||||||
|
return uint16(value << 4)
|
||||||
|
}
|
||||||
|
|
||||||
// PWM
|
// PWM
|
||||||
var (
|
var (
|
||||||
pwmChannelPins = [3]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
|
pwmChannelPins = [3]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
|
||||||
|
|
|
@ -4,6 +4,7 @@ package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/nrf"
|
"device/nrf"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Hardware pins
|
// Hardware pins
|
||||||
|
@ -77,6 +78,122 @@ func (i2c I2C) setPins(scl, sda Pin) {
|
||||||
i2c.Bus.PSEL.SDA.Set(uint32(sda))
|
i2c.Bus.PSEL.SDA.Set(uint32(sda))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SPI
|
||||||
|
func (spi SPI) setPins(sck, sdo, sdi Pin) {
|
||||||
|
if sck == 0 {
|
||||||
|
sck = SPI0_SCK_PIN
|
||||||
|
}
|
||||||
|
if sdo == 0 {
|
||||||
|
sdo = SPI0_SDO_PIN
|
||||||
|
}
|
||||||
|
if sdi == 0 {
|
||||||
|
sdi = SPI0_SDI_PIN
|
||||||
|
}
|
||||||
|
spi.Bus.PSEL.SCK.Set(uint32(sck))
|
||||||
|
spi.Bus.PSEL.MOSI.Set(uint32(sdo))
|
||||||
|
spi.Bus.PSEL.MISO.Set(uint32(sdi))
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitADC initializes the registers needed for ADC.
|
||||||
|
func InitADC() {
|
||||||
|
return // no specific setup on nrf52840 machine.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure configures an ADC pin to be able to read analog data.
|
||||||
|
func (a ADC) Configure(ADCConfig) {
|
||||||
|
return // no pin specific setup on nrf52840 machine.
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns the current value of a ADC pin in the range 0..0xffff.
|
||||||
|
func (a ADC) Get() uint16 {
|
||||||
|
var pwmPin uint32
|
||||||
|
var value int16
|
||||||
|
|
||||||
|
switch a.Pin {
|
||||||
|
case 2:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3
|
||||||
|
|
||||||
|
case 28:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4
|
||||||
|
|
||||||
|
case 29:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5
|
||||||
|
|
||||||
|
case 30:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6
|
||||||
|
|
||||||
|
case 31:
|
||||||
|
pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
nrf.SAADC.RESOLUTION.Set(nrf.SAADC_RESOLUTION_VAL_12bit)
|
||||||
|
|
||||||
|
// Enable ADC.
|
||||||
|
nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Enabled << nrf.SAADC_ENABLE_ENABLE_Pos)
|
||||||
|
for i := 0; i < 8; i++ {
|
||||||
|
nrf.SAADC.CH[i].PSELN.Set(nrf.SAADC_CH_PSELP_PSELP_NC)
|
||||||
|
nrf.SAADC.CH[i].PSELP.Set(nrf.SAADC_CH_PSELP_PSELP_NC)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure ADC.
|
||||||
|
nrf.SAADC.CH[0].CONFIG.Set(((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESP_Pos) & nrf.SAADC_CH_CONFIG_RESP_Msk) |
|
||||||
|
((nrf.SAADC_CH_CONFIG_RESP_Bypass << nrf.SAADC_CH_CONFIG_RESN_Pos) & nrf.SAADC_CH_CONFIG_RESN_Msk) |
|
||||||
|
((nrf.SAADC_CH_CONFIG_GAIN_Gain1_5 << nrf.SAADC_CH_CONFIG_GAIN_Pos) & nrf.SAADC_CH_CONFIG_GAIN_Msk) |
|
||||||
|
((nrf.SAADC_CH_CONFIG_REFSEL_Internal << nrf.SAADC_CH_CONFIG_REFSEL_Pos) & nrf.SAADC_CH_CONFIG_REFSEL_Msk) |
|
||||||
|
((nrf.SAADC_CH_CONFIG_TACQ_3us << nrf.SAADC_CH_CONFIG_TACQ_Pos) & nrf.SAADC_CH_CONFIG_TACQ_Msk) |
|
||||||
|
((nrf.SAADC_CH_CONFIG_MODE_SE << nrf.SAADC_CH_CONFIG_MODE_Pos) & nrf.SAADC_CH_CONFIG_MODE_Msk))
|
||||||
|
|
||||||
|
// Set pin to read.
|
||||||
|
nrf.SAADC.CH[0].PSELN.Set(pwmPin)
|
||||||
|
nrf.SAADC.CH[0].PSELP.Set(pwmPin)
|
||||||
|
|
||||||
|
// Destination for sample result.
|
||||||
|
nrf.SAADC.RESULT.PTR.Set(uint32(uintptr(unsafe.Pointer(&value))))
|
||||||
|
nrf.SAADC.RESULT.MAXCNT.Set(1) // One sample
|
||||||
|
|
||||||
|
// Start tasks.
|
||||||
|
nrf.SAADC.TASKS_START.Set(1)
|
||||||
|
for nrf.SAADC.EVENTS_STARTED.Get() == 0 {
|
||||||
|
}
|
||||||
|
nrf.SAADC.EVENTS_STARTED.Set(0x00)
|
||||||
|
|
||||||
|
// Start the sample task.
|
||||||
|
nrf.SAADC.TASKS_SAMPLE.Set(1)
|
||||||
|
|
||||||
|
// Wait until the sample task is done.
|
||||||
|
for nrf.SAADC.EVENTS_END.Get() == 0 {
|
||||||
|
}
|
||||||
|
nrf.SAADC.EVENTS_END.Set(0x00)
|
||||||
|
|
||||||
|
// Stop the ADC
|
||||||
|
nrf.SAADC.TASKS_STOP.Set(1)
|
||||||
|
for nrf.SAADC.EVENTS_STOPPED.Get() == 0 {
|
||||||
|
}
|
||||||
|
nrf.SAADC.EVENTS_STOPPED.Set(0)
|
||||||
|
|
||||||
|
// Disable the ADC.
|
||||||
|
nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Disabled << nrf.SAADC_ENABLE_ENABLE_Pos)
|
||||||
|
|
||||||
|
if value < 0 {
|
||||||
|
value = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return 16-bit result from 12-bit value.
|
||||||
|
return uint16(value << 4)
|
||||||
|
}
|
||||||
|
|
||||||
// PWM
|
// PWM
|
||||||
var (
|
var (
|
||||||
pwmChannelPins = [4]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
|
pwmChannelPins = [4]uint32{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче