1
+ /*
2
+ * A deeply magical library providing threadsafe IO via pipes.
3
+ */
4
+
5
+ #ifndef SPI_BUS_DEVICE_H_
6
+ #define SPI_BUS_DEVICE_H_
7
+
8
+ /* *************************************************************************************
9
+ * INCLUDE
10
+ **************************************************************************************/
11
+
12
+ #include < functional>
13
+
14
+ #include < Arduino.h>
15
+ #include < mbed.h>
16
+ #include < SPI.h>
17
+
18
+ #include " IoRequest.h"
19
+ #include " BusDevice.h"
20
+
21
+ /* *************************************************************************************
22
+ * CLASS DECLARATION
23
+ **************************************************************************************/
24
+
25
+ class SpiBusDeviceConfig
26
+ {
27
+ public:
28
+ typedef std::function<void (void )> SpiSelectFunc;
29
+ typedef std::function<void (void )> SpiDeselectFunc;
30
+ SpiBusDeviceConfig (SPISettings const & spi_settings, SpiSelectFunc spi_select, SpiDeselectFunc spi_deselect, uint8_t const fill_symbol = 0xFF )
31
+ : _spi_settings{spi_settings}
32
+ , _spi_select{spi_select}
33
+ , _spi_deselect{spi_deselect}
34
+ , _fill_symbol{fill_symbol}
35
+ { }
36
+ bool good () const { return (_spi_select && _spi_deselect); }
37
+ SPISettings settings () const { return _spi_settings; }
38
+ void select () const { if (_spi_select) _spi_select (); }
39
+ void deselect () const { if (_spi_deselect) _spi_deselect (); }
40
+ uint8_t fill_symbol () const { return _fill_symbol; }
41
+ private:
42
+ SPISettings _spi_settings;
43
+ SpiSelectFunc _spi_select{nullptr };
44
+ SpiDeselectFunc _spi_deselect{nullptr };
45
+ uint8_t _fill_symbol{0xFF };
46
+ };
47
+
48
+ class SpiIoRequest : public IoRequest
49
+ {
50
+ public:
51
+ SpiIoRequest (uint8_t const * const tx_buf, size_t const tx_buf_len, uint8_t * rx_buf, size_t * rx_buf_len)
52
+ : IoRequest(IoRequest::Type::SPI, tx_buf, tx_buf_len, rx_buf, rx_buf_len)
53
+ { }
54
+
55
+ void set_config (SpiBusDeviceConfig * config) { _config = config; }
56
+ SpiBusDeviceConfig & config () { return *_config; }
57
+
58
+ private:
59
+ SpiBusDeviceConfig * _config{nullptr };
60
+ };
61
+
62
+ extern rtos::Queue<IoRequest, 32 > _request_queue;
63
+
64
+ class SpiBusDevice : public BusDevice
65
+ {
66
+ public:
67
+ SpiBusDevice (std::string const & spi_bus, SpiBusDeviceConfig const & config) : _config{config}
68
+ {
69
+ /* TODO: Select SPI bus based in string. */
70
+ }
71
+ virtual Status transfer (IoRequest & req) override
72
+ {
73
+ if (!_config.good ())
74
+ return Status::ConfigError;
75
+
76
+ reinterpret_cast <SpiIoRequest*>(&req)->set_config (&_config);
77
+
78
+ /* Insert into queue. */
79
+ _request_queue.try_put (&req);
80
+
81
+ /* TODO: Instead of directly processing in here push
82
+ * the whole request into a queue and hand over processing
83
+ * to the IO thread.
84
+ */
85
+ /*
86
+ _config.select();
87
+
88
+ SPI.beginTransaction(_config.settings());
89
+
90
+ size_t bytes_received = 0,
91
+ bytes_sent = 0;
92
+ for(; bytes_received < (*req.rx_buf_len()); bytes_received++, bytes_sent++)
93
+ {
94
+ uint8_t tx_byte = 0;
95
+
96
+ if (bytes_sent < req.tx_buf_len())
97
+ tx_byte = req.tx_buf()[bytes_sent];
98
+ else
99
+ tx_byte = _config.fill_symbol();
100
+
101
+ req.rx_buf()[bytes_received] = SPI.transfer(tx_byte);
102
+ }
103
+ *req.rx_buf_len() = bytes_received;
104
+
105
+ SPI.endTransaction();
106
+
107
+ _config.deselect();
108
+ */
109
+
110
+ return Status::Ok;
111
+ }
112
+
113
+ private:
114
+
115
+ SpiBusDeviceConfig _config;
116
+
117
+ };
118
+
119
+ #endif /* SPI_BUS_DEVICE_H_ */
0 commit comments