TTK4155 Lab Node 1
Term project in the NTNU course TTK4155 Embedded and Industrial Computer Systems Design
Loading...
Searching...
No Matches
spi.c
Go to the documentation of this file.
1#include <avr/io.h>
2#include <util/delay.h>
3
4#include "spi.h"
5#include "utils.h"
6
7static unsigned char _ready = 0;
8
9int spi_init() {
10 int status = 0;
11
12 DDRB |= (1 << PB5) | (1 << PB7) |
13 (1 << PB4); // Sets the required PORT B pins to SPI mode
14
15 SPCR |= (1 << SPE) |
16 (1 << MSTR) // Enables the SPI-bus and sets it to master mode, MSB
17 | (1 << SPR0); // first, no interrupt, and a clock freq of f_osc/4
18
19 /*
20 // Define PB2, PB4 and PE2 as slave select pins
21 */
22 DDRB |= (1 << PB2) | (1 << PB3) | (1 << PB4);
23 DDRE |= (1 << PE2);
24
25 /*
26 // Ensure initial state off
27 */
28 status = spi_set_slave_select((enum spi_slave *)SSB2, 1);
29 status = spi_set_slave_select((enum spi_slave *)SSB3, 1);
30 status = spi_set_slave_select((enum spi_slave *)SSE2, 1);
31
32 if (status) {
33 return status;
34 }
35
36 _ready = 1;
37
38 return status;
39}
40
41int spi_ready() { return !_ready; }
42
43int spi_set_slave_select(enum spi_slave *slave, unsigned char state) {
44 switch (*slave) {
45 case SSB2:
46 if (!state) {
47 PORTB |= (1 << PB3);
48 PORTE |= (1 << PE2);
49
50 PORTB &= ~(1 << PB2);
51 } else {
52 PORTB |= (1 << PB2);
53 }
54 break;
55 case SSE2:
56 if (!state) {
57 PORTB |= (1 << PB2);
58 PORTB |= (1 << PB3);
59
60 PORTE &= ~(1 << PE2);
61 } else {
62 PORTE |= (1 << PE2);
63 }
64 break;
65 case SSB3:
66 if (!state) {
67 PORTB |= (1 << PB2);
68 PORTE |= (1 << PE2);
69
70 PORTB &= ~(1 << PB3);
71 } else {
72 PORTB |= (1 << PB3);
73 }
74 break;
75 default:
76 return -1;
77 }
78 return 0;
79}
80
81int spi_send_n(enum spi_slave *slave, unsigned char *data, int length) {
82 spi_duplex(slave, data, TRASHCAN, length);
83 return 0;
84}
85
86int spi_send(enum spi_slave *slave, unsigned char data) {
87 spi_duplex(slave, &data, TRASHCAN, 1);
88 return 0;
89}
90
91int spi_recieve(enum spi_slave *slave, unsigned char *out) {
92 spi_duplex(slave, TRASHCAN, out, 1);
93 return 0;
94}
95
96int spi_recieve_n(enum spi_slave *slave, unsigned char *out, int length) {
97 spi_duplex(slave, TRASHCAN, out, length);
98 return 0;
99}
100
101/*
102int spi_duplex(enum spi_slave *slave, unsigned char *data, unsigned char *out,
103 int length) {
104 spi_set_slave_select(slave, 0);
105
106 SPDR = data[0];
107 while (!(SPSR & (1 << SPIF))) {
108 }
109
110 out[0] = SPDR;
111
112
113 _delay_us(40);
114
115 for (int i = 1; i < length; i++) {
116
117 SPDR = data[i];
118 while (!(SPSR & (1 << SPIF))) {
119 }
120 if (TRASHCAN != out)
121 {
122 out[i] = SPDR;
123 }
124
125 }
126 spi_set_slave_select(slave, 1);
127 return 0;
128}
129*/
130
131int spi_duplex(enum spi_slave *slave, unsigned char *data, unsigned char *out,
132 int length) {
133 spi_set_slave_select(slave, 0);
134
135 for (int i = 0; i < length; i++) {
136 unsigned char tx = 0xFF;
137 if (data != TRASHCAN) {
138 tx = data[i];
139 }
140
141 SPDR = tx;
142 while (!(SPSR & (1 << SPIF))) {
143 }
144
145 if (out != TRASHCAN) {
146 out[i] = SPDR;
147 }
148 }
149
150 spi_set_slave_select(slave, 1);
151 return 0;
152}
153
154int spi_push(enum spi_slave *slave, unsigned char data, unsigned char *out) {
155
156 spi_set_slave_select(slave, 0);
157 SPDR = data;
158 while (!(SPSR & (1 << SPIF))) {
159 }
160
161 // Only write if pointer is valid
162 if (out != TRASHCAN) {
163 *out = SPDR;
164 }
165 return 0;
166}
int spi_recieve_n(enum spi_slave *slave, unsigned char *out, int length)
Receive several bytes from a slave.
Definition spi.c:96
int spi_send_n(enum spi_slave *slave, unsigned char *data, int length)
Send a sequence of bytes to a slave without reading response.
Definition spi.c:81
int spi_ready()
Check if the SPI subsystem is initialized.
Definition spi.c:41
int spi_duplex(enum spi_slave *slave, unsigned char *data, unsigned char *out, int length)
Full-duplex SPI transfer.
Definition spi.c:131
int spi_set_slave_select(enum spi_slave *slave, unsigned char state)
Set the slave-select line for the given device.
Definition spi.c:43
int spi_push(enum spi_slave *slave, unsigned char data, unsigned char *out)
Push one byte to a slave and optionally read the response.
Definition spi.c:154
int spi_send(enum spi_slave *slave, unsigned char data)
Send a single byte to a slave.
Definition spi.c:86
int spi_recieve(enum spi_slave *slave, unsigned char *out)
Receive one byte from a slave.
Definition spi.c:91
spi_slave
Identifiers for available SPI slave devices.
Definition spi.h:15
int spi_init()
Initialize SPI in master mode.
Definition spi.c:9
@ SSB2
Definition spi.h:16
@ SSB3
Definition spi.h:17
@ SSE2
Definition spi.h:18
#define TRASHCAN
Definition utils.h:19
static unsigned char _ready
Definition spi.c:7
SPI driver.
Utility and helper functions for joystick, LED debugging, and mapping.