Revision 731
code commented and cleaned up. should work but untested.
branches/encoders/code/projects/libdragonfly/spi.c | ||
---|---|---|
1 |
/* @file spi.c |
|
2 |
* @brief |
|
3 |
* SPI module |
|
4 |
* @bug broken |
|
5 |
*/ |
|
1 |
/** |
|
2 |
* @file spi.c |
|
3 |
* @brief Basic SPI module to handle encoders |
|
4 |
* @author Colony Project, CMU Robotics Club |
|
5 |
* @bug Not tested |
|
6 |
* Need to move spi.h include into dragonfly_lib.h when stable |
|
7 |
**/ |
|
6 | 8 |
|
7 | 9 |
#include <avr/interrupt.h> |
8 |
#include "ring_buffer.h"
|
|
10 |
#include <dragonfly_lib.h>
|
|
9 | 11 |
#include "spi.h" |
10 |
#include <dragonfly_lib.h> |
|
11 | 12 |
|
13 |
static volatile char spi_bytes; /* number of bytes to read */ |
|
14 |
static spi_fun_recv_t spi_recv_func; /* byte handler */ |
|
12 | 15 |
|
13 |
/* |
|
14 |
SS = PB0 |
|
15 |
SCK = PB1 |
|
16 |
MOSI = PB2 |
|
17 |
MISO = PB3 |
|
18 |
*/ |
|
19 |
/* Controls clock freq. see Table 72 of specs*/ |
|
16 |
void spi_init (spi_fun_recv_t recv_func) |
|
17 |
{ |
|
18 |
/* Enable Interrupt, Enable SPI Module, MSB First, Master Mode, Clock div = 64 */ |
|
19 |
SPCR = _BV(SPE) | _BV(SPIE) | _BV(DORD) | _BV(MSTR) | _BV(SPR1) | _BV(SPR0); |
|
20 |
SPSR = _BV(SPI2X); |
|
20 | 21 |
|
21 |
#define DOUBLE_SCK 1 |
|
22 |
#define SPR0_BIT 1 |
|
23 |
#define SPR1_BIT 0 |
|
24 |
#define LSB 1 |
|
25 |
#define MSB 0 |
|
26 |
#define FIRST_BYTE 1 |
|
27 |
#define SECOND_BYTE 2 |
|
28 |
|
|
29 |
RING_BUFFER_NEW(spi_buffer, 16, char, spi_send_buff, spi_rec_buff); |
|
30 |
volatile char spi_status; |
|
31 |
volatile char spi_mode; |
|
32 |
static spi_fun_recv_t spi_recv_function; |
|
33 |
//static spi_fun_send_t spi_send_function; |
|
34 |
static volatile uint16_t i; |
|
35 |
|
|
36 |
void spi_init(spi_fun_recv_t recv_func) { |
|
37 |
usb_puts("spi_init: start\n"); |
|
38 |
|
|
39 |
|
|
40 |
spi_recv_function = recv_func; |
|
41 |
//spi_send_function = send_func; |
|
42 |
|
|
43 |
/* Enables the SPI module |
|
44 |
* Enable Interrupt, Enable SPI Module, LSB First, Master Mode, Clock div = 64 |
|
45 |
*/ |
|
46 |
SPCR = _BV(SPE) | _BV(SPIE)|_BV(DORD) | _BV(MSTR)| _BV(SPR1) | _BV(SPR0); |
|
47 |
SPSR = _BV(SPI2X); |
|
48 |
|
|
49 |
spi_status = SPI_VOID; |
|
50 |
|
|
51 | 22 |
/* Set SCLK, SS, MOSI as outputs. MISO as input */ |
52 |
DDRB = MOSI | SCLK | SS; |
|
53 |
DDRB &= ~MISO; |
|
54 |
PORTB |= SS; //Keep SS High until transmit |
|
23 |
DDRB = MOSI | SCLK | SS; |
|
24 |
DDRB &= ~MISO; |
|
25 |
|
|
26 |
/* Keep SS high until transmit */ |
|
27 |
PORTB |= SS; |
|
55 | 28 |
|
56 |
//sei(); |
|
57 |
usb_puts("spi_init: end\n"); |
|
29 |
/* set function to be executed when we receive a byte */ |
|
30 |
spi_recv_func = recv_func; |
|
31 |
spi_bytes = 0; |
|
58 | 32 |
} |
59 | 33 |
|
60 |
void spi_transfer(char c){ |
|
61 |
|
|
62 |
spi_mode = FIRST_BYTE; |
|
63 |
PORTB &= ~SS; |
|
64 |
SPDR = c; |
|
34 |
/* Transfer a given byte to slave and receive a byte */ |
|
35 |
void spi_transfer(char bytes) |
|
36 |
{ |
|
37 |
spi_bytes = bytes; |
|
38 |
PORTB &= ~SS; /* Set SS low to initiate transmission */ |
|
39 |
SPDR = 0xff; /* Initiate data transmision */ |
|
65 | 40 |
} |
66 | 41 |
|
67 |
ISR(SIG_SPI) { |
|
68 |
//usb_puts("ISR: start\n\r"); |
|
69 |
//char c=SPDR; |
|
70 |
//PORTB |= SS; |
|
71 |
usb_puts("spi_mode is: "); usb_puti(spi_mode);usb_puts("\r\n"); |
|
72 |
if(spi_mode < 4){ |
|
73 |
i=0; |
|
74 |
i = (uint16_t)SPDR; |
|
75 |
spi_recv_function(SPDR); |
|
76 |
SPDR = 0xff; |
|
77 |
spi_mode++; |
|
78 |
//usb_puts("done\n\r"); |
|
79 |
} else { |
|
80 |
spi_recv_function(SPDR); |
|
81 |
//usb_puts("second byte\r\n"); |
|
82 |
i |= (uint16_t)SPDR << 8; |
|
83 |
spi_mode = 1; |
|
84 |
PORTB |= SS; |
|
85 |
usb_puts("\r\n"); |
|
86 |
} |
|
87 |
|
|
88 |
//usb_puts("ISR: end\n"); |
|
42 |
ISR(SIG_SPI) |
|
43 |
{ |
|
44 |
/* only handle intterupt when we are expecting data */ |
|
45 |
if(spi_bytes > 0){ |
|
46 |
/* process byte */ |
|
47 |
spi_recv_func(SPDR); |
|
48 |
/* if we've read all the bytes, set SS high to end transmission, |
|
49 |
* otherwise get the next byte */ |
|
50 |
if(--spi_bytes == 0) |
|
51 |
PORTB |= SS; |
|
52 |
else |
|
53 |
SPDR = 0xff; |
|
54 |
} |
|
89 | 55 |
} |
branches/encoders/code/projects/libdragonfly/spi.h | ||
---|---|---|
1 |
/** |
|
2 |
* @file spi.h |
|
3 |
* @brief Definitions for SPI |
|
4 |
* @author Colony Project, CMU Robotics Club |
|
5 |
**/ |
|
6 |
|
|
1 | 7 |
#ifndef __SPI_H__ |
2 | 8 |
#define __SPI_H__ |
3 | 9 |
|
4 | 10 |
#define DOUBLE_SCK 1 |
5 | 11 |
#define SPR0_BIT 1 |
6 |
#define LSB 1 |
|
7 |
#define MSB 0 |
|
12 |
|
|
8 | 13 |
#define MASTER 1 |
9 | 14 |
#define SLAVE 0 |
10 |
#define SPI_SENDING 1 |
|
11 |
#define SPI_VOID 0 |
|
12 |
#define SPI_MASTER_RECV 2 |
|
13 | 15 |
|
14 |
/* Pin Defines */ |
|
15 | 16 |
#define MOSI _BV(PB2) |
16 | 17 |
#define MISO _BV(PB3) |
17 |
#define SS _BV(PB0) |
|
18 |
#define SS _BV(PB0)
|
|
18 | 19 |
#define SCLK _BV(PB1) |
19 | 20 |
|
20 |
#define size_t int |
|
21 |
typedef void (*spi_fun_recv_t)(unsigned char); |
|
22 |
typedef void (*spi_fun_send_t)(unsigned char); |
|
23 |
void spi_init(spi_fun_recv_t recv_func); |
|
24 |
int spi_send(char *data, size_t bytes); |
|
25 |
void spi_master_recv_on(void); |
|
26 |
void spi_master_recv_off(void); |
|
27 |
void spi_transfer(char c); |
|
21 |
typedef void (*spi_fun_recv_t)(char); |
|
28 | 22 |
|
23 |
void spi_init (spi_fun_recv_t); |
|
24 |
void spi_transfer (char); |
|
25 |
|
|
29 | 26 |
#endif |
Also available in: Unified diff