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  }