//go:build sam && atsamd21 && atsamd21e18 // Peripheral abstraction layer for the atsamd21. // // Datasheet: // http://ww1.microchip.com/downloads/en/DeviceDoc/SAMD21-Family-DataSheet-DS40001882D.pdf package machine import ( "device/sam" "runtime/interrupt" ) var ( sercomUSART0 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM0_USART, SERCOM: 0} sercomUSART1 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM1_USART, SERCOM: 1} sercomUSART2 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM2_USART, SERCOM: 2} sercomUSART3 = UART{Buffer: NewRingBuffer(), Bus: sam.SERCOM3_USART, SERCOM: 3} sercomI2CM0 = &I2C{Bus: sam.SERCOM0_I2CM, SERCOM: 0} sercomI2CM1 = &I2C{Bus: sam.SERCOM1_I2CM, SERCOM: 1} sercomI2CM2 = &I2C{Bus: sam.SERCOM2_I2CM, SERCOM: 2} sercomI2CM3 = &I2C{Bus: sam.SERCOM3_I2CM, SERCOM: 3} sercomSPIM0 = SPI{Bus: sam.SERCOM0_SPI, SERCOM: 0} sercomSPIM1 = SPI{Bus: sam.SERCOM1_SPI, SERCOM: 1} sercomSPIM2 = SPI{Bus: sam.SERCOM2_SPI, SERCOM: 2} sercomSPIM3 = SPI{Bus: sam.SERCOM3_SPI, SERCOM: 3} ) func init() { sercomUSART0.Interrupt = interrupt.New(sam.IRQ_SERCOM0, sercomUSART0.handleInterrupt) sercomUSART1.Interrupt = interrupt.New(sam.IRQ_SERCOM1, sercomUSART1.handleInterrupt) sercomUSART2.Interrupt = interrupt.New(sam.IRQ_SERCOM2, sercomUSART2.handleInterrupt) sercomUSART3.Interrupt = interrupt.New(sam.IRQ_SERCOM3, sercomUSART3.handleInterrupt) } // Return the register and mask to enable a given GPIO pin. This can be used to // implement bit-banged drivers. func (p Pin) PortMaskSet() (*uint32, uint32) { return &sam.PORT.OUTSET0.Reg, 1 << uint8(p) } // Return the register and mask to disable a given port. This can be used to // implement bit-banged drivers. func (p Pin) PortMaskClear() (*uint32, uint32) { return &sam.PORT.OUTCLR0.Reg, 1 << uint8(p) } // Set the pin to high or low. // Warning: only use this on an output pin! func (p Pin) Set(high bool) { if high { sam.PORT.OUTSET0.Set(1 << uint8(p)) } else { sam.PORT.OUTCLR0.Set(1 << uint8(p)) } } // Get returns the current value of a GPIO pin when configured as an input or as // an output. func (p Pin) Get() bool { return (sam.PORT.IN0.Get()>>uint8(p))&1 > 0 } // Configure this pin with the given configuration. func (p Pin) Configure(config PinConfig) { switch config.Mode { case PinOutput: sam.PORT.DIRSET0.Set(1 << uint8(p)) // output is also set to input enable so pin can read back its own value p.setPinCfg(sam.PORT_PINCFG0_INEN) case PinInput: sam.PORT.DIRCLR0.Set(1 << uint8(p)) p.setPinCfg(sam.PORT_PINCFG0_INEN) case PinInputPulldown: sam.PORT.DIRCLR0.Set(1 << uint8(p)) sam.PORT.OUTCLR0.Set(1 << uint8(p)) p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN) case PinInputPullup: sam.PORT.DIRCLR0.Set(1 << uint8(p)) sam.PORT.OUTSET0.Set(1 << uint8(p)) p.setPinCfg(sam.PORT_PINCFG0_INEN | sam.PORT_PINCFG0_PULLEN) case PinSERCOM: if uint8(p)&1 > 0 { // odd pin, so save the even pins val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXO_Pos)) } else { // even pin, so save the odd pins val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk p.setPMux(val | (uint8(PinSERCOM) << sam.PORT_PMUX0_PMUXE_Pos)) } // enable port config p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR | sam.PORT_PINCFG0_INEN) case PinSERCOMAlt: if uint8(p)&1 > 0 { // odd pin, so save the even pins val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXO_Pos)) } else { // even pin, so save the odd pins val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk p.setPMux(val | (uint8(PinSERCOMAlt) << sam.PORT_PMUX0_PMUXE_Pos)) } // enable port config p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR) case PinCom: if uint8(p)&1 > 0 { // odd pin, so save the even pins val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXO_Pos)) } else { // even pin, so save the odd pins val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk p.setPMux(val | (uint8(PinCom) << sam.PORT_PMUX0_PMUXE_Pos)) } // enable port config p.setPinCfg(sam.PORT_PINCFG0_PMUXEN) case PinAnalog: if uint8(p)&1 > 0 { // odd pin, so save the even pins val := p.getPMux() & sam.PORT_PMUX0_PMUXE_Msk p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXO_Pos)) } else { // even pin, so save the odd pins val := p.getPMux() & sam.PORT_PMUX0_PMUXO_Msk p.setPMux(val | (uint8(PinAnalog) << sam.PORT_PMUX0_PMUXE_Pos)) } // enable port config p.setPinCfg(sam.PORT_PINCFG0_PMUXEN | sam.PORT_PINCFG0_DRVSTR) } } // getPMux returns the value for the correct PMUX register for this pin. func (p Pin) getPMux() uint8 { switch p >> 1 { case 0: return sam.PORT.PMUX0_0.Get() case 1: return sam.PORT.PMUX0_1.Get() case 2: return sam.PORT.PMUX0_2.Get() case 3: return sam.PORT.PMUX0_3.Get() case 4: return sam.PORT.PMUX0_4.Get() case 5: return sam.PORT.PMUX0_5.Get() case 6: return sam.PORT.PMUX0_6.Get() case 7: return sam.PORT.PMUX0_7.Get() case 8: return sam.PORT.PMUX0_8.Get() case 9: return sam.PORT.PMUX0_9.Get() case 10: return sam.PORT.PMUX0_10.Get() case 11: return sam.PORT.PMUX0_11.Get() case 12: return sam.PORT.PMUX0_12.Get() case 13: return sam.PORT.PMUX0_13.Get() case 14: return sam.PORT.PMUX0_14.Get() case 15: return sam.PORT.PMUX0_15.Get() default: return 0 } } // setPMux sets the value for the correct PMUX register for this pin. func (p Pin) setPMux(val uint8) { switch p >> 1 { case 0: sam.PORT.PMUX0_0.Set(val) case 1: sam.PORT.PMUX0_1.Set(val) case 2: sam.PORT.PMUX0_2.Set(val) case 3: sam.PORT.PMUX0_3.Set(val) case 4: sam.PORT.PMUX0_4.Set(val) case 5: sam.PORT.PMUX0_5.Set(val) case 6: sam.PORT.PMUX0_6.Set(val) case 7: sam.PORT.PMUX0_7.Set(val) case 8: sam.PORT.PMUX0_8.Set(val) case 9: sam.PORT.PMUX0_9.Set(val) case 10: sam.PORT.PMUX0_10.Set(val) case 11: sam.PORT.PMUX0_11.Set(val) case 12: sam.PORT.PMUX0_12.Set(val) case 13: sam.PORT.PMUX0_13.Set(val) case 14: sam.PORT.PMUX0_14.Set(val) case 15: sam.PORT.PMUX0_15.Set(val) } } // getPinCfg returns the value for the correct PINCFG register for this pin. func (p Pin) getPinCfg() uint8 { switch p { case 0: return sam.PORT.PINCFG0_0.Get() case 1: return sam.PORT.PINCFG0_1.Get() case 2: return sam.PORT.PINCFG0_2.Get() case 3: return sam.PORT.PINCFG0_3.Get() case 4: return sam.PORT.PINCFG0_4.Get() case 5: return sam.PORT.PINCFG0_5.Get() case 6: return sam.PORT.PINCFG0_6.Get() case 7: return sam.PORT.PINCFG0_7.Get() case 8: return sam.PORT.PINCFG0_8.Get() case 9: return sam.PORT.PINCFG0_9.Get() case 10: return sam.PORT.PINCFG0_10.Get() case 11: return sam.PORT.PINCFG0_11.Get() case 12: return sam.PORT.PINCFG0_12.Get() case 13: return sam.PORT.PINCFG0_13.Get() case 14: return sam.PORT.PINCFG0_14.Get() case 15: return sam.PORT.PINCFG0_15.Get() case 16: return sam.PORT.PINCFG0_16.Get() case 17: return sam.PORT.PINCFG0_17.Get() case 18: return sam.PORT.PINCFG0_18.Get() case 19: return sam.PORT.PINCFG0_19.Get() case 20: return sam.PORT.PINCFG0_20.Get() case 21: return sam.PORT.PINCFG0_21.Get() case 22: return sam.PORT.PINCFG0_22.Get() case 23: return sam.PORT.PINCFG0_23.Get() case 24: return sam.PORT.PINCFG0_24.Get() case 25: return sam.PORT.PINCFG0_25.Get() case 26: return sam.PORT.PINCFG0_26.Get() case 27: return sam.PORT.PINCFG0_27.Get() case 28: return sam.PORT.PINCFG0_28.Get() case 29: return sam.PORT.PINCFG0_29.Get() case 30: return sam.PORT.PINCFG0_30.Get() case 31: return sam.PORT.PINCFG0_31.Get() default: return 0 } } // setPinCfg sets the value for the correct PINCFG register for this pin. func (p Pin) setPinCfg(val uint8) { switch p { case 0: sam.PORT.PINCFG0_0.Set(val) case 1: sam.PORT.PINCFG0_1.Set(val) case 2: sam.PORT.PINCFG0_2.Set(val) case 3: sam.PORT.PINCFG0_3.Set(val) case 4: sam.PORT.PINCFG0_4.Set(val) case 5: sam.PORT.PINCFG0_5.Set(val) case 6: sam.PORT.PINCFG0_6.Set(val) case 7: sam.PORT.PINCFG0_7.Set(val) case 8: sam.PORT.PINCFG0_8.Set(val) case 9: sam.PORT.PINCFG0_9.Set(val) case 10: sam.PORT.PINCFG0_10.Set(val) case 11: sam.PORT.PINCFG0_11.Set(val) case 12: sam.PORT.PINCFG0_12.Set(val) case 13: sam.PORT.PINCFG0_13.Set(val) case 14: sam.PORT.PINCFG0_14.Set(val) case 15: sam.PORT.PINCFG0_15.Set(val) case 16: sam.PORT.PINCFG0_16.Set(val) case 17: sam.PORT.PINCFG0_17.Set(val) case 18: sam.PORT.PINCFG0_18.Set(val) case 19: sam.PORT.PINCFG0_19.Set(val) case 20: sam.PORT.PINCFG0_20.Set(val) case 21: sam.PORT.PINCFG0_21.Set(val) case 22: sam.PORT.PINCFG0_22.Set(val) case 23: sam.PORT.PINCFG0_23.Set(val) case 24: sam.PORT.PINCFG0_24.Set(val) case 25: sam.PORT.PINCFG0_25.Set(val) case 26: sam.PORT.PINCFG0_26.Set(val) case 27: sam.PORT.PINCFG0_27.Set(val) case 28: sam.PORT.PINCFG0_28.Set(val) case 29: sam.PORT.PINCFG0_29.Set(val) case 30: sam.PORT.PINCFG0_30.Set(val) case 31: sam.PORT.PINCFG0_31.Set(val) } }