| 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.
138 void quikeval_SPI_connect()
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
170 void spi_disable()
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 // }
output_high
#define output_high(pin)
Set "pin" high.
Definition: Linduino.h:75
Linduino.h
Header File for Linduino Libraries and Demo Code.
spi_write
void spi_write(int8_t data)
Write a data byte using the SPI hardware.
Definition: LT_SPI.cpp:176
QUIKEVAL_MUX_MODE_PIN
#define QUIKEVAL_MUX_MODE_PIN
QUIKEVAL_MUX_MODE_PIN defines the control pin for the QuikEval MUX.
Definition: Linduino.h:58
spi_enable
void spi_enable(uint8_t spi_clock_divider)
Setup the processor for hardware SPI communication.
Definition: LT_SPI.cpp:160
data
union LT_union_int32_4bytes data
Definition: DC2094A.ino:138
output_low
#define output_low(pin)
Set "pin" low.
Definition: Linduino.h:72
spi_transfer_word
void spi_transfer_word(uint8_t cs_pin, uint16_t tx, uint16_t *rx)
Reads and sends a word.
Definition: LT_SPI.cpp:98
quikeval_SPI_init
void quikeval_SPI_init(void)
Configure the SPI port for 4Mhz SCK.
Definition: LT_SPI.cpp:151
LT_SPI.h
LT_SPI: Routines to communicate with ATmega328P&#39;s hardware SPI port.
quikeval_SPI_connect
void quikeval_SPI_connect()
Connect SPI pins to QuikEval connector through the Linduino MUX. This will disconnect I2C...
Definition: LT_SPI.cpp:138
spi_read
int8_t spi_read(int8_t data)
The data byte to be written.
Definition: LT_SPI.cpp:189
spi_disable
void spi_disable()
Disable the SPI hardware port.
Definition: LT_SPI.cpp:170
spi_transfer_byte
void spi_transfer_byte(uint8_t cs_pin, uint8_t tx, uint8_t *rx)
Reads and sends a byte.
Definition: LT_SPI.cpp:87
i
static int i
Definition: DC2430A.ino:184
spi_transfer_block
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
QUIKEVAL_CS
#define QUIKEVAL_CS
QuikEval CS pin (SPI chip select on QuikEval connector pin 6) connects to Arduino SS pin...
Definition: Linduino.h:57