1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
|
/**
* Marlin 3D Printer Firmware
*
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* Fast IO functions for SAMD51
*/
#include "SAMD51.h"
/**
* Utility functions
*/
#ifndef MASK
#define MASK(PIN) _BV(PIN)
#endif
/**
* Magic I/O routines
*
* Now you can simply SET_OUTPUT(IO); WRITE(IO, HIGH); WRITE(IO, LOW);
*/
// Read a pin
#define READ(IO) ((PORT->Group[(EPortType)GET_SAMD_PORT(IO)].IN.reg & MASK(GET_SAMD_PIN(IO))) != 0)
// Write to a pin
#define WRITE(IO,V) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t mask = MASK(GET_SAMD_PIN(IO)); \
\
if (V) PORT->Group[port].OUTSET.reg = mask; \
else PORT->Group[port].OUTCLR.reg = mask; \
}while(0)
// Toggle a pin
#define TOGGLE(IO) PORT->Group[(EPortType)GET_SAMD_PORT(IO)].OUTTGL.reg = MASK(GET_SAMD_PIN(IO));
// Set pin as input
#define SET_INPUT(IO) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t pin = GET_SAMD_PIN(IO); \
\
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN); \
PORT->Group[port].DIRCLR.reg = MASK(pin); \
}while(0)
// Set pin as input with pullup
#define SET_INPUT_PULLUP(IO) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t pin = GET_SAMD_PIN(IO); \
const uint32_t mask = MASK(pin); \
\
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN | PORT_PINCFG_PULLEN); \
PORT->Group[port].DIRCLR.reg = mask; \
PORT->Group[port].OUTSET.reg = mask; \
}while(0)
// Set pin as input with pulldown
#define SET_INPUT_PULLDOWN(IO) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t pin = GET_SAMD_PIN(IO); \
const uint32_t mask = MASK(pin); \
\
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN | PORT_PINCFG_PULLEN); \
PORT->Group[port].DIRCLR.reg = mask; \
PORT->Group[port].OUTCLR.reg = mask; \
}while(0)
// Set pin as output (push pull)
#define SET_OUTPUT(IO) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t pin = GET_SAMD_PIN(IO); \
\
PORT->Group[port].DIRSET.reg = MASK(pin); \
PORT->Group[port].PINCFG[pin].reg = 0; \
}while(0)
// Set pin as output (open drain)
#define SET_OUTPUT_OD(IO) do{ \
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
const uint32_t pin = GET_SAMD_PIN(IO); \
\
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_PULLEN); \
PORT->Group[port].DIRCLR.reg = MASK(pin); \
}while(0)
// Set pin as PWM (push pull)
#define SET_PWM SET_OUTPUT
// Set pin as PWM (open drain)
#define SET_PWM_OD SET_OUTPUT_OD
// check if pin is an output
#define IS_OUTPUT(IO) ((PORT->Group[(EPortType)GET_SAMD_PORT(IO)].DIR.reg & MASK(GET_SAMD_PIN(IO))) \
|| (PORT->Group[(EPortType)GET_SAMD_PORT(IO)].PINCFG[GET_SAMD_PIN(IO)].reg & (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)) == PORT_PINCFG_PULLEN)
// check if pin is an input
#define IS_INPUT(IO) !IS_OUTPUT(IO)
// Shorthand
#define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
#define OUT_WRITE_OD(IO,V) do{ SET_OUTPUT_OD(IO); WRITE(IO,V); }while(0)
// digitalRead/Write wrappers
#define extDigitalRead(IO) digitalRead(IO)
#define extDigitalWrite(IO,V) digitalWrite(IO,V)
/**
* Ports and functions
* Added as necessary or if I feel like it- not a comprehensive list!
*/
#ifdef ADAFRUIT_GRAND_CENTRAL_M4
/*
* Adafruit Grand Central M4 has a lot of PWMs the availables are listed here.
* Some of these share the same source and so can't be used in the same time
*/
#define PWM_PIN(P) (WITHIN(P, 2, 13) || WITHIN(P, 22, 23) || WITHIN(P, 44, 45) || P == 48)
// Return fullfilled ADCx->INPUTCTRL.reg
#define PIN_TO_INPUTCTRL(P) ( (PIN_TO_AIN(P) == 0) ? ADC_INPUTCTRL_MUXPOS_AIN0 \
: (PIN_TO_AIN(P) == 1) ? ADC_INPUTCTRL_MUXPOS_AIN1 \
: (PIN_TO_AIN(P) == 2) ? ADC_INPUTCTRL_MUXPOS_AIN2 \
: (PIN_TO_AIN(P) == 3) ? ADC_INPUTCTRL_MUXPOS_AIN3 \
: (PIN_TO_AIN(P) == 4) ? ADC_INPUTCTRL_MUXPOS_AIN4 \
: (PIN_TO_AIN(P) == 5) ? ADC_INPUTCTRL_MUXPOS_AIN5 \
: (PIN_TO_AIN(P) == 6) ? ADC_INPUTCTRL_MUXPOS_AIN6 \
: (PIN_TO_AIN(P) == 7) ? ADC_INPUTCTRL_MUXPOS_AIN7 \
: (PIN_TO_AIN(P) == 8) ? ADC_INPUTCTRL_MUXPOS_AIN8 \
: (PIN_TO_AIN(P) == 9) ? ADC_INPUTCTRL_MUXPOS_AIN9 \
: (PIN_TO_AIN(P) == 10) ? ADC_INPUTCTRL_MUXPOS_AIN10 \
: (PIN_TO_AIN(P) == 11) ? ADC_INPUTCTRL_MUXPOS_AIN11 \
: (PIN_TO_AIN(P) == 12) ? ADC_INPUTCTRL_MUXPOS_AIN12 \
: (PIN_TO_AIN(P) == 13) ? ADC_INPUTCTRL_MUXPOS_AIN13 \
: (PIN_TO_AIN(P) == 14) ? ADC_INPUTCTRL_MUXPOS_AIN14 \
: ADC_INPUTCTRL_MUXPOS_AIN15)
#define ANAPIN_TO_SAMDPIN(P) ( (P == 0) ? PIN_TO_SAMD_PIN(67) \
: (P == 1) ? PIN_TO_SAMD_PIN(68) \
: (P == 2) ? PIN_TO_SAMD_PIN(69) \
: (P == 3) ? PIN_TO_SAMD_PIN(70) \
: (P == 4) ? PIN_TO_SAMD_PIN(71) \
: (P == 5) ? PIN_TO_SAMD_PIN(72) \
: (P == 6) ? PIN_TO_SAMD_PIN(73) \
: (P == 7) ? PIN_TO_SAMD_PIN(74) \
: (P == 8) ? PIN_TO_SAMD_PIN(54) \
: (P == 9) ? PIN_TO_SAMD_PIN(55) \
: (P == 10) ? PIN_TO_SAMD_PIN(56) \
: (P == 11) ? PIN_TO_SAMD_PIN(57) \
: (P == 12) ? PIN_TO_SAMD_PIN(58) \
: (P == 13) ? PIN_TO_SAMD_PIN(59) \
: (P == 14) ? PIN_TO_SAMD_PIN(60) \
: (P == 15) ? PIN_TO_SAMD_PIN(61) \
: (P == 16) ? PIN_TO_SAMD_PIN(12) \
: (P == 17) ? PIN_TO_SAMD_PIN(13) \
: PIN_TO_SAMD_PIN(9))
#define digitalPinToAnalogInput(P) (WITHIN(P, 67, 74) ? (P) - 67 : WITHIN(P, 54, 61) ? 8 + (P) - 54 : WITHIN(P, 12, 13) ? 16 + (P) - 12 : P == 9 ? 18 : -1)
/*
* pins
*/
// PORTA
#define DIO67_PIN PIN_PA02 // A0
#define DIO59_PIN PIN_PA04 // A13
#define DIO68_PIN PIN_PA05 // A1
#define DIO60_PIN PIN_PA06 // A14
#define DIO61_PIN PIN_PA07 // A15
#define DIO26_PIN PIN_PA12
#define DIO27_PIN PIN_PA13
#define DIO28_PIN PIN_PA14
#define DIO23_PIN PIN_PA15
#define DIO37_PIN PIN_PA16
#define DIO36_PIN PIN_PA17
#define DIO35_PIN PIN_PA18
#define DIO34_PIN PIN_PA19
#define DIO33_PIN PIN_PA20
#define DIO32_PIN PIN_PA21
#define DIO31_PIN PIN_PA22
#define DIO30_PIN PIN_PA23
// PORTB
#define DIO12_PIN PIN_PB00 // A16
#define DIO13_PIN PIN_PB01 // A17
#define DIO9_PIN PIN_PB02 // A18
#define DIO69_PIN PIN_PB03 // A2
#define DIO74_PIN PIN_PB04 // A7
#define DIO54_PIN PIN_PB05 // A8
#define DIO55_PIN PIN_PB06 // A9
#define DIO56_PIN PIN_PB07 // A10
#define DIO57_PIN PIN_PB08 // A11
#define DIO58_PIN PIN_PB09 // A12
#define DIO18_PIN PIN_PB12
#define DIO19_PIN PIN_PB13
#define DIO39_PIN PIN_PB14
#define DIO38_PIN PIN_PB15
#define DIO14_PIN PIN_PB16
#define DIO15_PIN PIN_PB17
#define DIO8_PIN PIN_PB18
#define DIO29_PIN PIN_PB19
#define DIO20_PIN PIN_PB20
#define DIO21_PIN PIN_PB21
#define DIO10_PIN PIN_PB22
#define DIO11_PIN PIN_PB23
#define DIO1_PIN PIN_PB24
#define DIO0_PIN PIN_PB25
#define DIO83_PIN PIN_PB28 // SD_CS
#define DIO95_PIN PIN_PB31 // SD_CD
// PORTC
#define DIO70_PIN PIN_PC00 // A3
#define DIO71_PIN PIN_PC01 // A4
#define DIO72_PIN PIN_PC02 // A5
#define DIO73_PIN PIN_PC03 // A6
#define DIO48_PIN PIN_PC04
#define DIO49_PIN PIN_PC05
#define DIO46_PIN PIN_PC06
#define DIO47_PIN PIN_PC07
#define DIO45_PIN PIN_PC10
#define DIO44_PIN PIN_PC11
#define DIO41_PIN PIN_PC12
#define DIO40_PIN PIN_PC13
#define DIO43_PIN PIN_PC14
#define DIO42_PIN PIN_PC15
#define DIO25_PIN PIN_PC16
#define DIO24_PIN PIN_PC17
#define DIO2_PIN PIN_PC18
#define DIO3_PIN PIN_PC19
#define DIO4_PIN PIN_PC20
#define DIO5_PIN PIN_PC21
#define DIO16_PIN PIN_PC22
#define DIO17_PIN PIN_PC23
#define DIO88_PIN PIN_PC24 // NEOPIXEL
// PORTD
#define DIO53_PIN PIN_PD10
#define DIO22_PIN PIN_PD12
#define DIO6_PIN PIN_PD20
#define DIO7_PIN PIN_PD21
#endif // ADAFRUIT_GRAND_CENTRAL_M4
|