Source file: /~heha/hs/UNI-T/dmm.zip/src/Fluke.cpp

#include "dmm.h"
#include <string.h>

/* This plugin assumes following presets: 
 *  Communication 9600 baud, no parity, 1 stopbit, no echo
 *  Trigger mode: auto or some external trigger > 0,3 Hz
 *  No decibel mode, no minmax mode
 * The plugin cannot distinct between Continuity Test
 *  vs. Diode Test from Ohmmeter vs. Voltage meter
 * Some combinations of readouts don't work,
 * for currently unknown reason.
 */

EXTERN_C void _cdecl _fltused(){};

struct Fluke_8808A:INDATA{
 void _stdcall Handler();
};

static char getunit(char c) {
 switch (c) {
  case 'V': return 1;		// VAC, VDC, VACDC
  case 'A': return 5;		// AAC, ADC, AACDC
  case 'O': return 2;		// OHMS
  case 'H': return 4;		// HZ
  default: return 0;		// unknown code
 }
}

void Fluke_8808A::Handler() {
 switch (msg) {
  case init:{
   rmax=64;
   counts=199999;
//   baud=9600;			// currently, default baudrate cannot be changed,
  }break;			// sorry for high-speed (100 Sa/s) data acquisition

  case open:{
   SendBytes("FORMAT 2\rVAL?\r",14);	// set verbose format (including unit) and query current display value
  }break;

  case data:{
   if (rlen<4) {ok=true; return;}
   char*p=(char*)rbuf;
   char*k=(char*)memchr(p,'\r',rlen);	// get end of string
   if (!k) {ok=true; return;}	// not enough characters received
   *k=0;
   READOUT ro[4];		// Accept up to 4 readouts
   ZeroMemory(ro,sizeof ro);
   DWORD flags=0;
   int i;
   for (i=0; k && i<elemof(ro); p=k+1,i++) {
    k=strchr(p,',');		// further value available?
    char *s;
    ro[i].value=strtod(p,&s);
    size_t l=s-p;
    while (*s==' ') s++;
    if (ro[i].unitcode=getunit(*s)) {	// Have valid unit?
     for(;;) {			// Scan for AC/DC suffixes
      switch (*++s) {
       case 'A': flags|=1<<F_AC; break;
       case 'D': flags|=1<<F_DC; break;
       default: goto breakloop;
      }
      ++s;			// skip 'C' character
     }
breakloop:
// Convert exponent value to unit prefix
     char*e=(char*)memchr(p,'E',l);
     if (e) {
      int ex=atoi(e+1);		// get exponent value (always multiple of 3?)
      if (!(ex%3)) {		// don't generate prefix if suddenly not multiple of 3
       ro[i].unitprefix=ex;	// set exponent (possibly 0)
       l=e-p;			// shorter digit string length
      }
     }
// TODO: Other flags require extra processing:
// F_AUTO: Querying "AUTO?"
// F_MIN, F_MAX, F_DIODE, F_CONT: how??
// Decibel ??
    }
    if (l>sizeof ro[i].digits-1) l=sizeof ro[i].digits-1;
    memcpy(ro[i].digits,p,l);	// copy digit string (with or without exponent)
    ro[i].digits[l]=0;
   }
   SetData(flags,ro,i);
   rlen=0;			// reset buffer
   ok=true;
  }goto meas;			// send next MEAS command which will return data after next trigger

  case tout:{			// after timeout (for some reason) repeat MEAS command
meas:
   SendBytes("MEAS?\r",6);
  }break;
 }
}

EXTERN_C bool /*_declspec(dllexport)*/ WINAPI EnumAll(int n, ENUMINFO* ei) {
 if (n) return false;
 strcpy(ei->ManufName,"Fluke");
 strcpy(ei->ModelName,"8808A");
 ei->IconIndex=2;	// desktop multimeter
 ei->ExtraAlloc=0;
 ei->pHandler=(void(_stdcall INDATA::*)())&Fluke_8808A::Handler;
 ei->lParam=0;
 return true;
}
Detected encoding: ASCII (7 bit)2