github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_nrf52xxx.go (about)

     1  //go:build nrf52 || nrf52840 || nrf52833
     2  
     3  package machine
     4  
     5  import (
     6  	"device/nrf"
     7  	"runtime/volatile"
     8  	"unsafe"
     9  )
    10  
    11  func CPUFrequency() uint32 {
    12  	return 64000000
    13  }
    14  
    15  // InitADC initializes the registers needed for ADC.
    16  func InitADC() {
    17  	return // no specific setup on nrf52 machine.
    18  }
    19  
    20  // Configure configures an ADC pin to be able to read analog data.
    21  func (a ADC) Configure(config ADCConfig) {
    22  	// Enable ADC.
    23  	// The ADC does not consume a noticeable amount of current simply by being
    24  	// enabled.
    25  	nrf.SAADC.ENABLE.Set(nrf.SAADC_ENABLE_ENABLE_Enabled << nrf.SAADC_ENABLE_ENABLE_Pos)
    26  
    27  	// Use fixed resolution of 12 bits.
    28  	// TODO: is it useful for users to change this?
    29  	nrf.SAADC.RESOLUTION.Set(nrf.SAADC_RESOLUTION_VAL_12bit)
    30  
    31  	var configVal uint32 = nrf.SAADC_CH_CONFIG_RESP_Bypass<<nrf.SAADC_CH_CONFIG_RESP_Pos |
    32  		nrf.SAADC_CH_CONFIG_RESP_Bypass<<nrf.SAADC_CH_CONFIG_RESN_Pos |
    33  		nrf.SAADC_CH_CONFIG_REFSEL_Internal<<nrf.SAADC_CH_CONFIG_REFSEL_Pos |
    34  		nrf.SAADC_CH_CONFIG_MODE_SE<<nrf.SAADC_CH_CONFIG_MODE_Pos
    35  
    36  	switch config.Reference {
    37  	case 150: // 0.15V
    38  		configVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain4 << nrf.SAADC_CH_CONFIG_GAIN_Pos
    39  	case 300: // 0.3V
    40  		configVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain2 << nrf.SAADC_CH_CONFIG_GAIN_Pos
    41  	case 600: // 0.6V
    42  		configVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1 << nrf.SAADC_CH_CONFIG_GAIN_Pos
    43  	case 1200: // 1.2V
    44  		configVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1_2 << nrf.SAADC_CH_CONFIG_GAIN_Pos
    45  	case 1800: // 1.8V
    46  		configVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1_3 << nrf.SAADC_CH_CONFIG_GAIN_Pos
    47  	case 2400: // 2.4V
    48  		configVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1_4 << nrf.SAADC_CH_CONFIG_GAIN_Pos
    49  	case 3000, 0: // 3.0V (default)
    50  		configVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1_5 << nrf.SAADC_CH_CONFIG_GAIN_Pos
    51  	case 3600: // 3.6V
    52  		configVal |= nrf.SAADC_CH_CONFIG_GAIN_Gain1_6 << nrf.SAADC_CH_CONFIG_GAIN_Pos
    53  	default:
    54  		// TODO: return an error
    55  	}
    56  
    57  	// Source resistance, according to table 89 on page 364 of the nrf52832 datasheet.
    58  	// https://infocenter.nordicsemi.com/pdf/nRF52832_PS_v1.4.pdf
    59  	if config.SampleTime <= 3 { // <= 10kΩ
    60  		configVal |= nrf.SAADC_CH_CONFIG_TACQ_3us << nrf.SAADC_CH_CONFIG_TACQ_Pos
    61  	} else if config.SampleTime <= 5 { // <= 40kΩ
    62  		configVal |= nrf.SAADC_CH_CONFIG_TACQ_5us << nrf.SAADC_CH_CONFIG_TACQ_Pos
    63  	} else if config.SampleTime <= 10 { // <= 100kΩ
    64  		configVal |= nrf.SAADC_CH_CONFIG_TACQ_10us << nrf.SAADC_CH_CONFIG_TACQ_Pos
    65  	} else if config.SampleTime <= 15 { // <= 200kΩ
    66  		configVal |= nrf.SAADC_CH_CONFIG_TACQ_15us << nrf.SAADC_CH_CONFIG_TACQ_Pos
    67  	} else if config.SampleTime <= 20 { // <= 400kΩ
    68  		configVal |= nrf.SAADC_CH_CONFIG_TACQ_20us << nrf.SAADC_CH_CONFIG_TACQ_Pos
    69  	} else { // <= 800kΩ
    70  		configVal |= nrf.SAADC_CH_CONFIG_TACQ_40us << nrf.SAADC_CH_CONFIG_TACQ_Pos
    71  	}
    72  
    73  	// Oversampling configuration.
    74  	burst := true
    75  	switch config.Samples {
    76  	default: // no oversampling
    77  		nrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Bypass)
    78  		burst = false
    79  	case 2:
    80  		nrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over2x)
    81  	case 4:
    82  		nrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over4x)
    83  	case 8:
    84  		nrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over8x)
    85  	case 16:
    86  		nrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over16x)
    87  	case 32:
    88  		nrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over32x)
    89  	case 64:
    90  		nrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over64x)
    91  	case 128:
    92  		nrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over128x)
    93  	case 256:
    94  		nrf.SAADC.OVERSAMPLE.Set(nrf.SAADC_OVERSAMPLE_OVERSAMPLE_Over256x)
    95  	}
    96  	if burst {
    97  		// BURST=1 is needed when oversampling
    98  		configVal |= nrf.SAADC_CH_CONFIG_BURST
    99  	}
   100  
   101  	// Configure channel 0, which is the only channel we use.
   102  	nrf.SAADC.CH[0].CONFIG.Set(configVal)
   103  }
   104  
   105  // Get returns the current value of a ADC pin in the range 0..0xffff.
   106  func (a ADC) Get() uint16 {
   107  	var pwmPin uint32
   108  	var rawValue volatile.Register16
   109  
   110  	switch a.Pin {
   111  	case 2:
   112  		pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput0
   113  
   114  	case 3:
   115  		pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput1
   116  
   117  	case 4:
   118  		pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput2
   119  
   120  	case 5:
   121  		pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput3
   122  
   123  	case 28:
   124  		pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput4
   125  
   126  	case 29:
   127  		pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput5
   128  
   129  	case 30:
   130  		pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput6
   131  
   132  	case 31:
   133  		pwmPin = nrf.SAADC_CH_PSELP_PSELP_AnalogInput7
   134  
   135  	default:
   136  		return 0
   137  	}
   138  
   139  	// Set pin to read.
   140  	nrf.SAADC.CH[0].PSELN.Set(pwmPin)
   141  	nrf.SAADC.CH[0].PSELP.Set(pwmPin)
   142  
   143  	// Destination for sample result.
   144  	nrf.SAADC.RESULT.PTR.Set(uint32(uintptr(unsafe.Pointer(&rawValue))))
   145  	nrf.SAADC.RESULT.MAXCNT.Set(1) // One sample
   146  
   147  	// Start tasks.
   148  	nrf.SAADC.TASKS_START.Set(1)
   149  	for nrf.SAADC.EVENTS_STARTED.Get() == 0 {
   150  	}
   151  	nrf.SAADC.EVENTS_STARTED.Set(0x00)
   152  
   153  	// Start the sample task.
   154  	nrf.SAADC.TASKS_SAMPLE.Set(1)
   155  
   156  	// Wait until the sample task is done.
   157  	for nrf.SAADC.EVENTS_END.Get() == 0 {
   158  	}
   159  	nrf.SAADC.EVENTS_END.Set(0x00)
   160  
   161  	// Stop the ADC
   162  	nrf.SAADC.TASKS_STOP.Set(1)
   163  	for nrf.SAADC.EVENTS_STOPPED.Get() == 0 {
   164  	}
   165  	nrf.SAADC.EVENTS_STOPPED.Set(0)
   166  
   167  	value := int16(rawValue.Get())
   168  	if value < 0 {
   169  		value = 0
   170  	}
   171  
   172  	// Return 16-bit result from 12-bit value.
   173  	return uint16(value << 4)
   174  }
   175  
   176  // SPI on the NRF.
   177  type SPI struct {
   178  	Bus *nrf.SPIM_Type
   179  	buf *[1]byte // 1-byte buffer for the Transfer method
   180  }
   181  
   182  // There are 3 SPI interfaces on the NRF528xx.
   183  var (
   184  	SPI0 = SPI{Bus: nrf.SPIM0, buf: new([1]byte)}
   185  	SPI1 = SPI{Bus: nrf.SPIM1, buf: new([1]byte)}
   186  	SPI2 = SPI{Bus: nrf.SPIM2, buf: new([1]byte)}
   187  )
   188  
   189  // SPIConfig is used to store config info for SPI.
   190  type SPIConfig struct {
   191  	Frequency uint32
   192  	SCK       Pin
   193  	SDO       Pin
   194  	SDI       Pin
   195  	LSBFirst  bool
   196  	Mode      uint8
   197  }
   198  
   199  // Configure is intended to setup the SPI interface.
   200  func (spi SPI) Configure(config SPIConfig) error {
   201  	// Disable bus to configure it
   202  	spi.Bus.ENABLE.Set(nrf.SPIM_ENABLE_ENABLE_Disabled)
   203  
   204  	// Pick a default frequency.
   205  	if config.Frequency == 0 {
   206  		config.Frequency = 4000000 // 4MHz
   207  	}
   208  
   209  	// set frequency
   210  	var freq uint32
   211  	switch {
   212  	case config.Frequency >= 8000000:
   213  		freq = nrf.SPIM_FREQUENCY_FREQUENCY_M8
   214  	case config.Frequency >= 4000000:
   215  		freq = nrf.SPIM_FREQUENCY_FREQUENCY_M4
   216  	case config.Frequency >= 2000000:
   217  		freq = nrf.SPIM_FREQUENCY_FREQUENCY_M2
   218  	case config.Frequency >= 1000000:
   219  		freq = nrf.SPIM_FREQUENCY_FREQUENCY_M1
   220  	case config.Frequency >= 500000:
   221  		freq = nrf.SPIM_FREQUENCY_FREQUENCY_K500
   222  	case config.Frequency >= 250000:
   223  		freq = nrf.SPIM_FREQUENCY_FREQUENCY_K250
   224  	default: // below 250kHz, default to the lowest speed available
   225  		freq = nrf.SPIM_FREQUENCY_FREQUENCY_K125
   226  	}
   227  	spi.Bus.FREQUENCY.Set(freq)
   228  
   229  	var conf uint32
   230  
   231  	// set bit transfer order
   232  	if config.LSBFirst {
   233  		conf = (nrf.SPIM_CONFIG_ORDER_LsbFirst << nrf.SPIM_CONFIG_ORDER_Pos)
   234  	}
   235  
   236  	// set mode
   237  	switch config.Mode {
   238  	case 0:
   239  		conf &^= (nrf.SPIM_CONFIG_CPOL_ActiveHigh << nrf.SPIM_CONFIG_CPOL_Pos)
   240  		conf &^= (nrf.SPIM_CONFIG_CPHA_Leading << nrf.SPIM_CONFIG_CPHA_Pos)
   241  	case 1:
   242  		conf &^= (nrf.SPIM_CONFIG_CPOL_ActiveHigh << nrf.SPIM_CONFIG_CPOL_Pos)
   243  		conf |= (nrf.SPIM_CONFIG_CPHA_Trailing << nrf.SPIM_CONFIG_CPHA_Pos)
   244  	case 2:
   245  		conf |= (nrf.SPIM_CONFIG_CPOL_ActiveLow << nrf.SPIM_CONFIG_CPOL_Pos)
   246  		conf &^= (nrf.SPIM_CONFIG_CPHA_Leading << nrf.SPIM_CONFIG_CPHA_Pos)
   247  	case 3:
   248  		conf |= (nrf.SPIM_CONFIG_CPOL_ActiveLow << nrf.SPIM_CONFIG_CPOL_Pos)
   249  		conf |= (nrf.SPIM_CONFIG_CPHA_Trailing << nrf.SPIM_CONFIG_CPHA_Pos)
   250  	default: // to mode
   251  		conf &^= (nrf.SPIM_CONFIG_CPOL_ActiveHigh << nrf.SPIM_CONFIG_CPOL_Pos)
   252  		conf &^= (nrf.SPIM_CONFIG_CPHA_Leading << nrf.SPIM_CONFIG_CPHA_Pos)
   253  	}
   254  	spi.Bus.CONFIG.Set(conf)
   255  
   256  	// set pins
   257  	if config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {
   258  		config.SCK = SPI0_SCK_PIN
   259  		config.SDO = SPI0_SDO_PIN
   260  		config.SDI = SPI0_SDI_PIN
   261  	}
   262  	spi.Bus.PSEL.SCK.Set(uint32(config.SCK))
   263  	spi.Bus.PSEL.MOSI.Set(uint32(config.SDO))
   264  	spi.Bus.PSEL.MISO.Set(uint32(config.SDI))
   265  
   266  	// Re-enable bus now that it is configured.
   267  	spi.Bus.ENABLE.Set(nrf.SPIM_ENABLE_ENABLE_Enabled)
   268  
   269  	return nil
   270  }
   271  
   272  // Transfer writes/reads a single byte using the SPI interface.
   273  func (spi SPI) Transfer(w byte) (byte, error) {
   274  	buf := spi.buf[:]
   275  	buf[0] = w
   276  	err := spi.Tx(buf[:], buf[:])
   277  	return buf[0], err
   278  }
   279  
   280  // Tx handles read/write operation for SPI interface. Since SPI is a syncronous
   281  // write/read interface, there must always be the same number of bytes written
   282  // as bytes read. Therefore, if the number of bytes don't match it will be
   283  // padded until they fit: if len(w) > len(r) the extra bytes received will be
   284  // dropped and if len(w) < len(r) extra 0 bytes will be sent.
   285  func (spi SPI) Tx(w, r []byte) error {
   286  	// Unfortunately the hardware (on the nrf52832) only supports up to 255
   287  	// bytes in the buffers, so if either w or r is longer than that the
   288  	// transfer needs to be broken up in pieces.
   289  	// The nrf52840 supports far larger buffers however, which isn't yet
   290  	// supported.
   291  	for len(r) != 0 || len(w) != 0 {
   292  		// Prepare the SPI transfer: set the DMA pointers and lengths.
   293  		// read buffer
   294  		nr := uint32(len(r))
   295  		if nr > 0 {
   296  			if nr > 255 {
   297  				nr = 255
   298  			}
   299  			spi.Bus.RXD.PTR.Set(uint32(uintptr(unsafe.Pointer(&r[0]))))
   300  			r = r[nr:]
   301  		}
   302  		spi.Bus.RXD.MAXCNT.Set(nr)
   303  
   304  		// write buffer
   305  		nw := uint32(len(w))
   306  		if nw > 0 {
   307  			if nw > 255 {
   308  				nw = 255
   309  			}
   310  			spi.Bus.TXD.PTR.Set(uint32(uintptr(unsafe.Pointer(&w[0]))))
   311  			w = w[nw:]
   312  		}
   313  		spi.Bus.TXD.MAXCNT.Set(nw)
   314  
   315  		// Do the transfer.
   316  		// Note: this can be improved by not waiting until the transfer is
   317  		// finished if the transfer is send-only (a common case).
   318  		spi.Bus.TASKS_START.Set(1)
   319  		for spi.Bus.EVENTS_END.Get() == 0 {
   320  		}
   321  		spi.Bus.EVENTS_END.Set(0)
   322  	}
   323  
   324  	return nil
   325  }
   326  
   327  // PWM is one PWM peripheral, which consists of a counter and multiple output
   328  // channels (that can be connected to actual pins). You can set the frequency
   329  // using SetPeriod, but only for all the channels in this PWM peripheral at
   330  // once.
   331  type PWM struct {
   332  	PWM *nrf.PWM_Type
   333  
   334  	channelValues [4]volatile.Register16
   335  }
   336  
   337  // Configure enables and configures this PWM.
   338  // On the nRF52 series, the maximum period is around 0.26s.
   339  func (pwm *PWM) Configure(config PWMConfig) error {
   340  	// Enable the peripheral.
   341  	pwm.PWM.ENABLE.Set(nrf.PWM_ENABLE_ENABLE_Enabled << nrf.PWM_ENABLE_ENABLE_Pos)
   342  
   343  	// Use up counting only. TODO: allow configuring as up-and-down.
   344  	pwm.PWM.MODE.Set(nrf.PWM_MODE_UPDOWN_Up << nrf.PWM_MODE_UPDOWN_Pos)
   345  
   346  	// Indicate there are four channels that each have a different value.
   347  	pwm.PWM.DECODER.Set(nrf.PWM_DECODER_LOAD_Individual<<nrf.PWM_DECODER_LOAD_Pos | nrf.PWM_DECODER_MODE_RefreshCount<<nrf.PWM_DECODER_MODE_Pos)
   348  
   349  	err := pwm.setPeriod(config.Period, true)
   350  	if err != nil {
   351  		return err
   352  	}
   353  
   354  	// Set the EasyDMA buffer, which has 4 values (one for each channel).
   355  	pwm.PWM.SEQ[0].PTR.Set(uint32(uintptr(unsafe.Pointer(&pwm.channelValues[0]))))
   356  	pwm.PWM.SEQ[0].CNT.Set(4)
   357  
   358  	// SEQ[0] is not yet started, it will be started on the first
   359  	// PWMChannel.Set() call.
   360  
   361  	return nil
   362  }
   363  
   364  // SetPeriod updates the period of this PWM peripheral.
   365  // To set a particular frequency, use the following formula:
   366  //
   367  //	period = 1e9 / frequency
   368  //
   369  // If you use a period of 0, a period that works well for LEDs will be picked.
   370  //
   371  // SetPeriod will not change the prescaler, but also won't change the current
   372  // value in any of the channels. This means that you may need to update the
   373  // value for the particular channel.
   374  //
   375  // Note that you cannot pick any arbitrary period after the PWM peripheral has
   376  // been configured. If you want to switch between frequencies, pick the lowest
   377  // frequency (longest period) once when calling Configure and adjust the
   378  // frequency here as needed.
   379  func (pwm *PWM) SetPeriod(period uint64) error {
   380  	return pwm.setPeriod(period, false)
   381  }
   382  
   383  func (pwm *PWM) setPeriod(period uint64, updatePrescaler bool) error {
   384  	const maxTop = 0x7fff // 15 bits counter
   385  
   386  	// The top value is the number of PWM ticks a PWM period takes. It is
   387  	// initially picked assuming an unlimited COUNTERTOP and no PWM prescaler.
   388  	var top uint64
   389  	if period == 0 {
   390  		// The period is 0, which means "pick something reasonable for LEDs".
   391  		top = maxTop
   392  	} else {
   393  		// The formula below calculates the following formula, optimized:
   394  		//     period * (16e6 / 1e9)
   395  		// The max frequency (16e6 or 16MHz) is set by the hardware.
   396  		top = period * 2 / 125
   397  	}
   398  
   399  	// The ideal PWM period may be larger than would fit in the PWM counter,
   400  	// which is only 15 bits (see maxTop). Therefore, try to make the PWM clock
   401  	// speed lower with a prescaler to make the top value fit the COUNTERTOP.
   402  	if updatePrescaler {
   403  		// This function was called during Configure().
   404  		switch {
   405  		case top <= maxTop:
   406  			pwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_1)
   407  		case top/2 <= maxTop:
   408  			pwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_2)
   409  			top /= 2
   410  		case top/4 <= maxTop:
   411  			pwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_4)
   412  			top /= 4
   413  		case top/8 <= maxTop:
   414  			pwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_8)
   415  			top /= 8
   416  		case top/16 <= maxTop:
   417  			pwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_16)
   418  			top /= 16
   419  		case top/32 <= maxTop:
   420  			pwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_32)
   421  			top /= 32
   422  		case top/64 <= maxTop:
   423  			pwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_64)
   424  			top /= 64
   425  		case top/128 <= maxTop:
   426  			pwm.PWM.PRESCALER.Set(nrf.PWM_PRESCALER_PRESCALER_DIV_128)
   427  			top /= 128
   428  		default:
   429  			return ErrPWMPeriodTooLong
   430  		}
   431  	} else {
   432  		// Do not update the prescaler, but use the already-configured
   433  		// prescaler. This is the normal SetPeriod case, where the prescaler
   434  		// must not be changed.
   435  		prescaler := pwm.PWM.PRESCALER.Get()
   436  		switch prescaler {
   437  		case nrf.PWM_PRESCALER_PRESCALER_DIV_1:
   438  			top /= 1
   439  		case nrf.PWM_PRESCALER_PRESCALER_DIV_2:
   440  			top /= 2
   441  		case nrf.PWM_PRESCALER_PRESCALER_DIV_4:
   442  			top /= 4
   443  		case nrf.PWM_PRESCALER_PRESCALER_DIV_8:
   444  			top /= 8
   445  		case nrf.PWM_PRESCALER_PRESCALER_DIV_16:
   446  			top /= 16
   447  		case nrf.PWM_PRESCALER_PRESCALER_DIV_32:
   448  			top /= 32
   449  		case nrf.PWM_PRESCALER_PRESCALER_DIV_64:
   450  			top /= 64
   451  		case nrf.PWM_PRESCALER_PRESCALER_DIV_128:
   452  			top /= 128
   453  		}
   454  		if top > maxTop {
   455  			return ErrPWMPeriodTooLong
   456  		}
   457  	}
   458  	pwm.PWM.COUNTERTOP.Set(uint32(top))
   459  
   460  	// Apparently this is needed to apply the new COUNTERTOP.
   461  	pwm.PWM.TASKS_SEQSTART[0].Set(1)
   462  
   463  	return nil
   464  }
   465  
   466  // Top returns the current counter top, for use in duty cycle calculation. It
   467  // will only change with a call to Configure or SetPeriod, otherwise it is
   468  // constant.
   469  //
   470  // The value returned here is hardware dependent. In general, it's best to treat
   471  // it as an opaque value that can be divided by some number and passed to
   472  // pwm.Set (see pwm.Set for more information).
   473  func (pwm *PWM) Top() uint32 {
   474  	return pwm.PWM.COUNTERTOP.Get()
   475  }
   476  
   477  // Channel returns a PWM channel for the given pin.
   478  func (pwm *PWM) Channel(pin Pin) (uint8, error) {
   479  	config := uint32(pin)
   480  	for ch := uint8(0); ch < 4; ch++ {
   481  		channelConfig := pwm.PWM.PSEL.OUT[ch].Get()
   482  		if channelConfig == 0xffffffff {
   483  			// Unused channel. Configure it.
   484  			pwm.PWM.PSEL.OUT[ch].Set(config)
   485  			// Configure the pin (required by the reference manual).
   486  			pin.Configure(PinConfig{Mode: PinOutput})
   487  			// Set channel to zero and non-inverting.
   488  			pwm.channelValues[ch].Set(0x8000)
   489  			return ch, nil
   490  		} else if channelConfig == config {
   491  			// This channel is already configured for this pin.
   492  			return ch, nil
   493  		}
   494  	}
   495  
   496  	// All four pins are already in use with other pins.
   497  	return 0, ErrInvalidOutputPin
   498  }
   499  
   500  // SetInverting sets whether to invert the output of this channel.
   501  // Without inverting, a 25% duty cycle would mean the output is high for 25% of
   502  // the time and low for the rest. Inverting flips the output as if a NOT gate
   503  // was placed at the output, meaning that the output would be 25% low and 75%
   504  // high with a duty cycle of 25%.
   505  func (pwm *PWM) SetInverting(channel uint8, inverting bool) {
   506  	ptr := &pwm.channelValues[channel]
   507  	if inverting {
   508  		ptr.Set(ptr.Get() &^ 0x8000)
   509  	} else {
   510  		ptr.Set(ptr.Get() | 0x8000)
   511  	}
   512  }
   513  
   514  // Set updates the channel value. This is used to control the channel duty
   515  // cycle. For example, to set it to a 25% duty cycle, use:
   516  //
   517  //	ch.Set(ch.Top() / 4)
   518  //
   519  // ch.Set(0) will set the output to low and ch.Set(ch.Top()) will set the output
   520  // to high, assuming the output isn't inverted.
   521  func (pwm *PWM) Set(channel uint8, value uint32) {
   522  	// Update the channel value while retaining the polarity bit.
   523  	ptr := &pwm.channelValues[channel]
   524  	ptr.Set(ptr.Get()&0x8000 | uint16(value)&0x7fff)
   525  
   526  	// Start the PWM, if it isn't already running.
   527  	pwm.PWM.TASKS_SEQSTART[0].Set(1)
   528  }