1 /*
2     PlaneWave Delta Protocol
3 
4     Copyright (C) 2020 Jasem Mutlaq (mutlaqja@ikarustech.com)
5 
6     This library is free software; you can redistribute it and/or
7     modify it under the terms of the GNU Lesser General Public
8     License as published by the Free Software Foundation; either
9     version 2.1 of the License, or (at your option) any later version.
10 
11     This library is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14     Lesser General Public License for more details.
15 
16     You should have received a copy of the GNU Lesser General Public
17     License along with this library; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19 
20 */
21 
22 #pragma once
23 
24 
25 #include "indifocuser.h"
26 #include "pid/pid.h"
27 
28 #include <memory>
29 #include <map>
30 
31 class DeltaT : public INDI::DefaultDevice
32 {
33     public:
34         DeltaT();
35 
36         virtual bool Handshake();
37         const char *getDefaultName() override;
38         virtual bool initProperties() override;
39         virtual bool updateProperties() override;
40 
41         virtual bool ISNewNumber(const char *dev, const char *name, double values[], char *names[], int n) override;
42         virtual bool ISNewSwitch(const char *dev, const char *name, ISState *states, char *names[], int n) override;
43 
44         enum
45         {
46             TEMP_GET = 0x26,
47             CMD_FORCE_RESET = 0x80,
48             CMD_FORCE_BOOT = 0x81,
49             COH_NUMHEATERS = 0xB0,
50             COH_ON_MANUAL = 0xB1,
51             COH_OFF = 0xB4,
52             COH_REPORT = 0xB5,
53             COH_RESCAN = 0xBF,
54             CMD_GET_VERSION = 0xFE,
55         };
56 
57         enum
58         {
59             DEVICE_PC = 0x20,
60             DEVICE_HC = 0x0D,
61             DEVICE_FOC = 0x12,
62             DEVICE_FAN = 0x13,
63             DEVICE_TEMP = 0x12,
64             DEVICE_DELTA = 0x32
65         };
66 
67         typedef struct
68         {
69             uint8_t  StateUB;
70             uint8_t  ModeUB;
71             uint16_t SetPointUW;
72             uint8_t  TempHtrIdUB;
73             uint16_t TempHtrUW;
74             uint16_t TempAmbUW;
75             uint16_t PeriodUW;
76             uint8_t  DutyCycleUB;
77         } HeaterReport;
78 
79 
80     protected:
81         virtual void TimerHit() override;
82         virtual bool saveConfigItems(FILE *fp) override;
83 
84     private:
85         ///////////////////////////////////////////////////////////////////////////////////
86         /// Query functions
87         ///////////////////////////////////////////////////////////////////////////////////
88         bool readReport(uint8_t index);
89         bool readTemperature();
90         bool initializeHeaters();
91 
92         ///////////////////////////////////////////////////////////////////////////////////
93         /// Set functions
94         ///////////////////////////////////////////////////////////////////////////////////
95         bool setHeaterEnabled(uint8_t index, bool enabled);
96         bool setHeaterParam(uint8_t index, double period, double duty);
97         bool forceBoot();
98         bool forceReset();
99 
100         ///////////////////////////////////////////////////////////////////////////////
101         /// Communication Functions
102         ///////////////////////////////////////////////////////////////////////////////
103         bool sendCommand(const char * cmd, char * res, uint32_t cmd_len, uint32_t res_len);
104         void hexDump(char * buf, const char * data, uint32_t size);
105         std::vector<std::string> split(const std::string &input, const std::string &regex);
106 
107         ///////////////////////////////////////////////////////////////////////////////////
108         /// Misc
109         ///////////////////////////////////////////////////////////////////////////////////
110         double calculateTemperature(uint8_t lsb, uint8_t msb);
111         uint8_t calculateCheckSum(const char *cmd, uint32_t len);
112         const char *getHeaterName(int index);
113         template <typename T> std::string to_string(const T a_value, const int n = 2);
114 
115         ///////////////////////////////////////////////////////////////////////////////////
116         /// Properties
117         ///////////////////////////////////////////////////////////////////////////////////
118 
119         // Delta-T Informatin
120         ITextVectorProperty InfoTP;
121         IText InfoT[1] {};
122         enum
123         {
124             INFO_VERSION
125         };
126 
127 
128         // Force Control
129         ISwitchVectorProperty ForceSP;
130         ISwitch ForceS[2];
131         enum
132         {
133             FORCE_RESET,
134             FORCE_BOOT
135         };
136 
137         // Heater Control
138         std::vector<std::unique_ptr<ISwitchVectorProperty>> HeaterControlSP;
139         std::vector<std::unique_ptr<ISwitch[]>> HeaterControlS;
140         enum
141         {
142             HEATER_OFF,
143             HEATER_ON,
144             HEATER_CONTROL,
145             HEATER_THRESHOLD
146         };
147 
148         // Control Params
149         std::vector<std::unique_ptr<INumberVectorProperty>> HeaterParamNP;
150         std::vector<std::unique_ptr<INumber[]>> HeaterParamN;
151         enum
152         {
153             PARAM_PERIOD,
154             PARAM_DUTY,
155             PARAM_CONTROL,
156             PARAM_THRESHOLD,
157         };
158 
159         // Monitor
160         std::vector<std::unique_ptr<INumberVectorProperty>> HeaterMonitorNP;
161         std::vector<std::unique_ptr<INumber[]>> HeaterMonitorN;
162         enum
163         {
164             MONITOR_PERIOD,
165             MONITOR_DUTY
166         };
167 
168         // Read Only Temperature Reporting
169         INumberVectorProperty TemperatureNP;
170         INumber TemperatureN[3];
171         enum
172         {
173             // Primary is 0 , not used in this driver.
174             // 1
175             TEMPERATURE_AMBIENT,
176             // 2
177             TEMPERATURE_SECONDARY,
178             // 3
179             TEMPERATURE_BACKPLATE,
180         };
181 
182         /////////////////////////////////////////////////////////////////////////////
183         /// Private variables
184         /////////////////////////////////////////////////////////////////////////////
185         Connection::Serial *serialConnection { nullptr };
186         double m_LastTemperature[3];
187         int PortFD { -1 };
188         std::vector<std::unique_ptr<PID>> m_Controllers;
189 
190         /////////////////////////////////////////////////////////////////////////////
191         /// Static Helper Values
192         /////////////////////////////////////////////////////////////////////////////
193         // Start of Message
194         static const char DRIVER_SOM { 0x3B };
195         // Temperature Reporting threshold
196         static constexpr double TEMPERATURE_REPORT_THRESHOLD { 0.05 };
197         // Temperature Control threshold
198         static constexpr double TEMPERATURE_CONTROL_THRESHOLD { 0.1 };
199         static constexpr const uint8_t DRIVER_LEN {32};
200         // Wait up to a maximum of 3 seconds for serial input
201         static constexpr const uint8_t DRIVER_TIMEOUT {3};
202 
203         // Primary Backplate heater
204         static constexpr const char *PRIMARY_TAB = "Primary Backplate Heater";
205         // Secondary Mirror heater
206         static constexpr const char *SECONDARY_TAB = "Secondary Mirror Heater";
207 };
208