github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_nrf52840.go (about) 1 //go:build nrf52840 2 3 package machine 4 5 import ( 6 "device/nrf" 7 "errors" 8 "unsafe" 9 ) 10 11 // Get peripheral and pin number for this GPIO pin. 12 func (p Pin) getPortPin() (*nrf.GPIO_Type, uint32) { 13 if p >= 32 { 14 return nrf.P1, uint32(p - 32) 15 } else { 16 return nrf.P0, uint32(p) 17 } 18 } 19 20 func (uart *UART) setPins(tx, rx Pin) { 21 nrf.UART0.PSEL.TXD.Set(uint32(tx)) 22 nrf.UART0.PSEL.RXD.Set(uint32(rx)) 23 } 24 25 func (i2c *I2C) setPins(scl, sda Pin) { 26 i2c.Bus.PSEL.SCL.Set(uint32(scl)) 27 i2c.Bus.PSEL.SDA.Set(uint32(sda)) 28 } 29 30 // PWM 31 var ( 32 PWM0 = &PWM{PWM: nrf.PWM0} 33 PWM1 = &PWM{PWM: nrf.PWM1} 34 PWM2 = &PWM{PWM: nrf.PWM2} 35 PWM3 = &PWM{PWM: nrf.PWM3} 36 ) 37 38 // PDM represents a PDM device 39 type PDM struct { 40 device *nrf.PDM_Type 41 defaultBuffer int16 42 } 43 44 // Configure is intended to set up the PDM interface prior to use. 45 func (pdm *PDM) Configure(config PDMConfig) error { 46 if config.DIN == 0 { 47 return errors.New("No DIN pin provided in configuration") 48 } 49 50 if config.CLK == 0 { 51 return errors.New("No CLK pin provided in configuration") 52 } 53 54 config.DIN.Configure(PinConfig{Mode: PinInput}) 55 config.CLK.Configure(PinConfig{Mode: PinOutput}) 56 pdm.device = nrf.PDM 57 pdm.device.PSEL.DIN.Set(uint32(config.DIN)) 58 pdm.device.PSEL.CLK.Set(uint32(config.CLK)) 59 pdm.device.PDMCLKCTRL.Set(nrf.PDM_PDMCLKCTRL_FREQ_Default) 60 pdm.device.RATIO.Set(nrf.PDM_RATIO_RATIO_Ratio64) 61 pdm.device.GAINL.Set(nrf.PDM_GAINL_GAINL_DefaultGain) 62 pdm.device.GAINR.Set(nrf.PDM_GAINR_GAINR_DefaultGain) 63 pdm.device.ENABLE.Set(nrf.PDM_ENABLE_ENABLE_Enabled) 64 65 if config.Stereo { 66 pdm.device.MODE.Set(nrf.PDM_MODE_OPERATION_Stereo | nrf.PDM_MODE_EDGE_LeftRising) 67 } else { 68 pdm.device.MODE.Set(nrf.PDM_MODE_OPERATION_Mono | nrf.PDM_MODE_EDGE_LeftRising) 69 } 70 71 pdm.device.SAMPLE.SetPTR(uint32(uintptr(unsafe.Pointer(&pdm.defaultBuffer)))) 72 pdm.device.SAMPLE.SetMAXCNT_BUFFSIZE(1) 73 pdm.device.SetTASKS_START(1) 74 return nil 75 } 76 77 // Read stores a set of samples in the given target buffer. 78 func (pdm *PDM) Read(buf []int16) (uint32, error) { 79 pdm.device.SAMPLE.SetPTR(uint32(uintptr(unsafe.Pointer(&buf[0])))) 80 pdm.device.SAMPLE.MAXCNT.Set(uint32(len(buf))) 81 pdm.device.EVENTS_STARTED.Set(0) 82 83 // Step 1: wait for new sampling to start for target buffer 84 for !pdm.device.EVENTS_STARTED.HasBits(nrf.PDM_EVENTS_STARTED_EVENTS_STARTED) { 85 } 86 pdm.device.EVENTS_END.Set(0) 87 88 // Step 2: swap out buffers for next recording so we don't continue to 89 // write to the target buffer 90 pdm.device.EVENTS_STARTED.Set(0) 91 pdm.device.SAMPLE.SetPTR(uint32(uintptr(unsafe.Pointer(&pdm.defaultBuffer)))) 92 pdm.device.SAMPLE.MAXCNT.Set(1) 93 94 // Step 3: wait for original event to end 95 for pdm.device.EVENTS_END.HasBits(nrf.PDM_EVENTS_STOPPED_EVENTS_STOPPED) { 96 } 97 98 // Step 4: wait for default buffer to start recording before proceeding 99 // otherwise we see the contents of target buffer change later 100 for !pdm.device.EVENTS_STARTED.HasBits(nrf.PDM_EVENTS_STARTED_EVENTS_STARTED) { 101 } 102 103 return uint32(len(buf)), nil 104 } 105 106 const eraseBlockSizeValue = 4096 107 108 func eraseBlockSize() int64 { 109 return eraseBlockSizeValue 110 }