root / branches / init_refactor / code / projects / libdragonfly / spi.c @ 1543
History | View | Annotate | Download (2.5 KB)
1 | 868 | justin | /**
|
---|---|---|---|
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 | 1462 | dsschult | |
10 | #include "dragonfly_defs.h" |
||
11 | 868 | justin | #include "spi.h" |
12 | |||
13 | 1461 | bneuman | unsigned char spi_initd=0; |
14 | 868 | justin | |
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 | 1461 | bneuman | *
|
25 | * @return 0 if init succesfull, an error code otherwise
|
||
26 | 868 | justin | */
|
27 | 1461 | bneuman | int spi_init (spi_fun_recv_t recv_func, spi_fun_recv_complete_t recv_complete_func)
|
28 | 868 | justin | { |
29 | 1461 | bneuman | if(spi_initd) {
|
30 | 1543 | bneuman | DRAGONFLY_DEBUG_PRINT("ERROR: SPI already init'd\r\n");
|
31 | 1461 | bneuman | return ERROR_INIT_ALREADY_INITD;
|
32 | } |
||
33 | |||
34 | 868 | justin | /* Enable Interrupt, Enable SPI Module, MSB First, Master Mode, Clock div = 64 */
|
35 | SPCR = _BV(SPE) | _BV(SPIE) /*| _BV(DORD)*/ | _BV(MSTR) | _BV(SPR1) | _BV(SPR0);
|
||
36 | SPSR = _BV(SPI2X); |
||
37 | |||
38 | /* Set SCLK, SS, MOSI as outputs. MISO as input */
|
||
39 | DDRB |= MOSI | SCLK | SS; |
||
40 | DDRB &= ~MISO; |
||
41 | |||
42 | /* Keep SS high until transmit */
|
||
43 | PORTB |= SS; |
||
44 | |||
45 | /* set function to be executed when we receive a byte */
|
||
46 | spi_recv_func = recv_func; |
||
47 | spi_recv_complete_func = recv_complete_func; |
||
48 | spi_bytes = 0;
|
||
49 | //usb_puts("\tspi.c Debug: SPI INITIALIZED\n");
|
||
50 | 1461 | bneuman | |
51 | spi_initd=1;
|
||
52 | return 0; |
||
53 | 868 | justin | } |
54 | |||
55 | /**
|
||
56 | * @brief Transfer a given byte to slave and receive a byte
|
||
57 | *
|
||
58 | * @param bytes The number of bytes to be transferred.
|
||
59 | **/
|
||
60 | 1461 | bneuman | int spi_transfer(char bytes) |
61 | 868 | justin | { |
62 | 1543 | bneuman | if(!spi_initd) {
|
63 | DRAGONFLY_DEBUG_PRINT("ERROR: SPI not init'd\r\n");
|
||
64 | return ERROR_LIBRARY_NOT_INITD;
|
||
65 | } |
||
66 | 1461 | bneuman | |
67 | 868 | justin | spi_bytes = bytes; |
68 | PORTB &= ~SS; /* Set SS low to initiate transmission */
|
||
69 | SPDR = 0xff; /* Initiate data transmision */ |
||
70 | 1461 | bneuman | |
71 | return 0; |
||
72 | 868 | justin | } |
73 | |||
74 | ISR(SIG_SPI) |
||
75 | { |
||
76 | //usb_puts("Interrupt");
|
||
77 | /* only handle intterupt when we are expecting data */
|
||
78 | if(spi_bytes > 0){ |
||
79 | /* process byte */
|
||
80 | spi_recv_func(SPDR); |
||
81 | /* if we've read all the bytes, set SS high to end transmission,
|
||
82 | * otherwise get the next byte */
|
||
83 | if(--spi_bytes == 0){ |
||
84 | //usb_puts("Read all bytes\r\n");
|
||
85 | PORTB |= SS; |
||
86 | if(spi_recv_complete_func)
|
||
87 | spi_recv_complete_func(); |
||
88 | }else {
|
||
89 | //usb_puts("There are this many bytes left: "); usb_puti(spi_bytes);usb_puts("\r\n");
|
||
90 | SPDR = 0xff;
|
||
91 | } |
||
92 | } |
||
93 | } |