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