#pragma once
#include <windows.h>
#define nobreak
#define elemof(x) (sizeof(x)/sizeof(*(x)))
#define T(x) TEXT(x)
extern const __int64 _sNaN; // signaling NaN
#define NaN (*(double*)&_sNaN)
#ifdef DMM_EXPORTS
# define FUNC(type) EXTERN_C type _declspec(dllexport) WINAPI
#else
# define FUNC(type) EXTERN_C type _declspec(dllimport) WINAPI
#endif
#ifdef __cplusplus
# define DEF(x) =(x)
#else
# define DEF(x)
typedef enum{false,true} bool;
#endif
struct INDATA{
enum MMSG{null,conf,init,open,data,close,tout};
MMSG msg; // message code
bool ok; // return value
BYTE idx; // multi-purpose index (unused)
LPARAM lParam; // multi-purpose parameter
BYTE *rbuf; // received data
void (_stdcall INDATA::*pHandler)();
int rlen; // size, in bytes, of data received - must be set to 0 after processing!
int rmax; // hint how long is recvbuf (default:400)
int trto; // total read time-out in milliseconds (maximum distance between two packets, default: 3000)
int icto; // inter-character read time-out, in ms (to detect a packet end, default: 20)
// BUGBUG: Windows (COMM driver) cannot detect timeouts less than 50 ms safely!
// So it cannot be used for general packet-end detection.
int counts; // maximum display value, default: 1999
int baud; // baud rate for interface, default: 9600
};
struct ENUMINFO {
ENUMINFO *next; // internal use
char ManufName[32]; // UTF-8 - not used
char ModelName[32]; // UTF-8
int IconIndex; // which icon should be shown
int ExtraAlloc; // Data bytes appended to INDATA structure
void (_stdcall INDATA::*pHandler)(); // Procedure pointer
LPARAM lParam; // Initialization value for INDATA::lParam
};
// enumerator for built-in UNI-T instruments
bool _stdcall EnumUT(int n, ENUMINFO* ei);
/* For unified data transfer from plugins */
typedef enum{
// Range 1: Symbols contained in UniT-a2.ttf font and not in Unicode
F_LowBat, // Low battery symbol
F_Beep, // Symbol for continuity check
F_Diode, // Diode symbol for checking pn transitions
// Range 2: Symbols contained in UniT-a2.ttf font but alternatively in Unicode
F_Delta, // REL measurement (°C auto-changes to K)
F_Sigma, // Summation active (not seen)
F_Beta, // Transistor current amplification (not seen)
F_Hold, // Displayed value frozen (some multimeters send same data, some different, some nothing)
F_Auto, // Auto-Range mode
// Range 3: Symbols to paint by this software - until there is a .TTF with this symbols
F_hFE, // Same as F_Beta? (not seen)
F_EF, // Cable installation locator (not seen)
// Range 4: Text strings
F_Man, // DEPRECATED, opposite to F_Auto
F_Min, // Minimum value
F_Max, // Maximum value
// Range 5: Text strings, but may be handled separately (AC+DC or symbolic)
F_AC, // RMS (or True-RMS) measurement; without DC: capacitive coupling, with DC: direct coupling
F_DC, // Mean value measurement
// Range 6: New for UT233 (three-phase AC voltage meter + one-phase AC current clamp)
F_Phase1, // Phase 1 value
F_Phase2, // Phase 2 value
F_Phase3, // Phase 3 value
F_LeftRot, // left rotation
F_RightRot, // right (regular) rotation
F_cosphi, // cos-phi (power factor) display
F_phi, // phi display
NUMFEATURES
}EFEATURE;
// unitprefix: As power of 10
// Allowed values: -18,-15,-12,-9(=n),-6(=µ),-3(=m),-2,-1,0,2,3(=k),6(=M),9,12,15,18
// unitcode: internal unit (low-nibble)
// 0 = none (hFE for example), use <unit> member
// 1 = V
// 2 = Ohm
// 3 = F
// 4 = Hz
// 5 = A
// 6 = °C
// 7 = °F
// 8 = W
// 9 = %
//10 = S (Siemens)
//11 = H (Henry, not seen yet)
//12 = K (Kelvin, for temperature difference in °C)
//13 = min^-1 (revolutions per minute)
//14 = s (seconds, internally used for scope)
//15 = VA
//16 = var
//17 = Wh
//18 = VAh (not seen yet)
//19 = varh (not seen yet)
//20 = °
typedef struct{
double value; // The measured value, without "unitprefix", -INF for underflow, +INF for overflow, NaN for unknown
double min,max; // The possible minimum and maximum values for current range, both 0.0 when unknown
double ec,ev; // constant and variable error (positive meaning ±), 0.0 when unknown
char digits[13]; // with leading zeroes, decimal point and "error" letters as shown in multimeter display, ASCII
char coupling; // 1=DC, 2=AC (capacitive), 4=TrueRMS
char unitprefix; // the unit prefix shown, 0-based, as power of 10 (not 1000)
char unitcode; // the unit code for common units, perfectly handled ANSI conversion
char unit[8]; // the unit string for uncommon units, UTF-8
char desc[8]; // a short descriptive string for multi-readout meters, UTF-8
}READOUT;
typedef struct{
char n; // number of traces, i.e. following TRACEDATA structures, must be 1-4
char datasize; // number of bytes per sample (low-nibble), high bit set if unsigned and 80h
char grid_x, grid_y; // number of grid cells (div)
int tracelen; // trace data len, in samples (not bytes)
int fullscale; // this range of trace data value reaches from bottom to top of grid (UT81B: 128)
char timebase; // 0=1s, 1=2s, 2=5s; -1=500ms etc.
char autorange; // !=0 in auto range mode
char xymode; // X/Y mode (unspecified for != 2 traces)
char tsource; // trigger channel (low nibble), edge and mode (high nibble)
int tx,ty; // position of trigger, x=tx/tracelen, y=0.5+ty/fullscale
}SCOPEDATA;
typedef struct{ // follows SCOPEDATA
char devicode; // deviation coefficient in 1-2-5 steps, 0=1V, 1=2V, 2=5V; -1=500mV etc.
char autorange; // auto-range for deviation
char unitcode; // only built-in units supported
char unused; // alignment filler
int ofs; // vertical beam shift (may be horizontal in X/Y mode)
const void *data; // raw trace data, mostly <char> samples, -128..127, bytelength = (datasize&0x0F)*tracelen
}TRACEDATA; // Interleaved trace data (as known from sound cards) is not supported
#define MAXREADOUT 4
#define MAXTRACE 4
// After succesful decode of a packet, finally call this function with:
// * <features> = bit field of EFEATURE bits
// * <readout> = one or more available numerical readouts
// * <num> = number of available readouts, currently, 0-4 supported
// (different display arrangements for each count)
// * <scope> = oscilloscope data, NULL if not available
// This program has the option to display scope data without readouts,
// so it can act as (slow but resizeable) PC scope display without controls.
// With <num>=0 AND <scope>=NULL, unsuccessful decoding can be shown.
// In this case, <features> is a string resource ID (unspecified yet).
// However, it is recommended to do nothing on unsuccessful decode,
// DMM.EXE will handle this situation automatically.
// With <num>=0 and <features>=0, the icon flashes showing incoming data (erraneous packets)
FUNC(bool) SetData(DWORD features,
const READOUT*readout,
int num DEF(1),
const SCOPEDATA* scope DEF(NULL));
/****************************************************************************************
* The following functions are made to ease some common tasks generating <READOUT> data *
****************************************************************************************/
// scalebase: The unit for the smallest value
// 4 dig. 5 dig. prefix
// 0 = xxxx xxxx.x
// 3 = x.xxx x.xxxx p
// 4 = xx.xx xx.xxx p
// 5 = xxx.x xxx.xx p
// 6 = x.xxx x.xxxx n
// 7 = xx.xx xx.xxx n
// 8 = xxx.x xxx.xx n
// 9 = x.xxx x.xxxx µ
// A = xx.xx xx.xxx µ
// B = xxx.x xxx.xx µ
// C = x.xxx x.xxxx m
// D = xx.xx xx.xxx m
// E = xxx.x xxx.xx m
// F = x.xxx x.xxxx
// 10 = xx.xx xx.xxx
// 11 = xxx.x xxx.xx
// 12 = x.xxx x.xxxx k
// 13 = xx.xx xx.xxx k
// 14 = xxx.x xxx.xx k
// 15 = x.xxx x.xxxx M
// 16 = xx.xx xx.xxx M
// 17 = xxx.x xxx.xx M
// 18 = x.xxx x.xxxx G
// 19 = xx.xx xx.xxx G
// 1A = xxx.x xxx.xx G
// modifier (high 3 bits)
// 00= range has all prefixes
// 20= range has only one prefix
// 40= range has only two prefixes
// 60= range has only three prefixes
// 80= range starts with .xxxx instead of xxx.x and one unit prefix less, i.e.
// .xxxx .xxxxx m first
// x.xxx x.xxxx m second etc.
// Calculates the decimal point position and the right unit prefix.
// The "decimal point position" counts the digits _before_ decimal point.
// Needed for most of UNI-T multimeters.
FUNC(int) dp(char scalebase, char scaleadd, char*unitprefix);
// Collects bits, based by p, adresses in BitTable. NumBits=sizeof(BitTable)
// Does not invert bits while collecting.
// Skips bits marked with 0xFF (0377 octal) in BitTable.
// So this function works on datagrams shorter than 32 bytes, 16 WORDs or 8 DWORDs.
FUNC(DWORD) CollectBits(const void*p, const BYTE*BitTable, BYTE NumBits);
// Calculates minimum and maximum values out of unit, flags etc.
// This function clears the free-form ro->unit, so you must add this later if necessary.
FUNC(void) GenMinMax(READOUT *ro, DWORD features, int maxnumber, char expo);
FUNC(int) SendBytes(const void*, int);// sends data to serial or USB device
extern HINSTANCE ghInst;
double e10(char neg, int base, char expo);
void ptc(char*s);
char comma();
void GenLogUnit(LPSTR d, const READOUT*ro);
int DoubleToString(double v, int nk, LPTSTR buf, UINT buflen);
int _cdecl MBox(HWND Wnd, UINT id, UINT Type, ...);
#define CONFMAX 16 // Buffer sizes, in characters, for ConfName and descendants
extern HWND ghMainWnd;
extern DWORD gDdeInst;
extern TCHAR ConfName[CONFMAX];
extern TCHAR HelpName[];
struct DDECH{
PTSTR ServiceTopicItem;
bool Reconnect();
int QueryInfo(char*buf,int blen,UINT cp,UINT what);
int QueryValue(char*buf,int blen,UINT cp,UINT how);
~DDECH();
//private:
HCONV hConv;
HSZ hszItem;
TCHAR buf[32]; // gets the request string from asynchronous REQUEST transaction
};
#define ECOLMAX 8 // Maximum extra columns
#include <stdio.h>
extern struct LOG{
void OnOff(HWND Wnd, int sw); // sw=switch: 1=on, 2=off, 3=toggle
void Line(int col, const READOUT*ro, DWORD features, DWORD change);
HDDEDATA DdeCallback(UINT uType,UINT uFmt,HCONV hConv,HSZ hsz1,HSZ hsz2,HDDEDATA hData);
private:
FILE *f;
__int64 starttime; // start time, either system or (in case of recorded data) user given
double T; // accumulator used for equidistant time column
double Interval; // if nonzero: equal distance dictates sample rate, take last DMM value (TODO)
int curcol;
DWORD curfeatures;
BYTE flags; // Bit 0: UseTime, 1: UseHeader, 2: UseTimeCol, 3: UseDmmCol
BYTE nExtra; // Number of additional data channels
DWORD Waiters; // flag bits for current "asynchronous" DDE requests
HANDLE WaitEvt;
HWND hDlg; // child dialog of GetSaveFileName()
PCTSTR propose; // string list of DDE channels, NULL = use standard
DDECH*Extra[ECOLMAX]; // additional data channel list (array)
TCHAR fname[MAX_PATH];
static UINT_PTR CALLBACK OFNHookProc(HWND,UINT,WPARAM,LPARAM);
// static BOOL CALLBACK EnumWindowsProc(HWND,LPARAM);
void ManageCombos(HWND Wnd, int was, int now); // Create/delete combo boxes for extra columns
double GetDiff();
}gLog;
Detected encoding: UTF-8 | 0
|