X-Git-Url: https://sigrok.org/gitweb/?p=libsigrok.git;a=blobdiff_plain;f=hardware%2Fbrymen-dmm%2Fparser.c;h=e4b12274d41d862b3f08c6b85182545a300e39d5;hp=b2c118b2de837284e16c1f63035278dbdf3d8ae4;hb=43cd4637285833706f8a404ca027bcf0ee75b9ae;hpb=601fb67cc4977d7e04e20916bde52147b35df970 diff --git a/hardware/brymen-dmm/parser.c b/hardware/brymen-dmm/parser.c index b2c118b2..e4b12274 100644 --- a/hardware/brymen-dmm/parser.c +++ b/hardware/brymen-dmm/parser.c @@ -1,5 +1,5 @@ /* - * This file is part of the sigrok project. + * This file is part of the libsigrok project. * * Copyright (C) 2012 Alexandru Gagniuc * @@ -18,17 +18,14 @@ */ #include "protocol.h" -#include -#include -#include -/* - * Flags passed from the DMM. - */ +#define MAX_PACKET_LEN 22 + +/* Flags passed from the DMM. */ struct brymen_flags { - gboolean low_batt; - gboolean decibel, duty_cycle, hertz, amp, beep, ohm, fahrenheit; - gboolean celsius, capacitance, diode, volt, dc, ac; + gboolean is_low_batt, is_decibel, is_duty_cycle, is_hertz, is_amp; + gboolean is_beep, is_ohm, is_fahrenheit, is_celsius, is_capacitance; + gboolean is_diode, is_volt, is_dc, is_ac; }; struct bm850_command { @@ -56,32 +53,36 @@ struct brymen_tail { /* * We only have one command because we only support the BM-857. However, the - * driver is easily extensible to support more models, as the protocols are very - * similar. + * driver is easily extensible to support more models, as the protocols are + * very similar. */ enum { BM_CMD_REQUEST_READING = 0x00, }; - static int bm_send_command(uint8_t command, uint8_t arg1, uint8_t arg2, struct sr_serial_dev_inst *serial) { - struct bm850_command cmdout = { - .dle = 0x10, .stx = 0x02, - .cmd = command, - .arg = {arg1, arg2}, - .checksum = arg1^arg2, .dle2 = 0x10, .etx = 0x03}; - int written; - - /* TODO: How do we compute the checksum? Hardware seems to ignore it */ - - /* Request reading */ - written = serial_write(serial, &cmdout, sizeof(cmdout)); - if(written != sizeof(cmdout)) - return SR_ERR; - - return SR_OK; + struct bm850_command cmdout; + int written; + + cmdout.dle = 0x10; + cmdout.stx = 0x02; + cmdout.cmd = command; + cmdout.arg[0] = arg1; + cmdout.arg[1] = arg2; + cmdout.checksum = arg1 ^ arg2; + cmdout.dle2 = 0x10; + cmdout.etx = 0x03; + + /* TODO: How to compute the checksum? Hardware seems to ignore it. */ + + /* Request reading. */ + written = serial_write(serial, &cmdout, sizeof(cmdout)); + if (written != sizeof(cmdout)) + return SR_ERR; + + return SR_OK; } SR_PRIV int brymen_packet_request(struct sr_serial_dev_inst *serial) @@ -92,29 +93,29 @@ SR_PRIV int brymen_packet_request(struct sr_serial_dev_inst *serial) SR_PRIV int brymen_packet_length(const uint8_t *buf, int *len) { struct brymen_header *hdr; - const int brymen_max_packet_len = 22; int packet_len; - const size_t buflen = *len; - - hdr = (void*)buf; - + size_t buflen; + + buflen = *len; + hdr = (void *)buf; + /* Did we receive a complete header yet? */ - if (buflen < sizeof(*hdr) ) + if (buflen < sizeof(*hdr)) return PACKET_NEED_MORE_DATA; - + if (hdr->dle != 0x10 || hdr->stx != 0x02) return PACKET_INVALID_HEADER; - - /* Our packet includes the header, the payload, and the tail */ + + /* Our packet includes the header, the payload, and the tail. */ packet_len = sizeof(*hdr) + hdr->len + sizeof(struct brymen_tail); - - /* In case we pick up an invalid header, limit our search */ - if (packet_len > brymen_max_packet_len) { + + /* In case we pick up an invalid header, limit our search. */ + if (packet_len > MAX_PACKET_LEN) { sr_spew("Header specifies an invalid payload length: %i.", hdr->len); return PACKET_INVALID_HEADER; } - + *len = packet_len; sr_spew("Expecting a %d-byte packet.", *len); return PACKET_HEADER_OK; @@ -126,16 +127,18 @@ SR_PRIV gboolean brymen_packet_is_valid(const uint8_t *buf) struct brymen_tail *tail; int i; uint8_t chksum = 0; - const uint8_t *payload = buf + sizeof(struct brymen_header); + uint8_t *payload; - hdr = (void*)buf; - tail = (void*)(payload + hdr->len); + payload = (uint8_t *)(buf + sizeof(struct brymen_header)); + + hdr = (void *)buf; + tail = (void *)(payload + hdr->len); for (i = 0; i< hdr->len; i++) chksum ^= payload[i]; if (tail->checksum != chksum) { - sr_dbg("Packet has invalid checksum 0x%.2x. Expected 0x%.2x", + sr_dbg("Packet has invalid checksum 0x%.2x. Expected 0x%.2x.", chksum, tail->checksum); return FALSE; } @@ -143,7 +146,7 @@ SR_PRIV gboolean brymen_packet_is_valid(const uint8_t *buf) return TRUE; } -static int parse_value(const char *strbuf, const int len, float *floatval) +static int parse_value(const char *strbuf, int len, float *floatval) { int s, d; char str[32]; @@ -155,125 +158,131 @@ static int parse_value(const char *strbuf, const int len, float *floatval) } memset(str, 0, sizeof(str)); - /* Spaces may interfere with strtod parsing the exponent. Strip them */ - for (s = 0, d = 0; s < len; s++) + /* Spaces may interfere with parsing the exponent. Strip them. */ + for (s = 0, d = 0; s < len; s++) { if (strbuf[s] != ' ') str[d++] = strbuf[s]; - /* YES, it's that simple !*/ - *floatval = strtod(str, NULL); + } + if (sr_atof_ascii(str, floatval) != SR_OK) + return SR_ERR; return SR_OK; } + static void parse_flags(const uint8_t *buf, struct brymen_flags *info) { - const uint8_t * bfunc = buf + sizeof(struct brymen_header); - - info->low_batt = (bfunc[3] & (1 << 7)) != 0; - - info->decibel = (bfunc[1] & (1 << 5)) != 0; - info->duty_cycle = (bfunc[1] & (1 << 3)) != 0; - info->hertz = (bfunc[1] & (1 << 2)) != 0; - info->amp = (bfunc[1] & (1 << 1)) != 0; - info->beep = (bfunc[1] & (1 << 0)) != 0; - - info->ohm = (bfunc[0] & (1 << 7)) != 0; - info->fahrenheit = (bfunc[0] & (1 << 6)) != 0; - info->celsius = (bfunc[0] & (1 << 5)) != 0; - info->diode = (bfunc[0] & (1 << 4)) != 0; - info->capacitance = (bfunc[0] & (1 << 3)) != 0; - info->volt = (bfunc[0] & (1 << 2)) != 0; - info->dc = (bfunc[0] & (1 << 1)) != 0; - info->ac = (bfunc[0] & (1 << 0)) != 0; + info->is_low_batt = (buf[4 + 3] & (1 << 7)) != 0; + + info->is_decibel = (buf[4 + 1] & (1 << 5)) != 0; + info->is_duty_cycle = (buf[4 + 1] & (1 << 3)) != 0; + info->is_hertz = (buf[4 + 1] & (1 << 2)) != 0; + info->is_amp = (buf[4 + 1] & (1 << 1)) != 0; + info->is_beep = (buf[4 + 1] & (1 << 0)) != 0; + + info->is_ohm = (buf[4 + 0] & (1 << 7)) != 0; + info->is_fahrenheit = (buf[4 + 0] & (1 << 6)) != 0; + info->is_celsius = (buf[4 + 0] & (1 << 5)) != 0; + info->is_diode = (buf[4 + 0] & (1 << 4)) != 0; + info->is_capacitance = (buf[4 + 0] & (1 << 3)) != 0; + info->is_volt = (buf[4 + 0] & (1 << 2)) != 0; + info->is_dc = (buf[4 + 0] & (1 << 1)) != 0; + info->is_ac = (buf[4 + 0] & (1 << 0)) != 0; } -SR_PRIV int sr_brymen_parse(const uint8_t *buf, float *floatval, - struct sr_datafeed_analog *analog, void *info) +SR_PRIV int brymen_parse(const uint8_t *buf, float *floatval, + struct sr_datafeed_analog *analog, void *info) { struct brymen_flags flags; - struct brymen_header *hdr = (void*) buf; - const uint8_t *bfunc = buf + sizeof(struct brymen_header); + struct brymen_header *hdr; + uint8_t *bfunc; int asciilen; (void)info; + + hdr = (void *)buf; + bfunc = (uint8_t *)(buf + sizeof(struct brymen_header)); + analog->mqflags = 0; - /* Give some debug info about the package */ + /* Give some debug info about the package. */ asciilen = hdr->len - 4; sr_dbg("DMM flags: %.2x %.2x %.2x %.2x", bfunc[3], bfunc[2], bfunc[1], bfunc[0]); - /* Value is an ASCII string */ + /* Value is an ASCII string. */ sr_dbg("DMM packet: \"%.*s\"", asciilen, bfunc + 4); parse_flags(buf, &flags); - parse_value((const char*)(bfunc + 4), asciilen, floatval); + if (parse_value((const char *)(bfunc + 4), asciilen, floatval) != SR_OK) + return SR_ERR; - if (flags.volt) { + if (flags.is_volt) { analog->mq = SR_MQ_VOLTAGE; analog->unit = SR_UNIT_VOLT; } - if (flags.amp) { + if (flags.is_amp) { analog->mq = SR_MQ_CURRENT; analog->unit = SR_UNIT_AMPERE; } - if (flags.ohm) { - if (flags.beep) + if (flags.is_ohm) { + if (flags.is_beep) analog->mq = SR_MQ_CONTINUITY; else analog->mq = SR_MQ_RESISTANCE; analog->unit = SR_UNIT_OHM; } - if (flags.hertz) { + if (flags.is_hertz) { analog->mq = SR_MQ_FREQUENCY; analog->unit = SR_UNIT_HERTZ; } - if (flags.duty_cycle) { + if (flags.is_duty_cycle) { analog->mq = SR_MQ_DUTY_CYCLE; analog->unit = SR_UNIT_PERCENTAGE; } - if (flags.capacitance) { + if (flags.is_capacitance) { analog->mq = SR_MQ_CAPACITANCE; analog->unit = SR_UNIT_FARAD; } - if (flags.fahrenheit) { + if (flags.is_fahrenheit) { analog->mq = SR_MQ_TEMPERATURE; analog->unit = SR_UNIT_FAHRENHEIT; } - if (flags.celsius) { + if (flags.is_celsius) { analog->mq = SR_MQ_TEMPERATURE; analog->unit = SR_UNIT_CELSIUS; } - if (flags.capacitance) { + if (flags.is_capacitance) { analog->mq = SR_MQ_CAPACITANCE; analog->unit = SR_UNIT_FARAD; } + /* - * The high-end brymen models have a configurable reference impedance. + * The high-end Brymen models have a configurable reference impedance. * When the reference impedance is changed, the DMM sends one packet * with the value of the new reference impedance. Both decibel and ohm * flags are set in this case, so we must be careful to correctly - * identify the value as ohm, not dBmW + * identify the value as ohm, not dBmW. */ - if (flags.decibel && !flags.ohm) { + if (flags.is_decibel && !flags.is_ohm) { analog->mq = SR_MQ_POWER; analog->unit = SR_UNIT_DECIBEL_MW; /* * For some reason, dBm measurements are sent by the multimeter * with a value three orders of magnitude smaller than the * displayed value. - * */ + */ *floatval *= 1000; } - if (flags.diode) + if (flags.is_diode) analog->mqflags |= SR_MQFLAG_DIODE; - /* We can have both AC+DC in a single measurement */ - if (flags.ac) + /* We can have both AC+DC in a single measurement. */ + if (flags.is_ac) analog->mqflags |= SR_MQFLAG_AC; - if (flags.dc) + if (flags.is_dc) analog->mqflags |= SR_MQFLAG_DC; - if (flags.low_batt) + if (flags.is_low_batt) sr_info("Low battery!"); return SR_OK; -} \ No newline at end of file +}