Linduino  1.3.0
Linear Technology Arduino-Compatible Demonstration Board
LT_SPI.cpp
Go to the documentation of this file.
1 //! @todo Review this document.
2 /*!
3 LT_SPI: Routines to communicate with ATmega328P's hardware SPI port.
4 
5 @verbatim
6 
7 LT_SPI implements the low level master SPI bus routines using
8 the hardware SPI port.
9 
10 SPI Frequency = (CPU Clock frequency)/(16+2(TWBR)*Prescaler)
11 SPCR = SPI Control Register (SPIE SPE DORD MSTR CPOL CPHA SPR1 SPR0)
12 SPSR = SPI Status Register (SPIF WCOL - - - - - SPI2X)
13 
14 Data Modes:
15 CPOL CPHA Leading Edge Trailing Edge
16 0 0 sample rising setup falling
17 0 1 setup rising sample falling
18 1 0 sample falling setup rising
19 1 1 sample rising setup rising
20 
21 CPU Frequency = 16MHz on Arduino Uno
22 SCK Frequency
23 SPI2X SPR1 SPR0 Frequency Uno_Frequency
24  0 0 0 fosc/4 4 MHz
25  0 0 1 fosc/16 1 MHz
26  0 1 0 fosc/64 250 kHz
27  0 1 1 fosc/128 125 kHz
28  0 0 0 fosc/2 8 MHz
29  0 0 1 fosc/8 2 MHz
30  0 1 0 fosc/32 500 kHz
31 
32 @endverbatim
33 
34 
35 Copyright 2018(c) Analog Devices, Inc.
36 
37 All rights reserved.
38 
39 Redistribution and use in source and binary forms, with or without
40 modification, are permitted provided that the following conditions are met:
41  - Redistributions of source code must retain the above copyright
42  notice, this list of conditions and the following disclaimer.
43  - Redistributions in binary form must reproduce the above copyright
44  notice, this list of conditions and the following disclaimer in
45  the documentation and/or other materials provided with the
46  distribution.
47  - Neither the name of Analog Devices, Inc. nor the names of its
48  contributors may be used to endorse or promote products derived
49  from this software without specific prior written permission.
50  - The use of this software may or may not infringe the patent rights
51  of one or more patent holders. This license does not release you
52  from the requirement that you obtain separate licenses from these
53  patent holders to use this software.
54  - Use of the software either in source or binary form, must be run
55  on or directly connected to an Analog Devices Inc. component.
56 
57 THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR
58 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT,
59 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60 IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT,
61 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
62 LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR
63 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
64 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
65 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
66 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
67 */
68 
69 //! @ingroup Linduino
70 //! @{
71 //! @defgroup LT_SPI LT_SPI: Routines to communicate with ATmega328P's hardware SPI port.
72 //! @}
73 
74 /*! @file
75  @ingroup LT_SPI
76  Library for LT_SPI: Routines to communicate with ATmega328P's hardware SPI port.
77 */
78 
79 #include <Arduino.h>
80 #include <stdint.h>
81 #include <SPI.h>
82 #include "Linduino.h"
83 #include "LT_SPI.h"
84 
85 // Reads and sends a byte
86 // Return 0 if successful, 1 if failed
87 void spi_transfer_byte(uint8_t cs_pin, uint8_t tx, uint8_t *rx)
88 {
89  output_low(cs_pin); //! 1) Pull CS low
90 
91  *rx = SPI.transfer(tx); //! 2) Read byte and send byte
92 
93  output_high(cs_pin); //! 3) Pull CS high
94 }
95 
96 // Reads and sends a word
97 // Return 0 if successful, 1 if failed
98 void spi_transfer_word(uint8_t cs_pin, uint16_t tx, uint16_t *rx)
99 {
100  union
101  {
102  uint8_t b[2];
103  uint16_t w;
104  } data_tx;
105 
106  union
107  {
108  uint8_t b[2];
109  uint16_t w;
110  } data_rx;
111 
112  data_tx.w = tx;
113 
114  output_low(cs_pin); //! 1) Pull CS low
115 
116  data_rx.b[1] = SPI.transfer(data_tx.b[1]); //! 2) Read MSB and send MSB
117  data_rx.b[0] = SPI.transfer(data_tx.b[0]); //! 3) Read LSB and send LSB
118 
119  *rx = data_rx.w;
120 
121  output_high(cs_pin); //! 4) Pull CS high
122 }
123 
124 // Reads and sends a byte array
125 void spi_transfer_block(uint8_t cs_pin, uint8_t *tx, uint8_t *rx, uint8_t length)
126 {
127  int8_t i;
128 
129  output_low(cs_pin); //! 1) Pull CS low
130 
131  for (i=(length-1); i >= 0; i--)
132  rx[i] = SPI.transfer(tx[i]); //! 2) Read and send byte array
133 
134  output_high(cs_pin); //! 3) Pull CS high
135 }
136 
137 // Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C.
139 {
140  pinMode(QUIKEVAL_CS, OUTPUT);
141  output_high(QUIKEVAL_CS); //! 1) Pull Chip Select High
142 
143  //! 2) Enable Main SPI
144  pinMode(QUIKEVAL_MUX_MODE_PIN, OUTPUT);
145  digitalWrite(QUIKEVAL_MUX_MODE_PIN, LOW);
146 }
147 
148 // Configure the SPI port for 4MHz SCK.
149 // This function or spi_enable() must be called
150 // before using the other SPI routines.
151 void quikeval_SPI_init(void) // Initializes SPI
152 {
153  spi_enable(SPI_CLOCK_DIV16); //! 1) Configure the spi port for 4MHz SCK
154 }
155 
156 // Setup the processor for hardware SPI communication.
157 // Must be called before using the other SPI routines.
158 // Alternatively, call quikeval_SPI_connect(), which automatically
159 // calls this function.
160 void spi_enable(uint8_t spi_clock_divider) // Configures SCK frequency. Use constant defined in header file.
161 {
162  //pinMode(SCK, OUTPUT); //! 1) Setup SCK as output
163  //pinMode(MOSI, OUTPUT); //! 2) Setup MOSI as output
164  //pinMode(QUIKEVAL_CS, OUTPUT); //! 3) Setup CS as output
165  SPI.begin();
166  SPI.setClockDivider(spi_clock_divider);
167 }
168 
169 // Disable the SPI hardware port
171 {
172  SPI.end();
173 }
174 
175 // Write a data byte using the SPI hardware
176 void spi_write(int8_t data) // Byte to be written to SPI port
177 {
178 #if defined(ARDUINO_ARCH_AVR)
179  SPDR = data; //! 1) Start the SPI transfer
180  while (!(SPSR & _BV(SPIF))); //! 2) Wait until transfer complete
181 #else
182  SPI.transfer(data);
183 #endif
184 
185 }
186 
187 // Read and write a data byte using the SPI hardware
188 // Returns the data byte read
189 int8_t spi_read(int8_t data) //!The data byte to be written
190 {
191 #if defined(ARDUINO_ARCH_AVR)
192  SPDR = data; //! 1) Start the SPI transfer
193  while (!(SPSR & _BV(SPIF))); //! 2) Wait until transfer complete
194  return SPDR; //! 3) Return the data read
195 #else
196  return SPI.transfer(data);
197 #endif
198 
199 
200 }
201 
202 // Below are implementations of spi_read, etc. that do not use the
203 // Arduino SPI library. To use these functions, uncomment them and comment out
204 // the correcsponding function above.
205 //
206 // // Reads and sends a byte
207 // // Return 0 if successful, 1 if failed
208 // uint8_t spi_transfer_byte(uint8_t cs_pin, uint8_t tx, uint8_t *rx)
209 // {
210 // output_low(cs_pin); //! 1) Pull CS low
211 //
212 // *rx = spi_read(tx); //! 2) Read byte and send byte
213 //
214 // output_high(cs_pin); //! 3) Pull CS high
215 //
216 // return(0);
217 // }
218 //
219 // // Reads and sends a word
220 // // Return 0 if successful, 1 if failed
221 // uint8_t spi_transfer_word(uint8_t cs_pin, uint16_t tx, uint16_t *rx)
222 // {
223 // union
224 // {
225 // uint8_t b[2];
226 // uint16_t w;
227 // } data_tx;
228 //
229 // union
230 // {
231 // uint8_t b[2];
232 // uint16_t w;
233 // } data_rx;
234 //
235 // data_tx.w = tx;
236 //
237 // output_low(cs_pin); //! 1) Pull CS low
238 //
239 // data_rx.b[1] = spi_read(data_tx.b[1]); //! 2) Read MSB and send MSB
240 // data_rx.b[0] = spi_read(data_tx.b[0]); //! 3) Read LSB and send LSB
241 // *rx = data_rx.w;
242 //
243 // output_high(cs_pin); //! 4) Pull CS high
244 //
245 // return(0);
246 // }
247 //
248 // // Reads and sends a byte array
249 // // Return 0 if successful, 1 if failed
250 // uint8_t spi_transfer_block(uint8_t cs_pin, uint8_t *tx, uint8_t *rx, uint8_t length)
251 // {
252 // int8_t i;
253 //
254 // output_low(cs_pin); //! 1) Pull CS low
255 //
256 // for(i=0; i < length; i++)
257 // rx[i] = spi_read(tx[i]); //! 2) Read and send byte array
258 //
259 // output_high(cs_pin); //! 3) Pull CS high
260 //
261 // return(0);
262 // }
263 //
264 // // Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C.
265 // void quikeval_SPI_connect()
266 // {
267 // output_high(QUIKEVAL_CS); //! 1) Pull Chip Select High
268 //
269 // //! 2) Enable Main SPI
270 // pinMode(QUIKEVAL_MUX_MODE_PIN, OUTPUT);
271 // digitalWrite(QUIKEVAL_MUX_MODE_PIN, LOW);
272 // }
273 //
274 // // Configure the SPI port for 4MHz SCK.
275 // // This function or spi_enable() must be called
276 // // before using the other SPI routines.
277 // void quikeval_SPI_init(void) // Initializes SPI
278 // {
279 // spi_enable(SPI_CLOCK_DIV32); //! 2) Configure the spi port for 4MHz SCK
280 // }
281 //
282 // // Setup the processor for hardware SPI communication.
283 // // Must be called before using the other SPI routines.
284 // // Alternatively, call quikeval_SPI_connect(), which automatically
285 // // calls this function.
286 // void spi_enable(uint8_t spi_clock_divider) // Configures SCK frequency. Use constant defined in header file.
287 // {
288 // pinMode(SCK, OUTPUT); //! 1) Setup SCK as output
289 // pinMode(MOSI, OUTPUT); //! 2) Setup MOSI as output
290 // pinMode(QUIKEVAL_CS, OUTPUT); //! 3) Setup CS as output
291 // output_low(SCK);
292 // output_low(MOSI);
293 // output_high(QUIKEVAL_CS);
294 // SPCR |= _BV(MSTR); //! 4) Set the SPI port to master mode
295 // //! 5) Set the SPI hardware rate
296 // SPCR = (SPCR & ~SPI_CLOCK_MASK) | (spi_clock_divider & SPI_CLOCK_MASK);
297 // SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((spi_clock_divider >> 2) & SPI_2XCLOCK_MASK);
298 // SPCR |= _BV(SPE); //! 5) Enable the SPI port
299 // }
300 //
301 // // Disable the SPI hardware port
302 // void spi_disable()
303 // {
304 // SPCR &= ~_BV(SPE);
305 // }
#define output_high(pin)
Set "pin" high.
Definition: Linduino.h:75
Header File for Linduino Libraries and Demo Code.
void spi_write(int8_t data)
Write a data byte using the SPI hardware.
Definition: LT_SPI.cpp:176
#define QUIKEVAL_MUX_MODE_PIN
QUIKEVAL_MUX_MODE_PIN defines the control pin for the QuikEval MUX.
Definition: Linduino.h:58
void spi_enable(uint8_t spi_clock_divider)
Setup the processor for hardware SPI communication.
Definition: LT_SPI.cpp:160
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
#define output_low(pin)
Set "pin" low.
Definition: Linduino.h:72
void spi_transfer_word(uint8_t cs_pin, uint16_t tx, uint16_t *rx)
Reads and sends a word.
Definition: LT_SPI.cpp:98
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
int8_t spi_read(int8_t data)
The data byte to be written.
Definition: LT_SPI.cpp:189
void spi_disable()
Disable the SPI hardware port.
Definition: LT_SPI.cpp:170
void spi_transfer_byte(uint8_t cs_pin, uint8_t tx, uint8_t *rx)
Reads and sends a byte.
Definition: LT_SPI.cpp:87
static int i
Definition: DC2430A.ino:184
void spi_transfer_block(uint8_t cs_pin, uint8_t *tx, uint8_t *rx, uint8_t length)
Reads and sends a byte array.
Definition: LT_SPI.cpp:125
#define QUIKEVAL_CS
QuikEval CS pin (SPI chip select on QuikEval connector pin 6) connects to Arduino SS pin...
Definition: Linduino.h:57