-
Notifications
You must be signed in to change notification settings - Fork 0
/
spi.h
106 lines (85 loc) · 2.76 KB
/
spi.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#ifndef __SPICONFIG_H_
#define __SPICONFIG_H_
#include <stdint.h>
#include "lock.h"
/*
*
*/
extern lock_t _spi_lock;
extern uint8_t _spi_busy;
/*
* Used to define a peripheral, notably its SS-pin. Create one of these in PROGMEM.
*
* Values:
* port_register: port register containing the SS-bar pin for this peripheral
* pin_mask: bit mask with a single bit set for the SS-bar pin
*
* If you want to manually control SS-bar, set port_register to NULL.
*
*/
typedef struct _spi_peripheral_cfg {
volatile uint8_t *port_register; //The PORTx register containing the SS-pin
uint8_t pin_mask; //Should be, e.g., 0b00001000 if pin 3 is the SS-pin
//TODO: Speed/timing config too
} spi_peripheral_cfg;
/*
* Sets up the SPI interface as a master, full speed
* Setup on the negedge
*/
void setup_spi(void);
/*
* Returns a true-ish value if SPI is used by the module of the specified lock_val
* Returns true if SPI is possessed by the given lock_val.
*
* A good convention for lock_val is to use a pointer to the peripheral's
* configuration struct in PROGMEM
*/
static inline uint8_t acquire_spi(const spi_peripheral_cfg *lock_val) {
return acquire_lock(&_spi_lock, lock_val);
}
static inline uint8_t has_spi(const spi_peripheral_cfg *lock_val) {
return has_lock(&_spi_lock, lock_val);
}
// Current holder of the SPI lock
static inline const spi_peripheral_cfg *current_spi(void) {
return (const spi_peripheral_cfg *)lock_ptr(&_spi_lock);
}
static inline void release_spi(void) {
release_lock(&_spi_lock);
}
//uint8_t write_spi_byte_nb(spi_buf_t *sb);
/*
* Writes a buffer out the SPI interface asynchronously, returns immediately
*/
void write_spi(const uint8_t *buf, short len);
/*
* Same as write_spi(), but additionally the buffer contents are overwritten
* with data read in from the SPI device.
*/
void rw_spi(const uint8_t *buf, short len);
/*
* Attempts to acquire the SPI lock for the given peripheral, lowers the
* configured SS pin, executes rw_spi(…), and releases the lock at the end.
* A future call to has_spi(cfg) will return false once the transfer is
* complete.
*
* Returns truthy if the transfer was initiated, falsy otherwise (and it
* should be retried later).
*/
uint8_t async_rw_spi(const spi_peripheral_cfg *cfg, uint8_t *restrict buf, short len);
/*
* Spins until it can acquire the SPI lock for the given peripheral, lowers the
* configured SS pin, executes rw_spi(…), and releases the lock at the end.
*
* Returns once the transfer is complete.
*/
void sync_rw_spi(const spi_peripheral_cfg *cfg, uint8_t *restrict buf, short len);
/*
* True if the SPI interface is busy sending a buf
*/
static inline uint8_t spi_busy(void) {
return _spi_busy;
}
//void reset_latch(void);
//void set_latch(void);
#endif