#pragma once
/*======================================================================*
* Data structures of ELCONTROL VIP System 3 / VIP MK3 Energy Analyzer *
* Added useful generic routines and necessary constant data *
* heha, 100811 *
* This is a C++ header file, not intended to be used with C *
*======================================================================*/
#include <windows.h> // definitions of BYTE, etc
struct HEXBYTE{
char d[2]; // two hexadecimal digits ('0'..'9', 'A'..'F'), LSD first!
};
// The "string" record, here for maximum data length
// This is very similar to an INTEL HEX record
struct STRING{
union{
char summed[39]; // 7 to 39 bytes, always odd length
struct{
char colon; // always ':'
HEXBYTE len; // the length of <summed>(?)
HEXBYTE addr[2]; // LSB first, sequence number, zero-based, EOF=0x1000 *)
HEXBYTE data[16]; // 0 to 16 data bytes
}; // Following struct members cannot be used directly!
};
char check; // one hexadecimal digit over <summed>, then HIGH and LOW nibble XORed
char cr; // always '\r'
char lf; // always '\n'
}; // sizeof() must be 42
// *) For memory pack transfers, addr is the byte address >>4.
enum{
wrong_hex=-1, // Wrong hexadecimal numbers (not [0-9A-F]) detected at string_decode(), NO small letters allowed!
wrong_length=-2, // Wrong length detected at string_decode(), wrong length given at string_encode() (must be 0..16)
wrong_header=-3, // Wrong header (not ':', or the two length characters) detected at string_decode()
wrong_footer=-4, // Wrong footer (not CR LF) detected at string_decode()
wrong_check=-5, // Wrong checksum detected at string_decode()
buffer_too_small=-6, // 1. The string_encode() target buffer must have enough room for data
// 2. The target buffer is too small while recording recordsizes
wrong_recordsize=-7, // record size received doesn't match to <delim> array given
cannot_record=-8, // delim buffer too small
no_buffer=-9, // no buffer allocated
incomplete=-10, // when buffer must be sent/received completely
wrong_echo=-14, // transmission error while canceling an (elsewhere correct) transmission due to a short receive buffer condition
unmatched_recordsize=-15, // wrong record size detected while receiving string records
sendrecv_errors=-256, // error codes are shifted below this value (i.e. 256 is subtracted)
};
// Two functions for conversion from/to raw data
// <dl> is the "destination length", in bytes or characters.
// The return value is the number of bytes/characters written, or a negative error value.
int string_encode(const void*s, int l, int a, char*d, int dl=42);
int string_decode(const char*s, int l, int*a, void*d, int dl=16);
// Two functions for processing longer STRING messages, with blocking sendrecv()
// sendrecv() must block until '\n' is received.
// sendrecv() should notify the waiting user for progress,
// because transferring can be time-consuming (some seconds).
int string_send(const void*s, int l, int(*sendrecv)(const char*,int,char*,int), const BYTE*delim=NULL, int a=0);
// <delim> says how to split the data given by <s>. If NULL, maximum sizes (16) are assumed.
// <a> holds the first block number or the high 16 bits of the first row address of a memory expansion module.
// The address is auto-incremented by 1 for each record.
// This enables memory transfers of up to 1 MByte, as designed by ELCONTROL.
// An EOF record is appended and sent automatically.
// The return value should be equal <l> but may be less if <delim> array is zero-terminated earlier.
int string_recv(void*d, int l, int(*sendrecv)(const char*,int,char*,int), BYTE*delim=NULL, int dl=0, int a=0);
// This function reads STRING records until it receives an EOF record, or the <d> buffer (byte size <l>) is full.
// In the latter case, an Abort (ESC A CR LF) is sent.
// The EOF record has zero data length, the EOF address (0x1000) is not checked.
// <delim> saves the received record sizes, its buffer size is given with <dl>
// If <dl> is zero and <delim> not NULL, this function /checks/ the received block sizes against <delim> array given
// (cast the const pointer, no write access is made)
// If <delim> is NULL, no checking or recording is done, <dl> should be 0.
// Both functions return negative error codes from <send>,<recv>,<string_encode>,<string_decode>,
// and failing delim-array match
// <a> is expected as first address.
/****************************************************************
* Definition of record sizes (<delim>), needed for encoding *
* (and for checking while receiving) STRING records *
****************************************************************/
extern const BYTE RecordListP[]; // ESC P (programming data) "packed" record sizes
extern const BYTE RecordList0[]; // ESC M (all measures) - but without tariff band tails
extern const BYTE RecordListT[]; // One tariff tail, and for ESC m<10> to ESC m<14>
extern const BYTE RecordList6[]; // ESC m6
extern const BYTE RecordList9[]; // ESC m9
extern const BYTE RecordListD[]; // ESC D
// Two helper functions
// 1. To check how many records must be read beyond a specific data byte offset
// Returns 0 on error (offset too large)
// All predefined record lists define less than 256 records, so you can cast the result to BYTE safely.
int offsettorecord(const BYTE*delim, int offset);
// 2. How often <sendrecv> is called for this list, to draw a meaningful progress bar.
// The EOF record and the initial "ESC?\r\n" are not counted, so add 2 for an exact progress.
int numberofrecords(const BYTE*delim);
/****************************************************************
* Definition of serial transferred data structures *
* AFTER decoding vs. BEFORE encoding into STRING records *
****************************************************************/
#pragma pack(1)
// The <short> data are only valid if:
// * the machine has little-endian architecture (otherwise, swap bytes)
// * the machine supports unaligned data access (otherwise, re-define the following 2 structs)
// The current targets are "x86" and "amd64", where these assumptions are true.
struct VAL2{
short w; // mantissa with fixed exponent (always a fixed-point number in the form "x.xxx" or "xx.xx")
double toFloat(char e) const;
};
struct VAL3{
short w; // mantissa (documentation says nothing about sign, but I've never seen integers larger than 9999)
char e; // exponent of base 10 (decimal point position and/or unit prefix)
double toFloat() const;
};
struct VAL9{
char b[9]; // ASCII data (maybe left-justified with zeroes) - but the manual says "packed BCD"
};
// Answer for all measurement values request (ESC M)
struct STRING_ESCM{
VAL2 f; // frequency * 10^-2
VAL3 i[4]; // instanteous currents (RMS - Effektivwert), sum - Stromsumme
VAL3 in; // neutral wire - Nullleiter
VAL3 u[4]; // instanteous voltages, mean value of u1..u3
VAL3 u12; // delta connection voltages - Spannungen der Dreieckschaltung
VAL2 u23; // common exponent with u12
VAL2 u31;
VAL3 p[4]; // active power - Wirkleistung
VAL3 pa[4]; // average active power - Gemittelte Wirkleistung
VAL3 s[4]; // apparent power - Scheinleistung
VAL3 sa[4]; // average apparent power - Gemittelte Scheinleistung
VAL3 q[4]; // reactive power - Blindleistung
VAL3 qa[4]; // average reactive power - Gemittelte Blindleistung
VAL2 d[4]; // harmonic distortion - Klirrfaktor * 10^-2 %
VAL2 da[4]; // average harmonic distortion - Klirrfaktor-Mittel * 10^-2 %
VAL2 c[4]; // power factor - Leistungsfaktor (cos phi) * 10^-3
VAL2 ca[4]; // average power factor - Leistungsfaktor-Mittel (cos phi) * 10^-3
VAL3 ta[4]; // average tan phi
VAL9 w1; // Phase 1 active energy consumption
VAL9 y1; // Phase 1 reactive energy "consumption"
VAL9 w2;
VAL9 y2;
VAL9 w3;
VAL9 y3;
VAL9 ws;
VAL9 ys; // packed BCD msb,lsb (ganze kWh? Wäre 18-stellig)
BYTE aux[6];
VAL3 pp[4]; // Maximum active power - Spitzen-Wirkleistung
VAL3 sp[4]; // Maximum apparent power - Spitzen-Scheinleistung
VAL3 qp[4]; // Maximum reactive power - Spitzen-Blindleistung
VAL2 dp[4]; // Maximum harmonic distortion - Spitzen-Klirrfaktor * 10^-2 %
}; // sizeof() should be 274!
// this is appended to STRING_ESCM for each tariff band set
struct STRING_ESC10{
VAL3 ca[4]; // average power factors
VAL3 ta[4]; // average tan phi
VAL9 w1,y1,w2,y2,w3,y3,ws,ys; // format ASCII msb,lsb (oder doch BCD?)
};
// Answer for ESC M 1 (?)
struct STRING_ESCM1{
VAL3 u,i,p; // Instanteous voltage, current, power (sum)
VAL2 c;
};
// Answer for ESC 5
struct STRING_ESC5{
VAL3 u12;
VAL2 u23;
VAL2 u31;
VAL3 in;
VAL2 f;
};
// Answer for ESC 6
struct STRING_ESC6{
VAL3 p[4]; // Instanteous powers (1-2-3-S)
VAL3 pa[4]; // Average powers
VAL3 pp[4]; // Peak powers
};
// Answer for ESC 9
struct STRING_ESC9{
VAL2 d[4];
VAL2 da[4];
VAL2 dp[4];
};
// Answer for ESC 15
struct STRING_ESC15{
VAL3 aux[2];
};
enum MODO{
F_3W, // instead of 4W
F_MediumVoltage, // instead of Low Voltage (max. 1000 V)
F_ClampMeterInversion,
F_BlackBox,
F_BB_with_secondary_program,
F_LMA, // otherwise, Pyrometer
F_Calibration
};
struct STRING_ESCP{
BYTE modo; // bits of MODO enum
BYTE colleg[2]; // 4 Wire -> 03,8A, 3 Wire -> 03,DE
BYTE t_tens[2]; // Low Voltage -> 04,8A, Medium Voltage -> 04,DE
BYTE ka[6]; // current full scale, ASCII msb,lsb
BYTE ku[6]; // voltage vull scale, ASCII msb,lsb
BYTE cos0[4]; // cos phi set, ASCII msb,lsb
BYTE t_integ[2]; // integration time, ASCII msb,lsb (minutes?)
BYTE t_stampa[2]; // print time, ASCII msb,lsb (minutes?)
BYTE t_p_all[2]; // alarm print time, ASCII msb,lsb (minutes?)
BYTE day[2];
BYTE month[2];
BYTE year[2];
BYTE hour[2];
BYTE minutes[2];
BYTE seconds[2]; // clock set-up, ASCII msb,lsb (minutes?)
BYTE lingua; // 0=it, 1=en, 2=de, 3=fr
BYTE layer[2]; // it->00,82, en->01,95, de->02,AC, fr->03,BF
// Local printer programming group
struct PR{
BYTE n_posiz; // positions occupied(?) 00/04
BYTE n_contat; // meters selected 00/02
BYTE n_grand; // other parameters selected 00/04
BYTE layer[8]; // pointer for display of the 4 parameters selected
BYTE strada[54]; // pointer for display of path of reverses for parameter select (??)
BYTE strad0; // bit 0: 1 -> at least 1 parameter selected
BYTE memori[8]; // parameter selection buffer
}pr;
// Plotter 1+2 programming data group
struct PL{
BYTE n_posiz; // positions occupied
BYTE layer[2];
BYTE strada[42];
BYTE strad0;
BYTE fifo[2];
BYTE range;
BYTE tcamp[2]; // sampling time (format ASCII)
BYTE bufexp[8]; // exponent of every parameter available
BYTE wplott[82]; // plotter range in manual selection
}pl[2];
// Remote printer programming data group
struct RPR{
BYTE n_posiz; // positions occupied 00/0D
BYTE layer[26];
BYTE strada[54];
BYTE strad0; // bit 5,6: 1,1 -> at least 1 parameter for remote print-out
BYTE driver[26]; // parameter selection buffer
BYTE n_ar_est[3]; // Number of spaced characters (format ASCII) e.g. "80"
BYTE n_car_com[3]; // Number of condensed characters e.g. "132"
BYTE seq_comp[8]; // Sequence for Compressed Font ON (17 cpi)
BYTE seq_decom[8]; // Sequence for Compressed Font OFF (10 cpi)
BYTE on_sott[8]; // Sequence for Underlining ON (e.g. ESC U 1)
BYTE off_sott[8]; // Sequence for Underlining ONF (e.g. ESC U 0)
}rpr;
// Relay 1+2 programming data group
struct REL{
BYTE n_posiz; // positions occupied 00/01
BYTE layer[2];
BYTE strad0;
BYTE strad2;
BYTE strad3; // bit 0: minimum alarm, bit 1: maximum alarm
BYTE fifo[3];
BYTE strada[84];
}rel[2];
// Alarm programming group
struct AL{
BYTE layer_min[96]; // pointer for display of parameter selected for Minimum Alarms
BYTE layer_max[96]; // pointer for display of parameter selected for Maximum Alarms
BYTE layer_tar[96]; // pointer for display of parameter selected for Tariff Band Alarms
BYTE wall1[206];
BYTE wall2[206];
BYTE bufexp[30];
BYTE wall5[192];
BYTE tins[2]; // intensity time
}al;
// RESET code
BYTE wres[4]; // RESET code (format ASCII) = Password
BYTE fascie; // Flag of band programmed, bit 0 = band 1 etc. up to band 4
// Timed Alarms
BYTE wfunz[32];
};
struct STRING_ESCD{
struct SURVEY{
BYTE YY[2],MM[2],GG[2],HH[2],mm[2]; // start/end time, format ASCII
}survey[2];
BYTE EE;
BYTE BB[4];
BYTE mm; // rate, in minutes
BYTE modo; // see MODO enum
BYTE ka[3]; // current full scale
BYTE ku[3]; // voltage full scale
BYTE cc; // full-scale power factor, HEX
BYTE tt; // integration time, packed BCD
};
struct STRING_ESCL{
BYTE cadenza[2]; // sampling rate for manual survey (01/99), format ASCII msb,lsb
BYTE codice[4]; // code of manual survey (0000/9999), format ASCII msb,lsb
};
#pragma pack()
Detected encoding: ANSI (CP1252) | 4
|
|