]> sigrok.org Git - libsigrok.git/blob - src/hardware/maynuo-m97/protocol.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / hardware / maynuo-m97 / protocol.c
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
20 #include <config.h>
21 #include "protocol.h"
22
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);
98         *model   = RB16(registers + 0);
99         *version = RB16(registers + 1);
100         return ret;
101 }
102
103
104 SR_PRIV const char *maynuo_m97_mode_to_str(enum maynuo_m97_mode mode)
105 {
106         switch (mode) {
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
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)
129 {
130         struct sr_datafeed_packet packet;
131         struct sr_datafeed_analog analog;
132         struct sr_analog_encoding encoding;
133         struct sr_analog_meaning meaning;
134         struct sr_analog_spec spec;
135
136         sr_analog_init(&analog, &encoding, &meaning, &spec, digits);
137         analog.meaning->channels = g_slist_append(NULL, ch);
138         analog.num_samples = 1;
139         analog.data = &value;
140         analog.meaning->mq = mq;
141         analog.meaning->unit = unit;
142         analog.meaning->mqflags = SR_MQFLAG_DC;
143
144         packet.type = SR_DF_ANALOG;
145         packet.payload = &analog;
146         sr_session_send(sdi, &packet);
147         g_slist_free(analog.meaning->channels);
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
164 SR_PRIV int maynuo_m97_receive_data(int fd, int revents, void *cb_data)
165 {
166         struct sr_dev_inst *sdi;
167         struct dev_context *devc;
168         struct sr_modbus_dev_inst *modbus;
169         struct sr_datafeed_packet packet;
170         uint16_t registers[4];
171
172         (void)fd;
173         (void)revents;
174
175         if (!(sdi = cb_data))
176                 return TRUE;
177
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;
184                 sr_session_send(sdi, &packet);
185
186                 maynuo_m97_session_send_value(sdi, sdi->channels->data,
187                                               RBFL(registers + 0),
188                                               SR_MQ_VOLTAGE, SR_UNIT_VOLT, 3);
189                 maynuo_m97_session_send_value(sdi, sdi->channels->next->data,
190                                               RBFL(registers + 2),
191                                               SR_MQ_CURRENT, SR_UNIT_AMPERE, 4);
192
193                 packet.type = SR_DF_FRAME_END;
194                 sr_session_send(sdi, &packet);
195                 sr_sw_limits_update_samples_read(&devc->limits, 1);
196         }
197
198         if (sr_sw_limits_check(&devc->limits)) {
199                 sr_dev_acquisition_stop(sdi);
200                 return TRUE;
201         }
202
203         maynuo_m97_capture_start(sdi);
204         return TRUE;
205 }