Project

General

Profile

Statistics
| Revision:

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

History | View | Annotate | Download (2.46 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
static spi_fun_recv_t  spi_recv_function;
31
static spi_fun_send_t  spi_send_function;
32

    
33

    
34
int spi_init(char mode, spi_fun_send_t send_func, spi_fun_recv_t recv_func) {
35
    usb_puts("spi_init: start\n");
36

    
37
        //cli();
38
        RING_BUFFER_CLEAR(spi_send_buff);
39
        RING_BUFFER_CLEAR(spi_rec_buff);
40

    
41
        spi_recv_function = recv_func;
42
        spi_send_function = send_func;
43

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

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

    
68
int spi_send(char *data, size_t bytes) {
69

    
70
        int i;
71
            
72
        usb_puts("spi_send: start\n");
73

    
74
    if(bytes == 0) 
75
        return -1; /* ...needed?*/
76
    
77
    //Prevent race condition on the buffer
78
    cli();
79
    for(i = 1; i < bytes; i++) {
80
        // Fail if the buffer is full
81
            if(RING_BUFFER_FULL(spi_send_buff)) {
82
                sei();
83
                return -1;
84
            }
85
        
86
            RING_BUFFER_ADD(spi_send_buff, data[i]);
87
    }
88
    
89
    sei();
90
    
91
    spi_status = SPI_SENDING;
92
    SPDR = *data;
93
        
94
        usb_puts("spi_send: end\n");
95
        //sei();
96
}
97

    
98
ISR(SIG_SPI) {
99
    usb_puts("ISR: start\n\r");
100
        char c = SPDR;
101

    
102
        usb_putc('['); usb_puti(c);usb_putc(',');usb_puti(spi_status);usb_puts("]\n\r");
103
        switch(spi_status){
104
                case SPI_SENDING:
105
                        if(!RING_BUFFER_EMPTY(spi_send_buff)) {
106
                                RING_BUFFER_REMOVE(spi_send_buff, c);
107
                                usb_puts("SPDR=["); usb_puti(c);usb_putc(',');usb_puti(spi_status);usb_puts("]\n\r");
108
                                SPDR = c;
109
                                c = SPDR;
110
                                usb_puts("c=["); usb_puti(c);usb_putc(',');usb_puti(spi_status);usb_puts("]\n");
111
                                
112
                        } else {
113
                                spi_status = SPI_VOID;
114
                        }
115
                        break;
116
                case SPI_VOID:
117
                        spi_recv_function(c);
118
                        break;
119
        }
120
                SPSR ^= (1 << SPIF);
121
        usb_puts("ISR: end\n");
122
}