source: firmware/FSC/src/spi_master.c@ 17689

Last change on this file since 17689 was 17630, checked in by dneise, 11 years ago
mostly whitespace changes and removed the use of the usart
File size: 8.0 KB
Line 
1#include "spi_master.h"
2
3volatile U08 spi_clock_index;
4volatile U08 spi_cpol;
5volatile U08 spi_cpha;
6volatile U08 spi_dord;
7volatile BOOL spi_ss_active_high;
8volatile U08 spi_read_buffer[SPI_READ_BUFFER_SIZE];
9volatile U08 spi_write_buffer[SPI_WRITE_BUFFER_SIZE];
10
11volatile U08 SPI_DEVICE_SS[4]={SPI_E_CS ,SPI_AD_CS ,SPI_M_CS ,SPI_A_CS };
12volatile BOOL SPI_DEVICE_ACTIVE_HIGH[4]={false ,false ,false ,false };
13
14void spi_setup_w5100() {
15 spi_clock_index = 0;
16 spi_dord = 0; // Data Order MSB first dord = 0 --> good for all devices
17 spi_cpol = 0;
18 spi_cpha = 0; // SPI mode=0 good for ethernet.
19 spi_setup(); // Setup SPI bits and clock speed
20}
21
22void spi_setup_ad7719() {
23 spi_clock_index = 6; // since AD7719 is not connected via level shifters .. we can go up to 4Mbps
24 spi_dord = 0; // Data Order MSB first dord = 0 --> good for all devices
25 spi_cpol = 1;
26 spi_cpha = 1; // SPI mode=3 good for AD7719.
27 spi_setup(); // Setup SPI bits and clock speed
28}
29
30void spi_init(void) {
31 // there are a total of 4 devices on the SPI bus:
32 // 1.) Ethernet Modul WIZ812MJ
33 // 2.) AD7719 24bit ADC
34 // 3.) LIS3LV accelerometer <---- not used yet.
35 // 4.) MAX6662 temp sensor <---- not assembled!
36
37 // We check if they all can live with the same SPI settings:
38 // 1.) Ethernet modul:
39 // supports spi mode=0 or mode=3 --> eighther cpol=cpha=0 or cpol=cpha=1
40 // THAT IS NOT TRUE!!!!
41 // only mode 0 !!!!!!!!!!!!!!!!!!!!!!!!!!!1
42 // MSB first
43 // SCLK time 70ns minimum --> 14.2MHz maximum
44 //
45 // 2.) AD7719
46 // supports mode=3 --> cpol=cpha=1
47 // MSB first
48 // SCLK time 200ns minimum --> 5MHz maximum
49 //
50 // 3.) LIS3LV
51 // SPI CLK idles high --> cpol=1
52 // data valid at rising edge. --> cpha=1 as well
53 // ==> mode 3 is supported only.
54 // MSB first, but take take at multi byte transfers. LSbyte first
55 // SCLK time - is not mentioned in the datasheet
56 //
57 // 4.) MAX6662 Tempsensor
58 // since it is not assembled, this information is not necessary.
59
60 // fastes SPI CLK frequency can be --> F_CPU/2 = 4MHz
61 // slowest can be --> F_CPU/128 = 62.5KHz
62
63 // Lets try with the fastest!
64 spi_clock_index = 4; // this is reasonable for W5100 because of slow level shifters on the FSC.
65
66 spi_dord = 0; // Data Order MSB first dord = 0 --> good for all devices
67 spi_cpol = 0;
68 spi_cpha = 0; // SPI mode=0 good for ethernet.
69 spi_setup(); // Setup SPI bits and clock speed
70}
71
72void spi_setup(void) {
73 SPCR = 0; // Disable SPI, clear all flags
74
75 // Set/Clear bits DORD, CPOL and CPHA in SPI Control Register
76 spi_dord & 0x01 ? (SPCR |= (1 << DORD)) : (SPCR &= ~(1 << DORD));
77 spi_cpol & 0x01 ? (SPCR |= (1 << CPOL)) : (SPCR &= ~(1 << CPOL));
78 spi_cpha & 0x01 ? (SPCR |= (1 << CPHA)) : (SPCR &= ~(1 << CPHA));
79
80 switch (spi_clock_index) {
81 case 0:{ // F_CPU / 128
82 SPCR |= (1 << SPR1) | (1 << SPR0);
83 SPSR &= ~(1 <<SPI2X);
84 }
85 break;
86 case 1:{ // F_CPU / 64
87 SPCR |= (1 << SPR1);
88 SPSR &= ~(1 << SPI2X);
89 }
90 break;
91 case 2:{ // F_CPU / 32
92 SPCR |= (1 << SPR1);
93 SPSR |= (1 << SPI2X);
94 }
95 break;
96 case 3:{ // F_CPU / 16
97 SPCR |= (1 << SPR0);
98 SPSR &= ~(1 << SPI2X);
99 }
100 break;
101 case 4:{ // F_CPU / 8
102 SPCR |= (1 << SPR0);
103 SPSR |= (1 << SPI2X);
104 }
105 break;
106 case 5: // F_CPU / 4
107 SPSR &= ~(1 << SPI2X);
108 break;
109 case 6: // F_CPU / 2
110 SPSR |= (1 << SPI2X);
111 break;
112 default:{ // F_CPU / 128
113 SPCR |= (1 << SPR1) | (1 << SPR0);
114 SPSR &= ~(1 << SPI2X);
115 }
116 }
117 // Enable SPI in Master Mode
118 SPCR |= (1 << SPE) | (1 << MSTR);
119}
120
121void spi_set_clock_index(U08 clock_index) {
122 if (clock_index > SPI_MAX_CLOCK_INDEX) {
123 clock_index = SPI_MAX_CLOCK_INDEX;
124 }
125 spi_clock_index = clock_index;
126 spi_setup(); // Setup SPI bits and clock speed
127}
128
129void spi_set_dord(U08 dord) {
130 if (dord > 1) {
131 dord = 1;
132 }
133 spi_dord = dord;
134 spi_setup(); // Setup SPI bits and clock speed
135}
136
137void spi_set_cpol(U08 cpol) {
138 if (cpol > 1) {
139 cpol = 1;
140 }
141 spi_cpol = cpol;
142 spi_setup(); // Setup SPI bits and clock speed
143}
144
145void spi_set_cpha(U08 cpha) {
146 if (cpha > 1) {
147 cpha = 1;
148 }
149 spi_cpha = cpha;
150 spi_setup(); // Setup SPI bits and clock speed
151}
152
153void spi_transfer(U08 bytes, U08 device) {
154 // transfer bytes from global write buffer to *device*
155
156 //#define SPI_E_CS PB4 //device 0
157 //#define SPI_AD_CS PD3 //device 1
158 //#define SPI_M_CS PD4 //device 2
159 //#define SPI_A_CS PD5 //device 3
160
161 // Transfer requested bytes
162 for (U08 n = 0; n < bytes; n++) {
163 PORTB |= 1<< PB3;
164 // Check for active slave select level
165 if (SPI_DEVICE_ACTIVE_HIGH[device]) {
166 if (device == 0) {
167 PORTB |= (1 << SPI_DEVICE_SS[device]); // Set Slave Select high
168 }
169 else {
170 PORTD |= (1 << SPI_DEVICE_SS[device]); // Set Slave Select high
171 }
172 }
173 else {
174 if (device == 0) {
175 PORTB &= ~(1 << SPI_DEVICE_SS[device]); // Set Slave Select low
176 }
177 else {
178 PORTD &= ~(1 << SPI_DEVICE_SS[device]); // Set Slave Select low
179 }
180 }
181
182 PORTB &= ~(1<< PB3);
183 spi_read_buffer[n] = spi_transfer_byte(spi_write_buffer[n]);
184 PORTB |= 1<< PB3;
185
186 // Check for inactive slave select level
187 if (SPI_DEVICE_ACTIVE_HIGH[device]) {
188 if (device == 0) {
189 PORTB &= ~(1 << SPI_DEVICE_SS[device]); // Set Slave Select low
190 }
191 else {
192 PORTD &= ~(1 << SPI_DEVICE_SS[device]); // Set Slave Select low
193 }
194 }
195 else {
196 if (device == 0) {
197 PORTB |= (1 << SPI_DEVICE_SS[device]); // Set Slave Select high
198 }
199 else {
200 PORTD |= (1 << SPI_DEVICE_SS[device]); // Set Slave Select high
201 }
202 }
203 PORTB &= ~(1<< PB3);
204 }
205}
206
207U08 spi_transfer_byte(U08 data) {
208 // Start SPI Transfer
209 if (!(SPCR & (1<<MSTR)) ) {
210 SPCR |= 1<<MSTR;
211 }
212 SPDR = data;
213
214 while (!(SPSR & (1 << SPIF))) {
215 // Wait for transfer completed
216 }
217
218 return SPDR;
219}
220
221void spi_transfer_string(U08 length, U08* addr, U08 device) {
222 //#define SPI_E_CS PB4 //device 0
223 //#define SPI_AD_CS PD3 //device 1
224 //#define SPI_M_CS PD4 //device 2
225 //#define SPI_A_CS PD5 //device 3
226
227 // I assume the CS line is in "not enable"-state;
228 if ( device == 0 ){
229 TGL_BIT(PORTB, SPI_DEVICE_SS[device]);
230 }
231 else {
232 TGL_BIT(PORTD, SPI_DEVICE_SS[device]);
233 }
234 // now the line is in "enable"-state
235
236 for (U08 n = 0; n < length; n++) {
237 spi_transfer_byte(addr[n]);
238 }
239 if ( device == 0 ){
240 TGL_BIT(PORTB, SPI_DEVICE_SS[device]);
241 }
242 else {
243 TGL_BIT(PORTD, SPI_DEVICE_SS[device]);
244 }
245
246}
247
248void spi_transfer_w5100(U08 bytes) {
249 SPCR |= 1<<MSTR; // make sure we are still SPI MASTER ... sometimes this bit is cleared by something ... dkw?
250 for (U08 n = 0; n < bytes; n++) {
251 PORTB &= ~(1<< PB4); // SS low
252 SPDR = spi_write_buffer[n];
253 while (!(SPSR & (1 << SPIF))){
254 spi_read_buffer[n] = SPDR;
255 }
256 PORTB |= (1<< PB4); // SS HIGH
257 }
258}
259
Note: See TracBrowser for help on using the repository browser.