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

     1  //go:build (sam && atsamd51) || (sam && atsame5x)
     2  
     3  // Peripheral abstraction layer for the atsamd51.
     4  //
     5  // Datasheet:
     6  // http://ww1.microchip.com/downloads/en/DeviceDoc/60001507C.pdf
     7  package machine
     8  
     9  import (
    10  	"bytes"
    11  	"device/arm"
    12  	"device/sam"
    13  	"encoding/binary"
    14  	"errors"
    15  	"runtime/interrupt"
    16  	"unsafe"
    17  )
    18  
    19  const deviceName = sam.Device
    20  
    21  // DS60001507, Section 9.6: Serial Number
    22  var deviceIDAddr = []uintptr{0x008061FC, 0x00806010, 0x00806014, 0x00806018}
    23  
    24  func CPUFrequency() uint32 {
    25  	return 120000000
    26  }
    27  
    28  const (
    29  	PinAnalog        PinMode = 1
    30  	PinSERCOM        PinMode = 2
    31  	PinSERCOMAlt     PinMode = 3
    32  	PinTimer         PinMode = 4
    33  	PinTimerAlt      PinMode = 5
    34  	PinTCCPDEC       PinMode = 6
    35  	PinCom           PinMode = 7
    36  	PinSDHC          PinMode = 8
    37  	PinI2S           PinMode = 9
    38  	PinPCC           PinMode = 10
    39  	PinGMAC          PinMode = 11
    40  	PinACCLK         PinMode = 12
    41  	PinCCL           PinMode = 13
    42  	PinDigital       PinMode = 14
    43  	PinInput         PinMode = 15
    44  	PinInputPullup   PinMode = 16
    45  	PinOutput        PinMode = 17
    46  	PinTCCE          PinMode = PinTimer
    47  	PinTCCF          PinMode = PinTimerAlt
    48  	PinTCCG          PinMode = PinTCCPDEC
    49  	PinInputPulldown PinMode = 18
    50  	PinCAN           PinMode = 19
    51  	PinCAN0          PinMode = PinSDHC
    52  	PinCAN1          PinMode = PinCom
    53  )
    54  
    55  type PinChange uint8
    56  
    57  // Pin change interrupt constants for SetInterrupt.
    58  const (
    59  	PinRising  PinChange = sam.EIC_CONFIG_SENSE0_RISE
    60  	PinFalling PinChange = sam.EIC_CONFIG_SENSE0_FALL
    61  	PinToggle  PinChange = sam.EIC_CONFIG_SENSE0_BOTH
    62  )
    63  
    64  // Callbacks to be called for pins configured with SetInterrupt. Unfortunately,
    65  // we also need to keep track of which interrupt channel is used by which pin,
    66  // as the only alternative would be iterating through all pins.
    67  //
    68  // We're using the magic constant 16 here because the SAM D21 has 16 interrupt
    69  // channels configurable for pins.
    70  var (
    71  	interruptPins [16]Pin // warning: the value is invalid when pinCallbacks[i] is not set!
    72  	pinCallbacks  [16]func(Pin)
    73  )
    74  
    75  // Hardware pins
    76  const (
    77  	PA00 Pin = 0
    78  	PA01 Pin = 1
    79  	PA02 Pin = 2
    80  	PA03 Pin = 3
    81  	PA04 Pin = 4
    82  	PA05 Pin = 5
    83  	PA06 Pin = 6
    84  	PA07 Pin = 7
    85  	PA08 Pin = 8  // peripherals: TCC0 channel 0, TCC1 channel 4
    86  	PA09 Pin = 9  // peripherals: TCC0 channel 1, TCC1 channel 5
    87  	PA10 Pin = 10 // peripherals: TCC0 channel 2, TCC1 channel 6
    88  	PA11 Pin = 11 // peripherals: TCC0 channel 3, TCC1 channel 7
    89  	PA12 Pin = 12 // peripherals: TCC0 channel 6, TCC1 channel 2
    90  	PA13 Pin = 13 // peripherals: TCC0 channel 7, TCC1 channel 3
    91  	PA14 Pin = 14 // peripherals: TCC2 channel 0, TCC1 channel 2
    92  	PA15 Pin = 15 // peripherals: TCC2 channel 1, TCC1 channel 3
    93  	PA16 Pin = 16 // peripherals: TCC1 channel 0, TCC0 channel 4
    94  	PA17 Pin = 17 // peripherals: TCC1 channel 1, TCC0 channel 5
    95  	PA18 Pin = 18 // peripherals: TCC1 channel 2, TCC0 channel 6
    96  	PA19 Pin = 19 // peripherals: TCC1 channel 3, TCC0 channel 7
    97  	PA20 Pin = 20 // peripherals: TCC1 channel 4, TCC0 channel 0
    98  	PA21 Pin = 21 // peripherals: TCC1 channel 5, TCC0 channel 1
    99  	PA22 Pin = 22 // peripherals: TCC1 channel 6, TCC0 channel 2
   100  	PA23 Pin = 23 // peripherals: TCC1 channel 7, TCC0 channel 3
   101  	PA24 Pin = 24 // peripherals: TCC2 channel 2
   102  	PA25 Pin = 25 // peripherals: TCC2 channel 3
   103  	PA26 Pin = 26
   104  	PA27 Pin = 27
   105  	PA28 Pin = 28
   106  	PA29 Pin = 29
   107  	PA30 Pin = 30 // peripherals: TCC2 channel 0
   108  	PA31 Pin = 31 // peripherals: TCC2 channel 1
   109  	PB00 Pin = 32
   110  	PB01 Pin = 33
   111  	PB02 Pin = 34 // peripherals: TCC2 channel 2
   112  	PB03 Pin = 35 // peripherals: TCC2 channel 3
   113  	PB04 Pin = 36
   114  	PB05 Pin = 37
   115  	PB06 Pin = 38
   116  	PB07 Pin = 39
   117  	PB08 Pin = 40
   118  	PB09 Pin = 41
   119  	PB10 Pin = 42 // peripherals: TCC0 channel 4, TCC1 channel 0
   120  	PB11 Pin = 43 // peripherals: TCC0 channel 5, TCC1 channel 1
   121  	PB12 Pin = 44 // peripherals: TCC3 channel 0, TCC0 channel 0
   122  	PB13 Pin = 45 // peripherals: TCC3 channel 1, TCC0 channel 1
   123  	PB14 Pin = 46 // peripherals: TCC4 channel 0, TCC0 channel 2
   124  	PB15 Pin = 47 // peripherals: TCC4 channel 1, TCC0 channel 3
   125  	PB16 Pin = 48 // peripherals: TCC3 channel 0, TCC0 channel 4
   126  	PB17 Pin = 49 // peripherals: TCC3 channel 1, TCC0 channel 5
   127  	PB18 Pin = 50 // peripherals: TCC1 channel 0
   128  	PB19 Pin = 51 // peripherals: TCC1 channel 1
   129  	PB20 Pin = 52 // peripherals: TCC1 channel 2
   130  	PB21 Pin = 53 // peripherals: TCC1 channel 3
   131  	PB22 Pin = 54
   132  	PB23 Pin = 55
   133  	PB24 Pin = 56
   134  	PB25 Pin = 57
   135  	PB26 Pin = 58 // peripherals: TCC1 channel 2
   136  	PB27 Pin = 59 // peripherals: TCC1 channel 3
   137  	PB28 Pin = 60 // peripherals: TCC1 channel 4
   138  	PB29 Pin = 61 // peripherals: TCC1 channel 5
   139  	PB30 Pin = 62 // peripherals: TCC4 channel 0, TCC0 channel 6
   140  	PB31 Pin = 63 // peripherals: TCC4 channel 1, TCC0 channel 7
   141  	PC00 Pin = 64
   142  	PC01 Pin = 65
   143  	PC02 Pin = 66
   144  	PC03 Pin = 67
   145  	PC04 Pin = 68 // peripherals: TCC0 channel 0
   146  	PC05 Pin = 69 // peripherals: TCC0 channel 1
   147  	PC06 Pin = 70
   148  	PC07 Pin = 71
   149  	PC08 Pin = 72
   150  	PC09 Pin = 73
   151  	PC10 Pin = 74 // peripherals: TCC0 channel 0, TCC1 channel 4
   152  	PC11 Pin = 75 // peripherals: TCC0 channel 1, TCC1 channel 5
   153  	PC12 Pin = 76 // peripherals: TCC0 channel 2, TCC1 channel 6
   154  	PC13 Pin = 77 // peripherals: TCC0 channel 3, TCC1 channel 7
   155  	PC14 Pin = 78 // peripherals: TCC0 channel 4, TCC1 channel 0
   156  	PC15 Pin = 79 // peripherals: TCC0 channel 5, TCC1 channel 1
   157  	PC16 Pin = 80 // peripherals: TCC0 channel 0
   158  	PC17 Pin = 81 // peripherals: TCC0 channel 1
   159  	PC18 Pin = 82 // peripherals: TCC0 channel 2
   160  	PC19 Pin = 83 // peripherals: TCC0 channel 3
   161  	PC20 Pin = 84 // peripherals: TCC0 channel 4
   162  	PC21 Pin = 85 // peripherals: TCC0 channel 5
   163  	PC22 Pin = 86 // peripherals: TCC0 channel 6
   164  	PC23 Pin = 87 // peripherals: TCC0 channel 7
   165  	PC24 Pin = 88
   166  	PC25 Pin = 89
   167  	PC26 Pin = 90
   168  	PC27 Pin = 91
   169  	PC28 Pin = 92
   170  	PC29 Pin = 93
   171  	PC30 Pin = 94
   172  	PC31 Pin = 95
   173  	PD00 Pin = 96
   174  	PD01 Pin = 97
   175  	PD02 Pin = 98
   176  	PD03 Pin = 99
   177  	PD04 Pin = 100
   178  	PD05 Pin = 101
   179  	PD06 Pin = 102
   180  	PD07 Pin = 103
   181  	PD08 Pin = 104 // peripherals: TCC0 channel 1
   182  	PD09 Pin = 105 // peripherals: TCC0 channel 2
   183  	PD10 Pin = 106 // peripherals: TCC0 channel 3
   184  	PD11 Pin = 107 // peripherals: TCC0 channel 4
   185  	PD12 Pin = 108 // peripherals: TCC0 channel 5
   186  	PD13 Pin = 109 // peripherals: TCC0 channel 6
   187  	PD14 Pin = 110
   188  	PD15 Pin = 111
   189  	PD16 Pin = 112
   190  	PD17 Pin = 113
   191  	PD18 Pin = 114
   192  	PD19 Pin = 115
   193  	PD20 Pin = 116 // peripherals: TCC1 channel 0
   194  	PD21 Pin = 117 // peripherals: TCC1 channel 1
   195  	PD22 Pin = 118
   196  	PD23 Pin = 119
   197  	PD24 Pin = 120
   198  	PD25 Pin = 121
   199  	PD26 Pin = 122
   200  	PD27 Pin = 123
   201  	PD28 Pin = 124
   202  	PD29 Pin = 125
   203  	PD30 Pin = 126
   204  	PD31 Pin = 127
   205  )
   206  
   207  const (
   208  	pinPadMapSERCOM0Pad0 uint16 = 0x1000
   209  	pinPadMapSERCOM1Pad0 uint16 = 0x2000
   210  	pinPadMapSERCOM2Pad0 uint16 = 0x3000
   211  	pinPadMapSERCOM3Pad0 uint16 = 0x4000
   212  	pinPadMapSERCOM4Pad0 uint16 = 0x5000
   213  	pinPadMapSERCOM5Pad0 uint16 = 0x6000
   214  	pinPadMapSERCOM6Pad0 uint16 = 0x7000
   215  	pinPadMapSERCOM7Pad0 uint16 = 0x8000
   216  	pinPadMapSERCOM0Pad2 uint16 = 0x1200
   217  	pinPadMapSERCOM1Pad2 uint16 = 0x2200
   218  	pinPadMapSERCOM2Pad2 uint16 = 0x3200
   219  	pinPadMapSERCOM3Pad2 uint16 = 0x4200
   220  	pinPadMapSERCOM4Pad2 uint16 = 0x5200
   221  	pinPadMapSERCOM5Pad2 uint16 = 0x6200
   222  	pinPadMapSERCOM6Pad2 uint16 = 0x7200
   223  	pinPadMapSERCOM7Pad2 uint16 = 0x8200
   224  
   225  	pinPadMapSERCOM0AltPad0 uint16 = 0x0010
   226  	pinPadMapSERCOM1AltPad0 uint16 = 0x0020
   227  	pinPadMapSERCOM2AltPad0 uint16 = 0x0030
   228  	pinPadMapSERCOM3AltPad0 uint16 = 0x0040
   229  	pinPadMapSERCOM4AltPad0 uint16 = 0x0050
   230  	pinPadMapSERCOM5AltPad0 uint16 = 0x0060
   231  	pinPadMapSERCOM6AltPad0 uint16 = 0x0070
   232  	pinPadMapSERCOM7AltPad0 uint16 = 0x0080
   233  	pinPadMapSERCOM0AltPad1 uint16 = 0x0011
   234  	pinPadMapSERCOM1AltPad1 uint16 = 0x0021
   235  	pinPadMapSERCOM2AltPad1 uint16 = 0x0031
   236  	pinPadMapSERCOM3AltPad1 uint16 = 0x0041
   237  	pinPadMapSERCOM4AltPad1 uint16 = 0x0051
   238  	pinPadMapSERCOM5AltPad1 uint16 = 0x0061
   239  	pinPadMapSERCOM6AltPad1 uint16 = 0x0071
   240  	pinPadMapSERCOM7AltPad1 uint16 = 0x0081
   241  	pinPadMapSERCOM0AltPad2 uint16 = 0x0012
   242  	pinPadMapSERCOM1AltPad2 uint16 = 0x0022
   243  	pinPadMapSERCOM2AltPad2 uint16 = 0x0032
   244  	pinPadMapSERCOM3AltPad2 uint16 = 0x0042
   245  	pinPadMapSERCOM4AltPad2 uint16 = 0x0052
   246  	pinPadMapSERCOM5AltPad2 uint16 = 0x0062
   247  	pinPadMapSERCOM6AltPad2 uint16 = 0x0072
   248  	pinPadMapSERCOM7AltPad2 uint16 = 0x0082
   249  )
   250  
   251  // pinPadMapping lists which pins have which SERCOMs attached to them.
   252  // The encoding is rather dense, with each uint16 encoding two pins and both
   253  // SERCOM and SERCOM-ALT.
   254  //
   255  // Observations:
   256  //   - There are eight SERCOMs. Those SERCOM numbers can be encoded in 4 bits.
   257  //   - Even pad numbers are usually on even pins, and odd pad numbers are usually
   258  //     on odd pins. The exception is SERCOM-ALT, which sometimes swaps pad 0 and 1.
   259  //     With that, there is still an invariant that the pad number for an odd pin is
   260  //     the pad number for the corresponding even pin with the low bit toggled.
   261  //   - Pin pads come in pairs. If PA00 has pad 0, then PA01 has pad 1.
   262  //
   263  // With this information, we can encode SERCOM pin/pad numbers much more
   264  // efficiently. Due to pads coming in pairs, we can ignore half the pins: the
   265  // information for an odd pin can be calculated easily from the preceding even
   266  // pin.
   267  //
   268  // Each word below is split in two bytes. The 8 high bytes are for SERCOM and
   269  // the 8 low bits are for SERCOM-ALT. Of each byte, the 4 high bits encode the
   270  // SERCOM + 1 while the two low bits encodes the pad number (the pad number for
   271  // the odd pin can be trivially calculated by toggling the low bit of the pad
   272  // number). It encodes SERCOM + 1 instead of just the SERCOM number, to make it
   273  // easy to check whether a nibble is set at all.
   274  //
   275  // Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/60001507E.pdf
   276  var pinPadMapping = [64]uint16{
   277  	// page 32
   278  	PA00 / 2: 0 | pinPadMapSERCOM1AltPad0,
   279  
   280  	// page 33
   281  	PB08 / 2: 0 | pinPadMapSERCOM4AltPad0,
   282  	PA04 / 2: 0 | pinPadMapSERCOM0AltPad0,
   283  	PA06 / 2: 0 | pinPadMapSERCOM0AltPad2,
   284  	PC04 / 2: pinPadMapSERCOM6Pad0 | 0,
   285  	PC06 / 2: pinPadMapSERCOM6Pad2 | 0,
   286  	PA08 / 2: pinPadMapSERCOM0Pad0 | pinPadMapSERCOM2AltPad1,
   287  	PA10 / 2: pinPadMapSERCOM0Pad2 | pinPadMapSERCOM2AltPad2,
   288  	PB10 / 2: 0 | pinPadMapSERCOM4AltPad2,
   289  	PB12 / 2: pinPadMapSERCOM4Pad0 | 0,
   290  	PB14 / 2: pinPadMapSERCOM4Pad2 | 0,
   291  	PD08 / 2: pinPadMapSERCOM7Pad0 | pinPadMapSERCOM6AltPad1,
   292  	PD10 / 2: pinPadMapSERCOM7Pad2 | pinPadMapSERCOM6AltPad2,
   293  	PC10 / 2: pinPadMapSERCOM6Pad2 | pinPadMapSERCOM7AltPad2,
   294  
   295  	// page 34
   296  	PC12 / 2: pinPadMapSERCOM7Pad0 | pinPadMapSERCOM6AltPad1,
   297  	PC14 / 2: pinPadMapSERCOM7Pad2 | pinPadMapSERCOM6AltPad2,
   298  	PA12 / 2: pinPadMapSERCOM2Pad0 | pinPadMapSERCOM4AltPad1,
   299  	PA14 / 2: pinPadMapSERCOM2Pad2 | pinPadMapSERCOM4AltPad2,
   300  	PA16 / 2: pinPadMapSERCOM1Pad0 | pinPadMapSERCOM3AltPad1,
   301  	PA18 / 2: pinPadMapSERCOM1Pad2 | pinPadMapSERCOM3AltPad2,
   302  	PC16 / 2: pinPadMapSERCOM6Pad0 | pinPadMapSERCOM0AltPad1,
   303  	PC18 / 2: pinPadMapSERCOM6Pad2 | pinPadMapSERCOM0AltPad2,
   304  	PC22 / 2: pinPadMapSERCOM1Pad0 | pinPadMapSERCOM3AltPad1,
   305  	PD20 / 2: pinPadMapSERCOM1Pad2 | pinPadMapSERCOM3AltPad2,
   306  	PB16 / 2: pinPadMapSERCOM5Pad0 | 0,
   307  	PB18 / 2: pinPadMapSERCOM5Pad2 | pinPadMapSERCOM7AltPad2,
   308  
   309  	// page 35
   310  	PB20 / 2: pinPadMapSERCOM3Pad0 | pinPadMapSERCOM7AltPad1,
   311  	PA20 / 2: pinPadMapSERCOM5Pad2 | pinPadMapSERCOM3AltPad2,
   312  	PA22 / 2: pinPadMapSERCOM3Pad0 | pinPadMapSERCOM5AltPad1,
   313  	PA24 / 2: pinPadMapSERCOM3Pad2 | pinPadMapSERCOM5AltPad2,
   314  	PB22 / 2: pinPadMapSERCOM1Pad2 | pinPadMapSERCOM5AltPad2,
   315  	PB24 / 2: pinPadMapSERCOM0Pad0 | pinPadMapSERCOM2AltPad1,
   316  	PB26 / 2: pinPadMapSERCOM2Pad0 | pinPadMapSERCOM4AltPad1,
   317  	PB28 / 2: pinPadMapSERCOM2Pad2 | pinPadMapSERCOM4AltPad2,
   318  	PC24 / 2: pinPadMapSERCOM0Pad2 | pinPadMapSERCOM2AltPad2,
   319  	//PC26 / 2: pinPadMapSERCOM1Pad1 | 0, // note: PC26 doesn't support SERCOM, but PC27 does
   320  	//PC28 / 2: pinPadMapSERCOM1Pad1 | 0, // note: PC29 doesn't exist in the datasheet?
   321  	PA30 / 2: 0 | pinPadMapSERCOM1AltPad2,
   322  
   323  	// page 36
   324  	PB30 / 2: 0 | pinPadMapSERCOM5AltPad1,
   325  	PB00 / 2: 0 | pinPadMapSERCOM5AltPad2,
   326  	PB02 / 2: 0 | pinPadMapSERCOM5AltPad0,
   327  }
   328  
   329  // findPinPadMapping looks up the pad number and the pinmode for a given pin and
   330  // SERCOM number. The result can either be SERCOM, SERCOM-ALT, or "not found"
   331  // (indicated by returning ok=false). The pad number is returned to calculate
   332  // the DOPO/DIPO bitfields of the various serial peripherals.
   333  func findPinPadMapping(sercom uint8, pin Pin) (pinMode PinMode, pad uint32, ok bool) {
   334  	if int(pin)/2 >= len(pinPadMapping) {
   335  		// This is probably NoPin, for which no mapping is available.
   336  		return
   337  	}
   338  
   339  	bytes := pinPadMapping[pin/2]
   340  	upper := byte(bytes >> 8)
   341  	lower := byte(bytes & 0xff)
   342  
   343  	if upper != 0 {
   344  		// SERCOM
   345  		if (upper>>4)-1 == sercom {
   346  			pinMode = PinSERCOM
   347  			pad |= uint32(upper % 4)
   348  			ok = true
   349  		}
   350  	}
   351  	if lower != 0 {
   352  		// SERCOM-ALT
   353  		if (lower>>4)-1 == sercom {
   354  			pinMode = PinSERCOMAlt
   355  			pad |= uint32(lower % 4)
   356  			ok = true
   357  		}
   358  	}
   359  
   360  	if ok {
   361  		// If the pin is uneven, toggle the lowest bit of the pad number.
   362  		if pin&1 != 0 {
   363  			pad ^= 1
   364  		}
   365  	}
   366  	return
   367  }
   368  
   369  // SetInterrupt sets an interrupt to be executed when a particular pin changes
   370  // state. The pin should already be configured as an input, including a pull up
   371  // or down if no external pull is provided.
   372  //
   373  // This call will replace a previously set callback on this pin. You can pass a
   374  // nil func to unset the pin change interrupt. If you do so, the change
   375  // parameter is ignored and can be set to any value (such as 0).
   376  func (p Pin) SetInterrupt(change PinChange, callback func(Pin)) error {
   377  	// Most pins follow a common pattern where the EXTINT value is the pin
   378  	// number modulo 16. However, there are a few exceptions, as you can see
   379  	// below.
   380  	extint := uint8(0)
   381  
   382  	switch p {
   383  	case PA08:
   384  		// Connected to NMI. This is not currently supported.
   385  		return ErrInvalidInputPin
   386  	case PB26:
   387  		extint = 12
   388  	case PB27:
   389  		extint = 13
   390  	case PB28:
   391  		extint = 14
   392  	case PB29:
   393  		extint = 15
   394  	case PC07:
   395  		extint = 9
   396  	case PD08:
   397  		extint = 3
   398  	case PD09:
   399  		extint = 4
   400  	case PD10:
   401  		extint = 5
   402  	case PD11:
   403  		extint = 6
   404  	case PD12:
   405  		extint = 7
   406  	case PD20:
   407  		extint = 10
   408  	case PD21:
   409  		extint = 11
   410  	default:
   411  		// All other pins follow a normal pattern.
   412  		extint = uint8(p) % 16
   413  	}
   414  
   415  	if callback == nil {
   416  		// Disable this pin interrupt (if it was enabled).
   417  		sam.EIC.INTENCLR.Set(1 << extint)
   418  		if pinCallbacks[extint] != nil {
   419  			pinCallbacks[extint] = nil
   420  		}
   421  		return nil
   422  	}
   423  
   424  	if pinCallbacks[extint] != nil {
   425  		// The pin was already configured.
   426  		// To properly re-configure a pin, unset it first and set a new
   427  		// configuration.
   428  		return ErrNoPinChangeChannel
   429  	}
   430  	pinCallbacks[extint] = callback
   431  	interruptPins[extint] = p
   432  
   433  	if !sam.EIC.CTRLA.HasBits(sam.EIC_CTRLA_ENABLE) {
   434  		// EIC peripheral has not yet been initialized. Initialize it now.
   435  
   436  		// The EIC needs two clocks: CLK_EIC_APB and GCLK_EIC. CLK_EIC_APB is
   437  		// enabled by default, so doesn't have to be re-enabled. The other is
   438  		// required for detecting edges and must be enabled manually.
   439  		sam.GCLK.PCHCTRL[4].Set((sam.GCLK_PCHCTRL_GEN_GCLK0 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)
   440  
   441  		// should not be necessary (CLKCTRL is not synchronized)
   442  		for sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK0 << sam.GCLK_SYNCBUSY_GENCTRL_Pos) {
   443  		}
   444  	}
   445  
   446  	// CONFIG register is enable-protected, so disable EIC.
   447  	sam.EIC.CTRLA.ClearBits(sam.EIC_CTRLA_ENABLE)
   448  
   449  	// Configure this pin. Set the 4 bits of the EIC.CONFIGx register to the
   450  	// sense value (filter bit set to 0, sense bits set to the change value).
   451  	addr := &sam.EIC.CONFIG[0]
   452  	if extint >= 8 {
   453  		addr = &sam.EIC.CONFIG[1]
   454  	}
   455  	pos := (extint % 8) * 4 // bit position in register
   456  	addr.ReplaceBits(uint32(change), 0xf, pos)
   457  
   458  	// Enable external interrupt for this pin.
   459  	sam.EIC.INTENSET.Set(1 << extint)
   460  
   461  	sam.EIC.CTRLA.Set(sam.EIC_CTRLA_ENABLE)
   462  	for sam.EIC.SYNCBUSY.HasBits(sam.EIC_SYNCBUSY_ENABLE) {
   463  	}
   464  
   465  	// Set the PMUXEN flag, while keeping the INEN and PULLEN flags (if they
   466  	// were set before). This avoids clearing the pin pull mode while
   467  	// configuring the pin interrupt.
   468  	p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | (p.getPinCfg() & (sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)))
   469  	if p&1 > 0 {
   470  		// odd pin, so save the even pins
   471  		val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
   472  		p.setPMux(val | (0 << sam.PORT_GROUP_PMUX_PMUXO_Pos))
   473  	} else {
   474  		// even pin, so save the odd pins
   475  		val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
   476  		p.setPMux(val | (0 << sam.PORT_GROUP_PMUX_PMUXE_Pos))
   477  	}
   478  
   479  	handleEICInterrupt := func(interrupt.Interrupt) {
   480  		flags := sam.EIC.INTFLAG.Get()
   481  		sam.EIC.INTFLAG.Set(flags)      // clear interrupt
   482  		for i := uint(0); i < 16; i++ { // there are 16 channels
   483  			if flags&(1<<i) != 0 {
   484  				pinCallbacks[i](interruptPins[i])
   485  			}
   486  		}
   487  	}
   488  	switch extint {
   489  	case 0:
   490  		interrupt.New(sam.IRQ_EIC_EXTINT_0, handleEICInterrupt).Enable()
   491  	case 1:
   492  		interrupt.New(sam.IRQ_EIC_EXTINT_1, handleEICInterrupt).Enable()
   493  	case 2:
   494  		interrupt.New(sam.IRQ_EIC_EXTINT_2, handleEICInterrupt).Enable()
   495  	case 3:
   496  		interrupt.New(sam.IRQ_EIC_EXTINT_3, handleEICInterrupt).Enable()
   497  	case 4:
   498  		interrupt.New(sam.IRQ_EIC_EXTINT_4, handleEICInterrupt).Enable()
   499  	case 5:
   500  		interrupt.New(sam.IRQ_EIC_EXTINT_5, handleEICInterrupt).Enable()
   501  	case 6:
   502  		interrupt.New(sam.IRQ_EIC_EXTINT_6, handleEICInterrupt).Enable()
   503  	case 7:
   504  		interrupt.New(sam.IRQ_EIC_EXTINT_7, handleEICInterrupt).Enable()
   505  	case 8:
   506  		interrupt.New(sam.IRQ_EIC_EXTINT_8, handleEICInterrupt).Enable()
   507  	case 9:
   508  		interrupt.New(sam.IRQ_EIC_EXTINT_9, handleEICInterrupt).Enable()
   509  	case 10:
   510  		interrupt.New(sam.IRQ_EIC_EXTINT_10, handleEICInterrupt).Enable()
   511  	case 11:
   512  		interrupt.New(sam.IRQ_EIC_EXTINT_11, handleEICInterrupt).Enable()
   513  	case 12:
   514  		interrupt.New(sam.IRQ_EIC_EXTINT_12, handleEICInterrupt).Enable()
   515  	case 13:
   516  		interrupt.New(sam.IRQ_EIC_EXTINT_13, handleEICInterrupt).Enable()
   517  	case 14:
   518  		interrupt.New(sam.IRQ_EIC_EXTINT_14, handleEICInterrupt).Enable()
   519  	case 15:
   520  		interrupt.New(sam.IRQ_EIC_EXTINT_15, handleEICInterrupt).Enable()
   521  	}
   522  
   523  	return nil
   524  }
   525  
   526  // Return the register and mask to enable a given GPIO pin. This can be used to
   527  // implement bit-banged drivers.
   528  func (p Pin) PortMaskSet() (*uint32, uint32) {
   529  	group, pin_in_group := p.getPinGrouping()
   530  	return &sam.PORT.GROUP[group].OUTSET.Reg, 1 << pin_in_group
   531  }
   532  
   533  // Return the register and mask to disable a given port. This can be used to
   534  // implement bit-banged drivers.
   535  func (p Pin) PortMaskClear() (*uint32, uint32) {
   536  	group, pin_in_group := p.getPinGrouping()
   537  	return &sam.PORT.GROUP[group].OUTCLR.Reg, 1 << pin_in_group
   538  }
   539  
   540  // Set the pin to high or low.
   541  // Warning: only use this on an output pin!
   542  func (p Pin) Set(high bool) {
   543  	group, pin_in_group := p.getPinGrouping()
   544  	if high {
   545  		sam.PORT.GROUP[group].OUTSET.Set(1 << pin_in_group)
   546  	} else {
   547  		sam.PORT.GROUP[group].OUTCLR.Set(1 << pin_in_group)
   548  	}
   549  }
   550  
   551  // Get returns the current value of a GPIO pin when configured as an input or as
   552  // an output.
   553  func (p Pin) Get() bool {
   554  	group, pin_in_group := p.getPinGrouping()
   555  	return (sam.PORT.GROUP[group].IN.Get()>>pin_in_group)&1 > 0
   556  }
   557  
   558  // Toggle switches an output pin from low to high or from high to low.
   559  // Warning: only use this on an output pin!
   560  func (p Pin) Toggle() {
   561  	group, pin_in_group := p.getPinGrouping()
   562  	sam.PORT.GROUP[group].OUTTGL.Set(1 << pin_in_group)
   563  }
   564  
   565  // Configure this pin with the given configuration.
   566  func (p Pin) Configure(config PinConfig) {
   567  	group, pin_in_group := p.getPinGrouping()
   568  	switch config.Mode {
   569  	case PinOutput:
   570  		sam.PORT.GROUP[group].DIRSET.Set(1 << pin_in_group)
   571  		// output is also set to input enable so pin can read back its own value
   572  		p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN)
   573  
   574  	case PinInput:
   575  		sam.PORT.GROUP[group].DIRCLR.Set(1 << pin_in_group)
   576  		p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN)
   577  
   578  	case PinInputPulldown:
   579  		sam.PORT.GROUP[group].DIRCLR.Set(1 << pin_in_group)
   580  		sam.PORT.GROUP[group].OUTCLR.Set(1 << pin_in_group)
   581  		p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)
   582  
   583  	case PinInputPullup:
   584  		sam.PORT.GROUP[group].DIRCLR.Set(1 << pin_in_group)
   585  		sam.PORT.GROUP[group].OUTSET.Set(1 << pin_in_group)
   586  		p.setPinCfg(sam.PORT_GROUP_PINCFG_INEN | sam.PORT_GROUP_PINCFG_PULLEN)
   587  
   588  	case PinSERCOM:
   589  		if p&1 > 0 {
   590  			// odd pin, so save the even pins
   591  			val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
   592  			p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
   593  		} else {
   594  			// even pin, so save the odd pins
   595  			val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
   596  			p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
   597  		}
   598  		// enable port config
   599  		p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR | sam.PORT_GROUP_PINCFG_INEN)
   600  
   601  	case PinSERCOMAlt:
   602  		if p&1 > 0 {
   603  			// odd pin, so save the even pins
   604  			val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
   605  			p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
   606  		} else {
   607  			// even pin, so save the odd pins
   608  			val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
   609  			p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
   610  		}
   611  		// enable port config
   612  		p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)
   613  
   614  	case PinCom:
   615  		if p&1 > 0 {
   616  			// odd pin, so save the even pins
   617  			val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
   618  			p.setPMux(val | (uint8(PinCom) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
   619  		} else {
   620  			// even pin, so save the odd pins
   621  			val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
   622  			p.setPMux(val | (uint8(PinCom) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
   623  		}
   624  		// enable port config
   625  		p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)
   626  	case PinAnalog:
   627  		if p&1 > 0 {
   628  			// odd pin, so save the even pins
   629  			val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
   630  			p.setPMux(val | (uint8(PinAnalog) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
   631  		} else {
   632  			// even pin, so save the odd pins
   633  			val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
   634  			p.setPMux(val | (uint8(PinAnalog) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
   635  		}
   636  		// enable port config
   637  		p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN | sam.PORT_GROUP_PINCFG_DRVSTR)
   638  	case PinSDHC:
   639  		if p&1 > 0 {
   640  			// odd pin, so save the even pins
   641  			val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
   642  			p.setPMux(val | (uint8(PinSDHC) << sam.PORT_GROUP_PMUX_PMUXO_Pos))
   643  		} else {
   644  			// even pin, so save the odd pins
   645  			val := p.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
   646  			p.setPMux(val | (uint8(PinSDHC) << sam.PORT_GROUP_PMUX_PMUXE_Pos))
   647  		}
   648  		// enable port config
   649  		p.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)
   650  	}
   651  }
   652  
   653  // getPMux returns the value for the correct PMUX register for this pin.
   654  func (p Pin) getPMux() uint8 {
   655  	group, pin_in_group := p.getPinGrouping()
   656  	return sam.PORT.GROUP[group].PMUX[pin_in_group>>1].Get()
   657  }
   658  
   659  // setPMux sets the value for the correct PMUX register for this pin.
   660  func (p Pin) setPMux(val uint8) {
   661  	group, pin_in_group := p.getPinGrouping()
   662  	sam.PORT.GROUP[group].PMUX[pin_in_group>>1].Set(val)
   663  }
   664  
   665  // getPinCfg returns the value for the correct PINCFG register for this pin.
   666  func (p Pin) getPinCfg() uint8 {
   667  	group, pin_in_group := p.getPinGrouping()
   668  	return sam.PORT.GROUP[group].PINCFG[pin_in_group].Get()
   669  }
   670  
   671  // setPinCfg sets the value for the correct PINCFG register for this pin.
   672  func (p Pin) setPinCfg(val uint8) {
   673  	group, pin_in_group := p.getPinGrouping()
   674  	sam.PORT.GROUP[group].PINCFG[pin_in_group].Set(val)
   675  }
   676  
   677  // getPinGrouping calculates the gpio group and pin id from the pin number.
   678  // Pins are split into groups of 32, and each group has its own set of
   679  // control registers.
   680  func (p Pin) getPinGrouping() (uint8, uint8) {
   681  	group := uint8(p) >> 5
   682  	pin_in_group := uint8(p) & 0x1f
   683  	return group, pin_in_group
   684  }
   685  
   686  // InitADC initializes the ADC.
   687  func InitADC() {
   688  	// ADC Bias Calibration
   689  	// NVMCTRL_SW0 0x00800080
   690  	// #define ADC0_FUSES_BIASCOMP_ADDR    NVMCTRL_SW0
   691  	// #define ADC0_FUSES_BIASCOMP_Pos     2            /**< \brief (NVMCTRL_SW0) ADC Comparator Scaling */
   692  	// #define ADC0_FUSES_BIASCOMP_Msk     (_Ul(0x7) << ADC0_FUSES_BIASCOMP_Pos)
   693  	// #define ADC0_FUSES_BIASCOMP(value)  (ADC0_FUSES_BIASCOMP_Msk & ((value) << ADC0_FUSES_BIASCOMP_Pos))
   694  
   695  	// #define ADC0_FUSES_BIASR2R_ADDR     NVMCTRL_SW0
   696  	// #define ADC0_FUSES_BIASR2R_Pos      8            /**< \brief (NVMCTRL_SW0) ADC Bias R2R ampli scaling */
   697  	// #define ADC0_FUSES_BIASR2R_Msk      (_Ul(0x7) << ADC0_FUSES_BIASR2R_Pos)
   698  	// #define ADC0_FUSES_BIASR2R(value)   (ADC0_FUSES_BIASR2R_Msk & ((value) << ADC0_FUSES_BIASR2R_Pos))
   699  
   700  	// #define ADC0_FUSES_BIASREFBUF_ADDR  NVMCTRL_SW0
   701  	// #define ADC0_FUSES_BIASREFBUF_Pos   5            /**< \brief (NVMCTRL_SW0) ADC Bias Reference Buffer Scaling */
   702  	// #define ADC0_FUSES_BIASREFBUF_Msk   (_Ul(0x7) << ADC0_FUSES_BIASREFBUF_Pos)
   703  	// #define ADC0_FUSES_BIASREFBUF(value) (ADC0_FUSES_BIASREFBUF_Msk & ((value) << ADC0_FUSES_BIASREFBUF_Pos))
   704  
   705  	// #define ADC1_FUSES_BIASCOMP_ADDR    NVMCTRL_SW0
   706  	// #define ADC1_FUSES_BIASCOMP_Pos     16           /**< \brief (NVMCTRL_SW0) ADC Comparator Scaling */
   707  	// #define ADC1_FUSES_BIASCOMP_Msk     (_Ul(0x7) << ADC1_FUSES_BIASCOMP_Pos)
   708  	// #define ADC1_FUSES_BIASCOMP(value)  (ADC1_FUSES_BIASCOMP_Msk & ((value) << ADC1_FUSES_BIASCOMP_Pos))
   709  
   710  	// #define ADC1_FUSES_BIASR2R_ADDR     NVMCTRL_SW0
   711  	// #define ADC1_FUSES_BIASR2R_Pos      22           /**< \brief (NVMCTRL_SW0) ADC Bias R2R ampli scaling */
   712  	// #define ADC1_FUSES_BIASR2R_Msk      (_Ul(0x7) << ADC1_FUSES_BIASR2R_Pos)
   713  	// #define ADC1_FUSES_BIASR2R(value)   (ADC1_FUSES_BIASR2R_Msk & ((value) << ADC1_FUSES_BIASR2R_Pos))
   714  
   715  	// #define ADC1_FUSES_BIASREFBUF_ADDR  NVMCTRL_SW0
   716  	// #define ADC1_FUSES_BIASREFBUF_Pos   19           /**< \brief (NVMCTRL_SW0) ADC Bias Reference Buffer Scaling */
   717  	// #define ADC1_FUSES_BIASREFBUF_Msk   (_Ul(0x7) << ADC1_FUSES_BIASREFBUF_Pos)
   718  	// #define ADC1_FUSES_BIASREFBUF(value) (ADC1_FUSES_BIASREFBUF_Msk & ((value) << ADC1_FUSES_BIASREFBUF_Pos))
   719  
   720  	adcFuse := *(*uint32)(unsafe.Pointer(uintptr(0x00800080)))
   721  
   722  	// uint32_t biascomp = (*((uint32_t *)ADC0_FUSES_BIASCOMP_ADDR) & ADC0_FUSES_BIASCOMP_Msk) >> ADC0_FUSES_BIASCOMP_Pos;
   723  	biascomp := (adcFuse & uint32(0x7<<2)) //>> 2
   724  
   725  	// uint32_t biasr2r = (*((uint32_t *)ADC0_FUSES_BIASR2R_ADDR) & ADC0_FUSES_BIASR2R_Msk) >> ADC0_FUSES_BIASR2R_Pos;
   726  	biasr2r := (adcFuse & uint32(0x7<<8)) //>> 8
   727  
   728  	// uint32_t biasref = (*((uint32_t *)ADC0_FUSES_BIASREFBUF_ADDR) & ADC0_FUSES_BIASREFBUF_Msk) >> ADC0_FUSES_BIASREFBUF_Pos;
   729  	biasref := (adcFuse & uint32(0x7<<5)) //>> 5
   730  
   731  	// calibrate ADC0
   732  	sam.ADC0.CALIB.Set(uint16(biascomp | biasr2r | biasref))
   733  
   734  	// biascomp = (*((uint32_t *)ADC1_FUSES_BIASCOMP_ADDR) & ADC1_FUSES_BIASCOMP_Msk) >> ADC1_FUSES_BIASCOMP_Pos;
   735  	biascomp = (adcFuse & uint32(0x7<<16)) //>> 16
   736  
   737  	// biasr2r = (*((uint32_t *)ADC1_FUSES_BIASR2R_ADDR) & ADC1_FUSES_BIASR2R_Msk) >> ADC1_FUSES_BIASR2R_Pos;
   738  	biasr2r = (adcFuse & uint32(0x7<<22)) //>> 22
   739  
   740  	// biasref = (*((uint32_t *)ADC1_FUSES_BIASREFBUF_ADDR) & ADC1_FUSES_BIASREFBUF_Msk) >> ADC1_FUSES_BIASREFBUF_Pos;
   741  	biasref = (adcFuse & uint32(0x7<<19)) //>> 19
   742  
   743  	// calibrate ADC1
   744  	sam.ADC1.CALIB.Set(uint16((biascomp | biasr2r | biasref) >> 16))
   745  }
   746  
   747  // Configure configures a ADCPin to be able to be used to read data.
   748  func (a ADC) Configure(config ADCConfig) {
   749  
   750  	for _, adc := range []*sam.ADC_Type{sam.ADC0, sam.ADC1} {
   751  
   752  		for adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_CTRLB) {
   753  		} // wait for sync
   754  
   755  		// Averaging (see datasheet table in AVGCTRL register description)
   756  		var resolution uint32 = sam.ADC_CTRLB_RESSEL_16BIT
   757  		var samples uint32
   758  		switch config.Samples {
   759  		case 2:
   760  			samples = sam.ADC_AVGCTRL_SAMPLENUM_2
   761  		case 4:
   762  			samples = sam.ADC_AVGCTRL_SAMPLENUM_4
   763  		case 8:
   764  			samples = sam.ADC_AVGCTRL_SAMPLENUM_8
   765  		case 16:
   766  			samples = sam.ADC_AVGCTRL_SAMPLENUM_16
   767  		case 32:
   768  			samples = sam.ADC_AVGCTRL_SAMPLENUM_32
   769  		case 64:
   770  			samples = sam.ADC_AVGCTRL_SAMPLENUM_64
   771  		case 128:
   772  			samples = sam.ADC_AVGCTRL_SAMPLENUM_128
   773  		case 256:
   774  			samples = sam.ADC_AVGCTRL_SAMPLENUM_256
   775  		case 512:
   776  			samples = sam.ADC_AVGCTRL_SAMPLENUM_512
   777  		case 1024:
   778  			samples = sam.ADC_AVGCTRL_SAMPLENUM_1024
   779  		default: // 1 sample only (no oversampling nor averaging), adjusting result by 0
   780  			// Resolutions less than 16 bits only make sense when sampling only
   781  			// once. Resulting ADC values become erratic when using both
   782  			// multi-sampling and less than 16 bits of resolution.
   783  			samples = sam.ADC_AVGCTRL_SAMPLENUM_1
   784  			switch config.Resolution {
   785  			case 8:
   786  				resolution = sam.ADC_CTRLB_RESSEL_8BIT
   787  			case 10:
   788  				resolution = sam.ADC_CTRLB_RESSEL_10BIT
   789  			case 12:
   790  				resolution = sam.ADC_CTRLB_RESSEL_12BIT
   791  			case 16:
   792  				resolution = sam.ADC_CTRLB_RESSEL_16BIT
   793  			default:
   794  				resolution = sam.ADC_CTRLB_RESSEL_12BIT
   795  			}
   796  		}
   797  
   798  		adc.AVGCTRL.Set(uint8(samples<<sam.ADC_AVGCTRL_SAMPLENUM_Pos) |
   799  			(0 << sam.ADC_AVGCTRL_ADJRES_Pos))
   800  
   801  		adc.CTRLA.SetBits(sam.ADC_CTRLA_PRESCALER_DIV32 << sam.ADC_CTRLA_PRESCALER_Pos)
   802  		adc.CTRLB.SetBits(uint16(resolution << sam.ADC_CTRLB_RESSEL_Pos))
   803  		adc.SAMPCTRL.Set(5) // sampling Time Length
   804  
   805  		for adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_SAMPCTRL) {
   806  		} // wait for sync
   807  
   808  		// No Negative input (Internal Ground)
   809  		adc.INPUTCTRL.Set(sam.ADC_INPUTCTRL_MUXNEG_GND << sam.ADC_INPUTCTRL_MUXNEG_Pos)
   810  		for adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_INPUTCTRL) {
   811  		} // wait for sync
   812  
   813  		for adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_AVGCTRL) {
   814  		} // wait for sync
   815  		for adc.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_REFCTRL) {
   816  		} // wait for sync
   817  
   818  		// TODO: use config.Reference to set AREF level
   819  
   820  		// default is 3V3 reference voltage
   821  		adc.REFCTRL.SetBits(sam.ADC_REFCTRL_REFSEL_INTVCC1)
   822  	}
   823  
   824  	a.Pin.Configure(PinConfig{Mode: PinAnalog})
   825  }
   826  
   827  // Get returns the current value of a ADC pin, in the range 0..0xffff.
   828  func (a ADC) Get() uint16 {
   829  	bus := a.getADCBus()
   830  	ch := a.getADCChannel()
   831  
   832  	for bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_INPUTCTRL) {
   833  	}
   834  
   835  	// Selection for the positive ADC input channel
   836  	bus.INPUTCTRL.ClearBits(sam.ADC_INPUTCTRL_MUXPOS_Msk)
   837  	for bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {
   838  	}
   839  	bus.INPUTCTRL.SetBits((uint16(ch) & sam.ADC_INPUTCTRL_MUXPOS_Msk) << sam.ADC_INPUTCTRL_MUXPOS_Pos)
   840  	for bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {
   841  	}
   842  
   843  	// Enable ADC
   844  	bus.CTRLA.SetBits(sam.ADC_CTRLA_ENABLE)
   845  	for bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {
   846  	}
   847  
   848  	// Start conversion
   849  	bus.SWTRIG.SetBits(sam.ADC_SWTRIG_START)
   850  	for !bus.INTFLAG.HasBits(sam.ADC_INTFLAG_RESRDY) {
   851  	}
   852  
   853  	// Clear the Data Ready flag
   854  	bus.INTFLAG.ClearBits(sam.ADC_INTFLAG_RESRDY)
   855  	for bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {
   856  	}
   857  
   858  	// Start conversion again, since first conversion after reference voltage changed is invalid.
   859  	bus.SWTRIG.SetBits(sam.ADC_SWTRIG_START)
   860  
   861  	// Waiting for conversion to complete
   862  	for !bus.INTFLAG.HasBits(sam.ADC_INTFLAG_RESRDY) {
   863  	}
   864  	val := bus.RESULT.Get()
   865  
   866  	// Disable ADC
   867  	for bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {
   868  	}
   869  	bus.CTRLA.ClearBits(sam.ADC_CTRLA_ENABLE)
   870  	for bus.SYNCBUSY.HasBits(sam.ADC_SYNCBUSY_ENABLE) {
   871  	}
   872  
   873  	// scales to 16-bit result
   874  	switch (bus.CTRLB.Get() & sam.ADC_CTRLB_RESSEL_Msk) >> sam.ADC_CTRLB_RESSEL_Pos {
   875  	case sam.ADC_CTRLB_RESSEL_8BIT:
   876  		val = val << 8
   877  	case sam.ADC_CTRLB_RESSEL_10BIT:
   878  		val = val << 6
   879  	case sam.ADC_CTRLB_RESSEL_12BIT:
   880  		val = val << 4
   881  	case sam.ADC_CTRLB_RESSEL_16BIT:
   882  		// Adjust for multiple samples. This is only configured when the
   883  		// resolution is 16 bits.
   884  		switch (bus.AVGCTRL.Get() & sam.ADC_AVGCTRL_SAMPLENUM_Msk) >> sam.ADC_AVGCTRL_SAMPLENUM_Pos {
   885  		case sam.ADC_AVGCTRL_SAMPLENUM_1:
   886  			val <<= 4
   887  		case sam.ADC_AVGCTRL_SAMPLENUM_2:
   888  			val <<= 3
   889  		case sam.ADC_AVGCTRL_SAMPLENUM_4:
   890  			val <<= 2
   891  		case sam.ADC_AVGCTRL_SAMPLENUM_8:
   892  			val <<= 1
   893  		default:
   894  			// These values are all shifted by the hardware so they fit exactly
   895  			// in a 16-bit integer, so they don't need to be shifted here.
   896  		}
   897  	}
   898  	return val
   899  }
   900  
   901  func (a ADC) getADCBus() *sam.ADC_Type {
   902  	if (a.Pin >= PB04 && a.Pin <= PB07) || (a.Pin >= PC00) {
   903  		return sam.ADC1
   904  	}
   905  	return sam.ADC0
   906  }
   907  
   908  func (a ADC) getADCChannel() uint8 {
   909  	switch a.Pin {
   910  	case PA02:
   911  		return 0
   912  	case PB08:
   913  		return 2
   914  	case PB09:
   915  		return 3
   916  	case PA04:
   917  		return 4
   918  	case PA05:
   919  		return 5
   920  	case PA06:
   921  		return 6
   922  	case PA07:
   923  		return 7
   924  	case PB00:
   925  		return 12
   926  	case PB01:
   927  		return 13
   928  	case PB02:
   929  		return 14
   930  	case PB03:
   931  		return 15
   932  	case PA09:
   933  		return 17
   934  	case PA11:
   935  		return 19
   936  
   937  	case PB04:
   938  		return 6
   939  	case PB05:
   940  		return 7
   941  	case PB06:
   942  		return 8
   943  	case PB07:
   944  		return 9
   945  
   946  	case PC00:
   947  		return 10
   948  	case PC01:
   949  		return 11
   950  	case PC02:
   951  		return 4
   952  	case PC03:
   953  		return 5
   954  	case PC30:
   955  		return 12
   956  	case PC31:
   957  		return 13
   958  
   959  	case PD00:
   960  		return 14
   961  	case PD01:
   962  		return 15
   963  	default:
   964  		panic("Invalid ADC pin")
   965  	}
   966  }
   967  
   968  // UART on the SAMD51.
   969  type UART struct {
   970  	Buffer    *RingBuffer
   971  	Bus       *sam.SERCOM_USART_INT_Type
   972  	SERCOM    uint8
   973  	Interrupt interrupt.Interrupt // RXC interrupt
   974  }
   975  
   976  var (
   977  	sercomUSART0 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM0_USART_INT, SERCOM: 0}
   978  	sercomUSART1 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM1_USART_INT, SERCOM: 1}
   979  	sercomUSART2 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM2_USART_INT, SERCOM: 2}
   980  	sercomUSART3 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM3_USART_INT, SERCOM: 3}
   981  	sercomUSART4 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM4_USART_INT, SERCOM: 4}
   982  	sercomUSART5 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM5_USART_INT, SERCOM: 5}
   983  )
   984  
   985  func init() {
   986  	sercomUSART0.Interrupt = interrupt.New(sam.IRQ_SERCOM0_2, sercomUSART0.handleInterrupt)
   987  	sercomUSART1.Interrupt = interrupt.New(sam.IRQ_SERCOM1_2, sercomUSART1.handleInterrupt)
   988  	sercomUSART2.Interrupt = interrupt.New(sam.IRQ_SERCOM2_2, sercomUSART2.handleInterrupt)
   989  	sercomUSART3.Interrupt = interrupt.New(sam.IRQ_SERCOM3_2, sercomUSART3.handleInterrupt)
   990  	sercomUSART4.Interrupt = interrupt.New(sam.IRQ_SERCOM4_2, sercomUSART4.handleInterrupt)
   991  	sercomUSART5.Interrupt = interrupt.New(sam.IRQ_SERCOM5_2, sercomUSART5.handleInterrupt)
   992  }
   993  
   994  const (
   995  	sampleRate16X = 16
   996  	lsbFirst      = 1
   997  )
   998  
   999  // Configure the UART.
  1000  func (uart *UART) Configure(config UARTConfig) error {
  1001  	// Default baud rate to 115200.
  1002  	if config.BaudRate == 0 {
  1003  		config.BaudRate = 115200
  1004  	}
  1005  
  1006  	// determine pins
  1007  	if config.TX == 0 && config.RX == 0 {
  1008  		// use default pins
  1009  		config.TX = UART_TX_PIN
  1010  		config.RX = UART_RX_PIN
  1011  	}
  1012  
  1013  	// Determine transmit pinout.
  1014  	txPinMode, txPad, ok := findPinPadMapping(uart.SERCOM, config.TX)
  1015  	if !ok {
  1016  		return ErrInvalidOutputPin
  1017  	}
  1018  	var txPadOut uint32
  1019  	// See CTRLA.RXPO bits of the SERCOM USART peripheral (page 945-946) for how
  1020  	// pads are mapped to pinout values.
  1021  	switch txPad {
  1022  	case 0:
  1023  		txPadOut = 0
  1024  	default:
  1025  		// should be flow control (RTS/CTS) pin
  1026  		return ErrInvalidOutputPin
  1027  	}
  1028  
  1029  	// Determine receive pinout.
  1030  	rxPinMode, rxPad, ok := findPinPadMapping(uart.SERCOM, config.RX)
  1031  	if !ok {
  1032  		return ErrInvalidInputPin
  1033  	}
  1034  	// As you can see in the CTRLA.RXPO bits of the SERCOM USART peripheral
  1035  	// (page 945), input pins are mapped directly.
  1036  	rxPadOut := rxPad
  1037  
  1038  	// configure pins
  1039  	config.TX.Configure(PinConfig{Mode: txPinMode})
  1040  	config.RX.Configure(PinConfig{Mode: rxPinMode})
  1041  
  1042  	// configure RTS/CTS pins if provided
  1043  	if config.RTS != 0 && config.CTS != 0 {
  1044  		rtsPinMode, _, ok := findPinPadMapping(uart.SERCOM, config.RTS)
  1045  		if !ok {
  1046  			return ErrInvalidOutputPin
  1047  		}
  1048  
  1049  		ctsPinMode, _, ok := findPinPadMapping(uart.SERCOM, config.CTS)
  1050  		if !ok {
  1051  			return ErrInvalidInputPin
  1052  		}
  1053  
  1054  		// See CTRLA.RXPO bits of the SERCOM USART peripheral (page 945-946) for how
  1055  		// pads are mapped to pinout values.
  1056  		txPadOut = 2
  1057  
  1058  		config.RTS.Configure(PinConfig{Mode: rtsPinMode})
  1059  		config.CTS.Configure(PinConfig{Mode: ctsPinMode})
  1060  	}
  1061  
  1062  	// reset SERCOM
  1063  	uart.Bus.CTRLA.SetBits(sam.SERCOM_USART_INT_CTRLA_SWRST)
  1064  	for uart.Bus.CTRLA.HasBits(sam.SERCOM_USART_INT_CTRLA_SWRST) ||
  1065  		uart.Bus.SYNCBUSY.HasBits(sam.SERCOM_USART_INT_SYNCBUSY_SWRST) {
  1066  	}
  1067  
  1068  	// set UART mode/sample rate
  1069  	// SERCOM_USART_CTRLA_MODE(mode) |
  1070  	// SERCOM_USART_CTRLA_SAMPR(sampleRate);
  1071  	// sam.SERCOM_USART_CTRLA_MODE_USART_INT_CLK = 1?
  1072  	uart.Bus.CTRLA.Set((1 << sam.SERCOM_USART_INT_CTRLA_MODE_Pos) |
  1073  		(1 << sam.SERCOM_USART_INT_CTRLA_SAMPR_Pos)) // sample rate of 16x
  1074  
  1075  	// set clock
  1076  	setSERCOMClockGenerator(uart.SERCOM, sam.GCLK_PCHCTRL_GEN_GCLK1)
  1077  
  1078  	// Set baud rate
  1079  	uart.SetBaudRate(config.BaudRate)
  1080  
  1081  	// setup UART frame
  1082  	// SERCOM_USART_CTRLA_FORM( (parityMode == SERCOM_NO_PARITY ? 0 : 1) ) |
  1083  	// dataOrder << SERCOM_USART_CTRLA_DORD_Pos;
  1084  	uart.Bus.CTRLA.SetBits((0 << sam.SERCOM_USART_INT_CTRLA_FORM_Pos) | // no parity
  1085  		(lsbFirst << sam.SERCOM_USART_INT_CTRLA_DORD_Pos)) // data order
  1086  
  1087  	// set UART stop bits/parity
  1088  	// SERCOM_USART_CTRLB_CHSIZE(charSize) |
  1089  	// 	nbStopBits << SERCOM_USART_CTRLB_SBMODE_Pos |
  1090  	// 	(parityMode == SERCOM_NO_PARITY ? 0 : parityMode) << SERCOM_USART_CTRLB_PMODE_Pos; //If no parity use default value
  1091  	uart.Bus.CTRLB.SetBits((0 << sam.SERCOM_USART_INT_CTRLB_CHSIZE_Pos) | // 8 bits is 0
  1092  		(0 << sam.SERCOM_USART_INT_CTRLB_SBMODE_Pos) | // 1 stop bit is zero
  1093  		(0 << sam.SERCOM_USART_INT_CTRLB_PMODE_Pos)) // no parity
  1094  
  1095  	// set UART pads. This is not same as pins...
  1096  	//  SERCOM_USART_CTRLA_TXPO(txPad) |
  1097  	//   SERCOM_USART_CTRLA_RXPO(rxPad);
  1098  	uart.Bus.CTRLA.SetBits((txPadOut << sam.SERCOM_USART_INT_CTRLA_TXPO_Pos) |
  1099  		(rxPadOut << sam.SERCOM_USART_INT_CTRLA_RXPO_Pos))
  1100  
  1101  	// Enable Transceiver and Receiver
  1102  	//sercom->USART.CTRLB.reg |= SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_RXEN ;
  1103  	uart.Bus.CTRLB.SetBits(sam.SERCOM_USART_INT_CTRLB_TXEN | sam.SERCOM_USART_INT_CTRLB_RXEN)
  1104  
  1105  	// Enable USART1 port.
  1106  	// sercom->USART.CTRLA.bit.ENABLE = 0x1u;
  1107  	uart.Bus.CTRLA.SetBits(sam.SERCOM_USART_INT_CTRLA_ENABLE)
  1108  	for uart.Bus.SYNCBUSY.HasBits(sam.SERCOM_USART_INT_SYNCBUSY_ENABLE) {
  1109  	}
  1110  
  1111  	// setup interrupt on receive
  1112  	uart.Bus.INTENSET.Set(sam.SERCOM_USART_INT_INTENSET_RXC)
  1113  
  1114  	// Enable RX IRQ.
  1115  	// This is a small note at the bottom of the NVIC section of the datasheet:
  1116  	// > The integer number specified in the source refers to the respective bit
  1117  	// > position in the INTFLAG register of respective peripheral.
  1118  	// Therefore, if we only need to listen to the RXC interrupt source (in bit
  1119  	// position 2), we only need interrupt source 2 for this SERCOM device.
  1120  	uart.Interrupt.Enable()
  1121  
  1122  	return nil
  1123  }
  1124  
  1125  // SetBaudRate sets the communication speed for the UART.
  1126  func (uart *UART) SetBaudRate(br uint32) {
  1127  	// Asynchronous fractional mode (Table 24-2 in datasheet)
  1128  	//   BAUD = fref / (sampleRateValue * fbaud)
  1129  	// (multiply by 8, to calculate fractional piece)
  1130  	// uint32_t baudTimes8 = (SystemCoreClock * 8) / (16 * baudrate);
  1131  	baud := (SERCOM_FREQ_REF * 8) / (sampleRate16X * br)
  1132  
  1133  	// sercom->USART.BAUD.FRAC.FP   = (baudTimes8 % 8);
  1134  	// sercom->USART.BAUD.FRAC.BAUD = (baudTimes8 / 8);
  1135  	uart.Bus.BAUD.Set(uint16(((baud % 8) << sam.SERCOM_USART_INT_BAUD_FRAC_MODE_FP_Pos) |
  1136  		((baud / 8) << sam.SERCOM_USART_INT_BAUD_FRAC_MODE_BAUD_Pos)))
  1137  }
  1138  
  1139  // WriteByte writes a byte of data to the UART.
  1140  func (uart *UART) writeByte(c byte) error {
  1141  	// wait until ready to receive
  1142  	for !uart.Bus.INTFLAG.HasBits(sam.SERCOM_USART_INT_INTFLAG_DRE) {
  1143  	}
  1144  	uart.Bus.DATA.Set(uint32(c))
  1145  	return nil
  1146  }
  1147  
  1148  func (uart *UART) flush() {}
  1149  
  1150  func (uart *UART) handleInterrupt(interrupt.Interrupt) {
  1151  	// should reset IRQ
  1152  	uart.Receive(byte((uart.Bus.DATA.Get() & 0xFF)))
  1153  	uart.Bus.INTFLAG.SetBits(sam.SERCOM_USART_INT_INTFLAG_RXC)
  1154  }
  1155  
  1156  // I2C on the SAMD51.
  1157  type I2C struct {
  1158  	Bus    *sam.SERCOM_I2CM_Type
  1159  	SERCOM uint8
  1160  }
  1161  
  1162  // I2CConfig is used to store config info for I2C.
  1163  type I2CConfig struct {
  1164  	Frequency uint32
  1165  	SCL       Pin
  1166  	SDA       Pin
  1167  }
  1168  
  1169  const (
  1170  	// SERCOM_FREQ_REF is always reference frequency on SAMD51 regardless of CPU speed.
  1171  	SERCOM_FREQ_REF       = 48000000
  1172  	SERCOM_FREQ_REF_GCLK0 = 120000000
  1173  
  1174  	// Default rise time in nanoseconds, based on 4.7K ohm pull up resistors
  1175  	riseTimeNanoseconds = 125
  1176  
  1177  	// wire bus states
  1178  	wireUnknownState = 0
  1179  	wireIdleState    = 1
  1180  	wireOwnerState   = 2
  1181  	wireBusyState    = 3
  1182  
  1183  	// wire commands
  1184  	wireCmdNoAction    = 0
  1185  	wireCmdRepeatStart = 1
  1186  	wireCmdRead        = 2
  1187  	wireCmdStop        = 3
  1188  )
  1189  
  1190  const i2cTimeout = 28000 // about 210us
  1191  
  1192  // Configure is intended to setup the I2C interface.
  1193  func (i2c *I2C) Configure(config I2CConfig) error {
  1194  	// Default I2C bus speed is 100 kHz.
  1195  	if config.Frequency == 0 {
  1196  		config.Frequency = 100 * KHz
  1197  	}
  1198  
  1199  	// Use default I2C pins if not set.
  1200  	if config.SDA == 0 && config.SCL == 0 {
  1201  		config.SDA = SDA_PIN
  1202  		config.SCL = SCL_PIN
  1203  	}
  1204  
  1205  	sclPinMode, sclPad, ok := findPinPadMapping(i2c.SERCOM, config.SCL)
  1206  	if !ok || sclPad != 1 {
  1207  		// SCL must be on pad 1, according to section 36.4 of the datasheet.
  1208  		// Note: this is not an exhaustive test for I2C support on the pin: not
  1209  		// all pins support I2C.
  1210  		return ErrInvalidClockPin
  1211  	}
  1212  	sdaPinMode, sdaPad, ok := findPinPadMapping(i2c.SERCOM, config.SDA)
  1213  	if !ok || sdaPad != 0 {
  1214  		// SDA must be on pad 0, according to section 36.4 of the datasheet.
  1215  		// Note: this is not an exhaustive test for I2C support on the pin: not
  1216  		// all pins support I2C.
  1217  		return ErrInvalidDataPin
  1218  	}
  1219  
  1220  	// reset SERCOM
  1221  	i2c.Bus.CTRLA.SetBits(sam.SERCOM_I2CM_CTRLA_SWRST)
  1222  	for i2c.Bus.CTRLA.HasBits(sam.SERCOM_I2CM_CTRLA_SWRST) ||
  1223  		i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SWRST) {
  1224  	}
  1225  
  1226  	// set clock
  1227  	setSERCOMClockGenerator(i2c.SERCOM, sam.GCLK_PCHCTRL_GEN_GCLK1)
  1228  
  1229  	// Set i2c controller mode
  1230  	//SERCOM_I2CM_CTRLA_MODE( I2C_MASTER_OPERATION )
  1231  	// sam.SERCOM_I2CM_CTRLA_MODE_I2C_MASTER = 5?
  1232  	i2c.Bus.CTRLA.Set(5 << sam.SERCOM_I2CM_CTRLA_MODE_Pos) // |
  1233  
  1234  	i2c.SetBaudRate(config.Frequency)
  1235  
  1236  	// Enable I2CM port.
  1237  	// sercom->USART.CTRLA.bit.ENABLE = 0x1u;
  1238  	i2c.Bus.CTRLA.SetBits(sam.SERCOM_I2CM_CTRLA_ENABLE)
  1239  	for i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_ENABLE) {
  1240  	}
  1241  
  1242  	// set bus idle mode
  1243  	i2c.Bus.STATUS.SetBits(wireIdleState << sam.SERCOM_I2CM_STATUS_BUSSTATE_Pos)
  1244  	for i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SYSOP) {
  1245  	}
  1246  
  1247  	// enable pins
  1248  	config.SDA.Configure(PinConfig{Mode: sdaPinMode})
  1249  	config.SCL.Configure(PinConfig{Mode: sclPinMode})
  1250  
  1251  	return nil
  1252  }
  1253  
  1254  // SetBaudRate sets the communication speed for I2C.
  1255  func (i2c *I2C) SetBaudRate(br uint32) error {
  1256  	// Synchronous arithmetic baudrate, via Adafruit SAMD51 implementation:
  1257  	// sercom->I2CM.BAUD.bit.BAUD = SERCOM_FREQ_REF / ( 2 * baudrate) - 1 ;
  1258  	baud := SERCOM_FREQ_REF/(2*br) - 1
  1259  	i2c.Bus.BAUD.Set(baud)
  1260  	return nil
  1261  }
  1262  
  1263  // Tx does a single I2C transaction at the specified address.
  1264  // It clocks out the given address, writes the bytes in w, reads back len(r)
  1265  // bytes and stores them in r, and generates a stop condition on the bus.
  1266  func (i2c *I2C) Tx(addr uint16, w, r []byte) error {
  1267  	var err error
  1268  	if len(w) != 0 {
  1269  		// send start/address for write
  1270  		i2c.sendAddress(addr, true)
  1271  
  1272  		// wait until transmission complete
  1273  		timeout := i2cTimeout
  1274  		for !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {
  1275  			timeout--
  1276  			if timeout == 0 {
  1277  				return errI2CWriteTimeout
  1278  			}
  1279  		}
  1280  
  1281  		// ACK received (0: ACK, 1: NACK)
  1282  		if i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) {
  1283  			return errI2CAckExpected
  1284  		}
  1285  
  1286  		// write data
  1287  		for _, b := range w {
  1288  			err = i2c.WriteByte(b)
  1289  			if err != nil {
  1290  				return err
  1291  			}
  1292  		}
  1293  
  1294  		err = i2c.signalStop()
  1295  		if err != nil {
  1296  			return err
  1297  		}
  1298  	}
  1299  	if len(r) != 0 {
  1300  		// send start/address for read
  1301  		i2c.sendAddress(addr, false)
  1302  
  1303  		// wait transmission complete
  1304  		for !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_SB) {
  1305  			// If the peripheral NACKS the address, the MB bit will be set.
  1306  			// In that case, send a stop condition and return error.
  1307  			if i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {
  1308  				i2c.Bus.CTRLB.SetBits(wireCmdStop << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Stop condition
  1309  				return errI2CAckExpected
  1310  			}
  1311  		}
  1312  
  1313  		// ACK received (0: ACK, 1: NACK)
  1314  		if i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) {
  1315  			return errI2CAckExpected
  1316  		}
  1317  
  1318  		// read first byte
  1319  		r[0] = i2c.readByte()
  1320  		for i := 1; i < len(r); i++ {
  1321  			// Send an ACK
  1322  			i2c.Bus.CTRLB.ClearBits(sam.SERCOM_I2CM_CTRLB_ACKACT)
  1323  
  1324  			i2c.signalRead()
  1325  
  1326  			// Read data and send the ACK
  1327  			r[i] = i2c.readByte()
  1328  		}
  1329  
  1330  		// Send NACK to end transmission
  1331  		i2c.Bus.CTRLB.SetBits(sam.SERCOM_I2CM_CTRLB_ACKACT)
  1332  
  1333  		err = i2c.signalStop()
  1334  		if err != nil {
  1335  			return err
  1336  		}
  1337  	}
  1338  
  1339  	return nil
  1340  }
  1341  
  1342  // WriteByte writes a single byte to the I2C bus.
  1343  func (i2c *I2C) WriteByte(data byte) error {
  1344  	// Send data byte
  1345  	i2c.Bus.DATA.Set(data)
  1346  
  1347  	// wait until transmission successful
  1348  	timeout := i2cTimeout
  1349  	for !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_MB) {
  1350  		// check for bus error
  1351  		if i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_BUSERR) {
  1352  			return errI2CBusError
  1353  		}
  1354  		timeout--
  1355  		if timeout == 0 {
  1356  			return errI2CWriteTimeout
  1357  		}
  1358  	}
  1359  
  1360  	if i2c.Bus.STATUS.HasBits(sam.SERCOM_I2CM_STATUS_RXNACK) {
  1361  		return errI2CAckExpected
  1362  	}
  1363  
  1364  	return nil
  1365  }
  1366  
  1367  // sendAddress sends the address and start signal
  1368  func (i2c *I2C) sendAddress(address uint16, write bool) error {
  1369  	data := (address << 1)
  1370  	if !write {
  1371  		data |= 1 // set read flag
  1372  	}
  1373  
  1374  	// wait until bus ready
  1375  	timeout := i2cTimeout
  1376  	for !i2c.Bus.STATUS.HasBits(wireIdleState<<sam.SERCOM_I2CM_STATUS_BUSSTATE_Pos) &&
  1377  		!i2c.Bus.STATUS.HasBits(wireOwnerState<<sam.SERCOM_I2CM_STATUS_BUSSTATE_Pos) {
  1378  		timeout--
  1379  		if timeout == 0 {
  1380  			return errI2CBusReadyTimeout
  1381  		}
  1382  	}
  1383  	i2c.Bus.ADDR.Set(uint32(data))
  1384  
  1385  	return nil
  1386  }
  1387  
  1388  func (i2c *I2C) signalStop() error {
  1389  	i2c.Bus.CTRLB.SetBits(wireCmdStop << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Stop command
  1390  	timeout := i2cTimeout
  1391  	for i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SYSOP) {
  1392  		timeout--
  1393  		if timeout == 0 {
  1394  			return errI2CSignalStopTimeout
  1395  		}
  1396  	}
  1397  	return nil
  1398  }
  1399  
  1400  func (i2c *I2C) signalRead() error {
  1401  	i2c.Bus.CTRLB.SetBits(wireCmdRead << sam.SERCOM_I2CM_CTRLB_CMD_Pos) // Read command
  1402  	timeout := i2cTimeout
  1403  	for i2c.Bus.SYNCBUSY.HasBits(sam.SERCOM_I2CM_SYNCBUSY_SYSOP) {
  1404  		timeout--
  1405  		if timeout == 0 {
  1406  			return errI2CSignalReadTimeout
  1407  		}
  1408  	}
  1409  	return nil
  1410  }
  1411  
  1412  func (i2c *I2C) readByte() byte {
  1413  	for !i2c.Bus.INTFLAG.HasBits(sam.SERCOM_I2CM_INTFLAG_SB) {
  1414  	}
  1415  	return byte(i2c.Bus.DATA.Get())
  1416  }
  1417  
  1418  // SPI
  1419  type SPI struct {
  1420  	Bus    *sam.SERCOM_SPIM_Type
  1421  	SERCOM uint8
  1422  }
  1423  
  1424  // SPIConfig is used to store config info for SPI.
  1425  type SPIConfig struct {
  1426  	Frequency uint32
  1427  	SCK       Pin
  1428  	SDO       Pin
  1429  	SDI       Pin
  1430  	LSBFirst  bool
  1431  	Mode      uint8
  1432  }
  1433  
  1434  // Configure is intended to setup the SPI interface.
  1435  func (spi SPI) Configure(config SPIConfig) error {
  1436  	// Use default pins if not set.
  1437  	if config.SCK == 0 && config.SDO == 0 && config.SDI == 0 {
  1438  		config.SCK = SPI0_SCK_PIN
  1439  		config.SDO = SPI0_SDO_PIN
  1440  		config.SDI = SPI0_SDI_PIN
  1441  	}
  1442  
  1443  	// set default frequency
  1444  	if config.Frequency == 0 {
  1445  		config.Frequency = 4000000
  1446  	}
  1447  
  1448  	// Determine the input pinout (for SDI).
  1449  	var dataInPinout uint32
  1450  	var SDIPinMode PinMode
  1451  	if config.SDI != NoPin {
  1452  		var ok bool
  1453  		SDIPinMode, dataInPinout, ok = findPinPadMapping(spi.SERCOM, config.SDI)
  1454  		if !ok {
  1455  			return ErrInvalidInputPin
  1456  		}
  1457  	}
  1458  
  1459  	// Determine the output pinout (for SDO/SCK).
  1460  	// See DOPO field in the CTRLA register on page 986 of the datasheet.
  1461  	var dataOutPinout uint32
  1462  	sckPinMode, sckPad, ok := findPinPadMapping(spi.SERCOM, config.SCK)
  1463  	if !ok || sckPad != 1 {
  1464  		// SCK pad must always be 1
  1465  		return ErrInvalidOutputPin
  1466  	}
  1467  	SDOPinMode, SDOPad, ok := findPinPadMapping(spi.SERCOM, config.SDO)
  1468  	if !ok {
  1469  		return ErrInvalidOutputPin
  1470  	}
  1471  	switch SDOPad {
  1472  	case 0:
  1473  		dataOutPinout = 0x0
  1474  	case 3:
  1475  		dataOutPinout = 0x2
  1476  	default:
  1477  		return ErrInvalidOutputPin
  1478  	}
  1479  
  1480  	// Disable SPI port.
  1481  	spi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_ENABLE)
  1482  	for spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_ENABLE) {
  1483  	}
  1484  
  1485  	// enable pins
  1486  	config.SCK.Configure(PinConfig{Mode: sckPinMode})
  1487  	config.SDO.Configure(PinConfig{Mode: SDOPinMode})
  1488  	if config.SDI != NoPin {
  1489  		config.SDI.Configure(PinConfig{Mode: SDIPinMode})
  1490  	}
  1491  
  1492  	// reset SERCOM
  1493  	spi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_SWRST)
  1494  	for spi.Bus.CTRLA.HasBits(sam.SERCOM_SPIM_CTRLA_SWRST) ||
  1495  		spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_SWRST) {
  1496  	}
  1497  
  1498  	// set bit transfer order
  1499  	dataOrder := uint32(0)
  1500  	if config.LSBFirst {
  1501  		dataOrder = 1
  1502  	}
  1503  
  1504  	// Set SPI controller
  1505  	// SERCOM_SPIM_CTRLA_MODE_SPI_MASTER = 3
  1506  	spi.Bus.CTRLA.Set((3 << sam.SERCOM_SPIM_CTRLA_MODE_Pos) |
  1507  		(dataOutPinout << sam.SERCOM_SPIM_CTRLA_DOPO_Pos) |
  1508  		(dataInPinout << sam.SERCOM_SPIM_CTRLA_DIPO_Pos) |
  1509  		(dataOrder << sam.SERCOM_SPIM_CTRLA_DORD_Pos))
  1510  
  1511  	spi.Bus.CTRLB.SetBits((0 << sam.SERCOM_SPIM_CTRLB_CHSIZE_Pos) | // 8bit char size
  1512  		sam.SERCOM_SPIM_CTRLB_RXEN) // receive enable
  1513  
  1514  	for spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_CTRLB) {
  1515  	}
  1516  
  1517  	// set mode
  1518  	switch config.Mode {
  1519  	case 0:
  1520  		spi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPHA)
  1521  		spi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPOL)
  1522  	case 1:
  1523  		spi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_CPHA)
  1524  		spi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPOL)
  1525  	case 2:
  1526  		spi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPHA)
  1527  		spi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_CPOL)
  1528  	case 3:
  1529  		spi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_CPHA | sam.SERCOM_SPIM_CTRLA_CPOL)
  1530  	default: // to mode 0
  1531  		spi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPHA)
  1532  		spi.Bus.CTRLA.ClearBits(sam.SERCOM_SPIM_CTRLA_CPOL)
  1533  	}
  1534  
  1535  	// Set the clock frequency.
  1536  	// There are two clocks we can use GCLK0 (120MHz) and GCLK1 (48MHz).
  1537  	// We can use any even divisor for these clock, which means:
  1538  	//   - for GCLK0 we can make 60MHz, 30MHz, 20MHz, 15MHz, 12MHz, 10MHz, etc
  1539  	//   - for GCLK1 we can make 24MHz, 12MHz, 8MHz, 6MHz, 4.8MHz, 4MHz, etc
  1540  	// This means that by trying both clocks, we can have a wider selection of
  1541  	// available SPI clock frequencies.
  1542  
  1543  	// Calculate the baudrate if we would use GCLK1 (48MHz), and the resulting
  1544  	// frequency. The baud rate is rounded up, so that the resulting frequency
  1545  	// is rounded down from the maximum value (meaning it will always be smaller
  1546  	// than or equal to config.Frequency).
  1547  	baudRateGCLK1 := (SERCOM_FREQ_REF/2 + config.Frequency - 1) / config.Frequency
  1548  	freqGCLK1 := SERCOM_FREQ_REF / 2 / baudRateGCLK1
  1549  
  1550  	// Same for GCLK0 (120MHz).
  1551  	baudRateGCLK0 := (SERCOM_FREQ_REF_GCLK0/2 + config.Frequency - 1) / config.Frequency
  1552  	freqGCLK0 := SERCOM_FREQ_REF_GCLK0 / 2 / baudRateGCLK0
  1553  
  1554  	// Pick the clock source that is the closest to the maximum baud rate.
  1555  	// Note: there may be reasons to prefer the lower frequency clock (like
  1556  	// power consumption). If that's the case, we might want to always use the
  1557  	// 48MHz clock at low frequencies (below 4MHz or so).
  1558  	if freqGCLK0 > freqGCLK1 && uint32(uint8(baudRateGCLK0-1))+1 == baudRateGCLK0 {
  1559  		// Pick this 120MHz clock if it results in a better frequency after
  1560  		// division, and the baudRate value fits in the BAUD register.
  1561  		setSERCOMClockGenerator(spi.SERCOM, sam.GCLK_PCHCTRL_GEN_GCLK0)
  1562  		spi.Bus.BAUD.Set(uint8(baudRateGCLK0 - 1))
  1563  	} else {
  1564  		// Use the 48MHz clock in other cases.
  1565  		setSERCOMClockGenerator(spi.SERCOM, sam.GCLK_PCHCTRL_GEN_GCLK1)
  1566  		spi.Bus.BAUD.Set(uint8(baudRateGCLK1 - 1))
  1567  	}
  1568  
  1569  	// Enable SPI port.
  1570  	spi.Bus.CTRLA.SetBits(sam.SERCOM_SPIM_CTRLA_ENABLE)
  1571  	for spi.Bus.SYNCBUSY.HasBits(sam.SERCOM_SPIM_SYNCBUSY_ENABLE) {
  1572  	}
  1573  
  1574  	return nil
  1575  }
  1576  
  1577  // Transfer writes/reads a single byte using the SPI interface.
  1578  func (spi SPI) Transfer(w byte) (byte, error) {
  1579  	// write data
  1580  	spi.Bus.DATA.Set(uint32(w))
  1581  
  1582  	// wait for receive
  1583  	for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
  1584  	}
  1585  
  1586  	// return data
  1587  	return byte(spi.Bus.DATA.Get()), nil
  1588  }
  1589  
  1590  // Tx handles read/write operation for SPI interface. Since SPI is a syncronous write/read
  1591  // interface, there must always be the same number of bytes written as bytes read.
  1592  // The Tx method knows about this, and offers a few different ways of calling it.
  1593  //
  1594  // This form sends the bytes in tx buffer, putting the resulting bytes read into the rx buffer.
  1595  // Note that the tx and rx buffers must be the same size:
  1596  //
  1597  //	spi.Tx(tx, rx)
  1598  //
  1599  // This form sends the tx buffer, ignoring the result. Useful for sending "commands" that return zeros
  1600  // until all the bytes in the command packet have been received:
  1601  //
  1602  //	spi.Tx(tx, nil)
  1603  //
  1604  // This form sends zeros, putting the result into the rx buffer. Good for reading a "result packet":
  1605  //
  1606  //	spi.Tx(nil, rx)
  1607  func (spi SPI) Tx(w, r []byte) error {
  1608  	switch {
  1609  	case w == nil:
  1610  		// read only, so write zero and read a result.
  1611  		spi.rx(r)
  1612  	case r == nil:
  1613  		// write only
  1614  		spi.tx(w)
  1615  
  1616  	default:
  1617  		// write/read
  1618  		if len(w) != len(r) {
  1619  			return ErrTxInvalidSliceSize
  1620  		}
  1621  
  1622  		spi.txrx(w, r)
  1623  	}
  1624  
  1625  	return nil
  1626  }
  1627  
  1628  func (spi SPI) tx(tx []byte) {
  1629  	for i := 0; i < len(tx); i++ {
  1630  		for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_DRE) {
  1631  		}
  1632  		spi.Bus.DATA.Set(uint32(tx[i]))
  1633  	}
  1634  	for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_TXC) {
  1635  	}
  1636  
  1637  	// read to clear RXC register
  1638  	for spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
  1639  		spi.Bus.DATA.Get()
  1640  	}
  1641  }
  1642  
  1643  func (spi SPI) rx(rx []byte) {
  1644  	spi.Bus.DATA.Set(0)
  1645  	for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_DRE) {
  1646  	}
  1647  
  1648  	for i := 1; i < len(rx); i++ {
  1649  		spi.Bus.DATA.Set(0)
  1650  		for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
  1651  		}
  1652  		rx[i-1] = byte(spi.Bus.DATA.Get())
  1653  	}
  1654  	for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
  1655  	}
  1656  	rx[len(rx)-1] = byte(spi.Bus.DATA.Get())
  1657  }
  1658  
  1659  func (spi SPI) txrx(tx, rx []byte) {
  1660  	spi.Bus.DATA.Set(uint32(tx[0]))
  1661  	for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_DRE) {
  1662  	}
  1663  
  1664  	for i := 1; i < len(rx); i++ {
  1665  		spi.Bus.DATA.Set(uint32(tx[i]))
  1666  		for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
  1667  		}
  1668  		rx[i-1] = byte(spi.Bus.DATA.Get())
  1669  	}
  1670  	for !spi.Bus.INTFLAG.HasBits(sam.SERCOM_SPIM_INTFLAG_RXC) {
  1671  	}
  1672  	rx[len(rx)-1] = byte(spi.Bus.DATA.Get())
  1673  }
  1674  
  1675  // The QSPI peripheral on ATSAMD51 is only available on the following pins
  1676  const (
  1677  	QSPI_SCK   = PB10
  1678  	QSPI_CS    = PB11
  1679  	QSPI_DATA0 = PA08
  1680  	QSPI_DATA1 = PA09
  1681  	QSPI_DATA2 = PA10
  1682  	QSPI_DATA3 = PA11
  1683  )
  1684  
  1685  // TCC is one timer peripheral, which consists of a counter and multiple output
  1686  // channels (that can be connected to actual pins). You can set the frequency
  1687  // using SetPeriod, but only for all the channels in this timer peripheral at
  1688  // once.
  1689  type TCC sam.TCC_Type
  1690  
  1691  //go:inline
  1692  func (tcc *TCC) timer() *sam.TCC_Type {
  1693  	return (*sam.TCC_Type)(tcc)
  1694  }
  1695  
  1696  // Configure enables and configures this TCC.
  1697  func (tcc *TCC) Configure(config PWMConfig) error {
  1698  	// Enable the TCC clock to be able to use the TCC.
  1699  	tcc.configureClock()
  1700  
  1701  	// Disable timer (if it was enabled). This is necessary because
  1702  	// tcc.setPeriod may want to change the prescaler bits in CTRLA, which is
  1703  	// only allowed when the TCC is disabled.
  1704  	tcc.timer().CTRLA.ClearBits(sam.TCC_CTRLA_ENABLE)
  1705  
  1706  	// Use "Normal PWM" (single-slope PWM)
  1707  	tcc.timer().WAVE.Set(sam.TCC_WAVE_WAVEGEN_NPWM)
  1708  
  1709  	// Wait for synchronization of all changed registers.
  1710  	for tcc.timer().SYNCBUSY.Get() != 0 {
  1711  	}
  1712  
  1713  	// Set the period and prescaler.
  1714  	err := tcc.setPeriod(config.Period, true)
  1715  
  1716  	// Enable the timer.
  1717  	tcc.timer().CTRLA.SetBits(sam.TCC_CTRLA_ENABLE)
  1718  
  1719  	// Wait for synchronization of all changed registers.
  1720  	for tcc.timer().SYNCBUSY.Get() != 0 {
  1721  	}
  1722  
  1723  	// Return any error that might have occured in the tcc.setPeriod call.
  1724  	return err
  1725  }
  1726  
  1727  // SetPeriod updates the period of this TCC peripheral.
  1728  // To set a particular frequency, use the following formula:
  1729  //
  1730  //	period = 1e9 / frequency
  1731  //
  1732  // If you use a period of 0, a period that works well for LEDs will be picked.
  1733  //
  1734  // SetPeriod will not change the prescaler, but also won't change the current
  1735  // value in any of the channels. This means that you may need to update the
  1736  // value for the particular channel.
  1737  //
  1738  // Note that you cannot pick any arbitrary period after the TCC peripheral has
  1739  // been configured. If you want to switch between frequencies, pick the lowest
  1740  // frequency (longest period) once when calling Configure and adjust the
  1741  // frequency here as needed.
  1742  func (tcc *TCC) SetPeriod(period uint64) error {
  1743  	return tcc.setPeriod(period, false)
  1744  }
  1745  
  1746  // setPeriod sets the period of this TCC, possibly updating the prescaler as
  1747  // well. The prescaler can only modified when the TCC is disabled, that is, in
  1748  // the Configure function.
  1749  func (tcc *TCC) setPeriod(period uint64, updatePrescaler bool) error {
  1750  	var top uint64
  1751  	if period == 0 {
  1752  		// Make sure the TOP value is at 0xffff (enough for a 16-bit timer).
  1753  		top = 0xffff
  1754  	} else {
  1755  		// The formula below calculates the following formula, optimized:
  1756  		//     period * (120e6 / 1e9)
  1757  		// This assumes that the chip is running from generic clock generator 0
  1758  		// at 120MHz.
  1759  		top = period * 3 / 25
  1760  	}
  1761  
  1762  	maxTop := uint64(0xffff)
  1763  	if tcc.timer() == sam.TCC0 || tcc.timer() == sam.TCC1 {
  1764  		// Only TCC0 and TCC1 are 24-bit timers, the rest are 16-bit.
  1765  		maxTop = 0xffffff
  1766  	}
  1767  
  1768  	if updatePrescaler {
  1769  		// This function was called during Configure(), with the timer disabled.
  1770  		// Note that updating the prescaler can only happen while the peripheral
  1771  		// is disabled.
  1772  		var prescaler uint32
  1773  		switch {
  1774  		case top <= maxTop:
  1775  			prescaler = sam.TCC_CTRLA_PRESCALER_DIV1
  1776  		case top/2 <= maxTop:
  1777  			prescaler = sam.TCC_CTRLA_PRESCALER_DIV2
  1778  			top = top / 2
  1779  		case top/4 <= maxTop:
  1780  			prescaler = sam.TCC_CTRLA_PRESCALER_DIV4
  1781  			top = top / 4
  1782  		case top/8 <= maxTop:
  1783  			prescaler = sam.TCC_CTRLA_PRESCALER_DIV8
  1784  			top = top / 8
  1785  		case top/16 <= maxTop:
  1786  			prescaler = sam.TCC_CTRLA_PRESCALER_DIV16
  1787  			top = top / 16
  1788  		case top/64 <= maxTop:
  1789  			prescaler = sam.TCC_CTRLA_PRESCALER_DIV64
  1790  			top = top / 64
  1791  		case top/256 <= maxTop:
  1792  			prescaler = sam.TCC_CTRLA_PRESCALER_DIV256
  1793  			top = top / 256
  1794  		case top/1024 <= maxTop:
  1795  			prescaler = sam.TCC_CTRLA_PRESCALER_DIV1024
  1796  			top = top / 1024
  1797  		default:
  1798  			return ErrPWMPeriodTooLong
  1799  		}
  1800  		tcc.timer().CTRLA.Set((tcc.timer().CTRLA.Get() &^ sam.TCC_CTRLA_PRESCALER_Msk) | (prescaler << sam.TCC_CTRLA_PRESCALER_Pos))
  1801  	} else {
  1802  		// Do not update the prescaler, but use the already-configured
  1803  		// prescaler. This is the normal SetPeriod case, where the prescaler
  1804  		// must not be changed.
  1805  		prescaler := (tcc.timer().CTRLA.Get() & sam.TCC_CTRLA_PRESCALER_Msk) >> sam.TCC_CTRLA_PRESCALER_Pos
  1806  		switch prescaler {
  1807  		case sam.TCC_CTRLA_PRESCALER_DIV1:
  1808  			top /= 1 // no-op
  1809  		case sam.TCC_CTRLA_PRESCALER_DIV2:
  1810  			top /= 2
  1811  		case sam.TCC_CTRLA_PRESCALER_DIV4:
  1812  			top /= 4
  1813  		case sam.TCC_CTRLA_PRESCALER_DIV8:
  1814  			top /= 8
  1815  		case sam.TCC_CTRLA_PRESCALER_DIV16:
  1816  			top /= 16
  1817  		case sam.TCC_CTRLA_PRESCALER_DIV64:
  1818  			top /= 64
  1819  		case sam.TCC_CTRLA_PRESCALER_DIV256:
  1820  			top /= 256
  1821  		case sam.TCC_CTRLA_PRESCALER_DIV1024:
  1822  			top /= 1024
  1823  		default:
  1824  			// unreachable
  1825  		}
  1826  		if top > maxTop {
  1827  			return ErrPWMPeriodTooLong
  1828  		}
  1829  	}
  1830  
  1831  	// Set the period (the counter top).
  1832  	tcc.timer().PER.Set(uint32(top) - 1)
  1833  
  1834  	// Wait for synchronization of CTRLA.PRESCALER and PER registers.
  1835  	for tcc.timer().SYNCBUSY.Get() != 0 {
  1836  	}
  1837  
  1838  	return nil
  1839  }
  1840  
  1841  // Top returns the current counter top, for use in duty cycle calculation. It
  1842  // will only change with a call to Configure or SetPeriod, otherwise it is
  1843  // constant.
  1844  //
  1845  // The value returned here is hardware dependent. In general, it's best to treat
  1846  // it as an opaque value that can be divided by some number and passed to
  1847  // tcc.Set (see tcc.Set for more information).
  1848  func (tcc *TCC) Top() uint32 {
  1849  	return tcc.timer().PER.Get() + 1
  1850  }
  1851  
  1852  // Counter returns the current counter value of the timer in this TCC
  1853  // peripheral. It may be useful for debugging.
  1854  func (tcc *TCC) Counter() uint32 {
  1855  	tcc.timer().CTRLBSET.Set(sam.TCC_CTRLBSET_CMD_READSYNC << sam.TCC_CTRLBSET_CMD_Pos)
  1856  	for tcc.timer().SYNCBUSY.Get() != 0 {
  1857  	}
  1858  	return tcc.timer().COUNT.Get()
  1859  }
  1860  
  1861  // Constants that encode a TCC number and WO number together in a single byte.
  1862  const (
  1863  	pinTCC0   = 1 << 4 // keep the value 0 usable as "no value"
  1864  	pinTCC1   = 2 << 4
  1865  	pinTCC2   = 3 << 4
  1866  	pinTCC3   = 4 << 4
  1867  	pinTCC4   = 5 << 4
  1868  	pinTCC0_0 = pinTCC0 | 0
  1869  	pinTCC0_1 = pinTCC0 | 1
  1870  	pinTCC0_2 = pinTCC0 | 2
  1871  	pinTCC0_3 = pinTCC0 | 3
  1872  	pinTCC0_4 = pinTCC0 | 4
  1873  	pinTCC0_5 = pinTCC0 | 5
  1874  	pinTCC0_6 = pinTCC0 | 6
  1875  	pinTCC1_0 = pinTCC1 | 0
  1876  	pinTCC1_2 = pinTCC1 | 2
  1877  	pinTCC1_4 = pinTCC1 | 4
  1878  	pinTCC1_6 = pinTCC1 | 6
  1879  	pinTCC2_0 = pinTCC2 | 0
  1880  	pinTCC2_2 = pinTCC2 | 2
  1881  	pinTCC3_0 = pinTCC3 | 0
  1882  	pinTCC4_0 = pinTCC4 | 0
  1883  )
  1884  
  1885  // This is a copy of columns F and G (the TCC columns) of table 6-1 in the
  1886  // datasheet:
  1887  // http://ww1.microchip.com/downloads/en/DeviceDoc/60001507E.pdf
  1888  // For example, "TCC0/WO[2]" is converted to pinTCC0_2.
  1889  // Only the even pin numbers are stored here. The odd pin numbers are left out,
  1890  // because their PWM output can be determined from the even number: just add one
  1891  // to the wave output (WO) number.
  1892  var pinTimerMapping = [...]struct{ F, G uint8 }{
  1893  	// page 33
  1894  	PC04 / 2: {pinTCC0_0, 0},
  1895  	PA08 / 2: {pinTCC0_0, pinTCC1_4},
  1896  	PA10 / 2: {pinTCC0_2, pinTCC1_6},
  1897  	PB10 / 2: {pinTCC0_4, pinTCC1_0},
  1898  	PB12 / 2: {pinTCC3_0, pinTCC0_0},
  1899  	PB14 / 2: {pinTCC4_0, pinTCC0_2},
  1900  	PD08 / 2: {pinTCC0_1, 0},
  1901  	PD10 / 2: {pinTCC0_3, 0},
  1902  	PD12 / 2: {pinTCC0_5, 0},
  1903  	PC10 / 2: {pinTCC0_0, pinTCC1_4},
  1904  	// page 34
  1905  	PC12 / 2: {pinTCC0_2, pinTCC1_6},
  1906  	PC14 / 2: {pinTCC0_4, pinTCC1_0},
  1907  	PA12 / 2: {pinTCC0_6, pinTCC1_2},
  1908  	PA14 / 2: {pinTCC2_0, pinTCC1_2},
  1909  	PA16 / 2: {pinTCC1_0, pinTCC0_4},
  1910  	PA18 / 2: {pinTCC1_2, pinTCC0_6},
  1911  	PC16 / 2: {pinTCC0_0, 0},
  1912  	PC18 / 2: {pinTCC0_2, 0},
  1913  	PC20 / 2: {pinTCC0_4, 0},
  1914  	PC22 / 2: {pinTCC0_6, 0},
  1915  	PD20 / 2: {pinTCC1_0, 0},
  1916  	PB16 / 2: {pinTCC3_0, pinTCC0_4},
  1917  	PB18 / 2: {pinTCC1_0, 0},
  1918  	// page 35
  1919  	PB20 / 2: {pinTCC1_2, 0},
  1920  	PA20 / 2: {pinTCC1_4, pinTCC0_0},
  1921  	PA22 / 2: {pinTCC1_6, pinTCC0_2},
  1922  	PA24 / 2: {pinTCC2_2, 0},
  1923  	PB26 / 2: {pinTCC1_2, 0},
  1924  	PB28 / 2: {pinTCC1_4, 0},
  1925  	PA30 / 2: {pinTCC2_0, 0},
  1926  	// page 36
  1927  	PB30 / 2: {pinTCC4_0, pinTCC0_6},
  1928  	PB02 / 2: {pinTCC2_2, 0},
  1929  }
  1930  
  1931  // findPinPadMapping returns the pin mode (PinTCCF or PinTCCG) and the channel
  1932  // number for a given timer and pin. A zero PinMode is returned if no mapping
  1933  // could be found.
  1934  func findPinTimerMapping(timer uint8, pin Pin) (PinMode, uint8) {
  1935  	if int(pin/2) >= len(pinTimerMapping) {
  1936  		return 0, 0 // invalid pin number
  1937  	}
  1938  
  1939  	mapping := pinTimerMapping[pin/2]
  1940  
  1941  	// Check for column F in the datasheet.
  1942  	if mapping.F>>4-1 == timer {
  1943  		return PinTCCF, mapping.F&0x0f + uint8(pin)&1
  1944  	}
  1945  
  1946  	// Check for column G in the datasheet.
  1947  	if mapping.G>>4-1 == timer {
  1948  		return PinTCCG, mapping.G&0x0f + uint8(pin)&1
  1949  	}
  1950  
  1951  	// Nothing found.
  1952  	return 0, 0
  1953  }
  1954  
  1955  // Channel returns a PWM channel for the given pin. Note that one channel may be
  1956  // shared between multiple pins, and so will have the same duty cycle. If this
  1957  // is not desirable, look for a different TCC or consider using a different pin.
  1958  func (tcc *TCC) Channel(pin Pin) (uint8, error) {
  1959  	pinMode, woOutput := findPinTimerMapping(tcc.timerNum(), pin)
  1960  
  1961  	if pinMode == 0 {
  1962  		// No pin could be found.
  1963  		return 0, ErrInvalidOutputPin
  1964  	}
  1965  
  1966  	// Convert from waveform output to channel, assuming WEXCTRL.OTMX equals 0.
  1967  	// See table 49-4 "Output Matrix Channel Pin Routing Configuration" on page
  1968  	// 1829 of the datasheet.
  1969  	// The number of channels varies by TCC instance, hence the need to switch
  1970  	// over them. For TCC2-4 the number of channels is equal to the number of
  1971  	// waveform outputs, so the WO number maps directly to the channel number.
  1972  	// For TCC0 and TCC1 this is not the case so they will need some special
  1973  	// handling.
  1974  	channel := woOutput
  1975  	switch tcc.timer() {
  1976  	case sam.TCC0:
  1977  		channel = woOutput % 6
  1978  	case sam.TCC1:
  1979  		channel = woOutput % 4
  1980  	}
  1981  
  1982  	// Enable the port multiplexer for pin
  1983  	pin.setPinCfg(sam.PORT_GROUP_PINCFG_PMUXEN)
  1984  
  1985  	// Connect timer/mux to pin.
  1986  	if pin&1 > 0 {
  1987  		// odd pin, so save the even pins
  1988  		val := pin.getPMux() & sam.PORT_GROUP_PMUX_PMUXE_Msk
  1989  		pin.setPMux(val | uint8(pinMode<<sam.PORT_GROUP_PMUX_PMUXO_Pos))
  1990  	} else {
  1991  		// even pin, so save the odd pins
  1992  		val := pin.getPMux() & sam.PORT_GROUP_PMUX_PMUXO_Msk
  1993  		pin.setPMux(val | uint8(pinMode<<sam.PORT_GROUP_PMUX_PMUXE_Pos))
  1994  	}
  1995  
  1996  	return channel, nil
  1997  }
  1998  
  1999  // SetInverting sets whether to invert the output of this channel.
  2000  // Without inverting, a 25% duty cycle would mean the output is high for 25% of
  2001  // the time and low for the rest. Inverting flips the output as if a NOT gate
  2002  // was placed at the output, meaning that the output would be 25% low and 75%
  2003  // high with a duty cycle of 25%.
  2004  func (tcc *TCC) SetInverting(channel uint8, inverting bool) {
  2005  	if inverting {
  2006  		tcc.timer().WAVE.SetBits(1 << (sam.TCC_WAVE_POL0_Pos + channel))
  2007  	} else {
  2008  		tcc.timer().WAVE.ClearBits(1 << (sam.TCC_WAVE_POL0_Pos + channel))
  2009  	}
  2010  
  2011  	// Wait for synchronization of the WAVE register.
  2012  	for tcc.timer().SYNCBUSY.Get() != 0 {
  2013  	}
  2014  }
  2015  
  2016  // Set updates the channel value. This is used to control the channel duty
  2017  // cycle, in other words the fraction of time the channel output is high (or low
  2018  // when inverted). For example, to set it to a 25% duty cycle, use:
  2019  //
  2020  //	tcc.Set(channel, tcc.Top() / 4)
  2021  //
  2022  // tcc.Set(channel, 0) will set the output to low and tcc.Set(channel,
  2023  // tcc.Top()) will set the output to high, assuming the output isn't inverted.
  2024  func (tcc *TCC) Set(channel uint8, value uint32) {
  2025  	// Update CCBUF, which provides double buffering. The update is applied on
  2026  	// the next cycle.
  2027  	tcc.timer().CCBUF[channel].Set(value)
  2028  	for tcc.timer().SYNCBUSY.Get() != 0 {
  2029  	}
  2030  }
  2031  
  2032  // EnterBootloader should perform a system reset in preparation
  2033  // to switch to the bootloader to flash new firmware.
  2034  func EnterBootloader() {
  2035  	arm.DisableInterrupts()
  2036  
  2037  	// Perform magic reset into bootloader, as mentioned in
  2038  	// https://github.com/arduino/ArduinoCore-samd/issues/197
  2039  	*(*uint32)(unsafe.Pointer(uintptr(0x20000000 + HSRAM_SIZE - 4))) = resetMagicValue
  2040  
  2041  	arm.SystemReset()
  2042  }
  2043  
  2044  // DAC on the SAMD51.
  2045  type DAC struct {
  2046  	Channel uint8
  2047  }
  2048  
  2049  var (
  2050  	DAC0 = DAC{Channel: 0}
  2051  	DAC1 = DAC{Channel: 1}
  2052  )
  2053  
  2054  // DACConfig placeholder for future expansion.
  2055  type DACConfig struct {
  2056  }
  2057  
  2058  // Configure the DAC.
  2059  // output pin must already be configured.
  2060  func (dac DAC) Configure(config DACConfig) {
  2061  	// Turn on clock for DAC
  2062  	sam.MCLK.APBDMASK.SetBits(sam.MCLK_APBDMASK_DAC_)
  2063  
  2064  	if !sam.GCLK.PCHCTRL[42].HasBits(sam.GCLK_PCHCTRL_CHEN) {
  2065  		// Use Generic Clock Generator 4 as source for DAC.
  2066  		sam.GCLK.PCHCTRL[42].Set((sam.GCLK_PCHCTRL_GEN_GCLK4 << sam.GCLK_PCHCTRL_GEN_Pos) | sam.GCLK_PCHCTRL_CHEN)
  2067  		for sam.GCLK.SYNCBUSY.HasBits(sam.GCLK_SYNCBUSY_GENCTRL_GCLK4 << sam.GCLK_SYNCBUSY_GENCTRL_Pos) {
  2068  		}
  2069  
  2070  		// reset DAC
  2071  		sam.DAC.CTRLA.Set(sam.DAC_CTRLA_SWRST)
  2072  
  2073  		// wait for reset complete
  2074  		for sam.DAC.CTRLA.HasBits(sam.DAC_CTRLA_SWRST) {
  2075  		}
  2076  		for sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_SWRST) {
  2077  		}
  2078  	}
  2079  
  2080  	sam.DAC.CTRLA.ClearBits(sam.DAC_CTRLA_ENABLE)
  2081  	for sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_ENABLE) {
  2082  	}
  2083  
  2084  	// enable
  2085  	sam.DAC.CTRLB.Set(sam.DAC_CTRLB_REFSEL_VREFPU << sam.DAC_CTRLB_REFSEL_Pos)
  2086  	sam.DAC.DACCTRL[dac.Channel].SetBits((sam.DAC_DACCTRL_CCTRL_CC12M << sam.DAC_DACCTRL_CCTRL_Pos) | sam.DAC_DACCTRL_ENABLE)
  2087  	sam.DAC.CTRLA.Set(sam.DAC_CTRLA_ENABLE)
  2088  
  2089  	for sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_ENABLE) {
  2090  	}
  2091  
  2092  	switch dac.Channel {
  2093  	case 0:
  2094  		for !sam.DAC.STATUS.HasBits(sam.DAC_STATUS_READY0) {
  2095  		}
  2096  	default:
  2097  		for !sam.DAC.STATUS.HasBits(sam.DAC_STATUS_READY1) {
  2098  		}
  2099  	}
  2100  }
  2101  
  2102  // Set writes a single 16-bit value to the DAC.
  2103  // Since the ATSAMD51 only has a 12-bit DAC, the passed-in value will be scaled down.
  2104  func (dac DAC) Set(value uint16) error {
  2105  	sam.DAC.DATA[dac.Channel].Set(value >> 4)
  2106  	dac.syncDAC()
  2107  	return nil
  2108  }
  2109  
  2110  func (dac DAC) syncDAC() {
  2111  	switch dac.Channel {
  2112  	case 0:
  2113  		for !sam.DAC.STATUS.HasBits(sam.DAC_STATUS_EOC0) {
  2114  		}
  2115  		for sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_DATA0) {
  2116  		}
  2117  	default:
  2118  		for !sam.DAC.STATUS.HasBits(sam.DAC_STATUS_EOC1) {
  2119  		}
  2120  		for sam.DAC.SYNCBUSY.HasBits(sam.DAC_SYNCBUSY_DATA1) {
  2121  		}
  2122  	}
  2123  }
  2124  
  2125  // GetRNG returns 32 bits of cryptographically secure random data
  2126  func GetRNG() (uint32, error) {
  2127  	if !sam.MCLK.APBCMASK.HasBits(sam.MCLK_APBCMASK_TRNG_) {
  2128  		// Turn on clock for TRNG
  2129  		sam.MCLK.APBCMASK.SetBits(sam.MCLK_APBCMASK_TRNG_)
  2130  
  2131  		// enable
  2132  		sam.TRNG.CTRLA.Set(sam.TRNG_CTRLA_ENABLE)
  2133  	}
  2134  	for !sam.TRNG.INTFLAG.HasBits(sam.TRNG_INTFLAG_DATARDY) {
  2135  	}
  2136  	ret := sam.TRNG.DATA.Get()
  2137  	return ret, nil
  2138  }
  2139  
  2140  // Flash related code
  2141  const memoryStart = 0x0
  2142  
  2143  // compile-time check for ensuring we fulfill BlockDevice interface
  2144  var _ BlockDevice = flashBlockDevice{}
  2145  
  2146  var Flash flashBlockDevice
  2147  
  2148  type flashBlockDevice struct {
  2149  	initComplete bool
  2150  }
  2151  
  2152  // ReadAt reads the given number of bytes from the block device.
  2153  func (f flashBlockDevice) ReadAt(p []byte, off int64) (n int, err error) {
  2154  	if FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {
  2155  		return 0, errFlashCannotReadPastEOF
  2156  	}
  2157  
  2158  	waitWhileFlashBusy()
  2159  
  2160  	data := unsafe.Slice((*byte)(unsafe.Add(unsafe.Pointer(FlashDataStart()), uintptr(off))), len(p))
  2161  	copy(p, data)
  2162  
  2163  	return len(p), nil
  2164  }
  2165  
  2166  // WriteAt writes the given number of bytes to the block device.
  2167  // Only word (32 bits) length data can be programmed.
  2168  // See SAM-D5x-E5x-Family-Data-Sheet-DS60001507.pdf page 591-592.
  2169  // If the length of p is not long enough it will be padded with 0xFF bytes.
  2170  // This method assumes that the destination is already erased.
  2171  func (f flashBlockDevice) WriteAt(p []byte, off int64) (n int, err error) {
  2172  	if FlashDataStart()+uintptr(off)+uintptr(len(p)) > FlashDataEnd() {
  2173  		return 0, errFlashCannotWritePastEOF
  2174  	}
  2175  
  2176  	address := FlashDataStart() + uintptr(off)
  2177  	padded := f.pad(p)
  2178  
  2179  	settings := disableFlashCache()
  2180  	defer restoreFlashCache(settings)
  2181  
  2182  	waitWhileFlashBusy()
  2183  
  2184  	sam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_PBC | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))
  2185  
  2186  	waitWhileFlashBusy()
  2187  
  2188  	for j := 0; j < len(padded); j += int(f.WriteBlockSize()) {
  2189  		// write first word using double-word low order word
  2190  		*(*uint32)(unsafe.Pointer(address)) = binary.LittleEndian.Uint32(padded[j : j+int(f.WriteBlockSize()/2)])
  2191  
  2192  		// write second word using double-word high order word
  2193  		*(*uint32)(unsafe.Add(unsafe.Pointer(address), uintptr(f.WriteBlockSize())/2)) = binary.LittleEndian.Uint32(padded[j+int(f.WriteBlockSize()/2) : j+int(f.WriteBlockSize())])
  2194  
  2195  		waitWhileFlashBusy()
  2196  
  2197  		sam.NVMCTRL.SetADDR(uint32(address))
  2198  		sam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_WQW | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))
  2199  
  2200  		waitWhileFlashBusy()
  2201  
  2202  		if err := checkFlashError(); err != nil {
  2203  			return j, err
  2204  		}
  2205  
  2206  		address += uintptr(f.WriteBlockSize())
  2207  	}
  2208  
  2209  	return len(padded), nil
  2210  }
  2211  
  2212  // Size returns the number of bytes in this block device.
  2213  func (f flashBlockDevice) Size() int64 {
  2214  	return int64(FlashDataEnd() - FlashDataStart())
  2215  }
  2216  
  2217  const writeBlockSize = 8
  2218  
  2219  // WriteBlockSize returns the block size in which data can be written to
  2220  // memory. It can be used by a client to optimize writes, non-aligned writes
  2221  // should always work correctly.
  2222  func (f flashBlockDevice) WriteBlockSize() int64 {
  2223  	return writeBlockSize
  2224  }
  2225  
  2226  const eraseBlockSizeValue = 8192
  2227  
  2228  func eraseBlockSize() int64 {
  2229  	return eraseBlockSizeValue
  2230  }
  2231  
  2232  // EraseBlockSize returns the smallest erasable area on this particular chip
  2233  // in bytes. This is used for the block size in EraseBlocks.
  2234  func (f flashBlockDevice) EraseBlockSize() int64 {
  2235  	return eraseBlockSize()
  2236  }
  2237  
  2238  // EraseBlocks erases the given number of blocks. An implementation may
  2239  // transparently coalesce ranges of blocks into larger bundles if the chip
  2240  // supports this. The start and len parameters are in block numbers, use
  2241  // EraseBlockSize to map addresses to blocks.
  2242  func (f flashBlockDevice) EraseBlocks(start, len int64) error {
  2243  	address := FlashDataStart() + uintptr(start*f.EraseBlockSize())
  2244  
  2245  	settings := disableFlashCache()
  2246  	defer restoreFlashCache(settings)
  2247  
  2248  	waitWhileFlashBusy()
  2249  
  2250  	for i := start; i < start+len; i++ {
  2251  		sam.NVMCTRL.SetADDR(uint32(address))
  2252  		sam.NVMCTRL.CTRLB.Set(sam.NVMCTRL_CTRLB_CMD_EB | (sam.NVMCTRL_CTRLB_CMDEX_KEY << sam.NVMCTRL_CTRLB_CMDEX_Pos))
  2253  
  2254  		waitWhileFlashBusy()
  2255  
  2256  		if err := checkFlashError(); err != nil {
  2257  			return err
  2258  		}
  2259  
  2260  		address += uintptr(f.EraseBlockSize())
  2261  	}
  2262  
  2263  	return nil
  2264  }
  2265  
  2266  // pad data if needed so it is long enough for correct byte alignment on writes.
  2267  func (f flashBlockDevice) pad(p []byte) []byte {
  2268  	overflow := int64(len(p)) % f.WriteBlockSize()
  2269  	if overflow == 0 {
  2270  		return p
  2271  	}
  2272  
  2273  	padding := bytes.Repeat([]byte{0xff}, int(f.WriteBlockSize()-overflow))
  2274  	return append(p, padding...)
  2275  }
  2276  
  2277  func disableFlashCache() uint16 {
  2278  	settings := sam.NVMCTRL.CTRLA.Get()
  2279  
  2280  	// disable caches
  2281  	sam.NVMCTRL.SetCTRLA_CACHEDIS0(1)
  2282  	sam.NVMCTRL.SetCTRLA_CACHEDIS1(1)
  2283  
  2284  	waitWhileFlashBusy()
  2285  
  2286  	return settings
  2287  }
  2288  
  2289  func restoreFlashCache(settings uint16) {
  2290  	sam.NVMCTRL.CTRLA.Set(settings)
  2291  	waitWhileFlashBusy()
  2292  }
  2293  
  2294  func waitWhileFlashBusy() {
  2295  	for sam.NVMCTRL.GetSTATUS_READY() != sam.NVMCTRL_STATUS_READY {
  2296  	}
  2297  }
  2298  
  2299  var (
  2300  	errFlashADDRE   = errors.New("errFlashADDRE")
  2301  	errFlashPROGE   = errors.New("errFlashPROGE")
  2302  	errFlashLOCKE   = errors.New("errFlashLOCKE")
  2303  	errFlashECCSE   = errors.New("errFlashECCSE")
  2304  	errFlashNVME    = errors.New("errFlashNVME")
  2305  	errFlashSEESOVF = errors.New("errFlashSEESOVF")
  2306  )
  2307  
  2308  func checkFlashError() error {
  2309  	switch {
  2310  	case sam.NVMCTRL.GetINTENSET_ADDRE() != 0:
  2311  		return errFlashADDRE
  2312  	case sam.NVMCTRL.GetINTENSET_PROGE() != 0:
  2313  		return errFlashPROGE
  2314  	case sam.NVMCTRL.GetINTENSET_LOCKE() != 0:
  2315  		return errFlashLOCKE
  2316  	case sam.NVMCTRL.GetINTENSET_ECCSE() != 0:
  2317  		return errFlashECCSE
  2318  	case sam.NVMCTRL.GetINTENSET_NVME() != 0:
  2319  		return errFlashNVME
  2320  	case sam.NVMCTRL.GetINTENSET_SEESOVF() != 0:
  2321  		return errFlashSEESOVF
  2322  	}
  2323  
  2324  	return nil
  2325  }
  2326  
  2327  // Watchdog provides access to the hardware watchdog available
  2328  // in the SAMD51.
  2329  var Watchdog = &watchdogImpl{}
  2330  
  2331  const (
  2332  	// WatchdogMaxTimeout in milliseconds (16s)
  2333  	WatchdogMaxTimeout = (16384 * 1000) / 1024 // CYC16384/1024kHz
  2334  )
  2335  
  2336  type watchdogImpl struct{}
  2337  
  2338  // Configure the watchdog.
  2339  //
  2340  // This method should not be called after the watchdog is started and on
  2341  // some platforms attempting to reconfigure after starting the watchdog
  2342  // is explicitly forbidden / will not work.
  2343  func (wd *watchdogImpl) Configure(config WatchdogConfig) error {
  2344  	// 1.024kHz clock
  2345  	cycles := int((int64(config.TimeoutMillis) * 1024) / 1000)
  2346  
  2347  	// period is expressed as a power-of-two, starting at 8 / 1024ths of a second
  2348  	period := uint8(0)
  2349  	cfgCycles := 8
  2350  	for cfgCycles < cycles {
  2351  		period++
  2352  		cfgCycles <<= 1
  2353  
  2354  		if period >= 0xB {
  2355  			break
  2356  		}
  2357  	}
  2358  
  2359  	sam.WDT.CONFIG.Set(period << sam.WDT_CONFIG_PER_Pos)
  2360  
  2361  	return nil
  2362  }
  2363  
  2364  // Starts the watchdog.
  2365  func (wd *watchdogImpl) Start() error {
  2366  	sam.WDT.CTRLA.SetBits(sam.WDT_CTRLA_ENABLE)
  2367  	return nil
  2368  }
  2369  
  2370  // Update the watchdog, indicating that `source` is healthy.
  2371  func (wd *watchdogImpl) Update() {
  2372  	// 0xA5 = magic value (see datasheet)
  2373  	sam.WDT.CLEAR.Set(0xA5)
  2374  }