* 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[] = {
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)
{
{
struct sr_dev_inst *sdi;
struct dev_context *devc;
+
if (!(sdi = inst))
return;
if (!(devc = sdi->priv))
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);
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)
drvc->instances = g_slist_append(drvc->instances, sdi);
devices = g_slist_append(devices, sdi);
-
scan_cleanup:
serial_close(serial);
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) {
/* 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");
}
(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;
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);
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,
/*
- * 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>
*
*/
#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 {
/*
* 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)
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;
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;
}
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];
}
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->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)
{
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;
-}
\ No newline at end of file
+}
* 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;
struct sr_datafeed_analog analog;
devc = sdi->priv;
-
+
analog.num_samples = 1;
analog.mq = -1;
/* 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;
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;
}
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;
}
* @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.
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);
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;
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:
/*
* 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++;
}
}
- 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);