Source file: /~heha/mb-iwp/NA/MSVC.zip/src/Worker.cpp

#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
Wrong umlauts? - Assume file is ANSI (CP1252) encoded