]> sigrok.org Git - libsigrok.git/blob - src/hardware/pce-322a/protocol.c
Add sr_dev_acquisition_stop(), factor out SR_ERR_DEV_CLOSED check.
[libsigrok.git] / src / hardware / pce-322a / protocol.c
1 /*
2  * This file is part of the libsigrok project.
3  *
4  * Copyright (C) 2016 George Hopkins <george-hopkins@null.net>
5  * Copyright (C) 2016 Matthieu Guillaumin <matthieu@guillaum.in>
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <config.h>
22 #include "protocol.h"
23
24 static int send_command(const struct sr_dev_inst *sdi, uint16_t command)
25 {
26         struct sr_serial_dev_inst *serial;
27         uint8_t buffer[2];
28
29         buffer[0] = command >> 8;
30         buffer[1] = command;
31
32         if (!(serial = sdi->conn))
33                 return SR_ERR;
34
35         if (serial_write_nonblocking(serial, (const void *)buffer, 2) != 2)
36                 return SR_ERR;
37
38         return SR_OK;
39 }
40
41 static int send_long_command(const struct sr_dev_inst *sdi, uint32_t command)
42 {
43         struct sr_serial_dev_inst *serial;
44         uint8_t buffer[4];
45
46         buffer[0] = command >> 24;
47         buffer[1] = command >> 16;
48         buffer[2] = command >> 8;
49         buffer[3] = command;
50
51         if (!(serial = sdi->conn))
52                 return SR_ERR;
53
54         if (serial_write_nonblocking(serial, (const void *)buffer, 4) != 4)
55                 return SR_ERR;
56
57         return SR_OK;
58 }
59
60 static void send_data(const struct sr_dev_inst *sdi, float sample)
61 {
62         struct dev_context *devc;
63         struct sr_datafeed_packet packet;
64         struct sr_datafeed_analog analog;
65         struct sr_analog_encoding encoding;
66         struct sr_analog_meaning meaning;
67         struct sr_analog_spec spec;
68
69         devc = sdi->priv;
70
71         sr_analog_init(&analog, &encoding, &meaning, &spec, 1);
72         meaning.mq = SR_MQ_SOUND_PRESSURE_LEVEL;
73         meaning.mqflags = devc->cur_mqflags;
74         meaning.unit = SR_UNIT_DECIBEL_SPL;
75         meaning.channels = sdi->channels;
76         analog.num_samples = 1;
77         analog.data = &sample;
78         packet.type = SR_DF_ANALOG;
79         packet.payload = &analog;
80         sr_session_send(sdi, &packet);
81
82         devc->num_samples++;
83         /* Limiting number of samples is only supported for live data. */
84         if (devc->cur_data_source == DATA_SOURCE_LIVE && devc->limit_samples && devc->num_samples >= devc->limit_samples)
85                 sr_dev_acquisition_stop((struct sr_dev_inst *)sdi);
86 }
87
88 static void process_measurement(const struct sr_dev_inst *sdi)
89 {
90         struct dev_context *devc;
91         unsigned short value;
92
93         devc = sdi->priv;
94
95         if (devc->buffer[3] & (1 << 0)) {
96                 devc->cur_mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_C;
97                 devc->cur_mqflags &= ~SR_MQFLAG_SPL_FREQ_WEIGHT_A;
98         } else {
99                 devc->cur_mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_A;
100                 devc->cur_mqflags &= ~SR_MQFLAG_SPL_FREQ_WEIGHT_C;
101         }
102
103         if (devc->buffer[3] & (1 << 1)) {
104                 devc->cur_mqflags |= SR_MQFLAG_SPL_TIME_WEIGHT_S;
105                 devc->cur_mqflags &= ~SR_MQFLAG_SPL_TIME_WEIGHT_F;
106         } else {
107                 devc->cur_mqflags |= SR_MQFLAG_SPL_TIME_WEIGHT_F;
108                 devc->cur_mqflags &= ~SR_MQFLAG_SPL_TIME_WEIGHT_S;
109         }
110
111         devc->cur_meas_range = devc->buffer[4] & 3;
112
113         if (devc->buffer[4] & (1 << 2)) {
114                 devc->cur_mqflags |= SR_MQFLAG_MAX;
115                 devc->cur_mqflags &= ~SR_MQFLAG_MIN;
116         } else if (devc->buffer[4] & (1 << 3)) {
117                 devc->cur_mqflags |= SR_MQFLAG_MIN;
118                 devc->cur_mqflags &= ~SR_MQFLAG_MAX;
119         } else {
120                 devc->cur_mqflags &= ~SR_MQFLAG_MIN;
121                 devc->cur_mqflags &= ~SR_MQFLAG_MAX;
122         }
123
124         value = devc->buffer[1] << 8 | devc->buffer[2];
125         send_data(sdi, value / 10.0);
126 }
127
128 static void process_memory_measurement(const struct sr_dev_inst *sdi)
129 {
130         struct dev_context *devc;
131         uint16_t value;
132
133         devc = sdi->priv;
134         value = devc->buffer[devc->buffer_len - 1] << 8;
135         value |= devc->buffer[devc->buffer_len - 2];
136
137         send_data(sdi, value / 10.0);
138 }
139
140 static void process_byte(const struct sr_dev_inst *sdi, const unsigned char c)
141 {
142         struct dev_context *devc;
143         unsigned int i;
144
145         devc = sdi->priv;
146
147         if (devc->buffer_len < BUFFER_SIZE) {
148                 devc->buffer[devc->buffer_len++] = c;
149         } else {
150                 for (i = 1; i < BUFFER_SIZE; i++)
151                         devc->buffer[i - 1] = devc->buffer[i];
152                 devc->buffer[BUFFER_SIZE - 1] = c;
153         }
154
155         if (devc->buffer_len == BUFFER_SIZE && devc->buffer[0] == 0x7f
156                         && devc->buffer[BUFFER_SIZE - 1] == 0x00) {
157                 process_measurement(sdi);
158                 devc->buffer_len = 0;
159         }
160 }
161
162 static void process_usage_byte(const struct sr_dev_inst *sdi, uint8_t c)
163 {
164         struct dev_context *devc;
165         unsigned int i;
166
167         devc = sdi->priv;
168
169         if (devc->buffer_len < MEM_USAGE_BUFFER_SIZE) {
170                 devc->buffer[devc->buffer_len++] = c;
171         } else {
172                 for (i = 1; i < MEM_USAGE_BUFFER_SIZE; i++)
173                         devc->buffer[i - 1] = devc->buffer[i];
174                 devc->buffer[MEM_USAGE_BUFFER_SIZE - 1] = c;
175         }
176
177         if (devc->buffer_len == MEM_USAGE_BUFFER_SIZE && devc->buffer[0] == 0xd1
178                         && devc->buffer[1] == 0x05 && devc->buffer[2] == 0x00
179                         && devc->buffer[3] == 0x01 && devc->buffer[4] == 0xd2
180                         && devc->buffer[MEM_USAGE_BUFFER_SIZE - 1] == 0x20) {
181                 devc->memory_block_usage = devc->buffer[5] << 8 | devc->buffer[6];
182                 devc->memory_last_block_usage = devc->buffer[7];
183                 sr_warn("Memory usage: %d blocks of 256 bytes, 1 block of %d bytes",
184                         devc->memory_block_usage - 1, devc->memory_last_block_usage);
185                 devc->buffer_len = 0;
186                 devc->buffer_skip = 1;
187                 devc->memory_state = MEM_STATE_REQUEST_MEMORY_BLOCK;
188                 devc->memory_block_cursor = 0;
189                 devc->memory_block_counter = 0;
190         }
191 }
192
193 static void process_memory_byte(const struct sr_dev_inst *sdi, uint8_t c)
194 {
195         struct dev_context *devc;
196         unsigned int i;
197
198         devc = sdi->priv;
199
200         if (devc->buffer_len < MEM_DATA_BUFFER_SIZE) {
201                 devc->buffer[devc->buffer_len++] = c;
202         } else {
203                 for (i = 1; i < MEM_DATA_BUFFER_SIZE; i++)
204                         devc->buffer[i - 1] = devc->buffer[i];
205                 devc->buffer[MEM_DATA_BUFFER_SIZE - 1] = c;
206         }
207
208         if (devc->buffer_skip == 0 \
209                         && (devc->buffer[devc->buffer_len-2] & 0x7f) == 0x7f
210                         && (devc->buffer[devc->buffer_len-1] & 0xf7) == 0xf7) {
211                 /* Recording session header bytes found, load next 7 bytes. */
212                 devc->buffer_skip = MEM_DATA_BUFFER_SIZE - 2;
213         }
214
215         if (devc->buffer_skip == 0 && devc->buffer_len == MEM_DATA_BUFFER_SIZE
216                         && (devc->buffer[0] & 0x7f) == 0x7f && (devc->buffer[1] & 0xf7) == 0xf7
217                         && devc->buffer[2] == 0x01 && devc->buffer[3] == 0x00) {
218                 /* Print information about recording. */
219                 sr_err("Recording dB(%X) %02x/%02x/%02x %02x:%02x:%02x ",
220                         devc->buffer[4], devc->buffer[5], devc->buffer[6], devc->buffer[7],
221                         devc->buffer[8] & 0x3f, devc->buffer[9], devc->buffer[10]);
222                 /* Set dBA/dBC flag for recording. */
223                 if (devc->buffer[4] == 0x0c) {
224                         devc->cur_mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_C;
225                         devc->cur_mqflags &= ~SR_MQFLAG_SPL_FREQ_WEIGHT_A;
226                 } else {
227                         devc->cur_mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_A;
228                         devc->cur_mqflags &= ~SR_MQFLAG_SPL_FREQ_WEIGHT_C;
229                 }
230                 send_data(sdi, -1.0); /* Signal switch of recording. */
231                 devc->buffer_skip = 2;
232         }
233
234         if (devc->buffer_skip == 0) {
235                 process_memory_measurement(sdi);
236                 devc->buffer_skip = 1;
237         } else {
238                 devc->buffer_skip -= 1;
239         }
240
241         devc->memory_block_cursor++; /* uint8_t goes back to 0 after 255. */
242         if (devc->memory_block_cursor == 0) {
243                 /* Current block is completed. */
244                 devc->memory_block_counter++;
245                 devc->memory_state = MEM_STATE_REQUEST_MEMORY_BLOCK;
246         }
247 }
248
249 SR_PRIV int pce_322a_receive_data(int fd, int revents, void *cb_data)
250 {
251         const struct sr_dev_inst *sdi;
252         struct dev_context *devc;
253         struct sr_serial_dev_inst *serial;
254         unsigned char c;
255
256         (void)fd;
257
258         if (!(sdi = cb_data))
259                 return TRUE;
260
261         if (!(devc = sdi->priv))
262                 return TRUE;
263
264         if (!(serial = sdi->conn))
265                 return TRUE;
266
267         if (devc->cur_data_source == DATA_SOURCE_MEMORY) {
268                 switch (devc->memory_state) {
269                 case MEM_STATE_REQUEST_MEMORY_USAGE:
270                         /* At init, disconnect and request the memory status. */
271                         sr_warn("Requesting memory usage.");
272                         pce_322a_disconnect(sdi);
273                         devc->memory_state = MEM_STATE_GET_MEMORY_USAGE;
274                         devc->memory_block_usage = 0;
275                         devc->memory_last_block_usage = 0;
276                         devc->memory_block_counter = 0;
277                         devc->memory_block_cursor = 0;
278                         pce_322a_memory_status(sdi);
279                         break;
280                 case MEM_STATE_GET_MEMORY_USAGE:
281                         /* Listen for memory usage answer. */
282                         if (revents == G_IO_IN) {
283                                 if (serial_read_nonblocking(serial, &c, 1) != 1)
284                                         return TRUE;
285                                 process_usage_byte(sdi, c);
286                         }
287                         break;
288                 case MEM_STATE_REQUEST_MEMORY_BLOCK:
289                         /* When cursor is 0, request next memory block. */
290                         if (devc->memory_block_counter <= devc->memory_block_usage) {
291                                 sr_warn("Requesting memory block %d.", devc->memory_block_counter);
292                                 pce_322a_memory_block(sdi, devc->memory_block_counter);
293                                 devc->memory_state = MEM_STATE_GET_MEMORY_BLOCK;
294                         } else {
295                                 sr_warn("Exhausted memory blocks.");
296                                 return FALSE;
297                         }
298                         break;
299                 case MEM_STATE_GET_MEMORY_BLOCK:
300                         /* Stop after reading last byte of last block. */
301                         if (devc->memory_block_counter >= devc->memory_block_usage
302                                         && devc->memory_block_cursor >= devc->memory_last_block_usage) {
303                                 sr_warn("Done reading memory (%d bytes).",
304                                         256 * (devc->memory_block_counter - 1)
305                                         + devc->memory_block_cursor);
306                                 return FALSE;
307                         }
308                         /* Listen for memory data. */
309                         if (revents == G_IO_IN) {
310                                 if (serial_read_nonblocking(serial, &c, 1) != 1)
311                                         return TRUE;
312                                 process_memory_byte(sdi, c);
313                         }
314                         break;
315                 }
316         } else {
317                 /* Listen for live data. */
318                 if (revents == G_IO_IN) {
319                         if (serial_read_nonblocking(serial, &c, 1) != 1)
320                                 return TRUE;
321                         process_byte(sdi, c);
322                 }
323         }
324
325         return TRUE;
326 }
327
328 SR_PRIV int pce_322a_connect(const struct sr_dev_inst *sdi)
329 {
330         return send_command(sdi, CMD_CONNECT);
331 }
332
333 SR_PRIV int pce_322a_disconnect(const struct sr_dev_inst *sdi)
334 {
335         return send_command(sdi, CMD_DISCONNECT);
336 }
337
338 SR_PRIV int pce_322a_memory_status(const struct sr_dev_inst *sdi)
339 {
340         return send_command(sdi, CMD_MEMORY_STATUS);
341 }
342
343 SR_PRIV int pce_322a_memory_clear(const struct sr_dev_inst *sdi)
344 {
345         return send_command(sdi, CMD_MEMORY_CLEAR);
346 }
347
348 SR_PRIV int pce_322a_memory_block(const struct sr_dev_inst *sdi, uint16_t memblk)
349 {
350         uint8_t buf0 = memblk;
351         uint8_t buf1 = memblk >> 8;
352         uint32_t command = CMD_MEMORY_TRANSFER << 16 | buf0 << 8 | buf1;
353         return send_long_command(sdi, command);
354 }
355
356 SR_PRIV uint64_t pce_322a_weight_freq_get(const struct sr_dev_inst *sdi)
357 {
358         struct dev_context *devc;
359
360         devc = sdi->priv;
361
362         return devc->cur_mqflags & (SR_MQFLAG_SPL_FREQ_WEIGHT_A | SR_MQFLAG_SPL_FREQ_WEIGHT_C);
363 }
364
365 SR_PRIV int pce_322a_weight_freq_set(const struct sr_dev_inst *sdi, uint64_t freqw)
366 {
367         struct dev_context *devc;
368
369         devc = sdi->priv;
370
371         if (devc->cur_mqflags & freqw)
372                 return SR_OK;
373
374         return send_command(sdi, CMD_TOGGLE_WEIGHT_FREQ);
375 }
376
377 SR_PRIV uint64_t pce_322a_weight_time_get(const struct sr_dev_inst *sdi)
378 {
379         struct dev_context *devc;
380
381         devc = sdi->priv;
382
383         return devc->cur_mqflags & (SR_MQFLAG_SPL_TIME_WEIGHT_F | SR_MQFLAG_SPL_TIME_WEIGHT_S);
384 }
385
386 SR_PRIV int pce_322a_weight_time_set(const struct sr_dev_inst *sdi, uint64_t timew)
387 {
388         struct dev_context *devc;
389
390         devc = sdi->priv;
391
392         if (devc->cur_mqflags & timew)
393                 return SR_OK;
394
395         return send_command(sdi, CMD_TOGGLE_WEIGHT_TIME);
396 }
397
398 SR_PRIV int pce_322a_meas_range_get(const struct sr_dev_inst *sdi,
399                 uint64_t *low, uint64_t *high)
400 {
401         struct dev_context *devc;
402
403         devc = sdi->priv;
404
405         switch (devc->cur_meas_range) {
406         case MEAS_RANGE_30_130:
407                 *low = 30;
408                 *high = 130;
409                 break;
410         case MEAS_RANGE_30_80:
411                 *low = 30;
412                 *high = 80;
413                 break;
414         case MEAS_RANGE_50_100:
415                 *low = 50;
416                 *high = 100;
417                 break;
418         case MEAS_RANGE_80_130:
419                 *low = 80;
420                 *high = 130;
421                 break;
422         default:
423                 return SR_ERR;
424         }
425
426         return SR_OK;
427 }
428
429 SR_PRIV int pce_322a_meas_range_set(const struct sr_dev_inst *sdi,
430                 uint64_t low, uint64_t high)
431 {
432         struct dev_context *devc;
433         uint8_t range;
434         int ret = SR_OK;
435
436         devc = sdi->priv;
437
438         if (low == 30 && high == 130)
439                 range = MEAS_RANGE_30_130;
440         else if (low == 30 && high == 80)
441                 range = MEAS_RANGE_30_80;
442         else if (low == 50 && high == 100)
443                 range = MEAS_RANGE_50_100;
444         else if (low == 80 && high == 130)
445                 range = MEAS_RANGE_80_130;
446         else
447                 return SR_ERR;
448
449         while (range != devc->cur_meas_range) {
450                 ret = send_command(sdi, CMD_TOGGLE_MEAS_RANGE);
451                 if (ret != SR_OK)
452                         break;
453                 range = (range - 1) & 3;
454         }
455
456         return ret;
457 }
458
459 SR_PRIV int pce_322a_power_off(const struct sr_dev_inst *sdi)
460 {
461         return send_command(sdi, CMD_POWER_OFF);
462 }