]> sigrok.org Git - libsigrok.git/blob - src/hardware/maynuo-m97/protocol.c
Minor whitespace and cosmetic fixes.
[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)
129 {
130         struct sr_datafeed_packet packet;
131         struct sr_datafeed_analog_old analog;
132
133         analog.channels = g_slist_append(NULL, ch);
134         analog.num_samples = 1;
135         analog.data = &value;
136         analog.mq = mq;
137         analog.unit = unit;
138         analog.mqflags = SR_MQFLAG_DC;
139
140         packet.type = SR_DF_ANALOG_OLD;
141         packet.payload = &analog;
142         sr_session_send(sdi, &packet);
143         g_slist_free(analog.channels);
144 }
145
146 SR_PRIV int maynuo_m97_capture_start(const struct sr_dev_inst *sdi)
147 {
148         struct dev_context *devc;
149         struct sr_modbus_dev_inst *modbus;
150         int ret;
151
152         modbus = sdi->conn;
153         devc = sdi->priv;
154
155         if ((ret = sr_modbus_read_holding_registers(modbus, U, 4, NULL)) == SR_OK)
156                 devc->expecting_registers = 4;
157         return ret;
158 }
159
160 SR_PRIV int maynuo_m97_receive_data(int fd, int revents, void *cb_data)
161 {
162         struct sr_dev_inst *sdi;
163         struct dev_context *devc;
164         struct sr_modbus_dev_inst *modbus;
165         struct sr_datafeed_packet packet;
166         uint16_t registers[4];
167         int64_t t;
168
169         (void)fd;
170         (void)revents;
171
172         if (!(sdi = cb_data))
173                 return TRUE;
174
175         modbus = sdi->conn;
176         devc = sdi->priv;
177
178         devc->expecting_registers = 0;
179         if (sr_modbus_read_holding_registers(modbus, -1, 4, registers) == SR_OK) {
180                 packet.type = SR_DF_FRAME_BEGIN;
181                 sr_session_send(cb_data, &packet);
182
183                 maynuo_m97_session_send_value(sdi, sdi->channels->data,
184                                               RBFL(registers + 0),
185                                               SR_MQ_VOLTAGE, SR_UNIT_VOLT);
186                 maynuo_m97_session_send_value(sdi, sdi->channels->next->data,
187                                               RBFL(registers + 2),
188                                               SR_MQ_CURRENT, SR_UNIT_AMPERE);
189
190                 packet.type = SR_DF_FRAME_END;
191                 sr_session_send(cb_data, &packet);
192                 devc->num_samples++;
193         }
194
195         if (devc->limit_samples && (devc->num_samples >= devc->limit_samples)) {
196                 sr_info("Requested number of samples reached.");
197                 sdi->driver->dev_acquisition_stop(sdi, cb_data);
198                 return TRUE;
199         }
200
201         if (devc->limit_msec) {
202                 t = (g_get_monotonic_time() - devc->starttime) / 1000;
203                 if (t > (int64_t)devc->limit_msec) {
204                         sr_info("Requested time limit reached.");
205                         sdi->driver->dev_acquisition_stop(sdi, cb_data);
206                         return TRUE;
207                 }
208         }
209
210         maynuo_m97_capture_start(sdi);
211         return TRUE;
212 }