GCC Code Coverage Report


Directory: ./
File: channeloutput/PCA9685.h
Date: 2026-10-29 08:11:58
Exec Total Coverage
Lines: 2 2 100.0%
Functions: 1 1 100.0%
Branches: 1 2 50.0%

Line Branch Exec Source
1 #pragma once
2 /*
3 * This file is part of the Falcon Player (FPP) and is Copyright (C)
4 * 2013-2022 by the Falcon Player Developers.
5 *
6 * The Falcon Player (FPP) is free software, and is covered under
7 * multiple Open Source licenses. Please see the included 'LICENSES'
8 * file for descriptions of what files are covered by each license.
9 *
10 * This source file is covered under the GPL v2 as described in the
11 * included LICENSE.GPL file.
12 */
13
14 #include "ChannelOutput.h"
15 #include "fpp-json.h"
16 #include "util/I2CUtils.h"
17 #include "commands/Commands.h"
18
19 #include <mutex>
20
21 class PCA9685Output : public ChannelOutput {
22 public:
23 class ServoPositionCommand : public Command {
24 public:
25 ServoPositionCommand(PCA9685Output* output);
26 virtual ~ServoPositionCommand();
27
28 virtual std::unique_ptr<Command::Result> run(const std::vector<std::string>& args) override;
29
30 private:
31 PCA9685Output* m_output;
32 };
33 PCA9685Output(unsigned int startChannel, unsigned int channelCount);
34 virtual ~PCA9685Output();
35
36 28 virtual std::string GetOutputType() const {
37
1/2
✓ Branch 0 taken 28 times.
✗ Branch 1 not taken.
56 return "PCA9685 PWM";
38 }
39
40 virtual void OverlayTestData(unsigned char* channelData, int cycleNum, float percentOfCycle, int testType, const Json::Value& config) override;
41 virtual bool SupportsTesting() const override;
42
43 virtual int Init(Json::Value config) override;
44 virtual int Close(void) override;
45
46 virtual void PrepData(unsigned char* channelData) override;
47 virtual int SendData(unsigned char* channelData) override;
48
49 virtual void StartingOutput() override;
50 virtual void StoppingOutput() override;
51
52 virtual void DumpConfig(void) override;
53
54 virtual void GetRequiredChannelRanges(const std::function<void(int, int)>& addRange) override;
55
56 enum class ZeroType {
57 HOLD = 0,
58 NORMAL = 1,
59 CENTER = 2,
60 OFF = 3,
61 MIN = 4,
62 MAX = 5
63 };
64
65 enum class DataType {
66 SCALED,
67 ABSOLUTE,
68 ABSOLUTE_HALF,
69 ABSOLUTE_DOUBLE
70 };
71
72 enum class PWMType {
73 SERVO,
74 LED
75 };
76
77 void restoreOriginalConfig();
78 void loadPortConfig(const Json::Value& portConfig);
79
80 // Made public for ServoPositionCommand access
81 I2CUtils* i2c;
82 int m_deviceID;
83 std::string m_i2cDevice;
84 int m_frequency;
85 float m_actualFrequency;
86
87 class PCA9685Port {
88 public:
89 std::string description;
90 PWMType type = PWMType::SERVO;
91 bool is16Bit = true;
92 uint32_t startChannel = 0;
93
94 // servo properties
95 int m_min = 1000;
96 int m_max = 2000;
97 int m_center = 1500;
98 DataType m_dataType = DataType::SCALED;
99 ZeroType m_zeroBehavior = ZeroType::HOLD;
100 bool m_reverse = false;
101
102 // LED properties
103 float gamma = 1.0f;
104 uint32_t brightness = 100;
105
106 unsigned short m_lastValue = 0;
107 unsigned short m_nextValue = 0;
108
109 unsigned short readValue(unsigned char* channelData, float frequency, int port);
110
111 unsigned short mapLEDValue(unsigned short val);
112 };
113
114 PCA9685Port m_ports[16];
115 uint32_t numPorts;
116
117 private:
118 std::atomic<uint64_t> lastFrameTime;
119 std::array<uint16_t, 32> data;
120 Json::Value origConfig;
121 int lastTestType = 0;
122
123 // The Servo Position command runs on a command thread and sets the ports
124 // and sends, while the output thread prepares and sends frames (and the
125 // test overlay reloads the port config): both write data[] and the bus.
126 // Recursive: the command calls SendData().
127 std::recursive_mutex m_portsLock;
128
129 // Servo Position Command
130 ServoPositionCommand* m_servoCommand = nullptr;
131 };
132