Source file: /~heha/hsn/AD9834.zip/src/Interface.c

#include "AD9834.h"
#include <shlwapi.h>
#include <setupapi.h>
 
/****************
 * USB-Geraffel *
 ****************/

static const GUID GUID_DEVINTERFACE_USBPRINT = {
  0x28d78fad,0x5a12,0x11D1,0xae,0x5b,0x00,0x00,0xf8,0x03,0xa8,0xc2};

int GetNumUsbPorts(void) {
 int i;
 SP_DEVICE_INTERFACE_DATA devinterface;
 HDEVINFO devs = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBPRINT,0,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
 if (devs==INVALID_HANDLE_VALUE) return 0;
 devinterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
 for (i=0; SetupDiEnumDeviceInterfaces(devs,0,&GUID_DEVINTERFACE_USBPRINT,i,&devinterface); i++);
 SetupDiDestroyDeviceInfoList(devs);
 return i;
}

static HANDLE OpenUsbPort(int n,DWORD FlagsAndAttributes) {
 HANDLE usbHandle=0;
 SP_DEVICE_INTERFACE_DATA devinterface;
 DWORD size;
 PSP_DEVICE_INTERFACE_DETAIL_DATA interface_detail;
 HDEVINFO devs = SetupDiGetClassDevs(&GUID_DEVINTERFACE_USBPRINT,0,0,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
 if (devs!=INVALID_HANDLE_VALUE) {
  devinterface.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
  if (SetupDiEnumDeviceInterfaces(devs, 0, &GUID_DEVINTERFACE_USBPRINT, n, &devinterface)) {
   size = 0;
   SetupDiGetDeviceInterfaceDetail(devs, &devinterface, 0, 0, &size, 0);
   interface_detail = LocalAlloc(LPTR,size);
   if (interface_detail) {
    interface_detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
    if (SetupDiGetDeviceInterfaceDetail(devs, &devinterface, interface_detail, size, NULL, NULL)) {
     usbHandle = CreateFile(interface_detail->DevicePath,GENERIC_WRITE,FILE_SHARE_READ,
       NULL,OPEN_EXISTING,FlagsAndAttributes,NULL);
     if (usbHandle == INVALID_HANDLE_VALUE) usbHandle = 0;
    }
    LocalFree(interface_detail);
   }
  }
  SetupDiDestroyDeviceInfoList(devs);
 }
 return usbHandle;
}

/***************************
 * Eigentliche Ein/Ausgabe *
 ***************************/

static HANDLE hCom;
static HANDLE hLibInOut;
static BYTE (_stdcall*inportb)(WORD);	// 2 Funktionszeiger
static void (_stdcall*outportb)(WORD,BYTE);
static BYTE OutSave[2];
static BYTE DefData;			// Sonstige Nicht-SPI-Datenbits (für parallel und USB->Drucker)
static bool ErrorPosted;		// Fehlermeldung (bei USB oder seriell) nur 1x posten
static HANDLE hUsb;
static OVERLAPPED ovl;
static BYTE *UsbPrnPtr;
static BYTE UsbPrnBuf[33*7];		// maximal 7 Blöcke zu je 33 Bytes

#define USBROT(x) (BYTE)((x)<<3&0xF8|(x)>>5&7)	// Bei USB alle Bits logisch um 3 Bit rotiert

static void PostError(void) {
 if (ErrorPosted) return;
 Beep(440,100);
 if (PostMessage(hMainWnd,WM_IOERROR,0,0)) ErrorPosted=true;
}

static int WriteUsb(const void*p,int len) {
 DWORD bw;
 if (!WriteFile(hUsb,p,len,&bw,&ovl)) {	// in einem Stück rausschießen
  if (GetLastError()!=ERROR_IO_PENDING) PostError();	// Handle ungültig
  else if (WaitForSingleObject(ovl.hEvent,200)) {
   CancelIo(hUsb);
   PostError();				// Brücke STB-ACK, BUSY-GND oder ERR-INIT fehlt
  }
 }
 GetOverlappedResult(hUsb,&ovl,&bw,FALSE);
 return bw;
}

void SpiSend(WORD w) {
 int i=16;
 switch (Config.iomode) {
  case 1: {	// seriell über Adapter
   if (!hCom) break;
   EscapeCommFunction(hCom,CLRBREAK);	// PCK = LOW
   do{		// so selten wie möglich EscapeCommFunction() aufrufen!
    if (w&0x8000 && !DefData) EscapeCommFunction(hCom,SETRTS), DefData=1;	// SDI = Datenbit
    else if (!(w&0x8000) && DefData) EscapeCommFunction(hCom,CLRRTS), DefData=0;
    EscapeCommFunction(hCom,CLRDTR);	// SCK = LOW
    EscapeCommFunction(hCom,SETDTR);	// SCK = HIGH
    w<<=1;	// nächstes Bit
   }while (--i);
   if (!EscapeCommFunction(hCom,SETBREAK))
     PostError();			// PCK = HIGH
  }break;

  case 2: {
   if (!hLibInOut) break;
   do{
    BYTE b=DefData&~6;			// Bit 1 (SDI) und 2 (PCK) löschen
    if (w&0x8000) b|=2;			// Bit 1 (SDI) setzen
    outportb(Config.paradr,b);		// PCK = LOW, SCK = HIGH, SDI = Datenbit
    b&=~1;
    outportb(Config.paradr,b);		//	      SCK = LOW
    w<<=1;
   }while (--i);
   outportb(Config.paradr,DefData);	// PCK = HIGH
  }break;

  case 3: {
   if (!hUsb) break;
   do{
    BYTE b=DefData&(BYTE)~USBROT(6);	// Bit 4 (SDI) und 5 (PCK) löschen
    if (w&0x8000) b|=USBROT(2);		// Bit 4 (SDI) setzen
    *UsbPrnPtr++=b;			// PCK = LOW, SCK = HIGH, SDI = Datenbit
    b&=~USBROT(1);
    *UsbPrnPtr++=b;			//	      SCK = LOW
    w<<=1;
   }while (--i);
   *UsbPrnPtr++=DefData;		// PCK = HIGH
   if (UsbPrnPtr-UsbPrnBuf==elemof(UsbPrnBuf)) SpiFlush();
  }break;
 }
}

void SetResetPin(void) {
 switch (Config.iomode) {
  case 2: {	// parallel
   outportb(Config.paradr+2,Config.control&1<<8?0x0C:0x0E);
  }break;
  case 3: {	// USB->Drucker
   if (Config.control&1<<8) DefData|=USBROT(8); else DefData&=~USBROT(8);	// hier Bit 6
  }break;
 }
}

void SetTrigger(bool t) {
 BYTE m=Config.iomode==3?USBROT(0xF0):0xF0;
 if (t) DefData|=m; else DefData&=~m;	// in beiden Fällen alle restlichen Bits
}

void SpiFlush(void) {
 switch (Config.iomode) {
  case 3: {
   if (UsbPrnPtr==UsbPrnBuf) break;
   WriteUsb(UsbPrnBuf,UsbPrnPtr-UsbPrnBuf);	// in einem Stück rausschießen
   UsbPrnPtr=UsbPrnBuf;
  }break;
 }
}

bool SpiOpen(HWND w) {
 switch (Config.iomode) {
  case 1: {	// seriell über Adapter
   TCHAR ComName[12];
   DCB dcb;
   wnsprintf(ComName,elemof(ComName),S[6],Config.comnum+1);
   hCom=CreateFile(ComName,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,0);
   if (hCom==INVALID_HANDLE_VALUE) hCom=0;
   if (!hCom) {
    MBox(w,42,MB_OK,Config.comnum+1);
    return false;
   }
   GetCommState(hCom,&dcb);
   dcb.fDtrControl=DTR_CONTROL_ENABLE;	// SCK = HIGH
   dcb.fRtsControl=RTS_CONTROL_DISABLE;	// SDI = LOW
   SetCommState(hCom,&dcb);
   DefData=0;				// Bit 0 speichert hier SDI = LOW
   EscapeCommFunction(hCom,SETBREAK);	// PCK = HIGH
  }break;

  case 2: {	// parallel AKA Direktzugriff
   DefData=5;
   hLibInOut=LoadLibraryA("inpout32.dll");
   if (!hLibInOut) {
    MBox(w,43,MB_OK);
    return false;
   }
   (FARPROC)inportb=GetProcAddress(hLibInOut,"Inp32");
   (FARPROC)outportb=GetProcAddress(hLibInOut,"Out32");
   OutSave[0]=inportb(Config.paradr);
   OutSave[1]=inportb(Config.paradr+2)&0x1F;
   outportb(Config.paradr,DefData);
   SetResetPin();
  }break;

  case 3: {
   DefData=USBROT(5);
   SetResetPin();
   hUsb=OpenUsbPort(Config.u2pnum,FILE_FLAG_OVERLAPPED);
   if (!hUsb) {
    MBox(w,44,MB_OK,Config.u2pnum);
    return false;
   }
   ovl.hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
   WriteUsb(&DefData,1);
   UsbPrnPtr=UsbPrnBuf;		// Füllzeiger auf Anfang setzen
  }break;

  default: return false;
 }
 return true;
}

void SpiClose(void) {
 if (hCom) {		// seriell über Adapter
  CloseHandle(hCom);
  hCom=0;
 }
 if (hLibInOut) {	// parallel AKA Direktzugriff
  outportb(Config.paradr,OutSave[0]);
  outportb(Config.paradr+2,OutSave[1]);
  FreeLibrary(hLibInOut);
  hLibInOut=0;
 }
 if (hUsb) {		// über USB-Drucker-Konverter (Schaltungsänderung)
  CloseHandle(hUsb);
  hUsb=0;
  CloseHandle(ovl.hEvent);
  ZeroMemory(&ovl,sizeof(ovl));
 }
 ErrorPosted=false;
}
Detected encoding: ANSI (CP1252)4
Wrong umlauts? - Assume file is ANSI (CP1252) encoded