1 /*
2  * Author: Brendan Le Foll <brendan.le.foll@intel.com>
3  * Copyright (c) 2014 Intel Corporation.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining
6  * a copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sublicense, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 
25 #pragma once
26 
27 #include "spi.h"
28 #include "types.hpp"
29 #include <stdexcept>
30 
31 namespace mraa
32 {
33 
34 /**
35  * MRAA SPI Modes
36  */
37 typedef enum {
38     SPI_MODE0 = 0, /**< CPOL = 0, CPHA = 0, Clock idle low, data is clocked in on rising edge,
39                       output data (change) on falling edge */
40     SPI_MODE1 = 1, /**< CPOL = 0, CPHA = 1, Clock idle low, data is clocked in on falling edge,
41                       output data (change) on rising edge */
42     SPI_MODE2 = 2, /**< CPOL = 1, CPHA = 0, Clock idle low, data is clocked in on falling edge,
43                       output data (change) on rising edge */
44     SPI_MODE3 = 3, /**< CPOL = 1, CPHA = 1, Clock idle low, data is clocked in on rising, edge
45                       output data (change) on falling edge */
46 } Spi_Mode;
47 
48 
49 /**
50 * @brief API to Serial Peripheral Interface
51 *
52 * This file defines the SPI interface for libmraa
53 *
54 * @snippet Spi-pot.cpp Interesting
55 */
56 class Spi
57 {
58   public:
59     /**
60      * Initialise SPI object using the board mapping to set muxes
61      *
62      * @param bus to use, as listed in the platform definition, normally 0
63      */
Spi(int bus)64     Spi(int bus)
65     {
66         m_spi = mraa_spi_init(bus);
67 
68         if (m_spi == NULL) {
69             throw std::invalid_argument("Error initialising SPI bus");
70         }
71     }
72 
73     /**
74      * Closes spi bus
75      */
~Spi()76     ~Spi()
77     {
78         mraa_spi_stop(m_spi);
79     }
80 
81     /**
82      * Set the SPI device mode. see spidev0-3
83      *
84      * @param mode the mode. See Linux spidev doc
85      * @return Result of operation
86      */
87     Result
mode(Spi_Mode mode)88     mode(Spi_Mode mode)
89     {
90         return (Result) mraa_spi_mode(m_spi, (mraa_spi_mode_t) mode);
91     }
92 
93     /**
94      * Set the SPI device operating clock frequency
95      *
96      * @param hz the frequency to set in hz
97      * @return Result of operation
98      */
99     Result
frequency(int hz)100     frequency(int hz)
101     {
102         return (Result) mraa_spi_frequency(m_spi, hz);
103     }
104 
105     /**
106      * Write single byte to the SPI device
107      *
108      * @param data the byte to send
109      * @return data received on the miso line or -1 in case of error
110      */
111     int
writeByte(uint8_t data)112     writeByte(uint8_t data)
113     {
114         return mraa_spi_write(m_spi, (uint8_t) data);
115     }
116 
117     /**
118      * Write single byte to the SPI device
119      *
120      * @param data the byte to send
121      * @return data received on the miso line
122      */
123     uint16_t
write_word(uint16_t data)124     write_word(uint16_t data)
125     {
126         return mraa_spi_write_word(m_spi, (uint16_t) data);
127     }
128 
129     /**
130      * Write buffer of bytes to SPI device The pointer return has to be
131      * free'd by the caller. It will return a NULL pointer in cases of
132      * error
133      *
134      * @param txBuf buffer to send
135      * @param length size of buffer to send
136      * @return uint8_t* data received on the miso line. Same length as passed in
137      */
138     uint8_t*
write(uint8_t * txBuf,int length)139     write(uint8_t* txBuf, int length)
140     {
141         return mraa_spi_write_buf(m_spi, txBuf, length);
142     }
143 
144 #ifndef SWIG
145     /**
146      * Write buffer of bytes to SPI device The pointer return has to be
147      * free'd by the caller. It will return a NULL pointer in cases of
148      * error
149      *
150      * @param txBuf buffer to send
151      * @param length size of buffer (in bytes) to send
152      * @return uint8_t* data received on the miso line. Same length as passed in
153      */
154     uint16_t*
write_word(uint16_t * txBuf,int length)155     write_word(uint16_t* txBuf, int length)
156     {
157         return mraa_spi_write_buf_word(m_spi, txBuf, length);
158     }
159 #endif
160 
161 #ifndef SWIG
162     /**
163      * Transfer data to and from SPI device Receive pointer may be null if
164      * return data is not needed.
165      *
166      * @param txBuf buffer to send
167      * @param rxBuf buffer to optionally receive data from spi device
168      * @param length size of buffer to send
169      * @return Result of operation
170      */
171     Result
transfer(uint8_t * txBuf,uint8_t * rxBuf,int length)172     transfer(uint8_t* txBuf, uint8_t* rxBuf, int length)
173     {
174         return (Result) mraa_spi_transfer_buf(m_spi, txBuf, rxBuf, length);
175     }
176 
177     /**
178      * Transfer data to and from SPI device Receive pointer may be null if
179      * return data is not needed.
180      *
181      * @param txBuf buffer to send
182      * @param rxBuf buffer to optionally receive data from spi device
183      * @param length size of buffer to send
184      * @return Result of operation
185      */
186     Result
transfer_word(uint16_t * txBuf,uint16_t * rxBuf,int length)187     transfer_word(uint16_t* txBuf, uint16_t* rxBuf, int length)
188     {
189         return (Result) mraa_spi_transfer_buf_word(m_spi, txBuf, rxBuf, length);
190     }
191 #endif
192 
193     /**
194      * Change the SPI lsb mode
195      *
196      * @param lsb Use least significant bit transmission - 0 for msbi
197      * @return Result of operation
198      */
199     Result
lsbmode(bool lsb)200     lsbmode(bool lsb)
201     {
202         return (Result) mraa_spi_lsbmode(m_spi, (mraa_boolean_t) lsb);
203     }
204 
205     /**
206      * Set bits per mode on transaction, default is 8
207      *
208      * @param bits bits per word
209      * @return Result of operation
210      */
211     Result
bitPerWord(unsigned int bits)212     bitPerWord(unsigned int bits)
213     {
214         return (Result) mraa_spi_bit_per_word(m_spi, bits);
215     }
216 
217   private:
218     mraa_spi_context m_spi;
219 };
220 }
221