Open Lighting Architecture  0.9.6
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
33 namespace ola {
34 namespace plugin {
35 namespace spi {
36 
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 
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<uint8_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;
134  bool m_exit;
135 
136  Outputs m_output_data;
137 
138  // GPIO members
139  GPIOFds m_gpio_fds;
140  const std::vector<uint8_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 
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;
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 
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_