brymen-dmm: Cosmetics, coding-style, consistency.

Also, name the driver "brymen-bm857" in preparation to doing "subdrivers"
for other Brymen models later (similar to serial-dmm).
This commit is contained in:
Uwe Hermann 2013-02-02 11:35:20 +01:00
parent 943e94f567
commit c5d6f5cc1c
5 changed files with 154 additions and 152 deletions

View File

@ -17,12 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <glib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include "libsigrok.h"
#include "libsigrok-internal.h"
#include "protocol.h"
static const int hwopts[] = {
@ -39,8 +33,8 @@ static const int hwcaps[] = {
0,
};
SR_PRIV struct sr_dev_driver brymen_dmm_driver_info;
static struct sr_dev_driver *di = &brymen_dmm_driver_info;
SR_PRIV struct sr_dev_driver brymen_bm857_driver_info;
static struct sr_dev_driver *di = &brymen_bm857_driver_info;
static int hw_init(struct sr_context *sr_ctx)
{
@ -51,6 +45,7 @@ static void free_instance(void *inst)
{
struct sr_dev_inst *sdi;
struct dev_context *devc;
if (!(sdi = inst))
return;
if (!(devc = sdi->priv))
@ -82,11 +77,13 @@ static GSList *brymen_scan(const char *conn, const char *serialcomm)
struct sr_serial_dev_inst *serial;
GSList *devices;
int ret;
uint8_t buf[128];
size_t len;
if (!(serial = sr_serial_dev_inst_new(conn, serialcomm)))
return NULL;
if (serial_open(serial, SERIAL_RDWR|SERIAL_NONBLOCK) != SR_OK)
if (serial_open(serial, SERIAL_RDWR | SERIAL_NONBLOCK) != SR_OK)
return NULL;
sr_info("Probing port %s.", conn);
@ -94,14 +91,12 @@ static GSList *brymen_scan(const char *conn, const char *serialcomm)
devices = NULL;
/* Request reading */
if (brymen_packet_request(serial) == -1) {
sr_err("Unable to send command. code: %d.", errno);
if ((ret = brymen_packet_request(serial)) < 0) {
sr_err("Unable to send command: %d.", ret);
goto scan_cleanup;
}
uint8_t buf[128];
size_t len = 128;
len = 128;
ret = brymen_stream_detect(serial, buf, &len, brymen_packet_length,
brymen_packet_is_valid, 1000, 9600);
if (ret != SR_OK)
@ -129,7 +124,6 @@ static GSList *brymen_scan(const char *conn, const char *serialcomm)
drvc->instances = g_slist_append(drvc->instances, sdi);
devices = g_slist_append(devices, sdi);
scan_cleanup:
serial_close(serial);
@ -153,12 +147,12 @@ static GSList *hw_scan(GSList *options)
for (l = options; l; l = l->next) {
src = l->data;
switch (src->key) {
case SR_CONF_CONN:
conn = src->value;
break;
case SR_CONF_SERIALCOMM:
serialcomm = src->value;
break;
case SR_CONF_CONN:
conn = src->value;
break;
case SR_CONF_SERIALCOMM:
serialcomm = src->value;
break;
}
}
if (!conn) {
@ -169,7 +163,7 @@ static GSList *hw_scan(GSList *options)
/* Use the provided comm specs. */
devices = brymen_scan(conn, serialcomm);
} else {
/* But 9600 8N1 should work all of the time */
/* But 9600/8n1 should work all of the time. */
devices = brymen_scan(conn, "9600/8n1/dtr=1/rts=1");
}
@ -232,12 +226,12 @@ static int config_list(int key, const void **data,
(void)sdi;
switch (key) {
case SR_CONF_SCAN_OPTIONS:
*data = hwopts;
break;
case SR_CONF_DEVICE_OPTIONS:
*data = hwcaps;
break;
case SR_CONF_SCAN_OPTIONS:
*data = hwopts;
break;
case SR_CONF_DEVICE_OPTIONS:
*data = hwcaps;
break;
default:
sr_err("Unknown config key: %d.", key);
return SR_ERR_ARG;
@ -264,11 +258,11 @@ static int hw_dev_config_set(int id, const void *value,
ret = SR_OK;
switch (id) {
case SR_CONF_LIMIT_SAMPLES:
devc->limit_samples = *(const uint64_t*)value;
case SR_CONF_LIMIT_SAMPLES:
devc->limit_samples = *(const uint64_t *)value;
break;
case SR_CONF_LIMIT_MSEC:
devc->limit_msec = *(const uint64_t*)value;
case SR_CONF_LIMIT_MSEC:
devc->limit_msec = *(const uint64_t *)value;
break;
default:
sr_err("Unknown hardware capability: %d.", id);
@ -345,9 +339,9 @@ static int hw_dev_acquisition_stop(struct sr_dev_inst *sdi, void *cb_data)
return SR_OK;
}
SR_PRIV struct sr_dev_driver brymen_dmm_driver_info = {
.name = "brymen-dmm",
.longname = "Brymen BM850 series",
SR_PRIV struct sr_dev_driver brymen_bm857_driver_info = {
.name = "brymen-bm857",
.longname = "Brymen BM857",
.api_version = 1,
.init = hw_init,
.cleanup = hw_cleanup,

View File

@ -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 <mr.nuke.me@gmail.com>
*
@ -18,17 +18,14 @@
*/
#include "protocol.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
/*
* 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,129 @@ 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 */
/* Spaces may interfere with strtod 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 !*/
/* Yes, it's that simple! */
*floatval = strtod(str, NULL);
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->is_low_batt = (buf[4 + 3] & (1 << 7)) != 0;
info->low_batt = (bfunc[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->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_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)
{
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);
parse_value((const char *)(bfunc + 4), asciilen, floatval);
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;
}
}

View File

@ -17,17 +17,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "libsigrok.h"
#include "libsigrok-internal.h"
#include "protocol.h"
#include <string.h>
/* --- parser.c --- */
/* parser.c */
SR_PRIV int sr_brymen_parse(const uint8_t *buf, float *floatval,
struct sr_datafeed_analog *analog, void *info);
static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi)
{
float floatval;
@ -36,7 +31,7 @@ static void handle_packet(const uint8_t *buf, struct sr_dev_inst *sdi)
struct sr_datafeed_analog analog;
devc = sdi->priv;
analog.num_samples = 1;
analog.mq = -1;
@ -73,19 +68,19 @@ static void handle_new_data(struct sr_dev_inst *sdi)
/* Now look for packets in that data. */
while (status != PACKET_NEED_MORE_DATA) {
/* We don't have a header, look for one */
/* We don't have a header, look for one. */
if (devc->next_packet_len == 0) {
len = devc->buflen - offset;
status = brymen_packet_length(devc->buf + offset, &len);
if (status == PACKET_HEADER_OK) {
/* We know how large the packet will be */
/* We know how large the packet will be. */
devc->next_packet_len = len;
} else if (status == PACKET_NEED_MORE_DATA) {
/* We did not yet receive the complete header */
/* We didn't yet receive the full header. */
devc->next_packet_len = 0;
break;
} else {
/* Invalid header. Move on */
/* Invalid header. Move on. */
devc->next_packet_len = 0;
offset++;
continue;
@ -96,13 +91,14 @@ static void handle_new_data(struct sr_dev_inst *sdi)
if (devc->buflen - offset < devc->next_packet_len)
break;
/* We should have a full packet here, so we can check it */
/* We should have a full packet here, so we can check it. */
if (brymen_packet_is_valid(devc->buf + offset)) {
handle_packet(devc->buf + offset, sdi);
offset += devc->next_packet_len;
} else {
offset++;
}
/* We are done with this packet. Look for a new one. */
devc->next_packet_len = 0;
}
@ -132,8 +128,7 @@ SR_PRIV int brymen_dmm_receive_data(int fd, int revents, void *cb_data)
handle_new_data(sdi);
} else {
/* Timeout, send another packet request. */
ret = brymen_packet_request(devc->serial);
if (ret < 0) {
if ((ret = brymen_packet_request(devc->serial)) < 0) {
sr_err("Failed to request packet: %d.", ret);
return FALSE;
}
@ -163,7 +158,7 @@ SR_PRIV int brymen_dmm_receive_data(int fd, int revents, void *cb_data)
* @param serial Previously initialized serial port structure.
* @param buf Buffer containing the bytes to write.
* @param buflen Size of the buffer.
* @param packet_size Callback that assesses the size of the incoming packet/
* @param get_packet_size Callback that assesses the size of incoming packets.
* @param is_valid Callback that assesses whether the packet is valid or not.
* @param timeout_ms The timeout after which, if no packet is detected, to
* abort scanning.
@ -187,7 +182,7 @@ SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial,
maxlen = *buflen;
sr_dbg("Detecting packets on FD %d (timeout = %" PRIu64
"ms, baudrate = %d).", serial->fd, timeout_ms, baudrate);
"ms, baudrate = %d).", serial->fd, timeout_ms, baudrate);
/* Assume 8n1 transmission. That is 10 bits for every byte. */
byte_delay_us = 10 * (1000000 / baudrate);
@ -198,7 +193,7 @@ SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial,
len = serial_read(serial, &buf[ibuf], maxlen - ibuf);
if (len > 0) {
ibuf += len;
sr_spew("Read %d bytes", len);
sr_spew("Read %d bytes.", len);
}
time = g_get_monotonic_time() - start;
@ -211,10 +206,10 @@ SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial,
status = get_packet_size(&buf[i], &packet_len);
switch(status) {
case PACKET_HEADER_OK:
/* We know how much data we need to wait for */
/* We know how much data we need to wait for. */
break;
case PACKET_NEED_MORE_DATA:
/* We did not receive the full header */
/* We did not receive the full header. */
packet_len = 0;
break;
case PACKET_INVALID_HEADER:
@ -222,7 +217,7 @@ SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial,
/*
* We had enough data, but here was an error in
* parsing the header. Restart parsing from the
* next byte
* next byte.
*/
packet_len = 0;
i++;
@ -230,22 +225,24 @@ SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial,
}
}
if ( (stream_len >= packet_len) && (packet_len != 0) ) {
if ((stream_len >= packet_len) && (packet_len != 0)) {
/* We have at least a packet's worth of data. */
if (is_valid(&buf[i])) {
sr_spew("Found valid %d-byte packet after "
"%" PRIu64 "ms.", packet_len, time);
"%" PRIu64 "ms.", packet_len, time);
*buflen = ibuf;
return SR_OK;
} else {
sr_spew("Got %d bytes, but not a valid "
"packet.", packet_len);
"packet.", packet_len);
}
/* Not a valid packet. Continue searching. */
i++;
packet_len = 0;
}
if (time >= (int64_t)timeout_ms) {
/* Timeout */
sr_dbg("Detection timed out after %dms.", time);

View File

@ -21,6 +21,10 @@
#define LIBSIGROK_HARDWARE_BRYMEN_DMM_PROTOCOL_H
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <glib.h>
#include "libsigrok.h"
#include "libsigrok-internal.h"
@ -33,7 +37,6 @@
#define sr_warn(s, args...) sr_warn(DRIVER_LOG_DOMAIN s, ## args)
#define sr_err(s, args...) sr_err(DRIVER_LOG_DOMAIN s, ## args)
#define DMM_BUFSIZE 256
enum packet_len_status {
@ -68,10 +71,10 @@ struct dev_context {
};
/**
* Callback that assesses the size and status of the incoming packet
* Callback that assesses the size and status of the incoming packet.
*
* @return PACKET_HEADER_OK - This is a proper packet header.
* PACKET_NEED_MORE_DATA The buffer does not contain the entire header
* PACKET_NEED_MORE_DATA The buffer does not contain the entire header.
* PACKET_INVALID_HEADER Not a valid start of packet.
*/
typedef int (*packet_length_t)(const uint8_t *buf, int *len);
@ -87,4 +90,5 @@ SR_PRIV int brymen_stream_detect(struct sr_serial_dev_inst *serial,
packet_length_t get_packet_size,
packet_valid_t is_valid,
uint64_t timeout_ms, int baudrate);
#endif

View File

@ -84,7 +84,7 @@ static struct sr_config_info sr_config_info_data[] = {
/** @cond PRIVATE */
#ifdef HAVE_HW_BRYMEN_DMM
extern SR_PRIV struct sr_dev_driver brymen_dmm_driver_info;
extern SR_PRIV struct sr_dev_driver brymen_bm857_driver_info;
#endif
#ifdef HAVE_HW_COLEAD_SLM
extern SR_PRIV struct sr_dev_driver colead_slm_driver_info;
@ -164,7 +164,7 @@ extern SR_PRIV struct sr_dev_driver voltcraft_vc820_driver_info;
static struct sr_dev_driver *drivers_list[] = {
#ifdef HAVE_HW_BRYMEN_DMM
&brymen_dmm_driver_info,
&brymen_bm857_driver_info,
#endif
#ifdef HAVE_HW_COLEAD_SLM
&colead_slm_driver_info,