Open Lighting Architecture
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SPIOutput.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  * SPIOutput.h
17  * An RDM-controllable SPI device. Takes up to one universe of DMX.
18  * Copyright (C) 2013 Simon Newton
19  */
20 
21 #ifndef PLUGINS_SPI_SPIOUTPUT_H_
22 #define PLUGINS_SPI_SPIOUTPUT_H_
23 
24 #include <string>
25 #include <vector>
26 #include "ola/DmxBuffer.h"
28 #include "ola/rdm/UID.h"
29 #include "ola/stl/STLUtils.h"
30 #include "ola/rdm/ResponderOps.h"
31 
32 namespace ola {
33 namespace plugin {
34 namespace spi {
35 
36 using ola::rdm::UID;
39 
40 class Personality {
41  public:
42  Personality(uint16_t footprint, const string &description)
43  : m_footprint(footprint),
44  m_description(description) {
45  }
46 
47  uint16_t footprint() const { return m_footprint; }
48  string description() const { return m_description; }
49 
50  private:
51  uint16_t m_footprint;
52  const string m_description;
53 };
54 
56  public:
57  PersonalityManager() : m_active_personality(0) {}
58 
60  STLDeleteElements(&m_personalities);
61  }
62 
63  void AddPersonality(uint16_t footprint, const string &description) {
64  m_personalities.push_back(new Personality(footprint, description));
65  }
66 
67  uint8_t PersonalityCount() const { return m_personalities.size(); }
68 
69  bool SetActivePersonality(uint8_t personality) {
70  if (personality == 0 || personality > m_personalities.size())
71  return false;
72  m_active_personality = personality;
73  return true;
74  }
75 
76  uint8_t ActivePersonalityNumber() const { return m_active_personality; }
77 
78  const Personality *ActivePersonality() const {
79  return Lookup(m_active_personality);
80  }
81 
82  uint16_t ActivePersonalityFootprint() const {
83  const Personality *personality = Lookup(m_active_personality);
84  return personality ? personality->footprint() : 0;
85  }
86 
87  string ActivePersonalityDescription() const {
88  const Personality *personality = Lookup(m_active_personality);
89  return personality ? personality->description() : "";
90  }
91 
92  // Lookup a personality. Personalities are numbers from 1.
93  const Personality *Lookup(uint8_t personality) const {
94  if (personality == 0 || personality > m_personalities.size())
95  return NULL;
96  return m_personalities[personality - 1];
97  }
98 
99  private:
100  std::vector<Personality*> m_personalities;
101  uint8_t m_active_personality;
102 };
103 
104 
106  public:
107  struct Options {
108  uint8_t pixel_count;
109  uint8_t output_number;
110 
111  explicit Options(uint8_t output_number)
112  : pixel_count(25), // For the https://www.adafruit.com/products/738
113  output_number(output_number) {
114  }
115  };
116 
117  SPIOutput(const UID &uid,
118  class SPIBackendInterface *backend,
119  const Options &options);
120 
121  uint8_t GetPersonality() const;
122  bool SetPersonality(uint16_t personality);
123  uint16_t GetStartAddress() const;
124  bool SetStartAddress(uint16_t start_address);
125  unsigned int PixelCount() const { return m_pixel_count; }
126 
127  string Description() const;
128  bool WriteDMX(const DmxBuffer &buffer);
129 
131  void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback);
132  void SendRDMRequest(const ola::rdm::RDMRequest *request,
133  ola::rdm::RDMCallback *callback);
134 
135  private:
139  class RDMOps : public ola::rdm::ResponderOps<SPIOutput> {
140  public:
141  static RDMOps *Instance() {
142  if (!instance)
143  instance = new RDMOps();
144  return instance;
145  }
146 
147  private:
148  RDMOps() : ola::rdm::ResponderOps<SPIOutput>(PARAM_HANDLERS) {}
149 
150  static RDMOps *instance;
151  };
152 
153  class SPIBackendInterface *m_backend;
154  const uint8_t m_output_number;
155  string m_spi_device_name;
156  const UID m_uid;
157  const unsigned int m_pixel_count;
158  uint16_t m_start_address; // starts from 1
159  bool m_identify_mode;
160  PersonalityManager m_personality_manager;
161 
162  // DMX methods
163  void IndividualWS2801Control(const DmxBuffer &buffer);
164  void CombinedWS2801Control(const DmxBuffer &buffer);
165  void IndividualLPD8806Control(const DmxBuffer &buffer);
166  void CombinedLPD8806Control(const DmxBuffer &buffer);
167  unsigned int LPD8806BufferSize() const;
168  void WriteSPIData(const uint8_t *data, unsigned int length);
169 
170  // RDM methods
171  const RDMResponse *GetDeviceInfo(const RDMRequest *request);
172  const RDMResponse *GetProductDetailList(const RDMRequest *request);
173  const RDMResponse *GetDeviceModelDescription(const RDMRequest *request);
174  const RDMResponse *GetManufacturerLabel(const RDMRequest *request);
175  const RDMResponse *GetDeviceLabel(const RDMRequest *request);
176  const RDMResponse *GetSoftwareVersionLabel(const RDMRequest *request);
177  const RDMResponse *GetDmxPersonality(const RDMRequest *request);
178  const RDMResponse *SetDmxPersonality(const RDMRequest *request);
179  const RDMResponse *GetPersonalityDescription(const RDMRequest *request);
180  const RDMResponse *GetDmxStartAddress(const RDMRequest *request);
181  const RDMResponse *SetDmxStartAddress(const RDMRequest *request);
182  const RDMResponse *GetIdentify(const RDMRequest *request);
183  const RDMResponse *SetIdentify(const RDMRequest *request);
184 
185  static const uint8_t SPI_MODE;
186  static const uint8_t SPI_BITS_PER_WORD;
187  static const uint16_t SPI_DELAY;
188  static const uint32_t SPI_SPEED;
189  static const uint16_t WS2801_SLOTS_PER_PIXEL;
190  static const uint16_t LPD8806_SLOTS_PER_PIXEL;
191 
193  PARAM_HANDLERS[];
194 };
195 } // namespace spi
196 } // namespace plugin
197 } // namespace ola
198 #endif // PLUGINS_SPI_SPIOUTPUT_H_