Open Lighting Architecture: plugins/spi/SPIBackend.h Source File

| Open Lighting Architecture 0.10.9

Loading...
Searching...
No Matches
SPIBackend.h
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
15 *
16 * SPIBackend.h
17 * The backend for SPI output. These are the classes which write the data to
18 * the SPI bus.
19 * Copyright (C) 2013 Simon Newton
20 */
21
22#ifndef PLUGINS_SPI_SPIBACKEND_H_
23#define PLUGINS_SPI_SPIBACKEND_H_
24
25#include <stdint.h>
26#include <ola/thread/Mutex.h>
27#include <ola/thread/Thread.h>
28#include <string>
29#include <vector>
30
31#include "plugins/spi/SPIWriter.h"
32
33namespace ola {
34namespace plugin {
35namespace spi {
36
40 class SPIBackendInterface {
41 public:
42 virtual ~SPIBackendInterface() {}
43
44 virtual uint8_t *Checkout(uint8_t output, unsigned int length) = 0;
45 virtual uint8_t *Checkout(uint8_t output,
46 unsigned int length,
47 unsigned int latch_bytes) = 0;
48 virtual void Commit(uint8_t output) = 0;
49
50 virtual std::string DevicePath() const = 0;
51
52 virtual bool Init() = 0;
53
54 protected:
55 static const char SPI_DROP_VAR[];
56 static const char SPI_DROP_VAR_KEY[];
57};
58
59
63 class HardwareBackend : public ola::thread::Thread,
64 public SPIBackendInterface {
65 public:
66 struct Options {
67 // Which GPIO bits to use to select the output. The number of outputs
68 // will be 2 ** gpio_pins.size();
69 std::vector<uint16_t> gpio_pins;
70 };
71
72 HardwareBackend(const Options &options,
73 SPIWriterInterface *writer,
74 ExportMap *export_map);
75 ~HardwareBackend();
76
77 bool Init();
78
79 uint8_t *Checkout(uint8_t output, unsigned int length) {
80 return Checkout(output, length, 0);
81 }
82
83 uint8_t *Checkout(uint8_t output,
84 unsigned int length,
85 unsigned int latch_bytes);
86 void Commit(uint8_t output);
87
88 std::string DevicePath() const { return m_spi_writer->DevicePath(); }
89
90 protected:
91 void* Run();
92
93 private:
94 class OutputData {
95 public:
96 OutputData()
97 : m_data(NULL),
98 m_write_pending(false),
99 m_size(0),
100 m_actual_size(0),
101 m_latch_bytes(0) {
102 }
103
104 ~OutputData() { delete[] m_data; }
105
106 uint8_t *Resize(unsigned int length);
107 void SetLatchBytes(unsigned int latch_bytes);
108 void SetPending();
109 bool IsPending() const { return m_write_pending; }
110 void ResetPending() { m_write_pending = false; }
111 const uint8_t *GetData() const { return m_data; }
112 unsigned int Size() const { return m_size; }
113
114 OutputData& operator=(const OutputData &other);
115
116 private:
117 uint8_t *m_data;
118 bool m_write_pending;
119 unsigned int m_size;
120 unsigned int m_actual_size;
121 unsigned int m_latch_bytes;
122
123 OutputData(const OutputData&);
124 };
125
126 typedef std::vector<int> GPIOFds;
127 typedef std::vector<OutputData*> Outputs;
128
129 SPIWriterInterface *m_spi_writer;
130 UIntMap *m_drop_map;
131 const uint8_t m_output_count;
132 ola::thread::Mutex m_mutex;
133 ola::thread::ConditionVariable m_cond_var;
134 bool m_exit;
135
136 Outputs m_output_data;
137
138 // GPIO members
139 GPIOFds m_gpio_fds;
140 const std::vector<uint16_t> m_gpio_pins;
141 std::vector<bool> m_gpio_pin_state;
142
143 void SetupOutputs(Outputs *outputs);
144 void WriteOutput(uint8_t output_id, OutputData *output);
145 bool SetupGPIO();
146 void CloseGPIOFDs();
147};
148
149
154 class SoftwareBackend : public SPIBackendInterface,
155 public ola::thread::Thread {
156 public:
157 struct Options {
158 /*
159 * The number of outputs.
160 */
161 uint8_t outputs;
162 /*
163 * Controls if we designate one of the outputs as the 'sync' output.
164 * If set >= 0, it denotes the output which triggers the SPI write.
165 * If set to -1, we perform an SPI write on each update.
166 */
167 int16_t sync_output;
168
169 Options() : outputs(1), sync_output(0) {}
170 };
171
172 SoftwareBackend(const Options &options,
173 SPIWriterInterface *writer,
174 ExportMap *export_map);
175 ~SoftwareBackend();
176
177 bool Init();
178
179 uint8_t *Checkout(uint8_t output, unsigned int length) {
180 return Checkout(output, length, 0);
181 }
182
183 uint8_t *Checkout(uint8_t output,
184 unsigned int length,
185 unsigned int latch_bytes);
186 void Commit(uint8_t output);
187
188 std::string DevicePath() const { return m_spi_writer->DevicePath(); }
189
190 protected:
191 void* Run();
192
193 private:
194 SPIWriterInterface *m_spi_writer;
195 UIntMap *m_drop_map;
196 ola::thread::Mutex m_mutex;
197 ola::thread::ConditionVariable m_cond_var;
198 bool m_write_pending;
199 bool m_exit;
200
201 const int16_t m_sync_output;
202 std::vector<unsigned int> m_output_sizes;
203 std::vector<unsigned int> m_latch_bytes;
204 uint8_t *m_output;
205 unsigned int m_length;
206};
207
208
213 class FakeSPIBackend : public SPIBackendInterface {
214 public:
215 explicit FakeSPIBackend(unsigned int outputs);
216 ~FakeSPIBackend();
217
218 uint8_t *Checkout(uint8_t output, unsigned int length) {
219 return Checkout(output, length, 0);
220 }
221
222 uint8_t *Checkout(uint8_t output,
223 unsigned int length,
224 unsigned int latch_bytes);
225
226 void Commit(uint8_t output);
227 const uint8_t *GetData(uint8_t output, unsigned int *length);
228
229 std::string DevicePath() const { return "/dev/test"; }
230
231 bool Init() { return true; }
232
233 unsigned int Writes(uint8_t output) const;
234
235 private:
236 class Output {
237 public:
238 Output() : data(NULL), length(0), writes(0) {}
239 ~Output() { delete[] data; }
240
241 uint8_t *data;
242 unsigned int length;
243 unsigned int writes;
244 };
245
246 typedef std::vector<Output*> Outputs;
247 Outputs m_outputs;
248};
249} // namespace spi
250} // namespace plugin
251} // namespace ola
252#endif // PLUGINS_SPI_SPIBACKEND_H_
ola::ExportMap
A container for the exported variables.
Definition ExportMap.h:324
ola::UIntMap
Definition ExportMap.h:242
ola::plugin::spi::HardwareBackend::Run
void * Run()
The entry point for the new thread.
Definition SPIBackend.cpp:172
ola::plugin::spi::SPIBackendInterface
Definition SPIBackend.h:40
ola::plugin::spi::SPIWriterInterface
Definition SPIWriter.h:36
ola::plugin::spi::SoftwareBackend::Run
void * Run()
The entry point for the new thread.
Definition SPIBackend.cpp:407
ola::thread::ConditionVariable
Definition Mutex.h:83
ola::thread::Mutex
Definition Mutex.h:41
ola::thread::Thread
Definition Thread.h:52
ola::plugin::spi
Code for SPI devices.
ola::plugin
Code for supported devices and protocols.
ola
The namespace containing all OLA symbols.
Definition Credentials.cpp:44
ola::plugin::spi::HardwareBackend::Options
Definition SPIBackend.h:66
ola::plugin::spi::SoftwareBackend::Options
Definition SPIBackend.h:157