better compilation on host
[aversive.git] / modules / comm / spi / spi.h
1 /*  
2  *  Copyright Droids Corporation (2008)
3  * 
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  */
19
20 /*
21  * Author : Julien LE GUEN - jlg@jleguen.info
22  */
23
24 /*
25  *  -- INFO --
26  *      This module enable the use of the SPI hardware
27  *      on some AVRs. For now, only MASTER mode is available.
28  *      You can have as many slaves as you want, as long as you
29  *      don't confuse them by trying to speak to several at the same time.
30  *
31  *      BIG WARNING: If you use /SS as a slave selector, always
32  *      register it using spi_register_ss_line() *before* calling
33  *      spi_init(). Read carrefully the datasheet, especially the
34  *      paragraph "SS Pin Functionnality" in SPI section. In master
35  *      mode, the SS pin must be configured as an output OR driven
36  *      high by an external circuitry.
37  *
38  *  -- USAGE --
39  *      So you have one (or several) device(s) that want to speak to your
40  *      shiny AVR over SPI ?
41  *      This is fairly easy. First, summon this module with spi_init().
42  *      You can configure
43  *       - the FORMAT of the link (sample on rising or falling edge, ...)
44  *       - the RATE of the connection (you set the prescaler dividing the CPU clock)
45  *      You can also set the data order (MSB or LSB first on the link)
46  *      
47  *      After that you can register your devices using spi_register_ss_line();
48  *      This returns you a device identifier you can use with spi_slave_[de]select();
49  *
50  *      Remember to ALWAYS select your slave before talking to it, and deselect if
51  *      once your are done.
52  */
53
54
55
56 #ifndef _SPI_H_
57 #define _SPI_H_
58
59 #include <stdint.h>
60
61 /* SPI modes */
62 typedef enum {
63         SPI_MODE_UNINIT,        /* not initialized */
64         SPI_MODE_MASTER         /* for now, only master mode as
65                                  * slave mode cannot be tested */
66 } spi_mode_t;
67
68
69 /* SPI transfert format 
70  * This defines the SCK phase and polarity.
71  * For instance in FORMAT_0, data lines are set on the falling edge
72  * of SCK, and sampled on its rising edge. This determines the order
73  * in which sampling and setting occurs.
74  * For more information on SPI formats, please see your CPU datasheet.
75  */
76 typedef enum {  
77 #ifdef HOST_VERSION
78         SPI_FORMAT_0,
79         SPI_FORMAT_1,
80         SPI_FORMAT_2,
81         SPI_FORMAT_3,
82 #else
83         SPI_FORMAT_0 = 0x00,                  /* Sample rising  Setup falling */
84         SPI_FORMAT_1 = _BV(CPHA),             /* Setup rising   Sample falling */
85         SPI_FORMAT_2 = _BV(CPOL),             /* Sample falling Setup rising */
86         SPI_FORMAT_3 = _BV(CPHA) | _BV(CPOL), /* Setup falling  Sample rising*/
87 #endif
88 } spi_format_t;
89
90
91 /* SPI Clock Rate
92  * This code the values for SPI2X (high nibble), SPR1 and SPR0 (low nibble)
93  * f_sck = f_osc / SPI_CLK_RATE_xx
94  */
95 typedef enum {
96         SPI_CLK_RATE_2 =        0x10,
97         SPI_CLK_RATE_4 =        0x00,
98         SPI_CLK_RATE_8 =        0x11,
99         SPI_CLK_RATE_16 =       0x01,
100         SPI_CLK_RATE_32 =       0x12,
101         SPI_CLK_RATE_64 =       0x02,
102         SPI_CLK_RATE_128 =      0x03
103 } spi_clk_rate_t;
104
105
106 /* 
107  * Data order (bits order)
108  * order is either SPI_LSB_FIRST or SPI_MSB_FIRST
109  * Default is MSB first
110  */
111 #define SPI_MSB_FIRST   0
112 #define SPI_LSB_FIRST   1
113 void spi_set_data_order(uint8_t order);
114
115
116
117
118 /* Initialize the SPI
119  * mode is SPI_MODE_MASTER (slave is not implemented)
120  * format defines the transfert format (see above)
121  * clk_rate defines the frequency of SCK line (f_sck = f_osc / clk_rate)
122  */
123 void spi_init(spi_mode_t mode, spi_format_t format, spi_clk_rate_t clk_rate);
124
125
126 /*
127  *      Returns the state of the SPI
128  */
129 spi_mode_t spi_get_mode(void);
130
131
132 /* 
133  * Register a pin as SS line
134  * Returns a unique identifier, or -1 on error
135  * There is always the physical SS line registered as 0
136  */
137 int8_t spi_register_ss_line(volatile uint8_t *port, uint8_t bitnum);
138
139
140 /*
141  *      Sends a byte (and receive one at the same time)
142  *      Returns the received byte
143  *      Wait for the end of transmission
144  */
145 uint8_t spi_send_and_receive_byte(uint8_t byte);
146
147
148 /*
149  *      Sends a byte, discards the received one.
150  *      Do NOT wait for the end of transmission
151  */
152 void spi_send_byte(uint8_t byte);
153
154 /*
155  *      Receives a byte (sends a NULL)
156  */
157 uint8_t spi_receive_byte(void);
158
159 /*
160  *      Select or Deselect the SS line
161  *      The SPI standard defines that only ONE slave can
162  *      be selected at any time. An internal mecanism prevents
163  *      the selection of several slaves at the same time, but
164  *      this is not completely foolproof.
165  *
166  *      /!\ Behavior is NOT ASSURED if you mess with SS lines
167  *      outside of this module, so PLEASE use these setters. /!\
168  *
169  *      This function returns EBUSY if there is already a selected slave
170  */
171 uint8_t spi_slave_select(uint8_t slave);
172
173 /*
174  *      Inconditionnaly releases the line.
175  */
176 void spi_slave_deselect(uint8_t slave);
177
178 /*
179  *      Display SS lines
180  */
181 void spi_display_ss_lines(void);
182
183
184 #endif /* _SPI_H_ */
185