root / trunk / code / projects / libdragonfly / spi.c @ 1462
History | View | Annotate | Download (2.38 KB)
1 |
/**
|
---|---|
2 |
* @file spi.c
|
3 |
* @brief Basic SPI module to handle encoders
|
4 |
* @author Colony Project, CMU Robotics Club
|
5 |
* Need to move spi.h include into dragonfly_lib.h when stable
|
6 |
**/
|
7 |
|
8 |
#include <avr/interrupt.h> |
9 |
|
10 |
#include "dragonfly_defs.h" |
11 |
#include "spi.h" |
12 |
|
13 |
unsigned char spi_initd=0; |
14 |
|
15 |
static volatile char spi_bytes; /* number of bytes to read */ |
16 |
static spi_fun_recv_t spi_recv_func; /* byte handler */ |
17 |
static spi_fun_recv_complete_t spi_recv_complete_func; /*transmission completion handler */ |
18 |
|
19 |
/**
|
20 |
* @brief Initialize SPI hardware for communication.
|
21 |
*
|
22 |
* @param recv_func The function to be called for each byte of data received.
|
23 |
* @param recv_complete_func The function to be called at the end of a complete transmission.
|
24 |
*
|
25 |
* @return 0 if init succesfull, an error code otherwise
|
26 |
*/
|
27 |
int spi_init (spi_fun_recv_t recv_func, spi_fun_recv_complete_t recv_complete_func)
|
28 |
{ |
29 |
if(spi_initd) {
|
30 |
return ERROR_INIT_ALREADY_INITD;
|
31 |
} |
32 |
|
33 |
/* Enable Interrupt, Enable SPI Module, MSB First, Master Mode, Clock div = 64 */
|
34 |
SPCR = _BV(SPE) | _BV(SPIE) /*| _BV(DORD)*/ | _BV(MSTR) | _BV(SPR1) | _BV(SPR0);
|
35 |
SPSR = _BV(SPI2X); |
36 |
|
37 |
/* Set SCLK, SS, MOSI as outputs. MISO as input */
|
38 |
DDRB |= MOSI | SCLK | SS; |
39 |
DDRB &= ~MISO; |
40 |
|
41 |
/* Keep SS high until transmit */
|
42 |
PORTB |= SS; |
43 |
|
44 |
/* set function to be executed when we receive a byte */
|
45 |
spi_recv_func = recv_func; |
46 |
spi_recv_complete_func = recv_complete_func; |
47 |
spi_bytes = 0;
|
48 |
//usb_puts("\tspi.c Debug: SPI INITIALIZED\n");
|
49 |
|
50 |
spi_initd=1;
|
51 |
return 0; |
52 |
} |
53 |
|
54 |
/**
|
55 |
* @brief Transfer a given byte to slave and receive a byte
|
56 |
*
|
57 |
* @param bytes The number of bytes to be transferred.
|
58 |
**/
|
59 |
int spi_transfer(char bytes) |
60 |
{ |
61 |
if(!spi_initd)
|
62 |
return ERROR_LIBRARY_NOT_INITD;
|
63 |
|
64 |
spi_bytes = bytes; |
65 |
PORTB &= ~SS; /* Set SS low to initiate transmission */
|
66 |
SPDR = 0xff; /* Initiate data transmision */ |
67 |
|
68 |
return 0; |
69 |
} |
70 |
|
71 |
ISR(SIG_SPI) |
72 |
{ |
73 |
//usb_puts("Interrupt");
|
74 |
/* only handle intterupt when we are expecting data */
|
75 |
if(spi_bytes > 0){ |
76 |
/* process byte */
|
77 |
spi_recv_func(SPDR); |
78 |
/* if we've read all the bytes, set SS high to end transmission,
|
79 |
* otherwise get the next byte */
|
80 |
if(--spi_bytes == 0){ |
81 |
//usb_puts("Read all bytes\r\n");
|
82 |
PORTB |= SS; |
83 |
if(spi_recv_complete_func)
|
84 |
spi_recv_complete_func(); |
85 |
}else {
|
86 |
//usb_puts("There are this many bytes left: "); usb_puti(spi_bytes);usb_puts("\r\n");
|
87 |
SPDR = 0xff;
|
88 |
} |
89 |
} |
90 |
} |