• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OpenLightingProject / ola / 16911433572

12 Aug 2025 02:08PM UTC coverage: 45.869% (-0.04%) from 45.909%
16911433572

Pull #1739

github

web-flow
Merge 02faeaa2d into 3566c28d9
Pull Request #1739: New web UI, store highest channel number used

7157 of 16316 branches covered (43.86%)

20915 of 45597 relevant lines covered (45.87%)

52.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

55.1
/plugins/spi/SPIPlugin.cpp
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
 * SPIPlugin.cpp
17
 * The SPI plugin for ola
18
 * Copyright (C) 2013 Simon Newton
19
 */
20

21
#include <memory>
22
#include <string>
23
#include <vector>
24
#include "ola/Logging.h"
25
#include "ola/StringUtils.h"
26
#include "ola/file/Util.h"
27
#include "ola/rdm/UID.h"
28
#include "ola/rdm/UIDAllocator.h"
29
#include "olad/PluginAdaptor.h"
30
#include "olad/Preferences.h"
31
#include "plugins/spi/SPIDevice.h"
32
#include "plugins/spi/SPIPlugin.h"
33

34

35
namespace ola {
36
namespace plugin {
37
namespace spi {
38

39
using ola::rdm::UID;
40
using std::auto_ptr;
41
using std::string;
42
using std::vector;
43

44
const char SPIPlugin::DEFAULT_BASE_UID[] = "7a70:00000100";
45
const char SPIPlugin::DEFAULT_SPI_DEVICE_PREFIX[] = "spidev";
46
const char SPIPlugin::PLUGIN_NAME[] = "SPI";
47
const char SPIPlugin::PLUGIN_PREFIX[] = "spi";
48
const char SPIPlugin::SPI_BASE_UID_KEY[] = "base_uid";
49
const char SPIPlugin::SPI_DEVICE_PREFIX_KEY[] = "device_prefix";
50

51
/*
52
 * Start the plugin
53
 * For now we just have one device.
54
 */
55
bool SPIPlugin::StartHook() {
1✔
56
  const string uid_str = m_preferences->GetValue(SPI_BASE_UID_KEY);
1✔
57
  auto_ptr<UID> base_uid(UID::FromString(uid_str));
1✔
58
  if (!base_uid.get()) {
1✔
59
    OLA_WARN << "Invalid UID " << uid_str << ", defaulting to "
×
60
             << DEFAULT_BASE_UID;
×
61
    base_uid.reset(UID::FromString(DEFAULT_BASE_UID));
×
62
    if (!base_uid.get()) {
×
63
      OLA_WARN << "Invalid UID " << DEFAULT_BASE_UID;
×
64
      return false;
×
65
    }
66
  }
67

68
  vector<string> spi_files;
1✔
69
  vector<string> spi_prefixes = m_preferences->GetMultipleValue(
1✔
70
      SPI_DEVICE_PREFIX_KEY);
1✔
71
  if (!ola::file::FindMatchingFiles("/dev", spi_prefixes, &spi_files)) {
1✔
72
    return false;
73
  }
74

75
  ola::rdm::UIDAllocator uid_allocator(*base_uid);
1✔
76
  vector<string>::const_iterator iter = spi_files.begin();
1✔
77
  for (; iter != spi_files.end(); ++iter) {
1✔
78
    SPIDevice *device = new SPIDevice(this, m_preferences, m_plugin_adaptor,
×
79
                                      *iter, &uid_allocator);
×
80

81
    if (!device) {
×
82
      continue;
×
83
    }
84

85
    if (!device->Start()) {
×
86
      delete device;
×
87
      continue;
×
88
    }
89
    m_devices.push_back(device);
×
90
    m_plugin_adaptor->RegisterDevice(device);
×
91
  }
92
  return true;
93
}
2✔
94

95

96
/*
97
 * Stop the plugin
98
 * @return true on success, false on failure
99
 */
100
bool SPIPlugin::StopHook() {
1✔
101
  vector<SPIDevice*>::iterator iter = m_devices.begin();
1✔
102
  bool ok = true;
1✔
103
  for (; iter != m_devices.end(); ++iter) {
1✔
104
    m_plugin_adaptor->UnregisterDevice(*iter);
×
105
    ok &= (*iter)->Stop();
×
106
    delete *iter;
×
107
  }
108
  return ok;
1✔
109
}
110

111

112
/*
113
 * Return the description for this plugin
114
 */
115
string SPIPlugin::Description() const {
×
116
  return
×
117
"SPI Plugin\n"
×
118
"----------------------------\n"
119
"\n"
120
"This plugin enables control of LED pixel strings using SPI. Each SPI output\n"
121
"is represented as an OLA Device. Devices can have multiple Ports, each of\n"
122
"which controls a pixel string. Each Port can use a different\n"
123
"personality (pixel type) and DMX start address, this allows a combination\n"
124
"of various strings lengths & pixel hardware types. The start address and\n"
125
"personality settings are controllable via RDM (each Port appears as a RDM\n"
126
"responder).\n"
127
"\n"
128
"To support multiple ports per SPI output, we use an SPI-Backend. Two\n"
129
"backends are supported right now, a software backend which concatenates\n"
130
"all the pixel data into a single buffer and a hardware multiplexer backend\n"
131
"which uses the GPIO pins to control an off-host multiplexer. It's\n"
132
"recommended to use the hardware multiplexer.\n"
133
"\n"
134
"--- Config file : ola-spi.conf ---\n"
135
"\n"
136
"base_uid = <string>\n"
137
"The starting UID to use for the SPI RDM , e.g. 7a70:00000100.\n"
138
"\n"
139
"device_prefix = <string>\n"
140
"The prefix of files to match in /dev. Usually set to 'spidev'. Each match\n"
141
"will instantiate a Device.\n"
142
"\n"
143
"--- Per Device Settings ---\n"
144
"<device>-spi-speed = <int>\n"
145
"The speed of the SPI bus, range is 0 - 32000000 Hz.\n"
146
"\n"
147
"<device>-ce-high = <bool>\n"
148
"The mode of the CE pin. Set to false this pulls the CE pin low when writing\n"
149
"data. Set to true this will pull the pin high when writing.\n"
150
"\n"
151
"<device>-backend = [software | hardware]\n"
152
"The backend to use to multiplex the SPI data.\n"
153
"\n"
154
"<device>-gpio-pin = <int>\n"
155
"The GPIO pins to use for the hardware multiplexer. Add one line for each\n"
156
"pin. The number of ports will be 2 ** (# of pins).\n"
157
"\n"
158
"<device>-ports = <int>\n"
159
"If the software backend is used, this defines the number of ports which\n"
160
"will be created.\n"
161
"\n"
162
"<device>-sync-port = <int>\n"
163
"Controls which port triggers a flush (write) of the SPI data. If set to -1\n"
164
"the SPI data is written when any port changes. This can result in a lot of\n"
165
"data writes (slow) and partial frames. If set to -2, the last port is used.\n"
166
"\n"
167
"--- Per Port Settings ---\n"
168
"Ports are indexed from 0.\n"
169
"\n"
170
"<device>-<port>-dmx-address = <int>\n"
171
"The DMX address to use. e.g. spidev0.1-0-dmx-address = 1\n"
172
"\n"
173
"<device>-<port>-device-label = <string>\n"
174
"The RDM device label to use.\n"
175
"\n"
176
"<device>-<port>-personality = <int>\n"
177
"The RDM personality to use.\n"
178
"\n"
179
"<device>-<port>-pixel-count = <int>\n"
180
"The number of pixels for this port. e.g. spidev0.1-1-pixel-count = 20.\n"
181
"\n";
×
182
}
183

184

185
/*
186
 * Load the plugin prefs and default to sensible values
187
 */
188
bool SPIPlugin::SetDefaultPreferences() {
1✔
189
  bool save = false;
1✔
190

191
  if (!m_preferences) {
1✔
192
    return false;
193
  }
194

195
  save |= m_preferences->SetDefaultValue(SPI_DEVICE_PREFIX_KEY,
1✔
196
                                         StringValidator(),
1✔
197
                                         DEFAULT_SPI_DEVICE_PREFIX);
198
  save |= m_preferences->SetDefaultValue(SPI_BASE_UID_KEY,
1✔
199
                                         StringValidator(),
1✔
200
                                         DEFAULT_BASE_UID);
201
  if (save) {
1✔
202
    m_preferences->Save();
1✔
203
  }
204

205
  if (m_preferences->GetValue(SPI_DEVICE_PREFIX_KEY).empty()) {
1✔
206
    return false;
207
  }
208

209
  return true;
210
}
211
}  // namespace spi
212
}  // namespace plugin
213
}  // namespace ola
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc