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  }