/* Ansteuerung des A/D-Wandlerchips LTC1291 mit dem PC am Parallelport
* h#s 08/04 Nur Win32!
*/
#ifndef __BORLANDC__
# pragma comment(linker,"/OPT:nowin98")
# pragma comment(linker,"/LARGEADDRESSAWARE /RELEASE")
#endif
#include "wutils.h"
#include "allowio.h"
#include <stdio.h>
DWORD LptBase;
void outbyte(DWORD a, BYTE b) {
_asm{ mov edx,[a]
add edx,[LptBase]
mov eax,dword ptr [b]
out dx,al
}
}
#ifdef __BORLANDC__
# pragma warn -rvl
#endif
BYTE inbyte(DWORD a) {
_asm{ mov edx,[a]
add edx,[LptBase]
in al,dx
}
}
// Bits am Datenport
// --- alle Datenportleitungen dienen der Stromversorgung!
// Bits am Statusport (+1)
#define n_DOUT 0x80 // Invertiert (Datenleitung)
#define d_UCC 0x08 // Nichtinvertiert (Betriebsspannungskontrolle)
// Bits am Steuerport (+2)
#define L_CLK 0x01 // Alles invertierte Pegel
#define H_CLK 0x00
#define L_nCS 0x02
#define H_nCS 0x00
#define L_DIN 0x08
#define H_DIN 0x00
void StartCS(void) {
outbyte(2,L_nCS|L_CLK|L_DIN); // /CS auf LOW setzen
}
void StopCS(void) {
outbyte(0,0xFF); // Datenbits high (Stromversorgung)
outbyte(2,H_nCS|L_CLK|L_DIN);
}
void SendBits(unsigned x, unsigned bits) {
bits=1<<(bits-1); // nun Maske
while (bits) {
BYTE b=(BYTE)(x&bits ? L_nCS|L_CLK|H_DIN : L_nCS|L_CLK|L_DIN);
outbyte(2,b);
b^=L_CLK^H_CLK; // Takt-Bit ändern
outbyte(2,b);
b^=L_CLK^H_CLK;
outbyte(2,b);
bits>>=1;
}
}
unsigned RecvBits(int bits) {
unsigned r=0;
while (bits) {
r<<=1;
if (!(inbyte(1)&n_DOUT)) r|=1;
outbyte(2,L_nCS|H_CLK|L_DIN);
outbyte(2,L_nCS|L_CLK|L_DIN);
bits--;
}
return r;
}
HINSTANCE HInstance;
HANDLE hPorttalk=INVALID_HANDLE_VALUE; // PORTTALK.SYS-Handle (nur NT)
HWND MainWnd; // Hauptfenster
HFONT LargeFont;
HBRUSH BlueBrush;
HBRUSH YellowBrush; // für DDE-Advise-Variablen
ATOM AtomBack;
TCHAR sDecimal[2];
TCHAR IniFileName[MAX_PATH];
TCHAR HelpFileName[]=T("LTC1291.HLP");
DWORD DdeInst;
HSZ hszService;
#define hszTopic hszService
#define WM_CONTINUEINIT (WM_USER+100)
typedef struct {
unsigned wert;
float skale; // Faktor für <wert>
float offset; // dimensionsbehaftet!
int ziffern; // Kommastellen
TCHAR einheit[8]; // Einheit (zur Anzeige)
HSZ hsz; // DDE-String-Handle
UINT id; // Static-ID
}TADWert;
TADWert ADWert[2];
UINT Millisek=1000;
BOOL DiffBetrieb;
HSZ CreateStringHandle(PCTSTR Str) {
return DdeCreateStringHandle(DdeInst,Str,CP_WINNEUTRAL);
}
void FreeStringHandle(HSZ hsz) {
if (hsz) DdeFreeStringHandle(DdeInst,hsz);
}
int CheckHsz(HSZ hsz) {
if (!DdeCmpStringHandles(hsz,ADWert[0].hsz)) return 108;
if (!DdeCmpStringHandles(hsz,ADWert[1].hsz)) return 110;
return 0; // alles andere ist Fehler
}
#ifdef __BORLANDC__
# pragma argsused
#endif
HDDEDATA CALLBACK DdeCallback(UINT type, UINT fmt, HCONV conv,
HSZ hsz1, HSZ hsz2, HDDEDATA data, DWORD data1, DWORD data2) {
switch (type) {
case XTYP_CONNECT: {
if (hsz1==hszTopic) {
SetDlgItemText(MainWnd,111,T("DDE-Verbindung gestartet"));
return (HDDEDATA)TRUE;
}
}break;
case XTYP_DISCONNECT: {
SetDlgItemText(MainWnd,111,T("DDE-Verbindung beendet"));
}break;
case XTYP_REQUEST:
case XTYP_ADVREQ: {
int id=CheckHsz(hsz2);
char s[16];
if (fmt!=CF_TEXT) break;
if (!id) break;
return DdeCreateDataHandle(DdeInst,(LPBYTE)s,
GetDlgItemTextA(MainWnd,id,s,elemof(s))+1,
0,hsz2,fmt,0);
}
case XTYP_ADVSTART:
case XTYP_ADVSTOP: {
int id=CheckHsz(hsz2);
HWND w;
if (!id) break;
w=GetDlgItem(MainWnd,id);
id=(int)GetProp(w,(LPTSTR)AtomBack);
id+=type==XTYP_ADVSTART?+1:-1;
if (id) SetProp(w,(LPTSTR)AtomBack,(HANDLE)id);
else RemoveProp(w,(LPTSTR)AtomBack);
InvalidateRect(w,NULL,TRUE);
return (HDDEDATA)TRUE;
}
}
return (HDDEDATA)FALSE;
}
void Float2String(PTSTR s, float z) {
_stprintf(s,T("%.6G"),z);
s=_tcschr(s,T('.'));
if (s) *s=sDecimal[0];
}
bool String2Float(PTSTR s, float*z) {
PTSTR p;
p=_tcschr(s,sDecimal[0]);
if (!p) p=_tcschr(s,T(','));
if (p) *p=T('.');
if (_stscanf(s,T("%G"),z)!=1) return false;
return true;
}
void LoadADWert(TADWert*w,PCTSTR sektion) {
TCHAR s[32];
GetPrivateProfileString(sektion,T("Skalierung"),T("1"),s,elemof(s),IniFileName);
String2Float(s,&w->skale);
GetPrivateProfileString(sektion,T("Offset"),T("0"),s,elemof(s),IniFileName);
String2Float(s,&w->offset);
w->ziffern=GetPrivateProfileInt(sektion,T("Kommastellen"),0,IniFileName);
GetPrivateProfileString(sektion,T("Einheit"),T(""),w->einheit,elemof(w->einheit),IniFileName);
}
void SetLptBase(DWORD a) {
if (LptBase==a) return;
if (hPorttalk!=INVALID_HANDLE_VALUE) {
EnablePorts(hPorttalk,0,0);
EnablePorts(hPorttalk,a,3);
}
LptBase=a;
}
void LoadConfig(void) {
TCHAR s[32];
int i=0;
if (GetPrivateProfileString(T("LTC1291"),T("PortBase"),T(""),s,elemof(s),IniFileName))
_stscanf(s,T("%i"),&i);
if (i<0x100) i=0x378;
SetLptBase(i);
Millisek=GetPrivateProfileInt(T("LTC1291"),T("Millisek"),1000,IniFileName);
DiffBetrieb=GetPrivateProfileInt(T("LTC1291"),T("DiffBetrieb"),0,IniFileName);
LoadADWert(ADWert+0,T("0"));
LoadADWert(ADWert+1,T("1"));
}
void SaveADWert(TADWert*w,PCTSTR sektion) {
TCHAR s[32];
Float2String(s,w->skale);
WritePrivateProfileString(sektion,T("Skalierung"),s,IniFileName);
Float2String(s,w->offset);
WritePrivateProfileString(sektion,T("Offset"),s,IniFileName);
_stprintf(s,T("%i"),w->ziffern);
WritePrivateProfileString(sektion,T("Kommastellen"),s,IniFileName);
WritePrivateProfileString(sektion,T("Einheit"),w->einheit,IniFileName);
}
void SaveConfig(void) {
TCHAR s[32];
_stprintf(s,T("0x%X"),LptBase);
WritePrivateProfileString(T("LTC1291"),T("PortBase"),s,IniFileName);
_stprintf(s,T("%i"),Millisek);
WritePrivateProfileString(T("LTC1291"),T("Millisek"),s,IniFileName);
_stprintf(s,T("%i"),DiffBetrieb);
WritePrivateProfileString(T("LTC1291"),T("DiffBetrieb"),s,IniFileName);
SaveADWert(ADWert+0,T("0"));
SaveADWert(ADWert+1,T("1"));
WritePrivateProfileString(NULL,NULL,NULL,IniFileName);
}
void DdeStart(void) {
DdeInitialize(&DdeInst,DdeCallback,
CBF_FAIL_POKES|CBF_FAIL_EXECUTES|
CBF_SKIP_REGISTRATIONS|CBF_SKIP_UNREGISTRATIONS,0);
hszService=CreateStringHandle(T("LTC1291"));
ADWert[0].hsz=CreateStringHandle(T("0"));
ADWert[1].hsz=CreateStringHandle(T("1"));
AtomBack=AddAtom(T("DdeAdvises"));
YellowBrush=CreateSolidBrush(0xC0FFFFL);
DdeNameService(DdeInst,hszService,0,DNS_REGISTER);
}
void DdeStop(void) {
DdeUninitialize(DdeInst);
DeleteObject(YellowBrush);
}
void PorttalkStart(void) {
OSVERSIONINFO os;
os.dwOSVersionInfoSize=sizeof(os);
if (GetVersionEx(&os) && os.dwPlatformId==VER_PLATFORM_WIN32_NT)
hPorttalk=OpenPortTalkDriver(MainWnd);
}
void PorttalkStop(void) {
if (hPorttalk!=INVALID_HANDLE_VALUE) CloseHandle(hPorttalk);
}
void SetWert(TADWert *w,unsigned wert) {
TCHAR buf[32];
PTSTR p;
if (w->wert==wert) return;
w->wert=wert;
_stprintf(buf,T("%.*f %s"),
w->ziffern,
w->wert*w->skale-w->offset,
w->einheit);
p=_tcschr(buf,T('.'));
if (p) *p=sDecimal[0];
SetDlgItemText(MainWnd,w->id,buf);
DdePostAdvise(DdeInst,hszTopic,w->hsz);
}
#ifdef __BORLANDC__
# pragma argsused
#endif
BOOL CALLBACK PortDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam){
const static unsigned Portadressen[]={0x378,0x278,0x3BC};
switch (Msg) {
case WM_INITDIALOG: {
int i;
for (i=0; i<elemof(Portadressen); i++) {
TCHAR s[16];
_stprintf(s,T("LPT%i (0x%X)"),i+1,Portadressen[i]);
SendDlgItemMessage(Wnd,101,CB_ADDSTRING,0,(LPARAM)(LPSTR)s);
if (LptBase==Portadressen[i]) SendDlgItemMessage(Wnd,101,CB_SETCURSEL,i,0);
} // unter Win32 ist kein Rankommen an die wahren Portadressen, oder??
SetDlgItemInt(Wnd,102,Millisek,FALSE);
}return TRUE;
case WM_COMMAND: switch (LOWORD(wParam)) {
case IDHELP: WinHelp(Wnd,HelpFileName,HELP_CONTEXT,0x21); break;
case IDOK: {
UINT pa;
UINT ms;
pa=(UINT)SendDlgItemMessage(Wnd,101,CB_GETCURSEL,0,0);
if (pa>=elemof(Portadressen)) {
MBox(Wnd,101,MB_ICONEXCLAMATION|MB_OK);
SetFocus(GetDlgItem(Wnd,101));
break;
}
ms=GetDlgItemInt(Wnd,102,NULL,FALSE);
if (!ms) {
MBox(Wnd,102,MB_ICONEXCLAMATION|MB_OK);
SetEditFocus(Wnd,102);
break;
}
SetLptBase(Portadressen[pa]);
if (!(inbyte(1)&d_UCC) && MBox(Wnd,103,MB_ICONEXCLAMATION|MB_OKCANCEL)!=IDOK) break;
Millisek=ms;
SetTimer(MainWnd,1,ms,NULL);
}nobreak;
case IDCANCEL: EndDialog(Wnd,wParam);
}
}
return FALSE;
}
void SetEdits(TADWert*w, HWND wnd, UINT idbase) {
TCHAR s[32];
Float2String(s,w->skale); SetDlgItemText(wnd, idbase,s);
Float2String(s,w->offset);SetDlgItemText(wnd,++idbase,s);
SetDlgItemInt (wnd,++idbase,w->ziffern,FALSE);
SetDlgItemText(wnd,++idbase,w->einheit);
}
bool GetEdits(TADWert*w, HWND wnd, UINT idbase) {
TCHAR s[32];
BOOL b;
GetDlgItemText(wnd,idbase,s,elemof(s));
if (!String2Float(s,&w->skale)) goto err;
GetDlgItemText(wnd,++idbase,s,elemof(s));
if (!String2Float(s,&w->offset)) goto err;
w->ziffern=GetDlgItemInt(wnd,++idbase,&b,FALSE);
if (!b || w->ziffern>6) goto err;
if ((unsigned)SendDlgItemMessage(wnd,++idbase,WM_GETTEXTLENGTH,0,0)
>=elemof(w->einheit)) goto err; // zu viele Zeichen
GetDlgItemText(wnd,idbase,w->einheit,elemof(w->einheit));
return true;
err:
MBox(wnd,102,MB_ICONEXCLAMATION|MB_OK);
SetEditFocus(wnd,idbase);
return false;
}
#ifdef __BORLANDC__
# pragma argsused
#endif
BOOL CALLBACK KoeffDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam){
switch (Msg) {
case WM_INITDIALOG: {
SetEdits(ADWert+0,Wnd,100);
SetEdits(ADWert+1,Wnd,104);
CheckDlgButton(Wnd,108,DiffBetrieb);
SendMessage(Wnd,WM_COMMAND,108,0);
}return TRUE;
case WM_COMMAND: switch (LOWORD(wParam)) {
case 108: EnableDlgItem(Wnd,109,IsDlgButtonChecked(Wnd,108)); break;
case IDHELP: WinHelp(Wnd,HelpFileName,HELP_CONTEXT,0x22); break;
case IDOK: {
if (!GetEdits(ADWert+0,Wnd,100)) break;
if (!GetEdits(ADWert+1,Wnd,104)) break;
DiffBetrieb=IsDlgButtonChecked(Wnd,108);
}nobreak;
case IDCANCEL: EndDialog(Wnd,wParam);
}
}
return FALSE;
}
#ifdef __BORLANDC__
# pragma argsused
#endif
BOOL CALLBACK AboutDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam){
switch (Msg) {
case WM_INITDIALOG: return TRUE;
case WM_COMMAND: EndDialog(Wnd,wParam);
}
return FALSE;
}
BOOL CALLBACK MainDlgProc(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam){
static TCHAR DefaultTitle[64];
switch (Msg) {
case WM_INITDIALOG: {
MainWnd=Wnd;
GetWindowText(Wnd,DefaultTitle,elemof(DefaultTitle));
LargeFont=CreateFont(40,0,0,0,700,0,0,0,0,0,0,0,0,T("Times"));
BlueBrush=CreateSolidBrush(0xFFC0C0L);
if (LargeFont) {
SendDlgItemMessage(Wnd,108,WM_SETFONT,(WPARAM)LargeFont,0);
SendDlgItemMessage(Wnd,110,WM_SETFONT,(WPARAM)LargeFont,0);
}
ADWert[0].id=108; // zur Ausgabe
ADWert[1].id=110;
PorttalkStart();
LoadConfig();
StopCS();
DdeStart();
SetTimer(Wnd,1,Millisek,NULL);
SendMessage(Wnd,WM_WININICHANGE,0,0);
PostMessage(Wnd,WM_CONTINUEINIT,0,0);
}return TRUE;
case WM_CONTINUEINIT: {
ShowWindow(Wnd,SW_SHOWDEFAULT);
}break;
case WM_WININICHANGE: {
GetProfileString(T("intl"),T("sDecimal"),T("."),sDecimal,elemof(sDecimal));
}break;
case WM_TIMER: {
static int Fehler;
StartCS();
SendBits(DiffBetrieb?0x11:0x19,6); // mit Startbit
if (!RecvBits(1)) {
SetWert(ADWert+0,RecvBits(12));
Fehler=0;
}else{
Fehler++; // Ab 10 Fehler Fenstertext löschen!
if (Fehler>10) SetDlgItemText(Wnd,108,T("--"));
}
StopCS();
StartCS();
SendBits(DiffBetrieb?0x15:0x1D,6);
if (!RecvBits(1)) {
SetWert(ADWert+1,RecvBits(12));
Fehler=0;
}else{
Fehler++;
if (Fehler>10) SetDlgItemText(Wnd,110,T("--"));
}
StopCS();
if (IsIconic(Wnd)) goto settitle;
}break;
case WM_SIZE: if (wParam==SIZEICONIC) {
TCHAR buf[64];
settitle:
GetDlgItemText(Wnd,108,buf,32);
lstrcat(buf,T("; "));
GetDlgItemText(Wnd,110,buf+lstrlen(buf),32);
SetWindowText(Wnd,buf);
}break;
case WM_QUERYOPEN: {
SetWindowText(Wnd,DefaultTitle);
}break;
case WM_CTLCOLORSTATIC: {
if ((HWND)lParam==GetDlgItem(Wnd,108)
|| (HWND)lParam==GetDlgItem(Wnd,110)) {
SetBkMode((HDC)wParam,TRANSPARENT);
if (GetProp((HWND)lParam,(LPTSTR)AtomBack)) return (BOOL)YellowBrush;
return (BOOL)BlueBrush;
}
}break;
case WM_COMMAND: switch (LOWORD(wParam)){
case 0x1F: SendMessage(Wnd,WM_CLOSE,0,0); break;
case 0x21: DialogBox(HInstance,MAKEINTRESOURCE(0x21),Wnd,PortDlgProc); break;
case 0x22: DialogBox(HInstance,MAKEINTRESOURCE(0x22),Wnd,KoeffDlgProc); break;
case 0x23: SaveConfig(); break;
case 0x31: WinHelp(Wnd,HelpFileName,HELP_INDEX,0); break;
case 0x32: WinHelp(Wnd,HelpFileName,HELP_CONTEXT,0x32); break;
case 0x3F: DialogBox(HInstance,MAKEINTRESOURCE(0x3F),Wnd,AboutDlgProc); break;
}break;
case WM_CLOSE: {
WinHelp(Wnd,HelpFileName,HELP_QUIT,0);
EndDialog(Wnd,0);
}break;
case WM_DESTROY: {
DdeStop();
PorttalkStop();
DeleteObject(LargeFont);
DeleteObject(BlueBrush);
}break;
}
return FALSE;
}
#ifdef __BORLANDC__
# pragma argsused
#endif
int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
static WNDCLASS wc={
CS_DBLCLKS,
DefDlgProc,
0,
DLGWINDOWEXTRA,
0,0,0,
(HBRUSH)(COLOR_BACKGROUND+1),
NULL,
T("LTC1291")};
HInstance=hInstance;
wc.hInstance=hInstance;
wc.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(100));
wc.hCursor=LoadCursor(0,IDC_ARROW);
if (!RegisterClass(&wc)) {
#ifdef UNICODE
CHAR buf[256];
LoadStringA(hInstance,210,buf,elemof(buf));
MessageBoxA(0,buf,NULL,MB_OK|MB_ICONSTOP); // Zwang: ANSI-Version
#endif
return -1;
}
GetModuleFileName(0,IniFileName,elemof(IniFileName));
lstrcpy(GetFileNamePtr(IniFileName),T("LTC1291.INI"));
return DialogBox(hInstance,MAKEINTRESOURCE(100),0,MainDlgProc);
}
| Detected encoding: ANSI (CP1252) | 4
|
|
|