Skip to content

Commit 6b4cd90

Browse files
committed
Backup-Point #1: This SPI access works.
0 parents  commit 6b4cd90

File tree

3 files changed

+254
-0
lines changed

3 files changed

+254
-0
lines changed
+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**************************************************************************************
2+
* INCLUDE
3+
**************************************************************************************/
4+
5+
#include <ThreadsafeIO.h>
6+
7+
/**************************************************************************************
8+
* CONSTANTS
9+
**************************************************************************************/
10+
11+
static int const BMP388_CS_PIN = 2;
12+
static int const BMP388_INT_PIN = 6;
13+
static uint8_t const BMP388_CHIP_ID_REG_ADDR = 0x00;
14+
15+
/**************************************************************************************
16+
* FUNCTION DECLARATION
17+
**************************************************************************************/
18+
19+
void bmp388_select();
20+
void bmp388_deselect();
21+
22+
/**************************************************************************************
23+
* GLOBAL VARIABLES
24+
**************************************************************************************/
25+
26+
27+
SpiBusDevice bmp388{"SPI",
28+
SpiBusDeviceConfig{
29+
SPISettings{1000000, MSBFIRST, SPI_MODE0},
30+
bmp388_select,
31+
bmp388_deselect,
32+
0x00}};
33+
34+
/**************************************************************************************
35+
* SETUP/LOOP
36+
**************************************************************************************/
37+
38+
void setup()
39+
{
40+
Serial.begin(9600);
41+
while (!Serial) { }
42+
43+
SPI.begin();
44+
45+
pinMode(BMP388_CS_PIN, OUTPUT);
46+
digitalWrite(BMP388_CS_PIN, HIGH);
47+
48+
auto bmp388_read_reg = [](uint8_t const reg_addr) -> uint8_t
49+
{
50+
uint8_t const tx_buf[3] = {static_cast<uint8_t>(0x80 | reg_addr), 0, 0};
51+
uint8_t rx_buf[3] = {0};
52+
size_t rx_buf_len = sizeof(rx_buf);
53+
54+
SpiIoRequest req(tx_buf, sizeof(tx_buf), rx_buf, &rx_buf_len);
55+
56+
bmp388.transfer(req);
57+
58+
return rx_buf[2];
59+
};
60+
61+
uint8_t const chip_id = bmp388_read_reg(BMP388_CHIP_ID_REG_ADDR);
62+
Serial.print("BMP388 CHIP ID = 0x");
63+
Serial.println(chip_id, HEX);
64+
}
65+
66+
void loop()
67+
{
68+
69+
}
70+
71+
/**************************************************************************************
72+
* FUNCTION DEFINITION
73+
**************************************************************************************/
74+
75+
void bmp388_select()
76+
{
77+
digitalWrite(BMP388_CS_PIN, LOW);
78+
}
79+
80+
void bmp388_deselect()
81+
{
82+
digitalWrite(BMP388_CS_PIN, HIGH);
83+
}

ThreadsafeIO/library.properties

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
name=ThreadsafeIO
2+
version=0.0.1
3+
author=Alexander Entinger <[email protected]>
4+
maintainer=Arduino <[email protected]>
5+
sentence=Enable threadsafe peripheral access via pipes.
6+
paragraph=
7+
category=Communication
8+
url=
9+
architectures=mbed
10+
include=ThreadsafeIO.h

ThreadsafeIO/src/ThreadsafeIO.h

+161
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/*
2+
* A deeply magical library providing threadsafe IO via pipes.
3+
*/
4+
5+
#ifndef THREADSAFE_IO_H_
6+
#define THREADSAFE_IO_H_
7+
8+
/**************************************************************************************
9+
* INCLUDE
10+
**************************************************************************************/
11+
12+
#include <algorithm>
13+
#include <functional>
14+
15+
#include <Arduino.h>
16+
#include <SPI.h>
17+
18+
/**************************************************************************************
19+
* CLASS DECLARATION
20+
**************************************************************************************/
21+
22+
/**************************************************************************************
23+
* IoRequest
24+
**************************************************************************************/
25+
26+
class IoRequest
27+
{
28+
public:
29+
enum class Type { None, SPI };
30+
31+
IoRequest(Type const type, uint8_t const * const tx_buf, size_t const tx_buf_len, uint8_t * rx_buf, size_t * rx_buf_len)
32+
: _type{type}
33+
, _tx_buf{tx_buf}
34+
, _tx_buf_len{tx_buf_len}
35+
, _rx_buf{rx_buf}
36+
, _rx_buf_len{rx_buf_len}
37+
{ }
38+
39+
Type _type{Type::None};
40+
uint8_t const * const _tx_buf{nullptr};
41+
size_t const _tx_buf_len{0};
42+
uint8_t * _rx_buf{nullptr};
43+
size_t * _rx_buf_len{0};
44+
};
45+
46+
class SpiIoRequest : public IoRequest
47+
{
48+
public:
49+
SpiIoRequest(uint8_t const * const tx_buf, size_t const tx_buf_len, uint8_t * rx_buf, size_t * rx_buf_len)
50+
: IoRequest(IoRequest::Type::SPI, tx_buf, tx_buf_len, rx_buf, rx_buf_len)
51+
{ }
52+
};
53+
54+
/**************************************************************************************
55+
* BusDevice
56+
**************************************************************************************/
57+
58+
class BusDevice
59+
{
60+
public:
61+
virtual ~BusDevice() { }
62+
enum class Status : int
63+
{
64+
Ok = 0,
65+
ConfigError = -1,
66+
};
67+
virtual Status transfer(IoRequest const & req) = 0;
68+
};
69+
70+
/**************************************************************************************
71+
* SpiBusDevice
72+
**************************************************************************************/
73+
74+
class SpiBusDeviceConfig
75+
{
76+
public:
77+
typedef std::function<void(void)> SpiSelectFunc;
78+
typedef std::function<void(void)> SpiDeselectFunc;
79+
SpiBusDeviceConfig(SPISettings const & spi_settings, SpiSelectFunc spi_select, SpiDeselectFunc spi_deselect, uint8_t const fill_symbol = 0xFF)
80+
: _spi_settings{spi_settings}
81+
, _spi_select{spi_select}
82+
, _spi_deselect{spi_deselect}
83+
, _fill_symbol{fill_symbol}
84+
{ }
85+
bool good () const { return (_spi_select && _spi_deselect); }
86+
SPISettings settings () const { return _spi_settings; }
87+
void select () const { if (_spi_select) _spi_select(); }
88+
void deselect () const { if (_spi_deselect) _spi_deselect(); }
89+
uint8_t fill_symbol() const { return _fill_symbol; }
90+
private:
91+
SPISettings _spi_settings;
92+
SpiSelectFunc _spi_select{nullptr};
93+
SpiDeselectFunc _spi_deselect{nullptr};
94+
uint8_t _fill_symbol{0xFF};
95+
};
96+
97+
class SpiBusDevice : public BusDevice
98+
{
99+
public:
100+
SpiBusDevice(std::string const & spi_bus, SpiBusDeviceConfig const & config) : _config{config}
101+
{
102+
/* TODO: Select SPI bus based in string. */
103+
}
104+
virtual Status transfer(IoRequest const & req) override
105+
{
106+
/* TODO: Instead of directly processing in here push
107+
* the whole request into a queue and hand over processing
108+
* to the IO thread.
109+
*/
110+
if (!_config.good())
111+
return Status::ConfigError;
112+
113+
_config.select();
114+
115+
SPI.beginTransaction(_config.settings());
116+
117+
size_t bytes_received = 0,
118+
bytes_sent = 0;
119+
for(; bytes_received < (*req._rx_buf_len); bytes_received++, bytes_sent++)
120+
{
121+
uint8_t tx_byte = 0;
122+
123+
if (bytes_sent < req._tx_buf_len)
124+
tx_byte = req._tx_buf[bytes_sent];
125+
else
126+
tx_byte = _config.fill_symbol();
127+
128+
req._rx_buf[bytes_received] = SPI.transfer(tx_byte);
129+
}
130+
*req._rx_buf_len = bytes_received;
131+
132+
SPI.endTransaction();
133+
134+
_config.deselect();
135+
136+
return Status::Ok;
137+
}
138+
private:
139+
SpiBusDeviceConfig _config;
140+
};
141+
142+
/**************************************************************************************
143+
* Stuff
144+
**************************************************************************************/
145+
146+
typedef int io_error_t;
147+
148+
class SpiIoManager
149+
{
150+
public:
151+
152+
io_error_t request(/* IoTransactionRequest const & req */);
153+
154+
155+
private:
156+
157+
void threadFunc();
158+
159+
};
160+
161+
#endif /* THREADSAFE_IO_H_ */

0 commit comments

Comments
 (0)