Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (3.34 KB)

1
/* @file spi.c
2
 * @brief
3
 * SPI module
4
 * @bug broken
5
 */
6

    
7
#include <avr/interrupt.h>
8
#include "ring_buffer.h"
9
#include "spi.h"
10
#include <dragonfly_lib.h>
11

    
12

    
13
/*
14
SS = PB0
15
SCK = PB1
16
MOSI = PB2
17
MISO = PB3
18
*/
19
/* Controls clock freq. see Table 72 of specs*/
20

    
21
#define DOUBLE_SCK 1
22
#define SPR0_BIT 1
23
#define SPR1_BIT 0
24
#define LSB 1
25
#define MSB 0
26

    
27

    
28
RING_BUFFER_NEW(spi_buffer, 16, char, spi_send_buff, spi_rec_buff);
29
volatile char spi_status;
30
char spi_mode;
31
static spi_fun_recv_t  spi_recv_function;
32
//static spi_fun_send_t  spi_send_function;
33

    
34

    
35
void spi_init(char mode, spi_fun_recv_t recv_func) {
36
    usb_puts("spi_init: start\n");
37

    
38
        spi_mode = mode;
39

    
40
        RING_BUFFER_CLEAR(spi_send_buff);
41
        RING_BUFFER_CLEAR(spi_rec_buff);
42

    
43
        spi_recv_function = recv_func;
44
        //spi_send_function = send_func;
45

    
46
    /* Enables the SPI module
47
     * Enable Interrupt, Enable SPI Module, LSB First, Master Mode, Clock div = 64
48
     */
49
    SPCR = 0x00;
50
        SPCR = _BV(SPIE) | _BV(SPE) | _BV(DORD) | _BV(MSTR)| _BV(SPR1) | _BV(SPR0);
51
    SPSR = 0x00;
52
        SPSR = _BV(SPI2X); 
53
        
54
        spi_status = SPI_IDLE;
55

    
56
    /* Set SCLK, SS, MOSI as outputs. MISO as input */
57
        if(mode == MASTER) {
58
            DDRB |= MOSI | SCLK | SS;
59
            DDRB &= ~MISO;
60
                PORTB |= SS;        //Keep SS High until transmit
61
        /* Set SCLK, SS, MOSI as inputs. MISO as output */
62
        } else {
63
            DDRB &= ~MOSI & ~SCLK & ~SS;
64
            DDRB |= MISO;
65
    }
66
        
67
        //sei();
68
        usb_puts("spi_init: end\n");
69
}
70

    
71
int spi_send(char *data, int bytes) {
72

    
73
        int i;
74

    
75
    if(bytes == 0) 
76
        return -1; /* ...needed?*/
77
    
78
    //Prevent race condition on the buffer
79
    cli();
80
    for(i = 1; i < bytes; i++) {
81
        // Fail if the buffer is full
82
            if(RING_BUFFER_FULL(spi_send_buff)) {
83
                sei();
84
                return -1;
85
            }
86
        
87
            RING_BUFFER_ADD(spi_send_buff, data[i]);
88
    }
89
    
90
    sei();
91
    
92
    spi_status |= SPI_SEND;
93
        
94
        if (spi_mode == MASTER ){
95
                PORTB &= ~SS;        //Select slave
96
        }
97
        
98
    SPDR = *data;
99
    
100
        if(spi_mode)
101
                usb_puts("MASTER");
102
        else
103
                usb_puts("SLAVE");
104
                
105
        usb_puts(": sending [");usb_putc(*data);usb_puts("]\n\r");
106
        
107
        //sei();
108
        
109
        return 1;
110
}
111

    
112
void spi_read(int bytes) {
113
    
114
    cli();
115
    for(int i = 1; i < bytes; i++) {
116
        // Fail if the buffer is full
117
            if(RING_BUFFER_FULL(spi_send_buff)) {
118
                sei();
119
                return;
120
            }
121
        
122
            RING_BUFFER_ADD(spi_send_buff, '\n');
123
    }
124
    
125
    sei();
126

    
127
    spi_status |= SPI_RECV;
128
        
129
        if (spi_mode == MASTER ){
130
                PORTB &= ~SS;        //Select slave
131
        }
132
        
133
    SPDR = '\n';
134

    
135
}
136

    
137
void spi_read_one(void)
138
{
139
        PORTB &= ~SS;
140
        SPDR = 'x';
141
}
142

    
143
ISR(SIG_SPI) {
144
        char c;
145

    
146
    //The clock is running so dequeue another byte to send        
147
        if(!RING_BUFFER_EMPTY(spi_send_buff)) {//cheap way to test if SPI_SEND
148
                RING_BUFFER_REMOVE(spi_send_buff, c);
149
                SPDR = c;
150
        
151
        //If we're the master and we're done sending, end the transmission
152
        } else if (spi_mode == MASTER) {
153
            PORTB |= SS;
154
        }
155
        
156
        //You always receive something. You need to handle it.
157
    spi_recv_function(SPDR);        
158
    
159
        /*
160
        if(spi_status & SPI_SEND) {
161
                spi_status ^= SPI_SEND;
162
                
163
        if (spi_mode == MASTER) {
164
                    PORTB |= SS;
165
        }
166
    } else if (spi_status & SPI_RECV) {
167
           
168
    }
169
    */
170
    //End the transmission if we are not sending or recieving anymore
171
        //} else if(spi_mode == MASTER) {
172
        //   PORTB |= SS;
173
        //}
174
        
175
        //Call the recv function whenver we recieve a byte
176
        //if(spi_status == SPI_RECV){
177
                //spi_recv_function(SPDR);
178
                //if(spi_mode == MASTER)
179
                        //PORTB |= SS;
180
        //}
181
}                
182