Open Lighting Architecture  Latest Git
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 <memory>
25 #include <string>
27 #include "ola/DmxBuffer.h"
29 #include "ola/rdm/UID.h"
30 #include "ola/stl/STLUtils.h"
31 #include "ola/rdm/ResponderOps.h"
32 #include "ola/rdm/ResponderPersonality.h"
34 
35 namespace ola {
36 namespace plugin {
37 namespace spi {
38 
40  public:
41  // definitions for all SPI Personalities
42  // keep personality order
43  // - it is important for backwards compatibility
44  // the integer representation is used to store the configuration in files
45  // and RDM Personality IDs should also be stable.
46  // new ones can be added at end.
47  // remember to increment RDM-Version in
48  // SPIOutput.cpp SPIOutput::GetDeviceInfo()
49  enum SPI_PERSONALITY {
50  PERS_WS2801_INDIVIDUAL = 1,
51  PERS_WS2801_COMBINED = 2,
52  PERS_LDP8806_INDIVIDUAL = 3,
53  PERS_LDP8806_COMBINED = 4,
54  PERS_P9813_INDIVIDUAL = 5,
55  PERS_P9813_COMBINED = 6,
56  PERS_APA102_INDIVIDUAL = 7,
57  PERS_APA102_COMBINED = 8,
58  PERS_APA102_PB_INDIVIDUAL,
59  PERS_APA102_PB_COMBINED,
60  };
61 
62  struct Options {
63  std::string device_label;
64  uint8_t pixel_count;
65  uint8_t output_number;
66 
67  explicit Options(uint8_t output_number, const std::string &spi_device_name)
68  : device_label("SPI Device - " + spi_device_name),
69  pixel_count(25), // For the https://www.adafruit.com/products/738
70  output_number(output_number) {
71  }
72  };
73 
74  SPIOutput(const ola::rdm::UID &uid,
75  class SPIBackendInterface *backend,
76  const Options &options);
77  ~SPIOutput();
78 
79  std::string GetDeviceLabel() const;
80  bool SetDeviceLabel(const std::string &device_label);
81  uint8_t GetPersonality() const;
82  bool SetPersonality(uint16_t personality);
83  uint16_t GetStartAddress() const;
84  bool SetStartAddress(uint16_t start_address);
85  unsigned int PixelCount() const { return m_pixel_count; }
86 
87  std::string Description() const;
88  bool WriteDMX(const DmxBuffer &buffer);
89 
93  ola::rdm::RDMCallback *callback);
94 
95  private:
99  class RDMOps : public ola::rdm::ResponderOps<SPIOutput> {
100  public:
101  static RDMOps *Instance() {
102  if (!instance)
103  instance = new RDMOps();
104  return instance;
105  }
106 
107  private:
108  RDMOps() : ola::rdm::ResponderOps<SPIOutput>(PARAM_HANDLERS) {}
109 
110  static RDMOps *instance;
111  };
112 
113  class SPIBackendInterface *m_backend;
114  const uint8_t m_output_number;
115  std::string m_spi_device_name;
116  const ola::rdm::UID m_uid;
117  const unsigned int m_pixel_count;
118  std::string m_device_label;
119  uint16_t m_start_address; // starts from 1
120  bool m_identify_mode;
121  std::auto_ptr<ola::rdm::PersonalityCollection> m_personality_collection;
122  std::auto_ptr<ola::rdm::PersonalityManager> m_personality_manager;
123  ola::rdm::Sensors m_sensors;
124  std::auto_ptr<ola::rdm::NetworkManagerInterface> m_network_manager;
125 
126  // DMX methods
127  bool InternalWriteDMX(const DmxBuffer &buffer);
128 
129  void IndividualWS2801Control(const DmxBuffer &buffer);
130  void CombinedWS2801Control(const DmxBuffer &buffer);
131  void IndividualLPD8806Control(const DmxBuffer &buffer);
132  void CombinedLPD8806Control(const DmxBuffer &buffer);
133  void IndividualP9813Control(const DmxBuffer &buffer);
134  void CombinedP9813Control(const DmxBuffer &buffer);
135  void IndividualAPA102Control(const DmxBuffer &buffer);
136  void CombinedAPA102Control(const DmxBuffer &buffer);
137  void IndividualAPA102ControlPixelBrightness(const DmxBuffer &buffer);
138  void CombinedAPA102ControlPixelBrightness(const DmxBuffer &buffer);
139 
140  unsigned int LPD8806BufferSize() const;
141  void WriteSPIData(const uint8_t *data, unsigned int length);
142 
143  // RDM methods
144  ola::rdm::RDMResponse *GetDeviceInfo(
145  const ola::rdm::RDMRequest *request);
146  ola::rdm::RDMResponse *GetProductDetailList(
147  const ola::rdm::RDMRequest *request);
148  ola::rdm::RDMResponse *GetDeviceModelDescription(
149  const ola::rdm::RDMRequest *request);
150  ola::rdm::RDMResponse *GetManufacturerLabel(
151  const ola::rdm::RDMRequest *request);
152  ola::rdm::RDMResponse *GetDeviceLabel(
153  const ola::rdm::RDMRequest *request);
154  ola::rdm::RDMResponse *SetDeviceLabel(
155  const ola::rdm::RDMRequest *request);
156  ola::rdm::RDMResponse *GetSoftwareVersionLabel(
157  const ola::rdm::RDMRequest *request);
158  ola::rdm::RDMResponse *GetDmxPersonality(
159  const ola::rdm::RDMRequest *request);
160  ola::rdm::RDMResponse *SetDmxPersonality(
161  const ola::rdm::RDMRequest *request);
162  ola::rdm::RDMResponse *GetPersonalityDescription(
163  const ola::rdm::RDMRequest *request);
164  ola::rdm::RDMResponse *GetSlotInfo(
165  const ola::rdm::RDMRequest *request);
166  ola::rdm::RDMResponse *GetDmxStartAddress(
167  const ola::rdm::RDMRequest *request);
168  ola::rdm::RDMResponse *SetDmxStartAddress(
169  const ola::rdm::RDMRequest *request);
170  ola::rdm::RDMResponse *GetIdentify(
171  const ola::rdm::RDMRequest *request);
172  ola::rdm::RDMResponse *SetIdentify(
173  const ola::rdm::RDMRequest *request);
174  ola::rdm::RDMResponse *GetSensorDefinition(
175  const ola::rdm::RDMRequest *request);
176  ola::rdm::RDMResponse *GetSensorValue(
177  const ola::rdm::RDMRequest *request);
178  ola::rdm::RDMResponse *SetSensorValue(
179  const ola::rdm::RDMRequest *request);
180  ola::rdm::RDMResponse *RecordSensor(
181  const ola::rdm::RDMRequest *request);
182  ola::rdm::RDMResponse *GetListInterfaces(
183  const ola::rdm::RDMRequest *request);
184  ola::rdm::RDMResponse *GetInterfaceLabel(
185  const ola::rdm::RDMRequest *request);
186  ola::rdm::RDMResponse *GetInterfaceHardwareAddressType1(
187  const ola::rdm::RDMRequest *request);
188  ola::rdm::RDMResponse *GetIPV4CurrentAddress(
189  const ola::rdm::RDMRequest *request);
190  ola::rdm::RDMResponse *GetIPV4DefaultRoute(
191  const ola::rdm::RDMRequest *request);
192  ola::rdm::RDMResponse *GetDNSHostname(
193  const ola::rdm::RDMRequest *request);
194  ola::rdm::RDMResponse *GetDNSDomainName(
195  const ola::rdm::RDMRequest *request);
196  ola::rdm::RDMResponse *GetDNSNameServer(
197  const ola::rdm::RDMRequest *request);
198 
199  // Helpers
200  uint8_t P9813CreateFlag(uint8_t red, uint8_t green, uint8_t blue);
201  static uint8_t CalculateAPA102LatchBytes(uint16_t pixel_count);
202  static uint8_t CalculateAPA102PixelBrightness(uint8_t brightness);
203 
204  static const uint8_t SPI_MODE;
205  static const uint8_t SPI_BITS_PER_WORD;
206  static const uint16_t SPI_DELAY;
207  static const uint32_t SPI_SPEED;
208  static const uint16_t WS2801_SLOTS_PER_PIXEL;
209  static const uint16_t LPD8806_SLOTS_PER_PIXEL;
210  static const uint16_t P9813_SLOTS_PER_PIXEL;
211  static const uint16_t P9813_SPI_BYTES_PER_PIXEL;
212  static const uint16_t APA102_SLOTS_PER_PIXEL;
213  static const uint16_t APA102_PB_SLOTS_PER_PIXEL;
214  static const uint16_t APA102_SPI_BYTES_PER_PIXEL;
215  static const uint16_t APA102_START_FRAME_BYTES;
216  static const uint8_t APA102_LEDFRAME_START_MARK;
217 
219  PARAM_HANDLERS[];
220 };
221 } // namespace spi
222 } // namespace plugin
223 } // namespace ola
224 #endif // PLUGINS_SPI_SPIOUTPUT_H_
Definitions and Interfaces to implement an RDMController that sends a single message at a time...
An RDM Command that represents responses (GET, SET or DISCOVER).
Definition: RDMCommand.h:457
Definition: SPIOutput.h:62
void RunIncrementalDiscovery(ola::rdm::RDMDiscoveryCallback *callback)
Start an incremental discovery operation.
Definition: SPIOutput.cpp:344
The interface that can send RDM commands, as well as perform discovery operations.
Definition: RDMControllerInterface.h:104
RDM Commands that represent requests (GET, SET or DISCOVER).
Definition: RDMCommand.h:234
Used to hold a single universe of DMX data.
Definition: DmxBuffer.h:49
A RDM unique identifier (UID).
Holds the information about a sensor.
A class used to hold a single universe of DMX data.
the structure that defines the behaviour for a specific PID.o
Definition: ResponderOps.h:76
A class which dispatches RDM requests to registered PID handlers.
Definition: ResponderOps.h:60
void RunFullDiscovery(ola::rdm::RDMDiscoveryCallback *callback)
Start a full discovery operation.
Definition: SPIOutput.cpp:337
Definition: SPIOutput.h:39
The base class for all 1 argument callbacks.
Definition: Callback.h:982
Helper functions for STL classes.
A framework for building RDM responders.
Represents a RDM UID.
Definition: UID.h:57
Definition: SPIBackend.h:40
The namespace containing all OLA symbols.
Definition: Credentials.cpp:44
void SendRDMRequest(ola::rdm::RDMRequest *request, ola::rdm::RDMCallback *callback)
Send a RDM command.
Definition: SPIOutput.cpp:352
Gets/sets real config about a network.