[224] | 1 | /*
|
---|
| 2 | Copyright (c) 2015 Arduino LLC. All right reserved.
|
---|
| 3 |
|
---|
| 4 | This library is free software; you can redistribute it and/or
|
---|
| 5 | modify it under the terms of the GNU Lesser General Public
|
---|
| 6 | License as published by the Free Software Foundation; either
|
---|
| 7 | version 2.1 of the License, or (at your option) any later version.
|
---|
| 8 |
|
---|
| 9 | This library is distributed in the hope that it will be useful,
|
---|
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
---|
| 12 | See the GNU Lesser General Public License for more details.
|
---|
| 13 |
|
---|
| 14 | You should have received a copy of the GNU Lesser General Public
|
---|
| 15 | License along with this library; if not, write to the Free Software
|
---|
| 16 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
---|
| 17 | */
|
---|
| 18 | /*
|
---|
| 19 | **Modified 04/04/2016 by Arduino.org development team
|
---|
| 20 | */
|
---|
| 21 |
|
---|
| 22 | #pragma once
|
---|
| 23 |
|
---|
| 24 | #include <Arduino.h>
|
---|
| 25 |
|
---|
| 26 | #include <stdlib.h>
|
---|
| 27 | #include <stdio.h>
|
---|
| 28 | #include <stdint.h>
|
---|
| 29 |
|
---|
| 30 | typedef uint8_t ep_t;
|
---|
| 31 |
|
---|
| 32 | class USBDevice_SAMD21G18x {
|
---|
| 33 | public:
|
---|
| 34 | USBDevice_SAMD21G18x() : usb(USB->DEVICE) {
|
---|
| 35 | // Empty
|
---|
| 36 | }
|
---|
| 37 |
|
---|
| 38 | // USB Device function mapping
|
---|
| 39 | // ---------------------------
|
---|
| 40 |
|
---|
| 41 | // Reset USB Device
|
---|
| 42 | void reset();
|
---|
| 43 |
|
---|
| 44 | // Enable
|
---|
| 45 | inline void enable() { usb.CTRLA.bit.ENABLE = 1; }
|
---|
| 46 | inline void disable() { usb.CTRLA.bit.ENABLE = 0; }
|
---|
| 47 |
|
---|
| 48 | // USB mode (device/host)
|
---|
| 49 | inline void setUSBDeviceMode() { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_DEVICE_Val; }
|
---|
| 50 | inline void setUSBHostMode() { usb.CTRLA.bit.MODE = USB_CTRLA_MODE_HOST_Val; }
|
---|
| 51 |
|
---|
| 52 | inline void runInStandby() { usb.CTRLA.bit.RUNSTDBY = 1; }
|
---|
| 53 | inline void noRunInStandby() { usb.CTRLA.bit.RUNSTDBY = 0; }
|
---|
| 54 |
|
---|
| 55 | // USB speed
|
---|
| 56 | inline void setFullSpeed() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_0_Val; }
|
---|
| 57 | inline void setLowSpeed() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_1_Val; }
|
---|
| 58 | inline void setHiSpeed() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_2_Val; }
|
---|
| 59 | inline void setHiSpeedTestMode() { usb.CTRLB.bit.SPDCONF = USB_DEVICE_CTRLB_SPDCONF_3_Val; }
|
---|
| 60 |
|
---|
| 61 | // Authorize attach if Vbus is present
|
---|
| 62 | inline void attach() { usb.CTRLB.bit.DETACH = 0; }
|
---|
| 63 | inline void detach() { usb.CTRLB.bit.DETACH = 1; }
|
---|
| 64 |
|
---|
| 65 | // USB Interrupts
|
---|
| 66 | inline bool isEndOfResetInterrupt() { return usb.INTFLAG.bit.EORST; }
|
---|
| 67 | inline void ackEndOfResetInterrupt() { usb.INTFLAG.reg = USB_DEVICE_INTFLAG_EORST; }
|
---|
| 68 | inline void enableEndOfResetInterrupt() { usb.INTENSET.bit.EORST = 1; }
|
---|
| 69 | inline void disableEndOfResetInterrupt() { usb.INTENCLR.bit.EORST = 1; }
|
---|
| 70 |
|
---|
| 71 | inline bool isStartOfFrameInterrupt() { return usb.INTFLAG.bit.SOF; }
|
---|
| 72 | inline void ackStartOfFrameInterrupt() { usb.INTFLAG.reg = USB_DEVICE_INTFLAG_SOF; }
|
---|
| 73 | inline void enableStartOfFrameInterrupt() { usb.INTENSET.bit.SOF = 1; }
|
---|
| 74 | inline void disableStartOfFrameInterrupt() { usb.INTENCLR.bit.SOF = 1; }
|
---|
| 75 |
|
---|
| 76 | // USB Address
|
---|
| 77 | inline void setAddress(uint32_t addr) { usb.DADD.bit.DADD = addr; usb.DADD.bit.ADDEN = 1; }
|
---|
| 78 | inline void unsetAddress() { usb.DADD.bit.DADD = 0; usb.DADD.bit.ADDEN = 0; }
|
---|
| 79 |
|
---|
| 80 | // Frame number
|
---|
| 81 | inline uint16_t frameNumber() { return usb.FNUM.bit.FNUM; }
|
---|
| 82 |
|
---|
| 83 | // Load calibration values
|
---|
| 84 | void calibrate();
|
---|
| 85 |
|
---|
| 86 | // USB Device Endpoints function mapping
|
---|
| 87 | // -------------------------------------
|
---|
| 88 |
|
---|
| 89 | // Config
|
---|
| 90 | inline void epBank0SetType(ep_t ep, uint8_t type) { usb.DeviceEndpoint[ep].EPCFG.bit.EPTYPE0 = type; }
|
---|
| 91 | inline void epBank1SetType(ep_t ep, uint8_t type) { usb.DeviceEndpoint[ep].EPCFG.bit.EPTYPE1 = type; }
|
---|
| 92 |
|
---|
| 93 | // Interrupts
|
---|
| 94 | inline uint16_t epInterruptSummary() { return usb.EPINTSMRY.reg; }
|
---|
| 95 |
|
---|
| 96 | inline bool epBank0IsSetupReceived(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.RXSTP; }
|
---|
| 97 | inline bool epBank0IsStalled(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.STALL0; }
|
---|
| 98 | inline bool epBank1IsStalled(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.STALL1; }
|
---|
| 99 | inline bool epBank0IsTransferComplete(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT0; }
|
---|
| 100 | inline bool epBank1IsTransferComplete(ep_t ep) { return usb.DeviceEndpoint[ep].EPINTFLAG.bit.TRCPT1; }
|
---|
| 101 |
|
---|
| 102 | inline void epBank0AckSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP; }
|
---|
| 103 | inline void epBank0AckStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(1); }
|
---|
| 104 | inline void epBank1AckStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_STALL(2); }
|
---|
| 105 | inline void epBank0AckTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(1); }
|
---|
| 106 | inline void epBank1AckTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_TRCPT(2); }
|
---|
| 107 |
|
---|
| 108 | inline void epBank0EnableSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.RXSTP = 1; }
|
---|
| 109 | inline void epBank0EnableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL0 = 1; }
|
---|
| 110 | inline void epBank1EnableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.STALL1 = 1; }
|
---|
| 111 | inline void epBank0EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT0 = 1; }
|
---|
| 112 | inline void epBank1EnableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENSET.bit.TRCPT1 = 1; }
|
---|
| 113 |
|
---|
| 114 | inline void epBank0DisableSetupReceived(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.RXSTP = 1; }
|
---|
| 115 | inline void epBank0DisableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL0 = 1; }
|
---|
| 116 | inline void epBank1DisableStalled(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.STALL1 = 1; }
|
---|
| 117 | inline void epBank0DisableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.TRCPT0 = 1; }
|
---|
| 118 | inline void epBank1DisableTransferComplete(ep_t ep) { usb.DeviceEndpoint[ep].EPINTENCLR.bit.TRCPT1 = 1; }
|
---|
| 119 |
|
---|
| 120 | // Status
|
---|
| 121 | inline bool epBank0IsReady(ep_t ep) { return usb.DeviceEndpoint[ep].EPSTATUS.bit.BK0RDY; }
|
---|
| 122 | inline bool epBank1IsReady(ep_t ep) { return usb.DeviceEndpoint[ep].EPSTATUS.bit.BK1RDY; }
|
---|
| 123 | inline void epBank0SetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.BK0RDY = 1; }
|
---|
| 124 | inline void epBank1SetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.BK1RDY = 1; }
|
---|
| 125 | inline void epBank0ResetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.BK0RDY = 1; }
|
---|
| 126 | inline void epBank1ResetReady(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.BK1RDY = 1; }
|
---|
| 127 |
|
---|
| 128 | inline void epBank0SetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.STALLRQ0 = 1; }
|
---|
| 129 | inline void epBank1SetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSSET.bit.STALLRQ1 = 1; }
|
---|
| 130 | inline void epBank0ResetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.STALLRQ0 = 1; }
|
---|
| 131 | inline void epBank1ResetStallReq(ep_t ep) { usb.DeviceEndpoint[ep].EPSTATUSCLR.bit.STALLRQ1 = 1; }
|
---|
| 132 |
|
---|
| 133 | // Packet
|
---|
| 134 | inline uint16_t epBank0ByteCount(ep_t ep) { return EP[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT; }
|
---|
| 135 | inline uint16_t epBank1ByteCount(ep_t ep) { return EP[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT; }
|
---|
| 136 | inline void epBank0SetByteCount(ep_t ep, uint16_t bc) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.BYTE_COUNT = bc; }
|
---|
| 137 | inline void epBank1SetByteCount(ep_t ep, uint16_t bc) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.BYTE_COUNT = bc; }
|
---|
| 138 | inline void epBank0SetMultiPacketSize(ep_t ep, uint16_t s) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.MULTI_PACKET_SIZE = s; }
|
---|
| 139 | inline void epBank1SetMultiPacketSize(ep_t ep, uint16_t s) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.MULTI_PACKET_SIZE = s; }
|
---|
| 140 |
|
---|
| 141 | inline void epBank0SetAddress(ep_t ep, void *addr) { EP[ep].DeviceDescBank[0].ADDR.reg = (uint32_t)addr; }
|
---|
| 142 | inline void epBank1SetAddress(ep_t ep, void *addr) { EP[ep].DeviceDescBank[1].ADDR.reg = (uint32_t)addr; }
|
---|
| 143 | inline void epBank0SetSize(ep_t ep, uint16_t size) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.SIZE = EP_PCKSIZE_SIZE(size); }
|
---|
| 144 | inline void epBank1SetSize(ep_t ep, uint16_t size) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.SIZE = EP_PCKSIZE_SIZE(size); }
|
---|
| 145 | inline uint8_t EP_PCKSIZE_SIZE(uint16_t size) {
|
---|
| 146 | switch (size) {
|
---|
| 147 | case 8: return 0;
|
---|
| 148 | case 16: return 1;
|
---|
| 149 | case 32: return 2;
|
---|
| 150 | case 64: return 3;
|
---|
| 151 | case 128: return 4;
|
---|
| 152 | case 256: return 5;
|
---|
| 153 | case 512: return 6;
|
---|
| 154 | case 1023: return 7;
|
---|
| 155 | default: return 0;
|
---|
| 156 | }
|
---|
| 157 | }
|
---|
| 158 |
|
---|
| 159 | inline void epBank0DisableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 0; }
|
---|
| 160 | inline void epBank1DisableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 0; }
|
---|
| 161 | inline void epBank0EnableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[0].PCKSIZE.bit.AUTO_ZLP = 1; }
|
---|
| 162 | inline void epBank1EnableAutoZLP(ep_t ep) { EP[ep].DeviceDescBank[1].PCKSIZE.bit.AUTO_ZLP = 1; }
|
---|
| 163 |
|
---|
| 164 | private:
|
---|
| 165 | // USB Device registers
|
---|
| 166 | UsbDevice &usb;
|
---|
| 167 |
|
---|
| 168 | // Endpoints descriptors table
|
---|
| 169 | __attribute__((__aligned__(4))) UsbDeviceDescriptor EP[USB_EPT_NUM];
|
---|
| 170 | };
|
---|
| 171 |
|
---|
| 172 | void USBDevice_SAMD21G18x::reset() {
|
---|
| 173 | usb.CTRLA.bit.SWRST = 1;
|
---|
| 174 | memset(EP, 0, sizeof(EP));
|
---|
| 175 | while (usb.SYNCBUSY.bit.SWRST) {}
|
---|
| 176 | usb.DESCADD.reg = (uint32_t)(&EP);
|
---|
| 177 | }
|
---|
| 178 |
|
---|
| 179 | void USBDevice_SAMD21G18x::calibrate() {
|
---|
| 180 | // Load Pad Calibration data from non-volatile memory
|
---|
| 181 | uint32_t *pad_transn_p = (uint32_t *) USB_FUSES_TRANSN_ADDR;
|
---|
| 182 | uint32_t *pad_transp_p = (uint32_t *) USB_FUSES_TRANSP_ADDR;
|
---|
| 183 | uint32_t *pad_trim_p = (uint32_t *) USB_FUSES_TRIM_ADDR;
|
---|
| 184 |
|
---|
| 185 | uint32_t pad_transn = (*pad_transn_p & USB_FUSES_TRANSN_Msk) >> USB_FUSES_TRANSN_Pos;
|
---|
| 186 | uint32_t pad_transp = (*pad_transp_p & USB_FUSES_TRANSP_Msk) >> USB_FUSES_TRANSP_Pos;
|
---|
| 187 | uint32_t pad_trim = (*pad_trim_p & USB_FUSES_TRIM_Msk ) >> USB_FUSES_TRIM_Pos;
|
---|
| 188 |
|
---|
| 189 | if (pad_transn == 0x1F) // maximum value (31)
|
---|
| 190 | pad_transn = 5;
|
---|
| 191 | if (pad_transp == 0x1F) // maximum value (31)
|
---|
| 192 | pad_transp = 29;
|
---|
| 193 | if (pad_trim == 0x7) // maximum value (7)
|
---|
| 194 | pad_trim = 3;
|
---|
| 195 |
|
---|
| 196 | usb.PADCAL.bit.TRANSN = pad_transn;
|
---|
| 197 | usb.PADCAL.bit.TRANSP = pad_transp;
|
---|
| 198 | usb.PADCAL.bit.TRIM = pad_trim;
|
---|
| 199 | }
|
---|
| 200 |
|
---|