source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/hardware/arduino/avr/libraries/SPI/src/SPI.cpp @ 4837

Last change on this file since 4837 was 4837, checked in by daduve, 3 years ago

Adding new version

File size: 5.6 KB
Line 
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
16SPIClass SPI;
17
18uint8_t SPIClass::initialized = 0;
19uint8_t SPIClass::interruptMode = 0;
20uint8_t SPIClass::interruptMask = 0;
21uint8_t SPIClass::interruptSave = 0;
22#ifdef SPI_TRANSACTION_MISMATCH_LED
23uint8_t SPIClass::inTransactionFlag = 0;
24#endif
25
26void SPIClass::begin()
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)){
39      digitalWrite(SS, HIGH);
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);
60    pinMode(MOSI, OUTPUT);
61  }
62  initialized++; // reference count
63  SREG = sreg;
64}
65
66void 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
120void 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
160void 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}
Note: See TracBrowser for help on using the repository browser.