]> sigrok.org Git - libsigrok.git/blame - src/dmm/bm25x.c
output/csv: use intermediate time_t var, silence compiler warning
[libsigrok.git] / src / dmm / bm25x.c
CommitLineData
a24c3f4a
JH
1/*
2 * This file is part of the libsigrok project.
3 *
4 * Copyright (C) 2014 Janne Huttunen <jahuttun@gmail.com>
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/**
21 * @file
22 *
23 * Brymen BM25x serial protocol parser.
24 */
25
6ec6c43b 26#include <config.h>
a24c3f4a 27#include <math.h>
c1aae900 28#include <libsigrok/libsigrok.h>
a24c3f4a
JH
29#include "libsigrok-internal.h"
30
31#define LOG_PREFIX "brymen-bm25x"
32
33#define MAX_DIGITS 4
34
35SR_PRIV gboolean sr_brymen_bm25x_packet_valid(const uint8_t *buf)
36{
37 int i;
38
39 if (buf[0] != 2)
40 return FALSE;
41
42 for (i = 1; i < BRYMEN_BM25X_PACKET_SIZE; i++)
43 if ((buf[i] >> 4) != i)
44 return FALSE;
45
46 return TRUE;
47}
48
49static int decode_digit(int num, const uint8_t *buf)
50{
51 int val;
52
53 val = (buf[3 + 2 * num] & 0xe) | ((buf[4 + 2 * num] << 4) & 0xf0);
54
55 switch (val) {
56 case 0xbe: return 0;
57 case 0xa0: return 1;
58 case 0xda: return 2;
59 case 0xf8: return 3;
60 case 0xe4: return 4;
61 case 0x7c: return 5;
62 case 0x7e: return 6;
63 case 0xa8: return 7;
64 case 0xfe: return 8;
65 case 0xfc: return 9;
66 case 0x00: return ' ';
67 case 0x40: return '-';
68 case 0x16: return 'L';
69 case 0x1e: return 'C';
70 case 0x4e: return 'F';
71 case 0x5e: return 'E';
72 case 0x62: return 'n';
73 case 0x42: return 'r';
74 default:
75 sr_dbg("Unknown digit: 0x%02x.", val);
76 return -1;
77 }
78}
79
80static int decode_point(const uint8_t *buf)
81{
82 int i, p = 0;
83
84 for (i = 1; i < MAX_DIGITS; i++) {
85 if ((buf[11 - 2 * i] & 1) == 0)
86 continue;
87 if (p != 0) {
88 sr_spew("Multiple decimal points found!");
89 return -1;
90 }
91 p = i;
92 }
93
94 return p;
95}
96
25198a7e 97static int decode_scale(int point, int digits)
a24c3f4a
JH
98{
99 int pos;
100
101 pos = point ? point + digits - MAX_DIGITS : 0;
102
25198a7e
AJ
103 if (pos < 0 || pos > 3) {
104 sr_dbg("Invalid decimal point %d (%d digits).", point, digits);
105 return 0;
a24c3f4a 106 }
25198a7e 107 return -pos;
a24c3f4a
JH
108}
109
25198a7e 110static int decode_prefix(const uint8_t *buf)
a24c3f4a 111{
25198a7e
AJ
112 if (buf[11] & 2) return 6;
113 if (buf[11] & 1) return 3;
114 if (buf[13] & 1) return -3;
115 if (buf[13] & 2) return -6;
116 if (buf[12] & 1) return -9;
a24c3f4a 117
25198a7e 118 return 0;
a24c3f4a
JH
119}
120
25198a7e 121static float decode_value(const uint8_t *buf, int *exponent)
a24c3f4a
JH
122{
123 float val = 0.0f;
124 int i, digit;
125
126 for (i = 0; i < MAX_DIGITS; i++) {
127 digit = decode_digit(i, buf);
128 if (i == 3 && (digit == 'C' || digit == 'F'))
129 break;
130 if (digit < 0 || digit > 9)
131 goto special;
132 val = 10.0 * val + digit;
133 }
134
25198a7e
AJ
135 *exponent = decode_scale(decode_point(buf), i);
136 return val;
a24c3f4a
JH
137
138special:
139 if (decode_digit(1, buf) == 0 && decode_digit(2, buf) == 'L')
140 return INFINITY;
141
142 return NAN;
143}
144
145SR_PRIV int sr_brymen_bm25x_parse(const uint8_t *buf, float *floatval,
b02bb45f 146 struct sr_datafeed_analog *analog, void *info)
a24c3f4a 147{
25198a7e 148 int exponent = 0;
a24c3f4a
JH
149 float val;
150
151 (void)info;
152
b02bb45f
UH
153 analog->meaning->mq = SR_MQ_GAIN;
154 analog->meaning->unit = SR_UNIT_UNITLESS;
155 analog->meaning->mqflags = 0;
a24c3f4a
JH
156
157 if (buf[1] & 8)
b02bb45f 158 analog->meaning->mqflags |= SR_MQFLAG_AUTORANGE;
a24c3f4a 159 if (buf[1] & 4)
b02bb45f 160 analog->meaning->mqflags |= SR_MQFLAG_DC;
a24c3f4a 161 if (buf[1] & 2)
b02bb45f 162 analog->meaning->mqflags |= SR_MQFLAG_AC;
a24c3f4a 163 if (buf[1] & 1)
b02bb45f 164 analog->meaning->mqflags |= SR_MQFLAG_RELATIVE;
a24c3f4a 165 if (buf[11] & 8)
b02bb45f 166 analog->meaning->mqflags |= SR_MQFLAG_HOLD;
a24c3f4a 167 if (buf[13] & 8)
b02bb45f 168 analog->meaning->mqflags |= SR_MQFLAG_MAX;
a24c3f4a 169 if (buf[14] & 8)
b02bb45f 170 analog->meaning->mqflags |= SR_MQFLAG_MIN;
a24c3f4a
JH
171
172 if (buf[14] & 4) {
b02bb45f
UH
173 analog->meaning->mq = SR_MQ_VOLTAGE;
174 analog->meaning->unit = SR_UNIT_VOLT;
175 if ((analog->meaning->mqflags & (SR_MQFLAG_DC | SR_MQFLAG_AC)) == 0)
64aa214a 176 analog->meaning->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC;
a24c3f4a
JH
177 }
178 if (buf[14] & 2) {
b02bb45f
UH
179 analog->meaning->mq = SR_MQ_CURRENT;
180 analog->meaning->unit = SR_UNIT_AMPERE;
a24c3f4a
JH
181 }
182 if (buf[12] & 4) {
b02bb45f
UH
183 analog->meaning->mq = SR_MQ_RESISTANCE;
184 analog->meaning->unit = SR_UNIT_OHM;
a24c3f4a
JH
185 }
186 if (buf[13] & 4) {
b02bb45f
UH
187 analog->meaning->mq = SR_MQ_CAPACITANCE;
188 analog->meaning->unit = SR_UNIT_FARAD;
a24c3f4a
JH
189 }
190 if (buf[12] & 2) {
b02bb45f
UH
191 analog->meaning->mq = SR_MQ_FREQUENCY;
192 analog->meaning->unit = SR_UNIT_HERTZ;
a24c3f4a
JH
193 }
194
195 if (decode_digit(3, buf) == 'C') {
b02bb45f
UH
196 analog->meaning->mq = SR_MQ_TEMPERATURE;
197 analog->meaning->unit = SR_UNIT_CELSIUS;
a24c3f4a
JH
198 }
199 if (decode_digit(3, buf) == 'F') {
b02bb45f
UH
200 analog->meaning->mq = SR_MQ_TEMPERATURE;
201 analog->meaning->unit = SR_UNIT_FAHRENHEIT;
a24c3f4a
JH
202 }
203
25198a7e
AJ
204 val = decode_value(buf, &exponent);
205 exponent += decode_prefix(buf);
206 val *= powf(10, exponent);
a24c3f4a
JH
207
208 if (buf[3] & 1)
209 val = -val;
210
211 *floatval = val;
d9251a2c 212 analog->encoding->digits = -exponent;
25198a7e 213 analog->spec->spec_digits = -exponent;
a24c3f4a
JH
214
215 return SR_OK;
216}