//----------------------------------------------------------------------------
// Created By : A. Hülsmann
// Created Date: 24.07.2023
// Copyright: Ondosense GmbH 2023
// ---------------------------------------------------------------------------
/*/
Simple example scripts to connect an Ondosense sensor via a serial port (COMx) and to retrieve IQ data.
/*/
// ---------------------------------------------------------------------------
// Copyright (c) 2023 OndoSense GmbH
/*
import time
import ondopython.os_sensor as os_sensor
import ondopython.interfaces_python as ip
import os
from scipy.signal import ZoomFFT
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import datetime as dt
fig, axs = plt.subplots(2,1, layout='constrained')
//axs = plt.plot()
import json
import numpy as np
from scipy.signal import blackman // Blackman is as good as best windowing function (Scherr)
from scipy.signal import hann
from scipy.signal import blackmanharris
import serial.tools.list_ports
com_ports = [comport.device for comport in serial.tools.list_ports.comports()]
print(com_ports)
*/
#include "plotxy/cplotxy.h"
#include "main.h"
#include <windowsx.h>
#include <stdio.h>
#include <tchar.h>
HWND ghMainWnd;
static void _stdcall outLog(const TCHAR*s) {
HWND hEdit=GetDlgItem(ghMainWnd,105);
DWORD selStart,selEnd;
SendMessage(hEdit,EM_GETSEL,(WPARAM)&selStart,(LPARAM)&selEnd);
Edit_SetSel(hEdit,-1,-1);
Edit_ReplaceSel(hEdit,s);
if (selStart==selEnd) Edit_ScrollCaret(hEdit); // nichts markiert: Ans Ende scrollen
else Edit_SetSel(hEdit,selStart,selEnd); // Markierung wiederherstellen
}
void _cdecl print(const char*fmt,...) { // ins Logfenster
va_list va;
va_start(va,fmt);
vcbprint(outLog,fmt,va);
va_end(va);
}
//static PlotXY*gPlot1,*gPlot2;
TCHAR MBoxTitle[64];
enum{
MB_SOUND = 1<<23
};
ComSel comsel;
/* Meldungsfenster */
int _cdecl vMBox(UINT string_id, UINT uType, va_list va) {
TCHAR s[256],t[256];
LoadString(0,string_id,t,elemof(t));
_vsntprintf(s,elemof(s),t,va);
if (uType&MB_SOUND) MessageBeep(uType&MB_TYPEMASK);
return MessageBox(ghMainWnd,s,MBoxTitle,uType&~MB_SOUND);
}
int _cdecl MBox(UINT string_id, UINT uType,...) {
va_list va;
va_start(va,uType);
int ret=vMBox(string_id,uType,va);
va_end(va);
return ret;
}
static void startThread() {
SetDlgItemText(ghMainWnd,105,0); // Log löschen
gEndThread = false;
ghThread = CreateThread(0,0,worker::ThreadProc,0,0,&gThreadId);
SetDlgItemText(ghMainWnd,10,TEXT("&Stop"));
}
static void endThread() {
if (ghThread && WaitForSingleObject(ghThread,0)) { // Noch nicht aufgeräumt
gEndThread=true; // Info an thread-interne Schleife via volatile-Variable
EnableWindow(GetDlgItem(ghMainWnd,10),FALSE);
SetTimer(ghMainWnd,21,1000,0);
}
}
static void onEndThread() {
KillTimer(ghMainWnd,21);
HWND hButton = GetDlgItem(ghMainWnd,10);
EnableWindow(hButton,TRUE);
SetWindowText(hButton,TEXT("&Start"));
DWORD exitcode;
GetExitCodeThread(ghThread,&exitcode);
print("Thread mit Exitkode %u beendet",exitcode);
CloseHandle(ghThread);
ghThread=0;
}
static void killThread() {
if (!ghThread) return;
gEndThread=true; // allerletzte Chance
if (WaitForSingleObject(ghThread,100) // liefert 0 wenn Thread beendet
&& TerminateThread(ghThread,99)) // töten
print("Unkooperativer Thread getötet!");
onEndThread();
}
POINT MinSize,WinSize;
HINSTANCE ghInstance;
static INT_PTR CALLBACK MainDlgProc(HWND Wnd,UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
case WM_INITDIALOG: { // So groß wie das Fenster in der Ressource definiert ist wird die minimale Größe angenommen
ghMainWnd=Wnd;
GetWindowText(Wnd,MBoxTitle,elemof(MBoxTitle));
HICON icon=LoadIcon(ghInstance,MAKEINTRESOURCE(1));
SetClassLongPtr(Wnd,GCLP_HICON,LPARAM(icon));
SetClassLongPtr(Wnd,GCLP_HICONSM,LPARAM(icon));
Rect<>r(Wnd); // GetWindowRect
MinSize.x=r.width();
MinSize.y=r.height();
new(&r) Rect<>(Wnd,true); // GetClientRect
WinSize.x=r.right;
WinSize.y=r.bottom;
CheckDlgButton(Wnd,106,BST_CHECKED);
if (worker::LoadSettings()) CheckDlgButton(Wnd,33,BST_CHECKED); // Subtrahieren ein
}break;
case WM_GETMINMAXINFO: {
MINMAXINFO&mmi=*(MINMAXINFO*)lParam;
mmi.ptMinTrackSize=MinSize;
}return TRUE;
case WM_SIZE: if (wParam==SIZE_MAXIMIZED || wParam==SIZE_RESTORED) {
POINT delta = {GET_X_LPARAM(lParam)-WinSize.x,GET_Y_LPARAM(lParam)-WinSize.y};
if (delta.x || delta.y) {
BYTE vsize=2; // erst mal ohne jeden Divider: Fenster abzählen
HDWP dwp=BeginDeferWindowPos(10);
for (HWND w=GetPrevSibling(GetDlgItem(Wnd,103));w;w=GetNextSibling(w)) {
Rect<>r(w);
r.right-=r.left; // width
r.bottom-=r.top; // height
ScreenToClient(Wnd,(POINT*)&r);
r.right+=delta.x;
if (vsize) r.bottom+=delta.y; else r.top+=delta.y;
dwp=DeferWindowPos(dwp,w,0,r.left,r.top,r.right,r.bottom,SWP_NOZORDER);
if (vsize) --vsize;
}
EndDeferWindowPos(dwp);
WinSize.x += delta.x;
WinSize.y += delta.y;
}
}break;
case WM_TIMER: switch (wParam) {
case 21: killThread(); break;
}break;
case WM_COMMAND: switch (wParam) {
case 10: if (ghThread) endThread(); else startThread(); break; // Thread starten oder abwürgen
case IDCANCEL: killThread(); worker::SaveSettings(); break;
// EndDialog(Wnd,0); macht ComSel::dialogHandler()
}break;
}
comsel.dialogHandler(Wnd,msg,wParam,lParam);
switch (msg) {
case WM_INITDIALOG: {
// Traces werden bereits von der Ressource initialisiert!
// startThread();
}return TRUE;
}
return FALSE;
}
// Statische Konstruktoren aufrufbar machen
#pragma bss_seg(".CRT$XCA")
char ctor_start; // Eine Null vor allen Konstruktorzeigern
// Eigentlich würde die Segmentadresse reichen, aber die ist in MSC/C++ nicht zu bekommen.
// In gcc geht das mit dem Linkerskript.
// Konstruktorzeiger landen in ".CRT$XCx" (x beliebig), wobei der Linker die Segmente alphabetisch sortiert
// und wegen Segmentausrichtung (bspw. 8 Byte) Nullen einfügt.
#pragma bss_seg(".CRT$XCZ")
char ctor_end; // Eine Null nach allen Konstruktorzeigern
#pragma bss_seg() // Standardverhalten reaktivieren
#pragma comment(linker,"/merge:.CRT=.data") // beseitigt 2 Linker-Warnings und erzeugt eine neue.
#pragma comment(linker,"/merge:.rdata=.text")
// _initterm(a,e) ruft alle Zeiger zwischen <a> und <e> auf, die nicht Null sind.
// Die Konstruktorfunktionen legen ggf. Destruktorkode für atexit() ab,
// daher gibt es kein Pendant für statische Destruktoren.
extern "C" void _cdecl _initterm(const char&a,const char&e);
int WinMainCRTStartup() {
_initterm(ctor_start,ctor_end); // Alle statischen Konstruktorzeiger zwischen ctor_start und ctor_end aufrufen
ghInstance=GetModuleHandle(0);
PlotXY::init();
ExitProcess(UINT(DialogBox(0,MAKEINTRESOURCE(100),0,MainDlgProc)));
}
| Detected encoding: UTF-8 | 0
|