Project

General

Profile

Statistics
| Revision:

root / branches / encoders / code / projects / libdragonfly / spi.c @ 565

History | View | Annotate | Download (3.57 KB)

1 316 bpoole
/* @file spi.c
2
 * @brief
3
 * SPI module
4
 * @bug broken
5 252 kwoo
 */
6
7 316 bpoole
#include <avr/interrupt.h>
8
#include "ring_buffer.h"
9
#include "spi.h"
10
#include <dragonfly_lib.h>
11
12
13 252 kwoo
/*
14
SS = PB0
15
SCK = PB1
16
MOSI = PB2
17
MISO = PB3
18
*/
19 316 bpoole
/* Controls clock freq. see Table 72 of specs*/
20 252 kwoo
21
#define DOUBLE_SCK 1
22
#define SPR0_BIT 1
23 316 bpoole
#define SPR1_BIT 0
24 252 kwoo
#define LSB 1
25
#define MSB 0
26
27
28 350 kwoo
RING_BUFFER_NEW(spi_buffer, 16, char, spi_send_buff, spi_rec_buff);
29 316 bpoole
volatile char spi_status;
30 367 kwoo
char spi_mode;
31 316 bpoole
static spi_fun_recv_t  spi_recv_function;
32 367 kwoo
//static spi_fun_send_t  spi_send_function;
33 252 kwoo
34 316 bpoole
35 367 kwoo
void spi_init(char mode, spi_fun_recv_t recv_func) {
36 316 bpoole
    usb_puts("spi_init: start\n");
37 252 kwoo
38 367 kwoo
        spi_mode = mode;
39
40 252 kwoo
        RING_BUFFER_CLEAR(spi_send_buff);
41
        RING_BUFFER_CLEAR(spi_rec_buff);
42 316 bpoole
43
        spi_recv_function = recv_func;
44 367 kwoo
        //spi_send_function = send_func;
45 316 bpoole
46 350 kwoo
    /* Enables the SPI module
47
     * Enable Interrupt, Enable SPI Module, LSB First, Master Mode, Clock div = 64
48
     */
49
    SPCR = 0x00;
50 565 kwoo
    if (spi_mode == MASTER) {
51
            SPCR = _BV(SPIE) | _BV(SPE) | _BV(DORD) | _BV(MSTR)| _BV(SPR1) | _BV(SPR0);
52
    } else {
53
            SPCR = _BV(SPIE) | _BV(SPE) | _BV(DORD) | ~_BV(MSTR)| _BV(SPR1) | _BV(SPR0);
54
    }
55
56 350 kwoo
    SPSR = 0x00;
57
        SPSR = _BV(SPI2X);
58 252 kwoo
59 546 kwoo
        spi_status = SPI_IDLE;
60 316 bpoole
61 350 kwoo
    /* Set SCLK, SS, MOSI as outputs. MISO as input */
62 565 kwoo
        if(spi_mode == MASTER) {
63 350 kwoo
            DDRB |= MOSI | SCLK | SS;
64
            DDRB &= ~MISO;
65 367 kwoo
                PORTB |= SS;        //Keep SS High until transmit
66 350 kwoo
        /* Set SCLK, SS, MOSI as inputs. MISO as output */
67
        } else {
68
            DDRB &= ~MOSI & ~SCLK & ~SS;
69
            DDRB |= MISO;
70
    }
71 252 kwoo
72 350 kwoo
        //sei();
73 565 kwoo
        //usb_puts("spi_init: end\n");
74 252 kwoo
}
75
76 546 kwoo
int spi_send(char *data, int bytes) {
77 350 kwoo
78
        int i;
79
80
    if(bytes == 0)
81
        return -1; /* ...needed?*/
82 316 bpoole
83 350 kwoo
    //Prevent race condition on the buffer
84 316 bpoole
    cli();
85
    for(i = 1; i < bytes; i++) {
86 350 kwoo
        // Fail if the buffer is full
87
            if(RING_BUFFER_FULL(spi_send_buff)) {
88
                sei();
89
                return -1;
90
            }
91
92
            RING_BUFFER_ADD(spi_send_buff, data[i]);
93 252 kwoo
    }
94 350 kwoo
95 316 bpoole
    sei();
96 350 kwoo
97 490 bpoole
    spi_status |= SPI_SEND;
98 367 kwoo
99
        if (spi_mode == MASTER ){
100
                PORTB &= ~SS;        //Select slave
101
        }
102 495 kwoo
103 316 bpoole
    SPDR = *data;
104 565 kwoo
    /*
105 490 bpoole
        if(spi_mode)
106
                usb_puts("MASTER");
107
        else
108
                usb_puts("SLAVE");
109 495 kwoo

110 490 bpoole
        usb_puts(": sending [");usb_putc(*data);usb_puts("]\n\r");
111 565 kwoo
        */
112 316 bpoole
        //sei();
113 367 kwoo
114
        return 1;
115 252 kwoo
}
116
117 495 kwoo
void spi_read(int bytes) {
118
119
    cli();
120 546 kwoo
    for(int i = 1; i < bytes; i++) {
121 495 kwoo
        // Fail if the buffer is full
122
            if(RING_BUFFER_FULL(spi_send_buff)) {
123
                sei();
124 546 kwoo
                return;
125 495 kwoo
            }
126
127 565 kwoo
            RING_BUFFER_ADD(spi_send_buff, '0');
128 495 kwoo
    }
129
130
    sei();
131
132
    spi_status |= SPI_RECV;
133
134
        if (spi_mode == MASTER ){
135
                PORTB &= ~SS;        //Select slave
136
        }
137
138 565 kwoo
    SPDR = '0';
139 495 kwoo
140
}
141
142 490 bpoole
void spi_read_one(void)
143
{
144 367 kwoo
        PORTB &= ~SS;
145 490 bpoole
        SPDR = 'x';
146 367 kwoo
}
147
148 316 bpoole
ISR(SIG_SPI) {
149 367 kwoo
        char c;
150 546 kwoo
151 564 kwoo
        //You always receive something. You need to handle it before you overwrite it.
152
    spi_recv_function(SPDR);
153
154 546 kwoo
    //The clock is running so dequeue another byte to send
155 490 bpoole
        if(!RING_BUFFER_EMPTY(spi_send_buff)) {//cheap way to test if SPI_SEND
156
                RING_BUFFER_REMOVE(spi_send_buff, c);
157
                SPDR = c;
158 546 kwoo
        //If we're the master and we're done sending, end the transmission
159
        } else if (spi_mode == MASTER) {
160 495 kwoo
            PORTB |= SS;
161 565 kwoo
        } else if (spi_mode == SLAVE) {
162
            SPDR = '0';
163 495 kwoo
        }
164
165 564 kwoo
166 546 kwoo
167
        /*
168
        if(spi_status & SPI_SEND) {
169
                spi_status ^= SPI_SEND;
170

171
        if (spi_mode == MASTER) {
172
                    PORTB |= SS;
173
        }
174
    } else if (spi_status & SPI_RECV) {
175

176
    }
177
    */
178
    //End the transmission if we are not sending or recieving anymore
179
        //} else if(spi_mode == MASTER) {
180
        //   PORTB |= SS;
181
        //}
182
183 495 kwoo
        //Call the recv function whenver we recieve a byte
184 546 kwoo
        //if(spi_status == SPI_RECV){
185
                //spi_recv_function(SPDR);
186 495 kwoo
                //if(spi_mode == MASTER)
187
                        //PORTB |= SS;
188 546 kwoo
        //}
189 490 bpoole
}