SPI.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010 by Cristian Maglie <c.maglie@arduino.cc>
3  * Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
4  * Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
5  * Copyright (c) 2014 by Andrew J. Kroll <xxxajk@gmail.com> (atomicity fixes)
6  * SPI Master library for arduino.
7  *
8  * This file is free software; you can redistribute it and/or modify
9  * it under the terms of either the GNU General Public License version 2
10  * or the GNU Lesser General Public License version 2.1, both as
11  * published by the Free Software Foundation.
12  */
13 
14 #include "SPI.h"
15 
17 
18 uint8_t SPIClass::initialized = 0;
19 uint8_t SPIClass::interruptMode = 0;
20 uint8_t SPIClass::interruptMask = 0;
21 uint8_t SPIClass::interruptSave = 0;
22 #ifdef SPI_TRANSACTION_MISMATCH_LED
23 uint8_t SPIClass::inTransactionFlag = 0;
24 #endif
25 
27 {
28  uint8_t sreg = SREG;
29  noInterrupts(); // Protect from a scheduler and prevent transactionBegin
30  if (!initialized) {
31  // Set SS to high so a connected chip will be "deselected" by default
32  uint8_t port = digitalPinToPort(SS);
33  uint8_t bit = digitalPinToBitMask(SS);
34  volatile uint8_t *reg = portModeRegister(port);
35 
36  // if the SS pin is not already configured as an output
37  // then set it high (to enable the internal pull-up resistor)
38  if(!(*reg & bit)){
40  }
41 
42  // When the SS pin is set as OUTPUT, it can be used as
43  // a general purpose output port (it doesn't influence
44  // SPI operations).
45  pinMode(SS, OUTPUT);
46 
47  // Warning: if the SS pin ever becomes a LOW INPUT then SPI
48  // automatically switches to Slave, so the data direction of
49  // the SS pin MUST be kept as OUTPUT.
50  SPCR |= _BV(MSTR);
51  SPCR |= _BV(SPE);
52 
53  // Set direction register for SCK and MOSI pin.
54  // MISO pin automatically overrides to INPUT.
55  // By doing this AFTER enabling SPI, we avoid accidentally
56  // clocking in a single bit since the lines go directly
57  // from "input" to SPI control.
58  // http://code.google.com/p/arduino/issues/detail?id=888
59  pinMode(SCK, OUTPUT);
61  }
62  initialized++; // reference count
63  SREG = sreg;
64 }
65 
66 void SPIClass::end() {
67  uint8_t sreg = SREG;
68  noInterrupts(); // Protect from a scheduler and prevent transactionBegin
69  // Decrease the reference counter
70  if (initialized)
71  initialized--;
72  // If there are no more references disable SPI
73  if (!initialized) {
74  SPCR &= ~_BV(SPE);
75  interruptMode = 0;
76  #ifdef SPI_TRANSACTION_MISMATCH_LED
77  inTransactionFlag = 0;
78  #endif
79  }
80  SREG = sreg;
81 }
82 
83 // mapping of interrupt numbers to bits within SPI_AVR_EIMSK
84 #if defined(__AVR_ATmega32U4__)
85  #define SPI_INT0_MASK (1<<INT0)
86  #define SPI_INT1_MASK (1<<INT1)
87  #define SPI_INT2_MASK (1<<INT2)
88  #define SPI_INT3_MASK (1<<INT3)
89  #define SPI_INT4_MASK (1<<INT6)
90 #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
91  #define SPI_INT0_MASK (1<<INT0)
92  #define SPI_INT1_MASK (1<<INT1)
93  #define SPI_INT2_MASK (1<<INT2)
94  #define SPI_INT3_MASK (1<<INT3)
95  #define SPI_INT4_MASK (1<<INT4)
96  #define SPI_INT5_MASK (1<<INT5)
97  #define SPI_INT6_MASK (1<<INT6)
98  #define SPI_INT7_MASK (1<<INT7)
99 #elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
100  #define SPI_INT0_MASK (1<<INT4)
101  #define SPI_INT1_MASK (1<<INT5)
102  #define SPI_INT2_MASK (1<<INT0)
103  #define SPI_INT3_MASK (1<<INT1)
104  #define SPI_INT4_MASK (1<<INT2)
105  #define SPI_INT5_MASK (1<<INT3)
106  #define SPI_INT6_MASK (1<<INT6)
107  #define SPI_INT7_MASK (1<<INT7)
108 #else
109  #ifdef INT0
110  #define SPI_INT0_MASK (1<<INT0)
111  #endif
112  #ifdef INT1
113  #define SPI_INT1_MASK (1<<INT1)
114  #endif
115  #ifdef INT2
116  #define SPI_INT2_MASK (1<<INT2)
117  #endif
118 #endif
119 
120 void SPIClass::usingInterrupt(uint8_t interruptNumber)
121 {
122  uint8_t mask = 0;
123  uint8_t sreg = SREG;
124  noInterrupts(); // Protect from a scheduler and prevent transactionBegin
125  switch (interruptNumber) {
126  #ifdef SPI_INT0_MASK
127  case 0: mask = SPI_INT0_MASK; break;
128  #endif
129  #ifdef SPI_INT1_MASK
130  case 1: mask = SPI_INT1_MASK; break;
131  #endif
132  #ifdef SPI_INT2_MASK
133  case 2: mask = SPI_INT2_MASK; break;
134  #endif
135  #ifdef SPI_INT3_MASK
136  case 3: mask = SPI_INT3_MASK; break;
137  #endif
138  #ifdef SPI_INT4_MASK
139  case 4: mask = SPI_INT4_MASK; break;
140  #endif
141  #ifdef SPI_INT5_MASK
142  case 5: mask = SPI_INT5_MASK; break;
143  #endif
144  #ifdef SPI_INT6_MASK
145  case 6: mask = SPI_INT6_MASK; break;
146  #endif
147  #ifdef SPI_INT7_MASK
148  case 7: mask = SPI_INT7_MASK; break;
149  #endif
150  default:
151  interruptMode = 2;
152  break;
153  }
154  interruptMask |= mask;
155  if (!interruptMode)
156  interruptMode = 1;
157  SREG = sreg;
158 }
159 
160 void SPIClass::notUsingInterrupt(uint8_t interruptNumber)
161 {
162  // Once in mode 2 we can't go back to 0 without a proper reference count
163  if (interruptMode == 2)
164  return;
165  uint8_t mask = 0;
166  uint8_t sreg = SREG;
167  noInterrupts(); // Protect from a scheduler and prevent transactionBegin
168  switch (interruptNumber) {
169  #ifdef SPI_INT0_MASK
170  case 0: mask = SPI_INT0_MASK; break;
171  #endif
172  #ifdef SPI_INT1_MASK
173  case 1: mask = SPI_INT1_MASK; break;
174  #endif
175  #ifdef SPI_INT2_MASK
176  case 2: mask = SPI_INT2_MASK; break;
177  #endif
178  #ifdef SPI_INT3_MASK
179  case 3: mask = SPI_INT3_MASK; break;
180  #endif
181  #ifdef SPI_INT4_MASK
182  case 4: mask = SPI_INT4_MASK; break;
183  #endif
184  #ifdef SPI_INT5_MASK
185  case 5: mask = SPI_INT5_MASK; break;
186  #endif
187  #ifdef SPI_INT6_MASK
188  case 6: mask = SPI_INT6_MASK; break;
189  #endif
190  #ifdef SPI_INT7_MASK
191  case 7: mask = SPI_INT7_MASK; break;
192  #endif
193  default:
194  break;
195  // this case can't be reached
196  }
197  interruptMask &= ~mask;
198  if (!interruptMask)
199  interruptMode = 0;
200  SREG = sreg;
201 }
void pinMode(uint8_t, uint8_t)
#define noInterrupts()
Definition: Arduino.h:102
static uint8_t interruptMode
Definition: SPI.h:314
static void end()
Definition: SPI.cpp:66
static void notUsingInterrupt(uint8_t interruptNumber)
Definition: SPI.cpp:160
static uint8_t interruptSave
Definition: SPI.h:316
static void usingInterrupt(uint8_t interruptNumber)
Definition: SPI.cpp:120
static const uint8_t SS
static const uint8_t MOSI
#define OUTPUT
Definition: Arduino.h:44
#define HIGH
Definition: Arduino.h:40
#define portModeRegister(P)
Definition: Arduino.h:183
static void begin()
Definition: SPI.cpp:26
Definition: SPI.h:156
static uint8_t initialized
Definition: SPI.h:313
#define bit(b)
Definition: Arduino.h:123
#define digitalPinToBitMask(P)
Definition: Arduino.h:178
static const uint8_t SCK
void digitalWrite(uint8_t, uint8_t)
static uint8_t interruptMask
Definition: SPI.h:315
GLenum GLint GLuint mask
#define digitalPinToPort(P)
Definition: Arduino.h:177
SPIClass SPI
Definition: SPI.cpp:16


arduino_daq
Author(s):
autogenerated on Mon Jun 10 2019 12:46:03