#pragma once
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x0501
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <windowsx.h> // Makros
#include <shlwapi.h> // nützliche Funktionen
#include <commctrl.h>
#define _USE_MATH_DEFINES
#include <math.h>
/************
* Globales *
************/
#ifdef UNICODE
# define CF_TXT CF_UNICODETEXT
# ifndef _UNICODE
# define _UNICODE
# endif
#else
# define CF_TXT CF_TEXT
#endif
#include <stdio.h>
#include <tchar.h>
#define elemof(x) (sizeof(x)/sizeof((x)[0]))
#define T(x) TEXT(x)
#define nobreak
#ifdef WIN32
# define Send_WM_Command(ToWnd,CtlId,NotifyCode,FromWnd)\
SendMessage(ToWnd,WM_COMMAND,MAKELONG(CtlId,NotifyCode),(LPARAM)FromWnd);
#else // Win16
# define Send_WM_Command(ToWnd,CtlId,NotifyCode,FromWnd)\
SendMessage(ToWnd,WM_COMMAND,CtlId,MAKELONG((UINT)FromWnd,NotifyCode));
#endif
#ifdef _DEBUG
void _cdecl DebugPrintf(const char*,...);
# define _debug(x) DebugPrintf x
#else
# define _debug(x) {}
#endif
/*** PiezoMess.cpp ***/
extern HINSTANCE ghInstance;
extern HWND ghMainWnd;
struct RECTS{
short left,top,right,bottom;
void operator=(const RECT&r) {
left=(short)r.left;
top=(short)r.top;
right=(short)r.right;
bottom=(short)r.bottom;
}
void toRect(RECT&r) const{
r.left=left;
r.top=top;
r.right=right;
r.bottom=bottom;
}
};
extern struct CONFIG{
RECTS WndPos;
char ShowCmd;
BYTE SerialNo; // 0 = COM1 usw.
BYTE HidNo;
BYTE flags; // Bit 0 = COM oder HID
// Bit 7 = bRunningUpdate
BYTE GuiDelay; // Aktualisierungsintervall in ms
}Config;
struct Trace{
TCHAR const *name; // Text
TCHAR const *unit; // Einheit
COLORREF color;
BYTE penwidth,penstyle;
Trace(TCHAR const*n,TCHAR const*u,COLORREF c,BYTE w,BYTE s=PS_SOLID)
:name(n),unit(u),color(c),penwidth(w),penstyle(s) {}
};
extern const struct Divider{
COLORREF color;
BYTE penwidth,penstyle;
}divider[2];
extern const struct ScaleCfg{
TCHAR const *fontname;
BYTE fontsize;
}scalecfg;
extern TCHAR gCsvName[MAX_PATH];
extern TCHAR sDecimal[2]; // je nach Windows-Einstellung
#ifdef _M_IX86
__forceinline __int64 llrint(double f) {
__int64 i;
_asm fld f
_asm fistp i
return i;
}
#else
__forceinline __int64 llrint(double f) {return (__int64)floor(f+0.5);}
#endif
#define lrint(x) (int)llrint(x)
void _fastcall InitStruct(PVOID,UINT);
typedef const TCHAR*PCTSTR;
int _cdecl MBox(HWND,PCTSTR,DWORD,...);
enum{
MB_Sound = 0x00200000L, // Ton ausgeben
MB_ErrorText = 0x00400000L, // System-Fehlerbescheibung (1. DWORD-Argument) nach 1 Leerzeile anhängen
};
extern const union _uNaN{
__int64 ll;
double d;
float f;
}uNaN;
#define NaN uNaN.d
#define fNaN uNaN.f
int FloatToStringW(double f, int nk, PWSTR s, int slen);
int FloatToStringA(double f, int nk, PSTR s, int slen);
#ifdef UNICODE
#define FloatToString FloatToStringW
#else
#define FloatToString FloatToStringA
#endif
/*****************************
* Daten vom Mikrocontroller *
*****************************/
extern struct ADCMEAN{ // Gemittelte A/D-Werte (jeweils das 16-fache der 12-bit-A/D-Werte)
WORD hv; // Hochspannung, U = hv*118>>16 V
WORD ref; // Referenzspannung des AD8302, U = ref*2.5>>16 V, typ. 1,8 V → 47186 (0,72 @ 2,5V Uref des MSP430)
WORD temp; // Temperatur, T = temp*238>>16 - 85 °C
}adcmean;
extern struct FEATURE{
short g; // Verstärkung
short o; // Offset
long fu; // „Untere“ Wobbel-Frequenz (2^28 = 66 MHz), f = {fu|fo|fs}*66666666>>28 Hz
long fa; // Addierwert
long fm; // Multiplizierwert: f += fa + f*fm>>16
WORD steps; // Anzahl Wobbel-Schritte (>=10!)
WORD hv; // Sollspannung (Hochspannungsgenerator), U = hv*118>>16 V
float GetFu();
float GetFo();
float GetT();
bool IsLog();
float GetHV();
void SetFu(float v);
void SetFo(float v);
void SetT(float v);
void SetLog(bool l);
void SetHV(float v);
void SetSteps(int v);
}feature;
#define SCALEWIDTH 50
#define FSCALE 0.248352684F // 66.666666>>28 * 1000, Frequenz in Hz
#define TSAMPLE 303E-6F // 1/Datenliefer-Rate in der Firmware, in s: 3,3 kSa/s
#define HVSCALE 0.0018F // Hochspannung in V
#define REFSCALE 3876E-7F // Referenzspannung in V
#define TEMPSCALE 363E-5F-85 // Temperatur in °C (ohne Klammer für Offset!!)
/**************************
* Gemeinsame GDI-Handles *
**************************/
struct myRECT:RECT{
inline int midx() const {return (left+right)>>1;}
inline int midy() const {return (top+bottom)>>1;}
inline int width() const {return right-left;}
inline int height() const {return bottom-top;}
};
extern struct GDI{ // Gemeinsam genutzte GDI-Objekte
HFONT fntBig;
HFONT fntScale[4]; // Schrift horizontal und vertikal, normal und fett
HPEN penGraph[2]; // zwei Graphen dick, zwei dünn
HPEN penDivider[2]; // Hilfslinien
HBITMAP bmpBack; // Doppelpufferungs-Bitmap (nur Graf, ohne Skalen)
void init();
void done();
}gdi;
/*** HardwareDlg.cpp ***/
INT_PTR CALLBACK HardwareDlgProc(HWND,UINT,WPARAM,LPARAM);
/*** SweepDlg.cpp ***/
extern struct UNIT{
int Pre; // Dezimalstellen, "k" = 3
float Mul; // Multiplikator, "k" = 1000
TCHAR Chr[4]; // Einheitenvorsatz-String
TCHAR Name[8]; // "Hz"
TCHAR Text[8]; // Gesamter aktueller Einheitentext ("kHz")
DWORD Typ; // HID-Einheitentyp
void Init(int p=0, PCTSTR n=0); // Ãœbergabe: Dezimalstellen, Name
}FreqUnit;
enum{
WM_ContinueInit = WM_USER+0x100,
WM_Update,
WM_UpdateFeature,
WM_ChangeFeature,
WM_ChangeUnit,
WM_ComFail,
};
INT_PTR CALLBACK SweepDlgProc(HWND,UINT,WPARAM,LPARAM);
extern HWND hSweepDlg;
/*** SaveTsv.cpp ***/
void SaveCSV();
/*** Axis.cpp ***/
/*******************
* Diagramm-Achsen *
*******************/
struct AXIS{
double a,e; // Anfangs- und Endwert
double tick; // große Striche
bool log; // Logarithmische Darstellung?
bool vert; // Vertikale Achse?
bool mirror; // rechts- oder linksseitige Ticks?
myRECT bbox; // Darstellungsgrenzen (bei WM_SIZE nachführen!)
int nk; // Nachkommastellen (oder besser: Formatbezeichner für Zahlenausgabe??)
// void Draw(HDC) const; // TODO: Hervorhebung Nulllinie, Verteilung der Zahlen
double FromNative(double) const; // skaliert einen Wert 0..1 auf a..e
double ToNative(double) const; // skaliert einen Wert a..e auf 0..1
bool okay() const; // Kein NaN bei a, e, tick; e>a bei tick>0
bool beyond(double) const;
double begin() const;
double next(double) const;
void AutoCalcTicks();
};
struct XAXIS:AXIS {
TCHAR const *name; // Text
TCHAR const *unit; // Einheit
void Draw(HDC) const;
};
struct YAXIS:AXIS {
Trace *trace;
void Draw(HDC) const;
};
/*** Sweep.cpp ***/
struct SDATA{ // So kommen die Daten von der seriellen Schnittstelle
char ap[3];
inline unsigned short amp() const {return *(unsigned short*)ap&0xFFF;} // Amplitudenwert
inline unsigned short pha() const {return *(unsigned short*)(ap+1)>>4;} // Phasenwert, 0 = ±90°
};
extern struct SWEEP{ // Irreführender Name: Diagramm!
int width; // Anzahl erwarteter Samples
int nsamp; // Anzahl eingelesener Messwerte (von fstart gerechnet)
myRECT bbox; // nur für das Diagramm
HANDLE hMutex;
XAXIS x;
YAXIS amp,pha;
void Draw(HDC dc, bool all=true) const;
void Resize(int cx, int cy);
void Resize(LPARAM lP) {Resize(GET_X_LPARAM(lP),GET_Y_LPARAM(lP));};
void ChangeScale();
void GenXPositions(const RECT*rcBack, POINT*pt) const;
void GenYPositions(const RECT*rcBack, POINT*pt, const SDATA *data, bool pha=false) const;
SDATA *data, **backup;
int nbackup; // Anzahl Backups im <backup>-Vektor
int writtento; // letztes beschriebens Sample von data
}sweep;
#if 0
union IF4{
long i;
float f;
};
struct SINFO{ // Sample-Info, ähnlich HIDP_???
IF4 minLog, maxLog;
IF4 minPhys, maxPhys;
char unitExp;
long unitCode;
WORD bitOffset; // 0..65535, typ. einige Bits
BYTE bitLen; // 1..32
WORD strucLen; // max. 8 KByte, typ. einige Byte
long GetI4(const void*data, int i) {
const BYTE*p=(const BYTE*)data;
p+=i*strucLen+(bitOffset>>3);
long r;
memcpy(&r,p,(bitLen+(bitOffset&7)+7)>>3);
char w=32-bitLen;
r<<=w-(bitOffset&7); // SLL: Barrel-Shift MSB-bündig
if (minLog.i<0) {
r>>=w; // SRA (vorzeichenbehaftet)
}else{
*(unsigned long*)&r>>=w; // SRL (vorzeichenlos)
}
return r;
}
};
#endif
/*** Worker.cpp ***/
extern struct WORKER{
void start(HWND);
void stop();
void post(BYTE c, void*data, int dlen);
// bool okay() {return hCom!=0;}
protected:
HANDLE hCom;
HANDLE hThread;
OVERLAPPED o; // <hCancel> MUSS sich direkt nach <o> befinden!!
HANDLE hCancel; // Thread soll beendet werden
DWORD ThreadId;
HWND InfoWnd;
// static const int timeout_ms=80;
void ThreadProc();
static DWORD CALLBACK ThreadProc(PVOID p) {((WORKER*)p)->ThreadProc(); return 0;}
void OpenCom();
void clear();
int wait();
int send(const void*buf, int buflen); // Synchrones Datensenden
int recv(void*buf, int buflen); // Synchroner Datenempfang
int GetData(char command, void*buf, int buflen);
int SetData(char command, const void*buf, int buflen);
}w;
Detected encoding: UTF-8 | 0
|