]>
Commit | Line | Data |
---|---|---|
e1ccfb19 AJ |
1 | /* |
2 | * This file is part of the libsigrok project. | |
3 | * | |
4 | * Copyright (C) 2015 Aurelien Jacobs <aurel@gnuage.org> | |
5 | * | |
6 | * This program is free software: you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation, either version 3 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program 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 | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
6ec6c43b | 20 | #include <config.h> |
e1ccfb19 AJ |
21 | #include "protocol.h" |
22 | ||
ffb580cf AJ |
23 | SR_PRIV int maynuo_m97_get_bit(struct sr_modbus_dev_inst *modbus, |
24 | enum maynuo_m97_coil address, int *value) | |
25 | { | |
26 | uint8_t coil; | |
27 | int ret = sr_modbus_read_coils(modbus, address, 1, &coil); | |
28 | *value = coil & 1; | |
29 | return ret; | |
30 | } | |
31 | ||
32 | SR_PRIV int maynuo_m97_set_bit(struct sr_modbus_dev_inst *modbus, | |
33 | enum maynuo_m97_coil address, int value) | |
34 | { | |
35 | return sr_modbus_write_coil(modbus, address, value); | |
36 | } | |
37 | ||
38 | SR_PRIV int maynuo_m97_get_float(struct sr_modbus_dev_inst *modbus, | |
39 | enum maynuo_m97_register address, float *value) | |
40 | { | |
41 | uint16_t registers[2]; | |
42 | int ret = sr_modbus_read_holding_registers(modbus, address, 2, registers); | |
43 | if (ret == SR_OK) | |
44 | *value = RBFL(registers); | |
45 | return ret; | |
46 | } | |
47 | ||
48 | SR_PRIV int maynuo_m97_set_float(struct sr_modbus_dev_inst *modbus, | |
49 | enum maynuo_m97_register address, float value) | |
50 | { | |
51 | uint16_t registers[2]; | |
52 | WBFL(registers, value); | |
53 | return sr_modbus_write_multiple_registers(modbus, address, 2, registers); | |
54 | } | |
55 | ||
56 | ||
57 | static int maynuo_m97_cmd(struct sr_modbus_dev_inst *modbus, | |
58 | enum maynuo_m97_mode cmd) | |
59 | { | |
60 | uint16_t registers[1]; | |
61 | WB16(registers, cmd); | |
62 | return sr_modbus_write_multiple_registers(modbus, CMD, 1, registers); | |
63 | } | |
64 | ||
65 | SR_PRIV int maynuo_m97_get_mode(struct sr_modbus_dev_inst *modbus, | |
66 | enum maynuo_m97_mode *mode) | |
67 | { | |
68 | uint16_t registers[1]; | |
69 | int ret; | |
70 | ret = sr_modbus_read_holding_registers(modbus, SETMODE, 1, registers); | |
71 | *mode = RB16(registers) & 0xFF; | |
72 | return ret; | |
73 | } | |
74 | ||
75 | SR_PRIV int maynuo_m97_set_mode(struct sr_modbus_dev_inst *modbus, | |
76 | enum maynuo_m97_mode mode) | |
77 | { | |
78 | return maynuo_m97_cmd(modbus, mode); | |
79 | } | |
80 | ||
81 | SR_PRIV int maynuo_m97_set_input(struct sr_modbus_dev_inst *modbus, int enable) | |
82 | { | |
83 | enum maynuo_m97_mode mode; | |
84 | int ret; | |
85 | if ((ret = maynuo_m97_get_mode(modbus, &mode)) != SR_OK) | |
86 | return ret; | |
87 | if ((ret = maynuo_m97_cmd(modbus, enable ? INPUT_ON : INPUT_OFF)) != SR_OK) | |
88 | return ret; | |
89 | return maynuo_m97_set_mode(modbus, mode); | |
90 | } | |
91 | ||
92 | SR_PRIV int maynuo_m97_get_model_version(struct sr_modbus_dev_inst *modbus, | |
93 | uint16_t *model, uint16_t *version) | |
94 | { | |
95 | uint16_t registers[2]; | |
96 | int ret; | |
97 | ret = sr_modbus_read_holding_registers(modbus, MODEL, 2, registers); | |
d9251a2c UH |
98 | *model = RB16(registers + 0); |
99 | *version = RB16(registers + 1); | |
ffb580cf AJ |
100 | return ret; |
101 | } | |
102 | ||
103 | ||
104 | SR_PRIV const char *maynuo_m97_mode_to_str(enum maynuo_m97_mode mode) | |
105 | { | |
0cadb8a3 | 106 | switch (mode) { |
ffb580cf AJ |
107 | case CC: return "CC"; |
108 | case CV: return "CV"; | |
109 | case CW: return "CP"; | |
110 | case CR: return "CR"; | |
111 | case CC_SOFT_START: return "CC Soft Start"; | |
112 | case DYNAMIC: return "Dynamic"; | |
113 | case SHORT_CIRCUIT: return "Short Circuit"; | |
114 | case LIST: return "List Mode"; | |
115 | case CC_L_AND_UL: return "CC Loading and Unloading"; | |
116 | case CV_L_AND_UL: return "CV Loading and Unloading"; | |
117 | case CW_L_AND_UL: return "CP Loading and Unloading"; | |
118 | case CR_L_AND_UL: return "CR Loading and Unloading"; | |
119 | case CC_TO_CV: return "CC + CV"; | |
120 | case CR_TO_CV: return "CR + CV"; | |
121 | case BATTERY_TEST: return "Battery Test"; | |
122 | case CV_SOFT_START: return "CV Soft Start"; | |
123 | default: return "UNKNOWN"; | |
124 | } | |
125 | } | |
126 | ||
127 | ||
4301f172 | 128 | static void maynuo_m97_session_send_value(const struct sr_dev_inst *sdi, struct sr_channel *ch, float value, enum sr_mq mq, enum sr_unit unit, int digits) |
ffb580cf AJ |
129 | { |
130 | struct sr_datafeed_packet packet; | |
94885d20 UH |
131 | struct sr_datafeed_analog analog; |
132 | struct sr_analog_encoding encoding; | |
133 | struct sr_analog_meaning meaning; | |
134 | struct sr_analog_spec spec; | |
ffb580cf | 135 | |
4301f172 | 136 | sr_analog_init(&analog, &encoding, &meaning, &spec, digits); |
94885d20 | 137 | analog.meaning->channels = g_slist_append(NULL, ch); |
ffb580cf AJ |
138 | analog.num_samples = 1; |
139 | analog.data = &value; | |
94885d20 UH |
140 | analog.meaning->mq = mq; |
141 | analog.meaning->unit = unit; | |
142 | analog.meaning->mqflags = SR_MQFLAG_DC; | |
ffb580cf | 143 | |
94885d20 | 144 | packet.type = SR_DF_ANALOG; |
ffb580cf AJ |
145 | packet.payload = &analog; |
146 | sr_session_send(sdi, &packet); | |
94885d20 | 147 | g_slist_free(analog.meaning->channels); |
ffb580cf AJ |
148 | } |
149 | ||
150 | SR_PRIV int maynuo_m97_capture_start(const struct sr_dev_inst *sdi) | |
151 | { | |
152 | struct dev_context *devc; | |
153 | struct sr_modbus_dev_inst *modbus; | |
154 | int ret; | |
155 | ||
156 | modbus = sdi->conn; | |
157 | devc = sdi->priv; | |
158 | ||
159 | if ((ret = sr_modbus_read_holding_registers(modbus, U, 4, NULL)) == SR_OK) | |
160 | devc->expecting_registers = 4; | |
161 | return ret; | |
162 | } | |
163 | ||
e1ccfb19 AJ |
164 | SR_PRIV int maynuo_m97_receive_data(int fd, int revents, void *cb_data) |
165 | { | |
ffb580cf | 166 | struct sr_dev_inst *sdi; |
e1ccfb19 | 167 | struct dev_context *devc; |
ffb580cf AJ |
168 | struct sr_modbus_dev_inst *modbus; |
169 | struct sr_datafeed_packet packet; | |
170 | uint16_t registers[4]; | |
e1ccfb19 AJ |
171 | |
172 | (void)fd; | |
ffb580cf | 173 | (void)revents; |
e1ccfb19 AJ |
174 | |
175 | if (!(sdi = cb_data)) | |
176 | return TRUE; | |
177 | ||
ffb580cf AJ |
178 | modbus = sdi->conn; |
179 | devc = sdi->priv; | |
180 | ||
181 | devc->expecting_registers = 0; | |
182 | if (sr_modbus_read_holding_registers(modbus, -1, 4, registers) == SR_OK) { | |
183 | packet.type = SR_DF_FRAME_BEGIN; | |
695dc859 | 184 | sr_session_send(sdi, &packet); |
ffb580cf AJ |
185 | |
186 | maynuo_m97_session_send_value(sdi, sdi->channels->data, | |
187 | RBFL(registers + 0), | |
4301f172 | 188 | SR_MQ_VOLTAGE, SR_UNIT_VOLT, 3); |
ffb580cf AJ |
189 | maynuo_m97_session_send_value(sdi, sdi->channels->next->data, |
190 | RBFL(registers + 2), | |
4301f172 | 191 | SR_MQ_CURRENT, SR_UNIT_AMPERE, 4); |
ffb580cf AJ |
192 | |
193 | packet.type = SR_DF_FRAME_END; | |
695dc859 | 194 | sr_session_send(sdi, &packet); |
45b75c36 | 195 | sr_sw_limits_update_samples_read(&devc->limits, 1); |
ffb580cf AJ |
196 | } |
197 | ||
45b75c36 | 198 | if (sr_sw_limits_check(&devc->limits)) { |
695dc859 | 199 | sdi->driver->dev_acquisition_stop(sdi); |
e1ccfb19 | 200 | return TRUE; |
ffb580cf | 201 | } |
e1ccfb19 | 202 | |
ffb580cf | 203 | maynuo_m97_capture_start(sdi); |
e1ccfb19 AJ |
204 | return TRUE; |
205 | } |