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