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