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 }