Open Lighting Architecture
 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 
37 using std::string;
38 using std::vector;
39 
44  public:
45  virtual ~SPIBackendInterface() {}
46 
47  virtual uint8_t *Checkout(uint8_t output, unsigned int length) = 0;
48  virtual uint8_t *Checkout(uint8_t output,
49  unsigned int length,
50  unsigned int latch_bytes) = 0;
51  virtual void Commit(uint8_t output) = 0;
52 
53  virtual string DevicePath() const = 0;
54 
55  virtual bool Init() = 0;
56 
57  protected:
58  static const char SPI_DROP_VAR[];
59  static const char SPI_DROP_VAR_KEY[];
60 };
61 
62 
67  public SPIBackendInterface {
68  public:
69  struct Options {
70  // Which GPIO bits to use to select the output. The number of outputs
71  // will be 2 ** gpio_pins.size();
72  vector<uint8_t> gpio_pins;
73  };
74 
75  HardwareBackend(const Options &options,
76  SPIWriterInterface *writer,
77  ExportMap *export_map);
78  ~HardwareBackend();
79 
80  bool Init();
81 
82  uint8_t *Checkout(uint8_t output, unsigned int length) {
83  return Checkout(output, length, 0);
84  }
85 
86  uint8_t *Checkout(uint8_t output,
87  unsigned int length,
88  unsigned int latch_bytes);
89  void Commit(uint8_t output);
90 
91  string DevicePath() const { return m_spi_writer->DevicePath(); }
92 
93  protected:
94  void* Run();
95 
96  private:
97  class OutputData {
98  public:
99  OutputData()
100  : m_data(NULL),
101  m_write_pending(false),
102  m_size(0),
103  m_actual_size(0),
104  m_latch_bytes(0) {
105  }
106 
107  ~OutputData() { delete[] m_data; }
108 
109  uint8_t *Resize(unsigned int length);
110  void SetLatchBytes(unsigned int latch_bytes);
111  void SetPending();
112  bool IsPending() const { return m_write_pending; }
113  void ResetPending() { m_write_pending = false; }
114  const uint8_t *GetData() const { return m_data; }
115  unsigned int Size() const { return m_size; }
116 
117  OutputData& operator=(const OutputData &other);
118 
119  private:
120  uint8_t *m_data;
121  bool m_write_pending;
122  unsigned int m_size;
123  unsigned int m_actual_size;
124  unsigned int m_latch_bytes;
125 
126  OutputData(const OutputData&);
127  };
128 
129  typedef vector<int> GPIOFds;
130  typedef vector<OutputData*> Outputs;
131 
132  SPIWriterInterface *m_spi_writer;
133  UIntMap *m_drop_map;
134  const uint8_t m_output_count;
135  ola::thread::Mutex m_mutex;
137  bool m_exit;
138 
139  Outputs m_output_data;
140 
141  // GPIO members
142  GPIOFds m_gpio_fds;
143  const vector<uint8_t> m_gpio_pins;
144  vector<bool> m_gpio_pin_state;
145 
146  void SetupOutputs(Outputs *outputs);
147  void WriteOutput(uint8_t output_id, OutputData *output);
148  bool SetupGPIO();
149  void CloseGPIOFDs();
150 };
151 
152 
158  public ola::thread::Thread {
159  public:
160  struct Options {
161  /*
162  * The number of outputs.
163  */
164  uint8_t outputs;
165  /*
166  * Controls if we designate one of the outputs as the 'sync' output.
167  * If set >= 0, it denotes the output which triggers the SPI write.
168  * If set to -1, we perform an SPI write on each update.
169  */
170  int16_t sync_output;
171 
172  explicit Options() : outputs(1), sync_output(0) {}
173  };
174 
175  SoftwareBackend(const Options &options,
176  SPIWriterInterface *writer,
177  ExportMap *export_map);
178  ~SoftwareBackend();
179 
180  bool Init();
181 
182  uint8_t *Checkout(uint8_t output, unsigned int length) {
183  return Checkout(output, length, 0);
184  }
185 
186  uint8_t *Checkout(uint8_t output,
187  unsigned int length,
188  unsigned int latch_bytes);
189  void Commit(uint8_t output);
190 
191  string DevicePath() const { return m_spi_writer->DevicePath(); }
192 
193  protected:
194  void* Run();
195 
196  private:
197  SPIWriterInterface *m_spi_writer;
198  UIntMap *m_drop_map;
199  ola::thread::Mutex m_mutex;
201  bool m_write_pending;
202  bool m_exit;
203 
204  const int16_t m_sync_output;
205  vector<unsigned int> m_output_sizes;
206  vector<unsigned int> m_latch_bytes;
207  uint8_t *m_output;
208  unsigned int m_length;
209  unsigned int m_buffer_size;
210 };
211 
212 
218  public:
219  explicit FakeSPIBackend(unsigned int outputs);
220  ~FakeSPIBackend();
221 
222  uint8_t *Checkout(uint8_t output, unsigned int length) {
223  return Checkout(output, length, 0);
224  }
225 
226  uint8_t *Checkout(uint8_t output,
227  unsigned int length,
228  unsigned int latch_bytes);
229 
230  void Commit(uint8_t output);
231  const uint8_t *GetData(uint8_t output, unsigned int *length);
232 
233  string DevicePath() const { return "/dev/test"; }
234 
235  bool Init() { return true; }
236 
237  unsigned int Writes(uint8_t output) const;
238 
239  private:
240  class Output {
241  public:
242  Output() : data(NULL), length(0), writes(0) {}
243  ~Output() { delete[] data; }
244 
245  uint8_t *data;
246  unsigned int length;
247  unsigned int writes;
248  };
249 
250  typedef vector<Output*> Outputs;
251  Outputs m_outputs;
252 };
253 } // namespace spi
254 } // namespace plugin
255 } // namespace ola
256 #endif // PLUGINS_SPI_SPIBACKEND_H_