X-Git-Url: https://sigrok.org/gitweb/?a=blobdiff_plain;f=hardware%2Ftekpower-dmm%2Fprotocol.c;h=87f83c15b5fb39606117c0010012d9320ad4272d;hb=f18297a5fd88f09a9e1a1330777f6db6dfe8999a;hp=a468cb9a417e56e638ed81fc8b4290f45d69b452;hpb=7dc55d930f87433fb35ebf6f18f767eddb7e8a17;p=libsigrok.git diff --git a/hardware/tekpower-dmm/protocol.c b/hardware/tekpower-dmm/protocol.c index a468cb9a..87f83c15 100644 --- a/hardware/tekpower-dmm/protocol.c +++ b/hardware/tekpower-dmm/protocol.c @@ -18,341 +18,91 @@ */ #include -#include "libsigrok.h" -#include "libsigrok-internal.h" -#include "config.h" -#include "protocol.h" #include #include #include #include +#include "libsigrok.h" +#include "libsigrok-internal.h" +#include "protocol.h" +/* User-defined FS9721_LP3 flag 'c2c1_10' means temperature on this DMM. */ +#define is_temperature info.is_c2c1_10 -static gboolean lcd14_is_sync_valid(const lcd14_packet *packet) -{ - size_t i; - /* Check the syncronization nibbles, and make sure they all match */ - for(i = 0; i < LCD14_PACKET_SIZE; i++) - { - uint8_t sync = (packet->raw[i] & LCD14_SYNC_MASK) >> 4; - if(sync != (i+1) ) - return FALSE; - } - return TRUE; -} - -static gboolean lcd14_is_selection_good(const lcd14_data *data) -{ - int n_postfix = 0; - int n_type = 0; - /* Does the packet have more than one multiplier ? */ - if(data->flags & LCD14_NANO) - n_postfix++; - if(data->flags & LCD14_MICRO) - n_postfix++; - if(data->flags & LCD14_MILLI) - n_postfix++; - if(data->flags & LCD14_KILO) - n_postfix++; - if(data->flags & LCD14_MEGA) - n_postfix++; - - if(n_postfix > 1) - return FALSE; - - /* Does the packet "measure" more than one type of value ?*/ - if(data->flags & LCD14_HZ) - n_type++; - if(data->flags & LCD14_OHM) - n_type++; - if(data->flags & LCD14_FARAD) - n_type++; - if(data->flags & LCD14_AMP) - n_type++; - if(data->flags & LCD14_VOLT) - n_type++; - if(data->flags & LCD14_DUTY) - n_type++; - if(data->flags & LCD14_CELSIUS) - n_type++; - /* Do not test for hFE. hFE is not implemented and always '1' */ - if(n_type > 1) - return FALSE; - - /* Both AC and DC ? */ - if( (data->flags & LCD14_AC) && (data->flags & LCD14_DC) ) - return FALSE; - - /* OK, no duplicates */ - return TRUE; -} - -/* We "cook" a raw lcd14_pcaket into a more pallatable form, lcd14_data */ -static void lcd14_cook_raw(const lcd14_packet *packet, lcd14_data * data) -{ - size_t i; - - /* Get the digits out */ - for(i = 0; i < 4; i++) - { - size_t j = (i << 1) + 1; - data->digit[i] = ( (packet->raw[j] & ~LCD14_SYNC_MASK) << 4 ) | - ( (packet->raw[j+1] & ~LCD14_SYNC_MASK) ); - } - - /* Now extract the flags */ - data->flags = ( (packet->raw[0] & ~LCD14_SYNC_MASK) << 20) | - ( (packet->raw[9] & ~LCD14_SYNC_MASK) << 16) | - ( (packet->raw[10]& ~LCD14_SYNC_MASK) << 12) | - ( (packet->raw[11]& ~LCD14_SYNC_MASK) << 8) | - ( (packet->raw[12]& ~LCD14_SYNC_MASK) << 4) | - ( (packet->raw[13]& ~LCD14_SYNC_MASK) ); -} - - -/* Since the DMM does not identify itslef in any way shape, or form, we really - * don't know for sure who is sending the data. We must use every possible - * check to filter out bad packets, especially since detection mechanism depends - * on how well we can filter out bad packets packets */ -SR_PRIV gboolean lcd14_is_packet_valid(const lcd14_packet *packet, - lcd14_data *data) -{ - /* Callers not interested in the data, pass NULL */ - lcd14_data placeholder; - if(data == NULL) - data = &placeholder; - /* We start with our syncronization nibbles, then move to more advanced - * checks */ - if(!lcd14_is_sync_valid(packet)) - return FALSE; - - lcd14_cook_raw(packet, data); - - if(!lcd14_is_selection_good(data)) - return FALSE; - - /* Made it here, huh? Then this looks to be a valid packet */ - return TRUE; -} - -static uint8_t lcd14_to_digit(uint8_t raw_digit) -{ - /* Take out the decimal point, so we can use a simple switch() */ - raw_digit &= ~LCD14_DP_MASK; - switch(raw_digit) - { - case 0x00: - case LCD14_LCD_0: - return 0; - case LCD14_LCD_1: - return 1; - case LCD14_LCD_2: - return 2; - case LCD14_LCD_3: - return 3; - case LCD14_LCD_4: - return 4; - case LCD14_LCD_5: - return 5; - case LCD14_LCD_6: - return 6; - case LCD14_LCD_7: - return 7; - case LCD14_LCD_8: - return 8; - case LCD14_LCD_9: - return 9; - default: - return LCD14_LCD_INVALID; - } -} - -static double lcdraw_to_double(lcd14_data *data) -{ - /* ********************************************************************* - * Get a raw floating point value from the data - **********************************************************************/ - double rawval; - double multiplier = 1; - uint8_t digit; - gboolean dp_reached = FALSE; - int i; - - /* We have 4 digits, and we start from the most significant */ - for(i = 0; i < 4; i++) - { - uint8_t raw_digit = data->digit[i]; - digit = lcd14_to_digit(raw_digit); - if(digit == LCD14_LCD_INVALID) { - rawval = NAN; - break; - } - /* Digit 1 does not have a decimal point. Instead, the decimal - * point is used to indicate MAX, so we must avoid testing it */ - if( (i > 0) && (raw_digit & LCD14_DP_MASK) ) - dp_reached = TRUE; - if(dp_reached) multiplier /= 10; - rawval = rawval * 10 + digit; - } - rawval *= multiplier; - if(data->digit[0] & LCD14_D0_NEG) - rawval *= -1; - - /* See if we need to multiply our raw value by anything */ - if(data->flags & LCD14_NANO) { - rawval *= 1E-9; - } else if(data->flags & LCD14_MICRO) { - rawval *= 1E-6; - } else if(data->flags & LCD14_MILLI) { - rawval *= 1E-3; - } else if(data->flags & LCD14_KILO) { - rawval *= 1E3; - } else if(data->flags & LCD14_MEGA) { - rawval *= 1E6; - } - - return rawval; -} - -static void lcd14_handle_packet(lcd14_data *data, struct dev_context *devc) +/* Now see what the value means, and pass that on. */ +static void fs9721_serial_handle_packet(const uint8_t *buf, + struct dev_context *devc) { - double rawval = lcdraw_to_double(data); - /* ********************************************************************* - * Now see what the value means, and pass that on - **********************************************************************/ + float floatval; struct sr_datafeed_packet packet; struct sr_datafeed_analog *analog; + struct fs9721_info info; - if( !(analog = g_try_malloc0(sizeof(struct sr_datafeed_analog))) ) { - sr_err("failed to malloc packet"); + if (!(analog = g_try_malloc0(sizeof(struct sr_datafeed_analog)))) { + sr_err("Analog packet malloc failed."); return; } - analog->num_samples = 1; - if( !(analog->data = g_try_malloc(sizeof(float))) ) { - sr_err("failed to malloc data"); + + if (!(analog->data = g_try_malloc(sizeof(float)))) { + sr_err("Analog value malloc failed."); g_free(analog); return; } - *analog->data = (float)rawval; + + analog->num_samples = 1; analog->mq = -1; - /* What does the data mean ? */ - if(data->flags & LCD14_VOLT) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - if(data->flags & LCD14_AC) - analog->mqflags |= SR_MQFLAG_AC; - else - analog->mqflags |= SR_MQFLAG_DC; - } - else if(data->flags & LCD14_AMP) { - analog->mq = SR_MQ_CURRENT; - analog->unit = SR_UNIT_AMPERE; - if(data->flags & LCD14_AC) - analog->mqflags |= SR_MQFLAG_AC; - else - analog->mqflags |= SR_MQFLAG_DC; - } - else if(data->flags & LCD14_OHM) { - if(data->flags & LCD14_BEEP) - analog->mq = SR_MQ_CONTINUITY; - else - analog->mq = SR_MQ_RESISTANCE; - if(!isnan(rawval) ) - analog->unit = SR_UNIT_OHM; - else { - analog->unit = SR_UNIT_BOOLEAN; - *analog->data = FALSE; - } - } - else if(data->flags & LCD14_FARAD) { - analog->mq = SR_MQ_CAPACITANCE; - analog->unit = SR_UNIT_FARAD; - } - else if(data->flags & LCD14_CELSIUS) { + sr_fs9721_parse(buf, &floatval, analog, &info); + *analog->data = floatval; + + if (is_temperature) { analog->mq = SR_MQ_TEMPERATURE; - /* No Kelvin or Fahrenheit from the deive, just Celsius */ + /* No Kelvin or Fahrenheit from the device, just Celsius. */ analog->unit = SR_UNIT_CELSIUS; } - else if(data->flags & LCD14_HZ) { - analog->mq = SR_MQ_FREQUENCY; - analog->unit = SR_UNIT_HERTZ; - } - else if(data->flags & LCD14_DUTY) { - analog->mq = SR_MQ_DUTY_CYCLE; - analog->unit = SR_UNIT_PERCENTAGE; - } - else if(data->flags & LCD14_HFE) { - analog->mq = SR_MQ_GAIN; - analog->unit = SR_UNIT_UNITLESS; - } - else if(data->flags & LCD14_DIODE) { - analog->mq = SR_MQ_VOLTAGE; - analog->unit = SR_UNIT_VOLT; - analog->mqflags |= SR_MQFLAG_DIODE | SR_MQFLAG_DC; - } - else { - sr_warn("unable to identify measurement mode"); - } - - /* What other flags are associated with the data? */ - if(data->flags & LCD14_HOLD) { - analog->mqflags |= SR_MQFLAG_HOLD; - } - if(data->flags & LCD14_AUTO) { - analog->mqflags |= SR_MQFLAG_AUTORANGE; - } - if(data->flags & LCD14_REL) { - analog->mqflags |= SR_MQFLAG_RELATIVE; - } if (analog->mq != -1) { /* Got a measurement. */ - sr_spew("val %f", rawval); packet.type = SR_DF_ANALOG; packet.payload = analog; sr_session_send(devc->cb_data, &packet); devc->num_samples++; } + g_free(analog->data); g_free(analog); } static void handle_new_data(struct dev_context *devc, int fd) { - int len; - size_t i; - size_t offset = 0; - /* Try to get as much data as the buffer can hold */ + int len, i, offset = 0; + + /* Try to get as much data as the buffer can hold. */ len = DMM_BUFSIZE - devc->buflen; len = serial_read(fd, devc->buf + devc->buflen, len); if (len < 1) { - sr_err("serial port read error!"); + sr_err("Serial port read error: %d.", len); return; } devc->buflen += len; - /* Now look for packets in that data */ - while((devc->buflen - offset) >= LCD14_PACKET_SIZE) - { - lcd14_packet * packet = (void *)(devc->buf + offset); - lcd14_data data; - if( lcd14_is_packet_valid(packet, &data) ) - { - lcd14_handle_packet(&data, devc); - offset += LCD14_PACKET_SIZE; + /* Now look for packets in that data. */ + while ((devc->buflen - offset) >= FS9721_PACKET_SIZE) { + if (sr_fs9721_packet_valid(devc->buf + offset)) { + fs9721_serial_handle_packet(devc->buf + offset, devc); + offset += FS9721_PACKET_SIZE; } else { offset++; } } - /* If we have any data left, move it to the beginning of our buffer */ - for(i = 0; i < devc->buflen - offset; i++) + /* If we have any data left, move it to the beginning of our buffer. */ + for (i = 0; i < devc->buflen - offset; i++) devc->buf[i] = devc->buf[offset + i]; devc->buflen -= offset; } -SR_PRIV int lcd14_receive_data(int fd, int revents, void *cb_data) +SR_PRIV int tekpower_dmm_receive_data(int fd, int revents, void *cb_data) { const struct sr_dev_inst *sdi; struct dev_context *devc; @@ -363,8 +113,7 @@ SR_PRIV int lcd14_receive_data(int fd, int revents, void *cb_data) if (!(devc = sdi->priv)) return TRUE; - if (revents == G_IO_IN) - { + if (revents == G_IO_IN) { /* Serial data arrived. */ handle_new_data(devc, fd); }