Subversion Repositories Tronxy-X3A-Marlin

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 ron 1
//https://github.com/niteris/ArduinoSoftSpi
2
 
3
#include <Arduino.h>
4
#ifdef __arm__
5
#ifdef CORE_TEENSY
6
//------------------------------------------------------------------------------
7
/** read pin value
8
 * @param[in] pin Arduino pin number
9
 * @return value read
10
 */
11
static inline __attribute__((always_inline))
12
bool fastDigitalRead(uint8_t pin) {
13
  return *portInputRegister(pin);
14
}
15
//------------------------------------------------------------------------------
16
/** Set pin value
17
 * @param[in] pin Arduino pin number
18
 * @param[in] level value to write
19
 */
20
static inline __attribute__((always_inline))
21
void fastDigitalWrite(uint8_t pin, bool value) {
22
  if (value) {
23
    *portSetRegister(pin) = 1;
24
  } else {
25
    *portClearRegister(pin) = 1;
26
  }
27
}
28
#else  // CORE_TEENSY
29
//------------------------------------------------------------------------------
30
/** read pin value
31
 * @param[in] pin Arduino pin number
32
 * @return value read
33
 */
34
static inline __attribute__((always_inline))
35
bool fastDigitalRead(uint8_t pin){
36
  return g_APinDescription[pin].pPort->PIO_PDSR & g_APinDescription[pin].ulPin;
37
}
38
//------------------------------------------------------------------------------
39
/** Set pin value
40
 * @param[in] pin Arduino pin number
41
 * @param[in] level value to write
42
 */
43
static inline __attribute__((always_inline))
44
void fastDigitalWrite(uint8_t pin, bool value){
45
  if (value)
46
    g_APinDescription[pin].pPort->PIO_SODR = g_APinDescription[pin].ulPin;
47
  else
48
    g_APinDescription[pin].pPort->PIO_CODR = g_APinDescription[pin].ulPin;
49
}
50
#endif  // CORE_TEENSY
51
//------------------------------------------------------------------------------
52
inline void fastDigitalToggle(uint8_t pin) {
53
 fastDigitalWrite(pin, !fastDigitalRead(pin));
54
 }
55
//------------------------------------------------------------------------------
56
inline void fastPinMode(uint8_t pin, bool mode) {pinMode(pin, mode);}
57
#else  // __arm__
58
#include <avr/io.h>
59
#include <util/atomic.h>
60
//------------------------------------------------------------------------------
61
/**
62
 * @class pin_map_t
63
 * @brief struct for mapping digital pins
64
 */
65
struct pin_map_t {
66
  volatile uint8_t* ddr;   /**< address of DDR for this pin */
67
  volatile uint8_t* pin;   /**< address of PIN for this pin */
68
  volatile uint8_t* port;  /**< address of PORT for this pin */
69
  uint8_t bit;             /**< bit number for this pin */
70
};
71
//------------------------------------------------------------------------------
72
#if defined(__AVR_ATmega168__)\
73
||defined(__AVR_ATmega168P__)\
74
||defined(__AVR_ATmega328P__)
75
// 168 and 328 Arduinos
76
const static pin_map_t pinMap[] = {
77
  {&DDRD, &PIND, &PORTD, 0},  // D0  0
78
  {&DDRD, &PIND, &PORTD, 1},  // D1  1
79
  {&DDRD, &PIND, &PORTD, 2},  // D2  2
80
  {&DDRD, &PIND, &PORTD, 3},  // D3  3
81
  {&DDRD, &PIND, &PORTD, 4},  // D4  4
82
  {&DDRD, &PIND, &PORTD, 5},  // D5  5
83
  {&DDRD, &PIND, &PORTD, 6},  // D6  6
84
  {&DDRD, &PIND, &PORTD, 7},  // D7  7
85
  {&DDRB, &PINB, &PORTB, 0},  // B0  8
86
  {&DDRB, &PINB, &PORTB, 1},  // B1  9
87
  {&DDRB, &PINB, &PORTB, 2},  // B2 10
88
  {&DDRB, &PINB, &PORTB, 3},  // B3 11
89
  {&DDRB, &PINB, &PORTB, 4},  // B4 12
90
  {&DDRB, &PINB, &PORTB, 5},  // B5 13
91
  {&DDRC, &PINC, &PORTC, 0},  // C0 14
92
  {&DDRC, &PINC, &PORTC, 1},  // C1 15
93
  {&DDRC, &PINC, &PORTC, 2},  // C2 16
94
  {&DDRC, &PINC, &PORTC, 3},  // C3 17
95
  {&DDRC, &PINC, &PORTC, 4},  // C4 18
96
  {&DDRC, &PINC, &PORTC, 5}   // C5 19
97
};
98
//------------------------------------------------------------------------------
99
#elif defined(__AVR_ATmega1280__)\
100
|| defined(__AVR_ATmega2560__)
101
// Mega
102
static const pin_map_t pinMap[] = {
103
  {&DDRE, &PINE, &PORTE, 0},  // E0  0
104
  {&DDRE, &PINE, &PORTE, 1},  // E1  1
105
  {&DDRE, &PINE, &PORTE, 4},  // E4  2
106
  {&DDRE, &PINE, &PORTE, 5},  // E5  3
107
  {&DDRG, &PING, &PORTG, 5},  // G5  4
108
  {&DDRE, &PINE, &PORTE, 3},  // E3  5
109
  {&DDRH, &PINH, &PORTH, 3},  // H3  6
110
  {&DDRH, &PINH, &PORTH, 4},  // H4  7
111
  {&DDRH, &PINH, &PORTH, 5},  // H5  8
112
  {&DDRH, &PINH, &PORTH, 6},  // H6  9
113
  {&DDRB, &PINB, &PORTB, 4},  // B4 10
114
  {&DDRB, &PINB, &PORTB, 5},  // B5 11
115
  {&DDRB, &PINB, &PORTB, 6},  // B6 12
116
  {&DDRB, &PINB, &PORTB, 7},  // B7 13
117
  {&DDRJ, &PINJ, &PORTJ, 1},  // J1 14
118
  {&DDRJ, &PINJ, &PORTJ, 0},  // J0 15
119
  {&DDRH, &PINH, &PORTH, 1},  // H1 16
120
  {&DDRH, &PINH, &PORTH, 0},  // H0 17
121
  {&DDRD, &PIND, &PORTD, 3},  // D3 18
122
  {&DDRD, &PIND, &PORTD, 2},  // D2 19
123
  {&DDRD, &PIND, &PORTD, 1},  // D1 20
124
  {&DDRD, &PIND, &PORTD, 0},  // D0 21
125
  {&DDRA, &PINA, &PORTA, 0},  // A0 22
126
  {&DDRA, &PINA, &PORTA, 1},  // A1 23
127
  {&DDRA, &PINA, &PORTA, 2},  // A2 24
128
  {&DDRA, &PINA, &PORTA, 3},  // A3 25
129
  {&DDRA, &PINA, &PORTA, 4},  // A4 26
130
  {&DDRA, &PINA, &PORTA, 5},  // A5 27
131
  {&DDRA, &PINA, &PORTA, 6},  // A6 28
132
  {&DDRA, &PINA, &PORTA, 7},  // A7 29
133
  {&DDRC, &PINC, &PORTC, 7},  // C7 30
134
  {&DDRC, &PINC, &PORTC, 6},  // C6 31
135
  {&DDRC, &PINC, &PORTC, 5},  // C5 32
136
  {&DDRC, &PINC, &PORTC, 4},  // C4 33
137
  {&DDRC, &PINC, &PORTC, 3},  // C3 34
138
  {&DDRC, &PINC, &PORTC, 2},  // C2 35
139
  {&DDRC, &PINC, &PORTC, 1},  // C1 36
140
  {&DDRC, &PINC, &PORTC, 0},  // C0 37
141
  {&DDRD, &PIND, &PORTD, 7},  // D7 38
142
  {&DDRG, &PING, &PORTG, 2},  // G2 39
143
  {&DDRG, &PING, &PORTG, 1},  // G1 40
144
  {&DDRG, &PING, &PORTG, 0},  // G0 41
145
  {&DDRL, &PINL, &PORTL, 7},  // L7 42
146
  {&DDRL, &PINL, &PORTL, 6},  // L6 43
147
  {&DDRL, &PINL, &PORTL, 5},  // L5 44
148
  {&DDRL, &PINL, &PORTL, 4},  // L4 45
149
  {&DDRL, &PINL, &PORTL, 3},  // L3 46
150
  {&DDRL, &PINL, &PORTL, 2},  // L2 47
151
  {&DDRL, &PINL, &PORTL, 1},  // L1 48
152
  {&DDRL, &PINL, &PORTL, 0},  // L0 49
153
  {&DDRB, &PINB, &PORTB, 3},  // B3 50
154
  {&DDRB, &PINB, &PORTB, 2},  // B2 51
155
  {&DDRB, &PINB, &PORTB, 1},  // B1 52
156
  {&DDRB, &PINB, &PORTB, 0},  // B0 53
157
  {&DDRF, &PINF, &PORTF, 0},  // F0 54
158
  {&DDRF, &PINF, &PORTF, 1},  // F1 55
159
  {&DDRF, &PINF, &PORTF, 2},  // F2 56
160
  {&DDRF, &PINF, &PORTF, 3},  // F3 57
161
  {&DDRF, &PINF, &PORTF, 4},  // F4 58
162
  {&DDRF, &PINF, &PORTF, 5},  // F5 59
163
  {&DDRF, &PINF, &PORTF, 6},  // F6 60
164
  {&DDRF, &PINF, &PORTF, 7},  // F7 61
165
  {&DDRK, &PINK, &PORTK, 0},  // K0 62
166
  {&DDRK, &PINK, &PORTK, 1},  // K1 63
167
  {&DDRK, &PINK, &PORTK, 2},  // K2 64
168
  {&DDRK, &PINK, &PORTK, 3},  // K3 65
169
  {&DDRK, &PINK, &PORTK, 4},  // K4 66
170
  {&DDRK, &PINK, &PORTK, 5},  // K5 67
171
  {&DDRK, &PINK, &PORTK, 6},  // K6 68
172
  {&DDRK, &PINK, &PORTK, 7},  // K7 69
173
 
174
//pins_MIGHTYBOARD_REVE.h
175
  {&DDRG, &PING, &PORTG, 4},  // G4 70
176
  {&DDRG, &PING, &PORTG, 3},  // G3 71
177
  {&DDRJ, &PINJ, &PORTJ, 2},  // J2 72
178
  {&DDRJ, &PINJ, &PORTJ, 3},  // J3 73
179
  {&DDRJ, &PINJ, &PORTJ, 7},  // J7 74
180
  {&DDRJ, &PINJ, &PORTJ, 4},  // J4 75
181
  {&DDRJ, &PINJ, &PORTJ, 5},  // J5 76
182
  {&DDRJ, &PINJ, &PORTJ, 6},  // J6 77
183
  {&DDRE, &PINE, &PORTE, 2},  // E2 78
184
  {&DDRE, &PINE, &PORTE, 6}   // E6 79
185
 
186
};
187
//------------------------------------------------------------------------------
188
#elif defined(__AVR_ATmega1284P__)\
189
|| defined(__AVR_ATmega1284__)\
190
|| defined(__AVR_ATmega644P__)\
191
|| defined(__AVR_ATmega644__)\
192
|| defined(__AVR_ATmega64__)\
193
|| defined(__AVR_ATmega32__)\
194
|| defined(__AVR_ATmega324__)\
195
|| defined(__AVR_ATmega16__)
196
 
197
#if defined(VARIANT_MIGHTY)
198
// Mighty Layout
199
static const pin_map_t pinMap[] = {
200
  {&DDRB, &PINB, &PORTB, 0},  // B0  0
201
  {&DDRB, &PINB, &PORTB, 1},  // B1  1
202
  {&DDRB, &PINB, &PORTB, 2},  // B2  2
203
  {&DDRB, &PINB, &PORTB, 3},  // B3  3
204
  {&DDRB, &PINB, &PORTB, 4},  // B4  4
205
  {&DDRB, &PINB, &PORTB, 5},  // B5  5
206
  {&DDRB, &PINB, &PORTB, 6},  // B6  6
207
  {&DDRB, &PINB, &PORTB, 7},  // B7  7
208
  {&DDRD, &PIND, &PORTD, 0},  // D0  8
209
  {&DDRD, &PIND, &PORTD, 1},  // D1  9
210
  {&DDRD, &PIND, &PORTD, 2},  // D2 10
211
  {&DDRD, &PIND, &PORTD, 3},  // D3 11
212
  {&DDRD, &PIND, &PORTD, 4},  // D4 12
213
  {&DDRD, &PIND, &PORTD, 5},  // D5 13
214
  {&DDRD, &PIND, &PORTD, 6},  // D6 14
215
  {&DDRD, &PIND, &PORTD, 7},  // D7 15
216
  {&DDRC, &PINC, &PORTC, 0},  // C0 16
217
  {&DDRC, &PINC, &PORTC, 1},  // C1 17
218
  {&DDRC, &PINC, &PORTC, 2},  // C2 18
219
  {&DDRC, &PINC, &PORTC, 3},  // C3 19
220
  {&DDRC, &PINC, &PORTC, 4},  // C4 20
221
  {&DDRC, &PINC, &PORTC, 5},  // C5 21
222
  {&DDRC, &PINC, &PORTC, 6},  // C6 22
223
  {&DDRC, &PINC, &PORTC, 7},  // C7 23
224
  {&DDRA, &PINA, &PORTA, 0},  // A0 24
225
  {&DDRA, &PINA, &PORTA, 1},  // A1 25
226
  {&DDRA, &PINA, &PORTA, 2},  // A2 26
227
  {&DDRA, &PINA, &PORTA, 3},  // A3 27
228
  {&DDRA, &PINA, &PORTA, 4},  // A4 28
229
  {&DDRA, &PINA, &PORTA, 5},  // A5 29
230
  {&DDRA, &PINA, &PORTA, 6},  // A6 30
231
  {&DDRA, &PINA, &PORTA, 7}   // A7 31
232
};
233
#elif defined(VARIANT_BOBUINO)
234
// Bobuino Layout
235
static const pin_map_t pinMap[] = {
236
  {&DDRD, &PIND, &PORTD, 0},  // D0  0
237
  {&DDRD, &PIND, &PORTD, 1},  // D1  1
238
  {&DDRD, &PIND, &PORTD, 2},  // D2  2
239
  {&DDRD, &PIND, &PORTD, 3},  // D3  3
240
  {&DDRB, &PINB, &PORTB, 0},  // B0  4
241
  {&DDRB, &PINB, &PORTB, 1},  // B1  5
242
  {&DDRB, &PINB, &PORTB, 2},  // B2  6
243
  {&DDRB, &PINB, &PORTB, 3},  // B3  7
244
  {&DDRD, &PIND, &PORTD, 5},  // D5  8
245
  {&DDRD, &PIND, &PORTD, 6},  // D6  9
246
  {&DDRB, &PINB, &PORTB, 4},  // B4 10
247
  {&DDRB, &PINB, &PORTB, 5},  // B5 11
248
  {&DDRB, &PINB, &PORTB, 6},  // B6 12
249
  {&DDRB, &PINB, &PORTB, 7},  // B7 13
250
  {&DDRA, &PINA, &PORTA, 7},  // A7 14
251
  {&DDRA, &PINA, &PORTA, 6},  // A6 15
252
  {&DDRA, &PINA, &PORTA, 5},  // A5 16
253
  {&DDRA, &PINA, &PORTA, 4},  // A4 17
254
  {&DDRA, &PINA, &PORTA, 3},  // A3 18
255
  {&DDRA, &PINA, &PORTA, 2},  // A2 19
256
  {&DDRA, &PINA, &PORTA, 1},  // A1 20
257
  {&DDRA, &PINA, &PORTA, 0},  // A0 21
258
  {&DDRC, &PINC, &PORTC, 0},  // C0 22
259
  {&DDRC, &PINC, &PORTC, 1},  // C1 23
260
  {&DDRC, &PINC, &PORTC, 2},  // C2 24
261
  {&DDRC, &PINC, &PORTC, 3},  // C3 25
262
  {&DDRC, &PINC, &PORTC, 4},  // C4 26
263
  {&DDRC, &PINC, &PORTC, 5},  // C5 27
264
  {&DDRC, &PINC, &PORTC, 6},  // C6 28
265
  {&DDRC, &PINC, &PORTC, 7},  // C7 29
266
  {&DDRD, &PIND, &PORTD, 4},  // D4 30
267
  {&DDRD, &PIND, &PORTD, 7}   // D7 31
268
};
269
#elif defined(VARIANT_STANDARD)
270
// Standard Layout
271
static const pin_map_t pinMap[] = {
272
  {&DDRB, &PINB, &PORTB, 0},  // B0  0
273
  {&DDRB, &PINB, &PORTB, 1},  // B1  1
274
  {&DDRB, &PINB, &PORTB, 2},  // B2  2
275
  {&DDRB, &PINB, &PORTB, 3},  // B3  3
276
  {&DDRB, &PINB, &PORTB, 4},  // B4  4
277
  {&DDRB, &PINB, &PORTB, 5},  // B5  5
278
  {&DDRB, &PINB, &PORTB, 6},  // B6  6
279
  {&DDRB, &PINB, &PORTB, 7},  // B7  7
280
  {&DDRD, &PIND, &PORTD, 0},  // D0  8
281
  {&DDRD, &PIND, &PORTD, 1},  // D1  9
282
  {&DDRD, &PIND, &PORTD, 2},  // D2 10
283
  {&DDRD, &PIND, &PORTD, 3},  // D3 11
284
  {&DDRD, &PIND, &PORTD, 4},  // D4 12
285
  {&DDRD, &PIND, &PORTD, 5},  // D5 13
286
  {&DDRD, &PIND, &PORTD, 6},  // D6 14
287
  {&DDRD, &PIND, &PORTD, 7},  // D7 15
288
  {&DDRC, &PINC, &PORTC, 0},  // C0 16
289
  {&DDRC, &PINC, &PORTC, 1},  // C1 17
290
  {&DDRC, &PINC, &PORTC, 2},  // C2 18
291
  {&DDRC, &PINC, &PORTC, 3},  // C3 19
292
  {&DDRC, &PINC, &PORTC, 4},  // C4 20
293
  {&DDRC, &PINC, &PORTC, 5},  // C5 21
294
  {&DDRC, &PINC, &PORTC, 6},  // C6 22
295
  {&DDRC, &PINC, &PORTC, 7},  // C7 23
296
  {&DDRA, &PINA, &PORTA, 7},  // A7 24
297
  {&DDRA, &PINA, &PORTA, 6},  // A6 25
298
  {&DDRA, &PINA, &PORTA, 5},  // A5 26
299
  {&DDRA, &PINA, &PORTA, 4},  // A4 27
300
  {&DDRA, &PINA, &PORTA, 3},  // A3 28
301
  {&DDRA, &PINA, &PORTA, 2},  // A2 29
302
  {&DDRA, &PINA, &PORTA, 1},  // A1 30
303
  {&DDRA, &PINA, &PORTA, 0}   // A0 31
304
};
305
#else  // VARIANT_MIGHTY
306
#error Undefined variant 1284, 644, 324, 64, 32
307
#endif  // VARIANT_MIGHTY
308
//------------------------------------------------------------------------------
309
#elif defined(__AVR_ATmega32U4__)
310
#ifdef CORE_TEENSY
311
// Teensy 2.0
312
static const pin_map_t pinMap[] = {
313
  {&DDRB, &PINB, &PORTB, 0},  // B0  0
314
  {&DDRB, &PINB, &PORTB, 1},  // B1  1
315
  {&DDRB, &PINB, &PORTB, 2},  // B2  2
316
  {&DDRB, &PINB, &PORTB, 3},  // B3  3
317
  {&DDRB, &PINB, &PORTB, 7},  // B7  4
318
  {&DDRD, &PIND, &PORTD, 0},  // D0  5
319
  {&DDRD, &PIND, &PORTD, 1},  // D1  6
320
  {&DDRD, &PIND, &PORTD, 2},  // D2  7
321
  {&DDRD, &PIND, &PORTD, 3},  // D3  8
322
  {&DDRC, &PINC, &PORTC, 6},  // C6  9
323
  {&DDRC, &PINC, &PORTC, 7},  // C7 10
324
  {&DDRD, &PIND, &PORTD, 6},  // D6 11
325
  {&DDRD, &PIND, &PORTD, 7},  // D7 12
326
  {&DDRB, &PINB, &PORTB, 4},  // B4 13
327
  {&DDRB, &PINB, &PORTB, 5},  // B5 14
328
  {&DDRB, &PINB, &PORTB, 6},  // B6 15
329
  {&DDRF, &PINF, &PORTF, 7},  // F7 16
330
  {&DDRF, &PINF, &PORTF, 6},  // F6 17
331
  {&DDRF, &PINF, &PORTF, 5},  // F5 18
332
  {&DDRF, &PINF, &PORTF, 4},  // F4 19
333
  {&DDRF, &PINF, &PORTF, 1},  // F1 20
334
  {&DDRF, &PINF, &PORTF, 0},  // F0 21
335
  {&DDRD, &PIND, &PORTD, 4},  // D4 22
336
  {&DDRD, &PIND, &PORTD, 5},  // D5 23
337
  {&DDRE, &PINE, &PORTE, 6}   // E6 24
338
};
339
//------------------------------------------------------------------------------
340
#else  // CORE_TEENSY
341
// Leonardo
342
static const pin_map_t pinMap[] = {
343
  {&DDRD, &PIND, &PORTD, 2},  // D2  0
344
  {&DDRD, &PIND, &PORTD, 3},  // D3  1
345
  {&DDRD, &PIND, &PORTD, 1},  // D1  2
346
  {&DDRD, &PIND, &PORTD, 0},  // D0  3
347
  {&DDRD, &PIND, &PORTD, 4},  // D4  4
348
  {&DDRC, &PINC, &PORTC, 6},  // C6  5
349
  {&DDRD, &PIND, &PORTD, 7},  // D7  6
350
  {&DDRE, &PINE, &PORTE, 6},  // E6  7
351
  {&DDRB, &PINB, &PORTB, 4},  // B4  8
352
  {&DDRB, &PINB, &PORTB, 5},  // B5  9
353
  {&DDRB, &PINB, &PORTB, 6},  // B6 10
354
  {&DDRB, &PINB, &PORTB, 7},  // B7 11
355
  {&DDRD, &PIND, &PORTD, 6},  // D6 12
356
  {&DDRC, &PINC, &PORTC, 7},  // C7 13
357
  {&DDRB, &PINB, &PORTB, 3},  // B3 14
358
  {&DDRB, &PINB, &PORTB, 1},  // B1 15
359
  {&DDRB, &PINB, &PORTB, 2},  // B2 16
360
  {&DDRB, &PINB, &PORTB, 0},  // B0 17
361
  {&DDRF, &PINF, &PORTF, 7},  // F7 18
362
  {&DDRF, &PINF, &PORTF, 6},  // F6 19
363
  {&DDRF, &PINF, &PORTF, 5},  // F5 20
364
  {&DDRF, &PINF, &PORTF, 4},  // F4 21
365
  {&DDRF, &PINF, &PORTF, 1},  // F1 22
366
  {&DDRF, &PINF, &PORTF, 0},  // F0 23
367
  {&DDRD, &PIND, &PORTD, 4},  // D4 24
368
  {&DDRD, &PIND, &PORTD, 7},  // D7 25
369
  {&DDRB, &PINB, &PORTB, 4},  // B4 26
370
  {&DDRB, &PINB, &PORTB, 5},  // B5 27
371
  {&DDRB, &PINB, &PORTB, 6},  // B6 28
372
  {&DDRD, &PIND, &PORTD, 6}   // D6 29
373
};
374
#endif  // CORE_TEENSY
375
//------------------------------------------------------------------------------
376
#elif defined(__AVR_AT90USB646__)\
377
|| defined(__AVR_AT90USB1286__)
378
// Teensy++ 1.0 & 2.0
379
static const pin_map_t pinMap[] = {
380
  {&DDRD, &PIND, &PORTD, 0},  // D0  0
381
  {&DDRD, &PIND, &PORTD, 1},  // D1  1
382
  {&DDRD, &PIND, &PORTD, 2},  // D2  2
383
  {&DDRD, &PIND, &PORTD, 3},  // D3  3
384
  {&DDRD, &PIND, &PORTD, 4},  // D4  4
385
  {&DDRD, &PIND, &PORTD, 5},  // D5  5
386
  {&DDRD, &PIND, &PORTD, 6},  // D6  6
387
  {&DDRD, &PIND, &PORTD, 7},  // D7  7
388
  {&DDRE, &PINE, &PORTE, 0},  // E0  8
389
  {&DDRE, &PINE, &PORTE, 1},  // E1  9
390
  {&DDRC, &PINC, &PORTC, 0},  // C0 10
391
  {&DDRC, &PINC, &PORTC, 1},  // C1 11
392
  {&DDRC, &PINC, &PORTC, 2},  // C2 12
393
  {&DDRC, &PINC, &PORTC, 3},  // C3 13
394
  {&DDRC, &PINC, &PORTC, 4},  // C4 14
395
  {&DDRC, &PINC, &PORTC, 5},  // C5 15
396
  {&DDRC, &PINC, &PORTC, 6},  // C6 16
397
  {&DDRC, &PINC, &PORTC, 7},  // C7 17
398
  {&DDRE, &PINE, &PORTE, 6},  // E6 18
399
  {&DDRE, &PINE, &PORTE, 7},  // E7 19
400
  {&DDRB, &PINB, &PORTB, 0},  // B0 20
401
  {&DDRB, &PINB, &PORTB, 1},  // B1 21
402
  {&DDRB, &PINB, &PORTB, 2},  // B2 22
403
  {&DDRB, &PINB, &PORTB, 3},  // B3 23
404
  {&DDRB, &PINB, &PORTB, 4},  // B4 24
405
  {&DDRB, &PINB, &PORTB, 5},  // B5 25
406
  {&DDRB, &PINB, &PORTB, 6},  // B6 26
407
  {&DDRB, &PINB, &PORTB, 7},  // B7 27
408
  {&DDRA, &PINA, &PORTA, 0},  // A0 28
409
  {&DDRA, &PINA, &PORTA, 1},  // A1 29
410
  {&DDRA, &PINA, &PORTA, 2},  // A2 30
411
  {&DDRA, &PINA, &PORTA, 3},  // A3 31
412
  {&DDRA, &PINA, &PORTA, 4},  // A4 32
413
  {&DDRA, &PINA, &PORTA, 5},  // A5 33
414
  {&DDRA, &PINA, &PORTA, 6},  // A6 34
415
  {&DDRA, &PINA, &PORTA, 7},  // A7 35
416
  {&DDRE, &PINE, &PORTE, 4},  // E4 36
417
  {&DDRE, &PINE, &PORTE, 5},  // E5 37
418
  {&DDRF, &PINF, &PORTF, 0},  // F0 38
419
  {&DDRF, &PINF, &PORTF, 1},  // F1 39
420
  {&DDRF, &PINF, &PORTF, 2},  // F2 40
421
  {&DDRF, &PINF, &PORTF, 3},  // F3 41
422
  {&DDRF, &PINF, &PORTF, 4},  // F4 42
423
  {&DDRF, &PINF, &PORTF, 5},  // F5 43
424
  {&DDRF, &PINF, &PORTF, 6},  // F6 44
425
  {&DDRF, &PINF, &PORTF, 7}   // F7 45
426
};
427
//------------------------------------------------------------------------------
428
#else  // CPU type
429
#error unknown CPU type
430
#endif  // CPU type
431
//------------------------------------------------------------------------------
432
/** count of pins */
433
static const uint8_t digitalPinCount = sizeof(pinMap)/sizeof(pin_map_t);
434
//==============================================================================
435
/** generate bad pin number error */
436
void badPinNumber(void)
437
  __attribute__((error("Pin number is too large or not a constant")));
438
//------------------------------------------------------------------------------
439
/** Check for valid pin number
440
 * @param[in] pin Number of pin to be checked.
441
 */
442
static inline __attribute__((always_inline))
443
void badPinCheck(uint8_t pin) {
444
  if (!__builtin_constant_p(pin) || pin >= digitalPinCount) {
445
     badPinNumber();
446
  }
447
}
448
//------------------------------------------------------------------------------
449
/** fast write helper
450
 * @param[in] address I/O register address
451
 * @param[in] bit bit number to write
452
 * @param[in] level value for bit
453
 */
454
static inline __attribute__((always_inline))
455
void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) {
456
  uint8_t oldSREG;
457
  if (address > (uint8_t*)0x5F) {
458
    oldSREG = SREG;
459
    cli();
460
  }
461
  if (level) {
462
    *address |= 1 << bit;
463
  } else {
464
    *address &= ~(1 << bit);
465
  }
466
  if (address > (uint8_t*)0x5F) {
467
    SREG = oldSREG;
468
  }
469
}
470
//------------------------------------------------------------------------------
471
/** read pin value
472
 * @param[in] pin Arduino pin number
473
 * @return value read
474
 */
475
static inline __attribute__((always_inline))
476
bool fastDigitalRead(uint8_t pin) {
477
  badPinCheck(pin);
478
  return (*pinMap[pin].pin >> pinMap[pin].bit) & 1;
479
}
480
//------------------------------------------------------------------------------
481
/** toggle a pin
482
 * @param[in] pin Arduino pin number
483
 *
484
 * If the pin is in output mode toggle the pin level.
485
 * If the pin is in input mode toggle the state of the 20K pullup.
486
 */
487
static inline __attribute__((always_inline))
488
void fastDigitalToggle(uint8_t pin) {
489
  badPinCheck(pin);
490
    if (pinMap[pin].pin > (uint8_t*)0x5F) {
491
      // must write bit to high address port
492
      *pinMap[pin].pin = 1 << pinMap[pin].bit;
493
    } else {
494
      // will compile to sbi and PIN register will not be read.
495
      *pinMap[pin].pin |= 1 << pinMap[pin].bit;
496
    }
497
}
498
//------------------------------------------------------------------------------
499
/** Set pin value
500
 * @param[in] pin Arduino pin number
501
 * @param[in] level value to write
502
 */
503
static inline __attribute__((always_inline))
504
void fastDigitalWrite(uint8_t pin, bool level) {
505
  badPinCheck(pin);
506
  fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level);
507
}
508
//------------------------------------------------------------------------------
509
/** set pin mode
510
 * @param[in] pin Arduino pin number
511
 * @param[in] mode if true set output mode else input mode
512
 *
513
 * fastPinMode does not enable or disable the 20K pullup for input mode.
514
 */
515
static inline __attribute__((always_inline))
516
void fastPinMode(uint8_t pin, bool mode) {
517
  badPinCheck(pin);
518
  fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode);
519
}
520
 
521
#endif  // __arm__
522
//------------------------------------------------------------------------------
523
/** set pin configuration
524
 * @param[in] pin Arduino pin number
525
 * @param[in] mode If true set output mode else input mode
526
 * @param[in] level If mode is output, set level high/low.
527
 *                  If mode is input, enable or disable the pin's 20K pullup.
528
 */
529
static inline __attribute__((always_inline))
530
void fastPinConfig(uint8_t pin, bool mode, bool level) {
531
  fastPinMode(pin, mode);
532
  fastDigitalWrite(pin, level);
533
}
534
//==============================================================================
535
/**
536
 * @class DigitalPin
537
 * @brief Fast digital port I/O
538
 */
539
template<uint8_t PinNumber>
540
class DigitalPin {
541
 public:
542
  //----------------------------------------------------------------------------
543
  /** Constructor */
544
  DigitalPin() {}
545
  //----------------------------------------------------------------------------
546
  /** Constructor
547
   * @param[in] pinMode if true set output mode else input mode.
548
   */
549
  explicit DigitalPin(bool pinMode) {
550
    mode(pinMode);
551
  }
552
  //----------------------------------------------------------------------------
553
  /** Constructor
554
   * @param[in] mode If true set output mode else input mode
555
   * @param[in] level If mode is output, set level high/low.
556
   *                  If mode is input, enable or disable the pin's 20K pullup.
557
   */
558
  DigitalPin(bool mode, bool level) {
559
    config(mode, level);
560
  }
561
  //----------------------------------------------------------------------------
562
  /** Asignment operator
563
   * @param[in] value If true set the pin's level high else set the
564
   *  pin's level low.
565
   *
566
   * @return This DigitalPin instance.
567
   */
568
  inline DigitalPin & operator = (bool value) __attribute__((always_inline)) {
569
    write(value);
570
    return *this;
571
  }
572
  //----------------------------------------------------------------------------
573
  /** Parenthesis operator
574
   * @return Pin's level
575
   */
576
  inline operator bool () const __attribute__((always_inline)) {
577
    return read();
578
  }
579
  //----------------------------------------------------------------------------
580
  /** set pin configuration
581
   * @param[in] mode If true set output mode else input mode
582
   * @param[in] level If mode is output, set level high/low.
583
   *                  If mode is input, enable or disable the pin's 20K pullup.
584
   */
585
  inline __attribute__((always_inline))
586
  void config(bool mode, bool level) {
587
    fastPinConfig(PinNumber, mode, level);
588
  }
589
  //----------------------------------------------------------------------------
590
  /**
591
   * Set pin level high if output mode or enable 20K pullup if input mode.
592
   */
593
  inline __attribute__((always_inline))
594
  void high() {write(true);}
595
  //----------------------------------------------------------------------------
596
  /**
597
   * Set pin level low if output mode or disable 20K pullup if input mode.
598
   */
599
  inline __attribute__((always_inline))
600
  void low() {write(false);}
601
  //----------------------------------------------------------------------------
602
  /**
603
   * Set pin mode
604
   * @param[in] pinMode if true set output mode else input mode.
605
   *
606
   * mode() does not enable or disable the 20K pullup for input mode.
607
   */
608
  inline __attribute__((always_inline))
609
  void mode(bool pinMode) {
610
    fastPinMode(PinNumber, pinMode);
611
  }
612
  //----------------------------------------------------------------------------
613
  /** @return Pin's level */
614
  inline __attribute__((always_inline))
615
  bool read() const {
616
    return fastDigitalRead(PinNumber);
617
  }
618
  //----------------------------------------------------------------------------
619
  /** toggle a pin
620
   *
621
   * If the pin is in output mode toggle the pin's level.
622
   * If the pin is in input mode toggle the state of the 20K pullup.
623
   */
624
  inline __attribute__((always_inline))
625
  void toggle() {
626
    fastDigitalToggle(PinNumber);
627
  }
628
  //----------------------------------------------------------------------------
629
  /** Write the pin's level.
630
   * @param[in] value If true set the pin's level high else set the
631
   *  pin's level low.
632
   */
633
  inline __attribute__((always_inline))
634
  void write(bool value) {
635
    fastDigitalWrite(PinNumber, value);
636
  }
637
};
638
 
639
//------------------------------------------------------------------------------
640
/** Nop for timing. */
641
#define nop asm volatile ("nop\n\t")
642
//------------------------------------------------------------------------------
643
/** Pin Mode for MISO is input.*/
644
const bool MISO_MODE  = false;
645
/** Pullups disabled for MISO are disabled. */
646
const bool MISO_LEVEL = false;
647
/** Pin Mode for MOSI is output.*/
648
const bool MOSI_MODE  = true;
649
/** Pin Mode for SCK is output. */
650
const bool SCK_MODE   = true;
651
//------------------------------------------------------------------------------
652
/**
653
 * @class SoftSPI
654
 * @brief Fast software SPI.
655
 */
656
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
657
class SoftSPI {
658
 public:
659
  //----------------------------------------------------------------------------
660
  /** Initialize SoftSPI pins. */
661
  void begin() {
662
    fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
663
    fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
664
    fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
665
  }
666
  //----------------------------------------------------------------------------
667
  /** Soft SPI receive byte.
668
   * @return Data byte received.
669
   */
670
  inline __attribute__((always_inline))
671
  uint8_t receive() {
672
    uint8_t data = 0;
673
    receiveBit(7, &data);
674
    receiveBit(6, &data);
675
    receiveBit(5, &data);
676
    receiveBit(4, &data);
677
    receiveBit(3, &data);
678
    receiveBit(2, &data);
679
    receiveBit(1, &data);
680
    receiveBit(0, &data);
681
    return data;
682
  }
683
  //----------------------------------------------------------------------------
684
  /** Soft SPI send byte.
685
   * @param[in] data Data byte to send.
686
   */
687
  inline __attribute__((always_inline))
688
  void send(uint8_t data) {
689
    sendBit(7, data);
690
    sendBit(6, data);
691
    sendBit(5, data);
692
    sendBit(4, data);
693
    sendBit(3, data);
694
    sendBit(2, data);
695
    sendBit(1, data);
696
    sendBit(0, data);
697
  }
698
  //----------------------------------------------------------------------------
699
  /** Soft SPI transfer byte.
700
   * @param[in] txData Data byte to send.
701
   * @return Data byte received.
702
   */
703
  inline __attribute__((always_inline))
704
  uint8_t transfer(uint8_t txData) {
705
    uint8_t rxData = 0;
706
    transferBit(7, &rxData, txData);
707
    transferBit(6, &rxData, txData);
708
    transferBit(5, &rxData, txData);
709
    transferBit(4, &rxData, txData);
710
    transferBit(3, &rxData, txData);
711
    transferBit(2, &rxData, txData);
712
    transferBit(1, &rxData, txData);
713
    transferBit(0, &rxData, txData);
714
    return rxData;
715
  }
716
 
717
 private:
718
  //----------------------------------------------------------------------------
719
  inline __attribute__((always_inline))
720
  bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;}
721
  inline __attribute__((always_inline))
722
  bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;}
723
  inline __attribute__((always_inline))
724
  void receiveBit(uint8_t bit, uint8_t* data) {
725
    if (MODE_CPHA(Mode)) {
726
      fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
727
    }
728
    nop;
729
    nop;
730
    fastDigitalWrite(SckPin,
731
      MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
732
    if (fastDigitalRead(MisoPin)) *data |= 1 << bit;
733
    if (!MODE_CPHA(Mode)) {
734
      fastDigitalWrite(SckPin, MODE_CPOL(Mode));
735
    }
736
  }
737
  //----------------------------------------------------------------------------
738
  inline __attribute__((always_inline))
739
  void sendBit(uint8_t bit, uint8_t data) {
740
    if (MODE_CPHA(Mode)) {
741
      fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
742
    }
743
    fastDigitalWrite(MosiPin, data & (1 << bit));
744
    fastDigitalWrite(SckPin,
745
      MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
746
    nop;
747
    nop;
748
    if (!MODE_CPHA(Mode)) {
749
      fastDigitalWrite(SckPin, MODE_CPOL(Mode));
750
    }
751
  }
752
  //----------------------------------------------------------------------------
753
  inline __attribute__((always_inline))
754
  void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) {
755
    if (MODE_CPHA(Mode)) {
756
      fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
757
    }
758
    fastDigitalWrite(MosiPin, txData & (1 << bit));
759
    fastDigitalWrite(SckPin,
760
      MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
761
    if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit;
762
    if (!MODE_CPHA(Mode)) {
763
      fastDigitalWrite(SckPin, MODE_CPOL(Mode));
764
    }
765
  }
766
  //----------------------------------------------------------------------------
767
};
768
 
769