Add PDM support for circuitplay-bluefruit (#3359)
machine/nrf52840: add PDM support Signed-off-by: Marcus Sorensen <marcus@turboio.com>
Этот коммит содержится в:
родитель
0d646d8e95
коммит
e7ba07dd5a
4 изменённых файлов: 110 добавлений и 0 удалений
27
src/examples/pdm/pdm.go
Обычный файл
27
src/examples/pdm/pdm.go
Обычный файл
|
@ -0,0 +1,27 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"machine"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
audio = make([]int16, 16)
|
||||||
|
pdm = machine.PDM{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
machine.BUTTONA.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})
|
||||||
|
err := pdm.Configure(machine.PDMConfig{CLK: machine.PDM_CLK_PIN, DIN: machine.PDM_DIN_PIN})
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("Failed to configure PDM:%v", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
if machine.BUTTONA.Get() {
|
||||||
|
println("Recording new audio clip into memory")
|
||||||
|
pdm.Read(audio)
|
||||||
|
println(fmt.Sprintf("Recorded new audio clip into memory: %v", audio))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -73,6 +73,12 @@ const (
|
||||||
SPI0_SDI_PIN = P0_23 // SDI
|
SPI0_SDI_PIN = P0_23 // SDI
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PDM pins
|
||||||
|
const (
|
||||||
|
PDM_CLK_PIN = P0_17 // CLK
|
||||||
|
PDM_DIN_PIN = P0_16 // DIN
|
||||||
|
)
|
||||||
|
|
||||||
// USB CDC identifiers
|
// USB CDC identifiers
|
||||||
const (
|
const (
|
||||||
usb_STRING_PRODUCT = "Adafruit Circuit Playground Bluefruit"
|
usb_STRING_PRODUCT = "Adafruit Circuit Playground Bluefruit"
|
||||||
|
|
|
@ -4,6 +4,8 @@ package machine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"device/nrf"
|
"device/nrf"
|
||||||
|
"errors"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get peripheral and pin number for this GPIO pin.
|
// Get peripheral and pin number for this GPIO pin.
|
||||||
|
@ -32,3 +34,71 @@ var (
|
||||||
PWM2 = &PWM{PWM: nrf.PWM2}
|
PWM2 = &PWM{PWM: nrf.PWM2}
|
||||||
PWM3 = &PWM{PWM: nrf.PWM3}
|
PWM3 = &PWM{PWM: nrf.PWM3}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PDM represents a PDM device
|
||||||
|
type PDM struct {
|
||||||
|
device *nrf.PDM_Type
|
||||||
|
defaultBuffer int16
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure is intended to set up the PDM interface prior to use.
|
||||||
|
func (pdm *PDM) Configure(config PDMConfig) error {
|
||||||
|
if config.DIN == 0 {
|
||||||
|
return errors.New("No DIN pin provided in configuration")
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.CLK == 0 {
|
||||||
|
return errors.New("No CLK pin provided in configuration")
|
||||||
|
}
|
||||||
|
|
||||||
|
config.DIN.Configure(PinConfig{Mode: PinInput})
|
||||||
|
config.CLK.Configure(PinConfig{Mode: PinOutput})
|
||||||
|
pdm.device = nrf.PDM
|
||||||
|
pdm.device.PSEL.DIN.Set(uint32(config.DIN))
|
||||||
|
pdm.device.PSEL.CLK.Set(uint32(config.CLK))
|
||||||
|
pdm.device.PDMCLKCTRL.Set(nrf.PDM_PDMCLKCTRL_FREQ_Default)
|
||||||
|
pdm.device.RATIO.Set(nrf.PDM_RATIO_RATIO_Ratio64)
|
||||||
|
pdm.device.GAINL.Set(nrf.PDM_GAINL_GAINL_DefaultGain)
|
||||||
|
pdm.device.GAINR.Set(nrf.PDM_GAINR_GAINR_DefaultGain)
|
||||||
|
pdm.device.ENABLE.Set(nrf.PDM_ENABLE_ENABLE_Enabled)
|
||||||
|
|
||||||
|
if config.Stereo {
|
||||||
|
pdm.device.MODE.Set(nrf.PDM_MODE_OPERATION_Stereo | nrf.PDM_MODE_EDGE_LeftRising)
|
||||||
|
} else {
|
||||||
|
pdm.device.MODE.Set(nrf.PDM_MODE_OPERATION_Mono | nrf.PDM_MODE_EDGE_LeftRising)
|
||||||
|
}
|
||||||
|
|
||||||
|
pdm.device.SAMPLE.SetPTR(uint32(uintptr(unsafe.Pointer(&pdm.defaultBuffer))))
|
||||||
|
pdm.device.SAMPLE.SetMAXCNT_BUFFSIZE(1)
|
||||||
|
pdm.device.SetTASKS_START(1)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read stores a set of samples in the given target buffer.
|
||||||
|
func (pdm *PDM) Read(buf []int16) (uint32, error) {
|
||||||
|
pdm.device.SAMPLE.SetPTR(uint32(uintptr(unsafe.Pointer(&buf[0]))))
|
||||||
|
pdm.device.SAMPLE.MAXCNT.Set(uint32(len(buf)))
|
||||||
|
pdm.device.EVENTS_STARTED.Set(0)
|
||||||
|
|
||||||
|
// Step 1: wait for new sampling to start for target buffer
|
||||||
|
for !pdm.device.EVENTS_STARTED.HasBits(nrf.PDM_EVENTS_STARTED_EVENTS_STARTED) {
|
||||||
|
}
|
||||||
|
pdm.device.EVENTS_END.Set(0)
|
||||||
|
|
||||||
|
// Step 2: swap out buffers for next recording so we don't continue to
|
||||||
|
// write to the target buffer
|
||||||
|
pdm.device.EVENTS_STARTED.Set(0)
|
||||||
|
pdm.device.SAMPLE.SetPTR(uint32(uintptr(unsafe.Pointer(&pdm.defaultBuffer))))
|
||||||
|
pdm.device.SAMPLE.MAXCNT.Set(1)
|
||||||
|
|
||||||
|
// Step 3: wait for original event to end
|
||||||
|
for pdm.device.EVENTS_END.HasBits(nrf.PDM_EVENTS_STOPPED_EVENTS_STOPPED) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4: wait for default buffer to start recording before proceeding
|
||||||
|
// otherwise we see the contents of target buffer change later
|
||||||
|
for !pdm.device.EVENTS_STARTED.HasBits(nrf.PDM_EVENTS_STARTED_EVENTS_STARTED) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return uint32(len(buf)), nil
|
||||||
|
}
|
||||||
|
|
7
src/machine/pdm.go
Обычный файл
7
src/machine/pdm.go
Обычный файл
|
@ -0,0 +1,7 @@
|
||||||
|
package machine
|
||||||
|
|
||||||
|
type PDMConfig struct {
|
||||||
|
Stereo bool
|
||||||
|
DIN Pin
|
||||||
|
CLK Pin
|
||||||
|
}
|
Загрузка…
Создание таблицы
Сослаться в новой задаче