github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_atsamd21e18.go (about) 1 //go:build sam && atsamd21 && atsamd21e18 2 3 // Peripheral abstraction layer for the atsamd21. 4 // 5 // Datasheet: 6 // http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf 7 package machine 8 9 import ( 10 "device/sam" 11 "runtime/interrupt" 12 ) 13 14 var ( 15 sercomUSART0 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM0_USART, SERCOM: 0} 16 sercomUSART1 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM1_USART, SERCOM: 1} 17 sercomUSART2 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM2_USART, SERCOM: 2} 18 sercomUSART3 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM3_USART, SERCOM: 3} 19 20 sercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0} 21 sercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1} 22 sercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2} 23 sercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3} 24 25 sercomSPIM0 = SPI{Bus: sam.SERCOM0_SPI, SERCOM: 0} 26 sercomSPIM1 = SPI{Bus: sam.SERCOM1_SPI, SERCOM: 1} 27 sercomSPIM2 = SPI{Bus: sam.SERCOM2_SPI, SERCOM: 2} 28 sercomSPIM3 = SPI{Bus: sam.SERCOM3_SPI, SERCOM: 3} 29 ) 30 31 func init() { 32 sercomUSART0.Interrupt = interrupt.New(sam.IRQ_SERCOM0, sercomUSART0.handleInterrupt) 33 sercomUSART1.Interrupt = interrupt.New(sam.IRQ_SERCOM1, sercomUSART1.handleInterrupt) 34 sercomUSART2.Interrupt = interrupt.New(sam.IRQ_SERCOM2, sercomUSART2.handleInterrupt) 35 sercomUSART3.Interrupt = interrupt.New(sam.IRQ_SERCOM3, sercomUSART3.handleInterrupt) 36 } 37 38 // Return the register and mask to enable a given GPIO pin. This can be used to 39 // implement bit-banged drivers. 40 func (p Pin) PortMaskSet() (*uint32, uint32) { 41 return &sam.PORT.OUTSET0.Reg, 1 << uint8(p) 42 } 43 44 // Return the register and mask to disable a given port. This can be used to 45 // implement bit-banged drivers. 46 func (p Pin) PortMaskClear() (*uint32, uint32) { 47 return &sam.PORT.OUTCLR0.Reg, 1 << uint8(p) 48 } 49 50 // Set the pin to high or low. 51 // Warning: only use this on an output pin! 52 func (p Pin) Set(high bool) { 53 if high { 54 sam.PORT.OUTSET0.Set(1 << uint8(p)) 55 } else { 56 sam.PORT.OUTCLR0.Set(1 << uint8(p)) 57 } 58 } 59 60 // Get returns the current value of a GPIO pin when configured as an input or as 61 // an output. 62 func (p Pin) Get() bool { 63 return (sam.PORT.IN0.Get()>>uint8(p))&1 > 0 64 } 65 66 // Configure this pin with the given configuration. 67 func (p Pin) Configure(config PinConfig) { 68 switch config.Mode { 69 case PinOutput: 70 sam.PORT.DIRSET0.Set(1 << uint8(p)) 71 // output is also set to input enable so pin can read back its own value 72 p.setPinCfg(sam.PORT_PINCFG0_INEN) 73 74 case PinInput: 75 sam.PORT.DIRCLR0.Set(1 << uint8(p)) 76 p.setPinCfg(sam.PORT_PINCFG0_INEN) 77 78 case PinInputPulldown: 79 sam.PORT.DIRCLR0.Set(1 << uint8(p)) 80 sam.PORT.OUTCLR0.Set(1 << uint8(p)) 81 p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN) 82 83 case PinInputPullup: 84 sam.PORT.DIRCLR0.Set(1 << uint8(p)) 85 sam.PORT.OUTSET0.Set(1 << uint8(p)) 86 p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN) 87 88 case PinSERCOM: 89 if uint8(p)&1 > 0 { 90 // odd pin, so save the even pins 91 val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk 92 p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos)) 93 } else { 94 // even pin, so save the odd pins 95 val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk 96 p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos)) 97 } 98 // enable port config 99 p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN) 100 101 case PinSERCOMAlt: 102 if uint8(p)&1 > 0 { 103 // odd pin, so save the even pins 104 val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk 105 p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos)) 106 } else { 107 // even pin, so save the odd pins 108 val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk 109 p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos)) 110 } 111 // enable port config 112 p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR) 113 114 case PinCom: 115 if uint8(p)&1 > 0 { 116 // odd pin, so save the even pins 117 val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk 118 p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXO_Pos)) 119 } else { 120 // even pin, so save the odd pins 121 val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk 122 p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXE_Pos)) 123 } 124 // enable port config 125 p.setPinCfg(sam.PORT_PINCFG0_PMUXEN) 126 case PinAnalog: 127 if uint8(p)&1 > 0 { 128 // odd pin, so save the even pins 129 val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk 130 p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXO_Pos)) 131 } else { 132 // even pin, so save the odd pins 133 val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk 134 p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXE_Pos)) 135 } 136 // enable port config 137 p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR) 138 } 139 } 140 141 // getPMux returns the value for the correct PMUX register for this pin. 142 func (p Pin) getPMux() uint8 { 143 switch p >> 1 { 144 case 0: 145 return sam.PORT.PMUX0_0.Get() 146 case 1: 147 return sam.PORT.PMUX0_1.Get() 148 case 2: 149 return sam.PORT.PMUX0_2.Get() 150 case 3: 151 return sam.PORT.PMUX0_3.Get() 152 case 4: 153 return sam.PORT.PMUX0_4.Get() 154 case 5: 155 return sam.PORT.PMUX0_5.Get() 156 case 6: 157 return sam.PORT.PMUX0_6.Get() 158 case 7: 159 return sam.PORT.PMUX0_7.Get() 160 case 8: 161 return sam.PORT.PMUX0_8.Get() 162 case 9: 163 return sam.PORT.PMUX0_9.Get() 164 case 10: 165 return sam.PORT.PMUX0_10.Get() 166 case 11: 167 return sam.PORT.PMUX0_11.Get() 168 case 12: 169 return sam.PORT.PMUX0_12.Get() 170 case 13: 171 return sam.PORT.PMUX0_13.Get() 172 case 14: 173 return sam.PORT.PMUX0_14.Get() 174 case 15: 175 return sam.PORT.PMUX0_15.Get() 176 default: 177 return 0 178 } 179 } 180 181 // setPMux sets the value for the correct PMUX register for this pin. 182 func (p Pin) setPMux(val uint8) { 183 switch p >> 1 { 184 case 0: 185 sam.PORT.PMUX0_0.Set(val) 186 case 1: 187 sam.PORT.PMUX0_1.Set(val) 188 case 2: 189 sam.PORT.PMUX0_2.Set(val) 190 case 3: 191 sam.PORT.PMUX0_3.Set(val) 192 case 4: 193 sam.PORT.PMUX0_4.Set(val) 194 case 5: 195 sam.PORT.PMUX0_5.Set(val) 196 case 6: 197 sam.PORT.PMUX0_6.Set(val) 198 case 7: 199 sam.PORT.PMUX0_7.Set(val) 200 case 8: 201 sam.PORT.PMUX0_8.Set(val) 202 case 9: 203 sam.PORT.PMUX0_9.Set(val) 204 case 10: 205 sam.PORT.PMUX0_10.Set(val) 206 case 11: 207 sam.PORT.PMUX0_11.Set(val) 208 case 12: 209 sam.PORT.PMUX0_12.Set(val) 210 case 13: 211 sam.PORT.PMUX0_13.Set(val) 212 case 14: 213 sam.PORT.PMUX0_14.Set(val) 214 case 15: 215 sam.PORT.PMUX0_15.Set(val) 216 } 217 } 218 219 // getPinCfg returns the value for the correct PINCFG register for this pin. 220 func (p Pin) getPinCfg() uint8 { 221 switch p { 222 case 0: 223 return sam.PORT.PINCFG0_0.Get() 224 case 1: 225 return sam.PORT.PINCFG0_1.Get() 226 case 2: 227 return sam.PORT.PINCFG0_2.Get() 228 case 3: 229 return sam.PORT.PINCFG0_3.Get() 230 case 4: 231 return sam.PORT.PINCFG0_4.Get() 232 case 5: 233 return sam.PORT.PINCFG0_5.Get() 234 case 6: 235 return sam.PORT.PINCFG0_6.Get() 236 case 7: 237 return sam.PORT.PINCFG0_7.Get() 238 case 8: 239 return sam.PORT.PINCFG0_8.Get() 240 case 9: 241 return sam.PORT.PINCFG0_9.Get() 242 case 10: 243 return sam.PORT.PINCFG0_10.Get() 244 case 11: 245 return sam.PORT.PINCFG0_11.Get() 246 case 12: 247 return sam.PORT.PINCFG0_12.Get() 248 case 13: 249 return sam.PORT.PINCFG0_13.Get() 250 case 14: 251 return sam.PORT.PINCFG0_14.Get() 252 case 15: 253 return sam.PORT.PINCFG0_15.Get() 254 case 16: 255 return sam.PORT.PINCFG0_16.Get() 256 case 17: 257 return sam.PORT.PINCFG0_17.Get() 258 case 18: 259 return sam.PORT.PINCFG0_18.Get() 260 case 19: 261 return sam.PORT.PINCFG0_19.Get() 262 case 20: 263 return sam.PORT.PINCFG0_20.Get() 264 case 21: 265 return sam.PORT.PINCFG0_21.Get() 266 case 22: 267 return sam.PORT.PINCFG0_22.Get() 268 case 23: 269 return sam.PORT.PINCFG0_23.Get() 270 case 24: 271 return sam.PORT.PINCFG0_24.Get() 272 case 25: 273 return sam.PORT.PINCFG0_25.Get() 274 case 26: 275 return sam.PORT.PINCFG0_26.Get() 276 case 27: 277 return sam.PORT.PINCFG0_27.Get() 278 case 28: 279 return sam.PORT.PINCFG0_28.Get() 280 case 29: 281 return sam.PORT.PINCFG0_29.Get() 282 case 30: 283 return sam.PORT.PINCFG0_30.Get() 284 case 31: 285 return sam.PORT.PINCFG0_31.Get() 286 default: 287 return 0 288 } 289 } 290 291 // setPinCfg sets the value for the correct PINCFG register for this pin. 292 func (p Pin) setPinCfg(val uint8) { 293 switch p { 294 case 0: 295 sam.PORT.PINCFG0_0.Set(val) 296 case 1: 297 sam.PORT.PINCFG0_1.Set(val) 298 case 2: 299 sam.PORT.PINCFG0_2.Set(val) 300 case 3: 301 sam.PORT.PINCFG0_3.Set(val) 302 case 4: 303 sam.PORT.PINCFG0_4.Set(val) 304 case 5: 305 sam.PORT.PINCFG0_5.Set(val) 306 case 6: 307 sam.PORT.PINCFG0_6.Set(val) 308 case 7: 309 sam.PORT.PINCFG0_7.Set(val) 310 case 8: 311 sam.PORT.PINCFG0_8.Set(val) 312 case 9: 313 sam.PORT.PINCFG0_9.Set(val) 314 case 10: 315 sam.PORT.PINCFG0_10.Set(val) 316 case 11: 317 sam.PORT.PINCFG0_11.Set(val) 318 case 12: 319 sam.PORT.PINCFG0_12.Set(val) 320 case 13: 321 sam.PORT.PINCFG0_13.Set(val) 322 case 14: 323 sam.PORT.PINCFG0_14.Set(val) 324 case 15: 325 sam.PORT.PINCFG0_15.Set(val) 326 case 16: 327 sam.PORT.PINCFG0_16.Set(val) 328 case 17: 329 sam.PORT.PINCFG0_17.Set(val) 330 case 18: 331 sam.PORT.PINCFG0_18.Set(val) 332 case 19: 333 sam.PORT.PINCFG0_19.Set(val) 334 case 20: 335 sam.PORT.PINCFG0_20.Set(val) 336 case 21: 337 sam.PORT.PINCFG0_21.Set(val) 338 case 22: 339 sam.PORT.PINCFG0_22.Set(val) 340 case 23: 341 sam.PORT.PINCFG0_23.Set(val) 342 case 24: 343 sam.PORT.PINCFG0_24.Set(val) 344 case 25: 345 sam.PORT.PINCFG0_25.Set(val) 346 case 26: 347 sam.PORT.PINCFG0_26.Set(val) 348 case 27: 349 sam.PORT.PINCFG0_27.Set(val) 350 case 28: 351 sam.PORT.PINCFG0_28.Set(val) 352 case 29: 353 sam.PORT.PINCFG0_29.Set(val) 354 case 30: 355 sam.PORT.PINCFG0_30.Set(val) 356 case 31: 357 sam.PORT.PINCFG0_31.Set(val) 358 } 359 }