#include "PiezoMess.h"
/*****************
* Worker-Thread *
*****************/
WORKER w;
void WORKER::start(HWND w) {
stop();
InfoWnd=w;
hCancel=CreateEvent(NULL,TRUE,FALSE,NULL);
hThread=CreateThread(NULL,0,ThreadProc,this,0,&ThreadId);
if (hThread==INVALID_HANDLE_VALUE) hThread=0;
else SetThreadPriority(hThread,THREAD_PRIORITY_BELOW_NORMAL);
}
void WORKER::stop() {
if (hThread) {
SetEvent(hCancel);
WaitForSingleObject(hThread,INFINITE); // auf Thread-Ende warten
if (CloseHandle(hThread)) hThread=0;
}
if (hCancel && CloseHandle(hCancel)) hCancel=0;
}
void WORKER::post(BYTE c, void*data, int dlen) {
PostThreadMessage(ThreadId,c,dlen,(LPARAM)data); // senden lassen
}
/*** protected ***/
void WORKER::ThreadProc() {
OpenCom();
if (hCom) {
int i;
clear();
for (i=0; i<3; i++) {
int k=GetData('C',&feature,sizeof(feature));
if (k==sizeof feature) break; // richtige "Antwort"
if (k<0) {
_debug(("ThreadProc: Abbruch durch hCancel-Event (%d)\n",1));
goto exi;
}
clear();
}
if (i==3) MBox(ghMainWnd,(PCTSTR)3,MB_OK);
else{
_debug(("GetData('C') hat %d Versuch(e) benötigt\n",i+1));
PostMessage(ghMainWnd,WM_UpdateFeature,0,0);
while (WaitForSingleObject(hCancel,0)){ // liefert 0 wenn hCancel gesetzt
MSG msg;
if (PeekMessage(&msg,0,0,0,PM_REMOVE)) { // I/O-Prozedur einschieben?
clear();
if (msg.message&0x80) {
clear();
int k=SetData(msg.message,(const void*)msg.lParam,(int)msg.wParam);
if (k<0) {
_debug(("ThreadProc: Abbruch durch hCancel-Event (%d)\n",2));
goto exi;
}
}else{
int k=GetData(msg.message,(void*)msg.lParam,(int)msg.wParam);
if (k<0) {
_debug(("ThreadProc: Abbruch durch hCancel-Event (%d)\n",3));
goto exi;
}else if (k!=(int)msg.wParam) {
_debug(("ThreadProc: Eingeschobenes GetData('%c') mit TimeOut!\n",msg.message));
}
}
clear();
}else if (sweep.data) {
if (Config.flags&0x80) {
int k=GetData('D',&adcmean,sizeof(adcmean));
if (k<0) {
_debug(("ThreadProc: Abbruch durch hCancel-Event (%d)\n",4));
goto exi;
}
if (k!=sizeof adcmean) {
_debug(("ThreadProc: GetData('D') mit TimeOut!\n"));
//EscapeCommFunction(hCom,CLRDTR); // Mikrocontroller-Reset
clear();
//EscapeCommFunction(hCom,SETDTR);
}else{
if (hSweepDlg) PostMessage(hSweepDlg,WM_Update,0,0);
int ll=sweep.width*sizeof(SDATA); // erwartete Gesamtlänge
BYTE *buf = new BYTE[ll]; // Zwischenpuffer, der während des Empfangs "giftig" ist
int d=0; // Laufzeiger für Zielpuffer
int l=GetData('A',buf,ll);
if (l<0) {
_debug(("ThreadProc: Abbruch durch hCancel-Event (%d)\n",5));
goto exi;
}
while (l>0) { // kein Abbruch?
_debug(("l=%d ",l));
WaitForSingleObject(sweep.hMutex,INFINITE);
int l1=sweep.width*sizeof(SDATA); // Zielpuffer kann sich zwischendurch verkleinern!
if (ll>l1) ll=l1;
if (d>ll) break;
if (d+l>ll) l=ll-d;
if (sweep.data) CopyMemory((BYTE*)sweep.data+d,buf,l); // bytegenau kopieren
PostMessage(ghMainWnd,WM_Update,d/sizeof(SDATA),(d+l)/sizeof(SDATA)); // samplegenau melden
d+=l;
sweep.nsamp=d/sizeof(SDATA);
if (sweep.writtento<sweep.nsamp) sweep.writtento=sweep.nsamp;
ReleaseMutex(sweep.hMutex);
if (d>=ll) break;
l=recv(buf,ll-d); // Restliche Stücke
}
_debug(("(%d)\n",ll));
delete[] buf;
}
}else clear();
}
}
}
exi:
CloseHandle(hCom);
CloseHandle(o.hEvent);
hCom=0;
}else PostMessage(InfoWnd,WM_ComFail,GetLastError(),0);
}
void WORKER::OpenCom() {
TCHAR ComName[12]; // ohne Backslashes geht's nur bis COM9!
_sntprintf(ComName,elemof(ComName),T("\\\\.\\COM%u"),Config.SerialNo+1);
hCom=CreateFile(ComName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
if (hCom==INVALID_HANDLE_VALUE) hCom=0;
if (hCom) {
DCB dcb;
InitStruct(&dcb,sizeof(dcb));
dcb.BaudRate=115200;
dcb.ByteSize=8;
dcb.fBinary=TRUE;
dcb.fDtrControl=DTR_CONTROL_ENABLE;
dcb.fRtsControl=RTS_CONTROL_ENABLE;
SetCommState(hCom,&dcb);
COMMTIMEOUTS to;
ZeroMemory(&to,sizeof to);
to.ReadTotalTimeoutConstant=Config.GuiDelay;
to.WriteTotalTimeoutConstant=Config.GuiDelay;
SetCommTimeouts(hCom,(LPCOMMTIMEOUTS)&to);
ZeroMemory(&o,sizeof(o));
o.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
}
}
void WORKER::clear() {
PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
Sleep(Config.GuiDelay);
PurgeComm(hCom,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
}
int WORKER::wait() {
int k=WaitForMultipleObjects(2,&o.hEvent,FALSE,INFINITE); // liefert 1 bei Abbruch via hCancel, 0 wenn Daten komplett
switch (k) {
case 1: CancelIo(hCom); return -1;
}
GetOverlappedResult(hCom,&o,(DWORD*)&k,FALSE); // Übertragene Bytes
return k;
}
// Synchrones Datensenden
int WORKER::send(const void*buf, int buflen) {
int bw;
if (WriteFile(hCom,buf,buflen,(DWORD*)&bw,&o)) return bw;
if (GetLastError()!=ERROR_IO_PENDING) {
_debug(("send:oops\n"));
return -2;
}
bw=wait();
if (bw!=buflen) _debug(("send:oops\n"));
return bw;
}
// Synchroner Datenempfang
int WORKER::recv(void*buf, int buflen) {
int br;
if (ReadFile(hCom,buf,buflen,(DWORD*)&br,&o)) return br;
if (GetLastError()!=ERROR_IO_PENDING) {
_debug(("recv:oops\n"));
return -2;
}
br=wait();
if (br!=buflen && buflen<500) _debug(("recv:oops\n"));
return br; // Empfangene Bytes
}
// Daten senden mit Kommandobyte voraus
int WORKER::SetData(char command, const void*buf, int buflen) {
int k=send(&command,1);
if (k!=1) return k;
#if 0
const char *p=(const char*)buf; // ganz langsam (damit µC hinterher kommt?)
for (int i=0; i<buflen; i++) {
Sleep(20);
send(p,1);
}
return buflen;
#else
if (buflen && send(&buflen,1)!=1) return -1;
return send(buf,buflen);
#endif
}
// Daten empfangen, vorher Kommandobyte senden
int WORKER::GetData(char command, void*buf, int buflen) {
if (command) {
int k=send(&command,1);
if (k!=1) return k;
}
return recv(buf,buflen);
}
#if 0
void QueryTemp() {
TCHAR Anzeige[12];
LoadString(ghInstance,3/*Fehler*/,Anzeige,elemof(Anzeige));
gValue=NaN; // ungültige Zahl zuweisen
PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
char ReadMsg[8];
DWORD bytes;
if (WriteFile(hCom,WriteMsg,9,&bytes,NULL)
&& bytes==9
&& ReadFile(hCom,ReadMsg,8,&bytes,NULL)
&& bytes==8
&& ReadMsg[0]==0x06
&& ReadMsg[1]=='*') {
ReadMsg[0]='0';
ReadMsg[1]='x';
ReadMsg[6]=0;
int t; // Temperatur in Hundertstel
if (StrToIntExA(ReadMsg,STIF_SUPPORT_HEX,&t)) {
t=(short)t; // Vorzeichen aufblasen
gValue=(double)t/100; // gültige Zahl zuweisen
if (-10000<=t && t<=20000) {
TCHAR sign=' ';
if (gShowSign && t>0) sign='+'; // falls gewünscht
if (t<0) {
sign='-';
t=-t;
}
wnsprintf4(Anzeige,elemof(Anzeige),T("%c%u%c%02u °C"),sign,t/100,sDecimal[0],t%100);
}
}
}
}
if (lstrcmp(gAnzeige,Anzeige)) {
lstrcpy(gAnzeige,Anzeige);
if (IsIconic(ghMainWnd)) SetWindowText(ghMainWnd,gAnzeige);
else InvalidateRect(ghMainWnd,NULL,FALSE);
DdePostAdvise(gDdeInst,0,0);
}
}
HDDEDATA CALLBACK DdeCallback(UINT uType,UINT uFmt,HCONV,HSZ,HSZ hsz2,
HDDEDATA,ULONG_PTR,ULONG_PTR) {
HDDEDATA ret=DDE_FNOTPROCESSED;
switch (uType) {
case XTYP_CONNECT: ret=(HDDEDATA)TRUE; break;
case XTYP_ADVSTART: if (uFmt==CF_TEXT || uFmt==CF_UNICODETEXT || uFmt==CF_XlTable) ret=(HDDEDATA)TRUE; break;
case XTYP_ADVREQ:
case XTYP_REQUEST: {
if (uFmt==CF_TEXT) {
#ifdef UNICODE
CHAR buf[elemof(gAnzeige)];
int len=WideCharToMultiByte(CP_ACP,0,gAnzeige,-1,buf,elemof(buf),NULL,NULL)+1;
ret=DdeCreateDataHandle(gDdeInst,(LPBYTE)buf,len,0,hsz2,uFmt,0);
#else
ret=DdeCreateDataHandle(gDdeInst,(LPBYTE)gAnzeige,lstrlen(gAnzeige)+1,0,hsz2,uFmt,0);
#endif
}else if (uFmt==CF_UNICODETEXT) {
#ifdef UNICODE
ret=DdeCreateDataHandle(gDdeInst,(LPBYTE)gAnzeige,(lstrlen(gAnzeige)+1)<<1,0,hsz2,uFmt,0);
#else
WCHAR buf[elemof(gAnzeige)];
int len=MultiByteToWideChar(CP_ACP,0,gAnzeige,-1,buf,elemof(buf))+1;
ret=DdeCreateDataHandle(gDdeInst,(LPBYTE)buf,len<<1,0,hsz2,uFmt,0);
#endif
}else if (uFmt==CF_XlTable) {
#pragma pack(2)
struct{
short tdtTable,dimensions,rows,cols;
short tdtType,tdtSize;
union{
double tdtDouble;
short tdtShort;
};
}XlTable={
0x0010, // Header
4, // 4 Bytes folgen
1, // 1 Spalte
1, // 1 Zeile
1, // DOUBLE
sizeof(double),
gValue};
#pragma pack()
unsigned size=sizeof(XlTable);
if (gValue!=gValue) { // INF, NaN und ähnliches
XlTable.tdtType=4; // Error
XlTable.tdtSize=sizeof(short);
XlTable.tdtShort=42; // "#NV" (nicht verfügbar)
size-=6;
}
ret=DdeCreateDataHandle(gDdeInst,(LPBYTE)&XlTable,size,0,hsz2,uFmt,0);
}
}
}
return ret;
}
#endif
Detected encoding: ANSI (CP1252) | 4
|
|