2 * This file is part of the libsigrok project.
4 * Copyright (C) 2014 Janne Huttunen <jahuttun@gmail.com>
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.
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.
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/>.
23 * Brymen BM25x serial protocol parser.
28 #include <libsigrok/libsigrok.h>
29 #include "libsigrok-internal.h"
31 #define LOG_PREFIX "brymen-bm25x"
35 SR_PRIV gboolean sr_brymen_bm25x_packet_valid(const uint8_t *buf)
42 for (i = 1; i < BRYMEN_BM25X_PACKET_SIZE; i++)
43 if ((buf[i] >> 4) != i)
49 static int decode_digit(int num, const uint8_t *buf)
53 val = (buf[3 + 2 * num] & 0xe) | ((buf[4 + 2 * num] << 4) & 0xf0);
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';
75 sr_dbg("Unknown digit: 0x%02x.", val);
80 static int decode_point(const uint8_t *buf)
84 for (i = 1; i < MAX_DIGITS; i++) {
85 if ((buf[11 - 2 * i] & 1) == 0)
88 sr_spew("Multiple decimal points found!");
97 static float scale_value(float val, int point, int digits)
101 pos = point ? point + digits - MAX_DIGITS : 0;
105 case 1: return val * 1e-1;
106 case 2: return val * 1e-2;
107 case 3: return val * 1e-3;
110 sr_dbg("Invalid decimal point %d (%d digits).", point, digits);
115 static float decode_prefix(const uint8_t *buf)
117 if (buf[11] & 2) return 1e+6;
118 if (buf[11] & 1) return 1e+3;
119 if (buf[13] & 1) return 1e-3;
120 if (buf[13] & 2) return 1e-6;
121 if (buf[12] & 1) return 1e-9;
126 static float decode_value(const uint8_t *buf)
131 for (i = 0; i < MAX_DIGITS; i++) {
132 digit = decode_digit(i, buf);
133 if (i == 3 && (digit == 'C' || digit == 'F'))
135 if (digit < 0 || digit > 9)
137 val = 10.0 * val + digit;
140 return scale_value(val, decode_point(buf), i);
143 if (decode_digit(1, buf) == 0 && decode_digit(2, buf) == 'L')
149 SR_PRIV int sr_brymen_bm25x_parse(const uint8_t *buf, float *floatval,
150 struct sr_datafeed_analog_old *analog, void *info)
156 analog->mq = SR_MQ_GAIN;
157 analog->unit = SR_UNIT_UNITLESS;
161 analog->mqflags |= SR_MQFLAG_AUTORANGE;
163 analog->mqflags |= SR_MQFLAG_DC;
165 analog->mqflags |= SR_MQFLAG_AC;
167 analog->mqflags |= SR_MQFLAG_RELATIVE;
169 analog->mqflags |= SR_MQFLAG_HOLD;
171 analog->mqflags |= SR_MQFLAG_MAX;
173 analog->mqflags |= SR_MQFLAG_MIN;
176 analog->mq = SR_MQ_VOLTAGE;
177 analog->unit = SR_UNIT_VOLT;
178 if ((analog->mqflags & (SR_MQFLAG_DC | SR_MQFLAG_AC)) == 0)
179 analog->mqflags |= SR_MQFLAG_DIODE;
182 analog->mq = SR_MQ_CURRENT;
183 analog->unit = SR_UNIT_AMPERE;
186 analog->mq = SR_MQ_RESISTANCE;
187 analog->unit = SR_UNIT_OHM;
190 analog->mq = SR_MQ_CAPACITANCE;
191 analog->unit = SR_UNIT_FARAD;
194 analog->mq = SR_MQ_FREQUENCY;
195 analog->unit = SR_UNIT_HERTZ;
198 if (decode_digit(3, buf) == 'C') {
199 analog->mq = SR_MQ_TEMPERATURE;
200 analog->unit = SR_UNIT_CELSIUS;
202 if (decode_digit(3, buf) == 'F') {
203 analog->mq = SR_MQ_TEMPERATURE;
204 analog->unit = SR_UNIT_FAHRENHEIT;
207 val = decode_value(buf) * decode_prefix(buf);