]> sigrok.org Git - libsigrok.git/blob - hardware/tondaj-sl-814/protocol.c
tondaj-sl-814: Fix unused parameter warning
[libsigrok.git] / hardware / tondaj-sl-814 / protocol.c
1 /*
2  * This file is part of the sigrok project.
3  *
4  * Copyright (C) 2012 Uwe Hermann <uwe@hermann-uwe.de>
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 2 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, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19  */
20
21 #include <string.h>
22 #include <glib.h>
23 #include "libsigrok.h"
24 #include "libsigrok-internal.h"
25 #include "protocol.h"
26
27 /* States */
28 enum {
29         SEND_INIT,
30         GET_INIT_REPLY,
31         SEND_PACKET_REQUEST,
32         GET_PACKET,
33 };
34
35 static void parse_packet(const uint8_t *buf, float *floatval,
36                          struct sr_datafeed_analog *analog)
37 {
38         gboolean is_a, is_fast;
39         uint16_t intval;
40         uint8_t level = 0, level_bits;
41
42         /* Byte 0 [7:7]: 0 = A, 1 = C */
43         is_a = ((buf[0] & (1 << 7)) == 0);
44
45         /* Byte 0 [6:6]: Unknown/unused? */
46
47         /* Byte 0 [5:4]: Level (00 = 40, 01 = 60, 10 = 80, 11 = 100) */
48         level_bits = (buf[0] >> 4) & 0x03;
49         if (level_bits == 0)
50                 level = 40;
51         else if (level_bits == 1)
52                 level = 60;
53         else if (level_bits == 2)
54                 level = 80;
55         else if (level_bits == 3)
56                 level = 100;
57
58         /* Byte 0 [3:3]: 0 = fast, 1 = slow */
59         is_fast = ((buf[0] & (1 << 3)) == 0);
60
61         /* Byte 0 [2:0]: value[10..8] */
62         /* Byte 1 [7:0]: value[7..0] */
63         intval = (buf[0] & 0x7) << 8;
64         intval |= buf[1];
65
66         *floatval = (float)intval;
67
68         /* The value on the display always has one digit after the comma. */
69         *floatval /= 10;
70
71         analog->mq = SR_MQ_SOUND_PRESSURE_LEVEL;
72         analog->unit = SR_UNIT_DECIBEL_SPL;
73
74         if (is_a)
75                 analog->mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_A;
76         else
77                 analog->mqflags |= SR_MQFLAG_SPL_FREQ_WEIGHT_C;
78
79         if (is_fast)
80                 analog->mqflags |= SR_MQFLAG_SPL_TIME_WEIGHT_F;
81         else
82                 analog->mqflags |= SR_MQFLAG_SPL_TIME_WEIGHT_S;
83
84         /* TODO: How to handle level? */
85         (void)level;
86 }
87
88 static void decode_packet(struct dev_context *devc)
89 {
90         struct sr_datafeed_packet packet;
91         struct sr_datafeed_analog analog;
92         float floatval;
93
94         memset(&analog, 0, sizeof(struct sr_datafeed_analog));
95
96         parse_packet(devc->buf, &floatval, &analog);
97
98         /* Send a sample packet with one analog value. */
99         analog.num_samples = 1;
100         analog.data = &floatval;
101         packet.type = SR_DF_ANALOG;
102         packet.payload = &analog;
103         sr_session_send(devc->cb_data, &packet);
104
105         devc->num_samples++;
106 }
107
108 int tondaj_sl_814_receive_data(int fd, int revents, void *cb_data)
109 {
110         struct sr_dev_inst *sdi;
111         struct dev_context *devc;
112         uint8_t buf[3];
113         int ret;
114
115         (void)fd;
116         (void)revents;
117
118         sdi = cb_data;
119         devc = sdi->priv;
120
121         /* TODO: Parts of this code need to be improved later. */
122
123         /* State machine. */
124         if (devc->state == SEND_INIT) {
125                 /* On the first run, send the "init" command. */
126                 buf[0] = 0x10;
127                 buf[1] = 0x04;
128                 buf[2] = 0x0d;
129                 sr_spew("Sending init command: %02x %02x %02x.",
130                         buf[0], buf[1], buf[2]);
131                 if ((ret = serial_write(devc->serial, buf, 3)) < 0) {
132                         sr_err("Error sending init command: %d.", ret);
133                         return FALSE;
134                 }
135                 devc->state = GET_INIT_REPLY;
136         } else if (devc->state == GET_INIT_REPLY) {
137                 /* If we just sent the "init" command, get its reply. */
138                 if ((ret = serial_read(devc->serial, buf, 2)) < 0) {
139                         sr_err("Error reading init reply: %d.", ret);
140                         return FALSE;
141                 }
142                 sr_spew("Received init reply: %02x %02x.", buf[0], buf[1]);
143                 /* Expected reply: 0x05 0x0d */
144                 if (buf[0] != 0x05 || buf[1] != 0x0d) {
145                         sr_err("Received incorrect init reply, retrying.");
146                         devc->state = SEND_INIT;
147                         return TRUE;
148                 }
149                 devc->state = SEND_PACKET_REQUEST;
150         } else if (devc->state == SEND_PACKET_REQUEST) {
151                 /* Request a packet (send 0x30 ZZ 0x0d). */
152                 buf[0] = 0x30;
153                 buf[1] = 0x00; /* ZZ */
154                 buf[2] = 0x0d;
155                 sr_spew("Sending data request command: %02x %02x %02x.",
156                         buf[0], buf[1], buf[2]);
157                 if ((ret = serial_write(devc->serial, buf, 3)) < 0) {
158                         sr_err("Error sending request command: %d.", ret);
159                         return FALSE;
160                 }
161                 devc->buflen = 0;
162                 devc->state = GET_PACKET;
163         } else if (devc->state == GET_PACKET) {
164                 /* Read a packet from the device. */
165                 ret = serial_read(devc->serial, devc->buf + devc->buflen,
166                                   4 - devc->buflen);
167                 if (ret < 0) {
168                         sr_err("Error reading packet: %d.", ret);
169                         return TRUE;
170                 }
171
172                 devc->buflen += ret;
173
174                 /* Didn't receive all 4 bytes, yet. */
175                 if (devc->buflen != 4)
176                         return TRUE;
177
178                 sr_spew("Received packet: %02x %02x %02x %02x.", devc->buf[0],
179                         devc->buf[1], devc->buf[2], devc->buf[3]);
180
181                 /* Expected reply: AA BB ZZ+1 0x0d */
182                 if (devc->buf[2] != 0x01 || devc->buf[3] != 0x0d) {
183                         sr_err("Received incorrect request reply, retrying.");
184                         devc->state = SEND_PACKET_REQUEST;
185                         return TRUE;
186                 }
187
188                 decode_packet(devc);
189
190                 devc->state = SEND_PACKET_REQUEST;
191         } else {
192                 sr_err("Invalid state: %d.", devc->state);
193                 return FALSE;
194         }
195
196         /* Stop acquisition if we acquired enough samples. */
197         if (devc->limit_samples > 0) {
198                 if (devc->num_samples >= devc->limit_samples) {
199                         sr_info("Requested number of samples reached.");
200                         sdi->driver->dev_acquisition_stop(sdi, cb_data);
201                 }
202         }
203
204         return TRUE;
205 }