Cody King


First, I'll have to admit that my coding skills have been unused for several years now, but this is one thing I believe that VFP should handle no problem. Here is the setup:

This program gets data from an A to D board and it utilizes DLPORTIO.DLL to address the parallel port and go thru 8 channels. (I know.... old school...but that's why I got it!)

I've done the Declare statements to register the DLL but I just can't seem to get the syntax right to get to the "channels" on the A to D board. It recognizes the 0x378 address and I can page the port, but that's as far as I can get. Has anyone done any routines using this DLL that could shed some light on this for me The entire program in C++ is not that big - heck, most of it is in the screen paints, but low level stuff has never been my strong point.

Thanks in advance!

Gene

What the heck.... here's the program!

* This prog appears to control the A to D board and the output ports.

*

// ASHDlg.cpp : implementation file

//

#include "stdafx.h"

#include "ASH.h"

#include "ASHDlg.h"

//Parallel port direct access library, you must also install dlportio.lib in the link settings

#include "dlportio.h" //dlportio.dll needs to be in c:\windows\system32 directory

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

#define DATA_ADDR (0x378) //data register of LPT1

#define STAT_ADDR (0x379) //status register of LPT1

#define CONT_ADDR (0x37a) //control register of LPT1

#define DATA(x) (DlPortWritePortUchar(DATA_ADDR,(x)))//;(Sleep(1))

#define CONTROL(x) (DlPortWritePortUchar(CONT_ADDR,(x)))//;(Sleep(1))

//inverted at the port

#define CLR_STROBE (DlPortWritePortUchar(CONT_ADDR,(control|=0x01)))//;(Sleep(1))

#define SET_STROBE (DlPortWritePortUchar(CONT_ADDR,(control&=~0x01)))

#define CLR_AD_CS (DlPortWritePortUchar(CONT_ADDR,(control|=0x08)))

#define SET_AD_CS (DlPortWritePortUchar(CONT_ADDR,(control&=~0x08)))

//straight at the port

#define SET_166_PE (DlPortWritePortUchar(DATA_ADDR,(relay_data|=0x40)))

#define CLR_166_PE (DlPortWritePortUchar(DATA_ADDR,(relay_data&=~0x40)))

#define SET_CLK (DlPortWritePortUchar(DATA_ADDR,(relay_data|=0x80)))

#define CLR_CLK (DlPortWritePortUchar(DATA_ADDR,(relay_data&=~0x80)))

unsigned char relay_data=0, control=0xff;

/////////////////////////////////////////////////////////////////////////////

// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog

{

public:

CAboutDlg();

// Dialog Data

//{{AFX_DATA(CAboutDlg)

enum { IDD = IDD_ABOUTBOX };

//}}AFX_DATA

// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(CAboutDlg)

protected:

virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

//}}AFX_VIRTUAL

// Implementation

protected:

//{{AFX_MSG(CAboutDlg)

//}}AFX_MSG

DECLARE_MESSAGE_MAP()

};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)

{

//{{AFX_DATA_INIT(CAboutDlg)

//}}AFX_DATA_INIT

}

void CAboutDlg:Big SmileoDataExchange(CDataExchange* pDX)

{

CDialog:Big SmileoDataExchange(pDX);

//{{AFX_DATA_MAP(CAboutDlg)

//}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)

//{{AFX_MSG_MAP(CAboutDlg)

// No message handlers

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CASHDlg dialog

CASHDlg::CASHDlg(CWnd* pParent /*=NULL*/)

: CDialog(CASHDlg::IDD, pParent)

{

//{{AFX_DATA_INIT(CASHDlg)

m_PollToggle = 1;

m_CrOn2 = -1;

m_CrOn5 = -1;

m_CrOn4 = -1;

m_CrOn3 = -1;

m_AIn0 = 0;

m_AIn1 = 0;

m_AIn2 = 0;

m_AIn3 = 0;

m_AIn4 = 0;

m_AIn5 = 0;

m_AIn6 = 0;

m_InOn0 = -1;

m_InOn1 = -1;

m_InOn10 = -1;

m_InOn11 = -1;

m_InOn12 = -1;

m_InOn13 = -1;

m_InOn15 = -1;

m_InOn14 = -1;

m_InOn2 = -1;

m_InOn3 = -1;

m_InOn4 = -1;

m_InOn5 = -1;

m_InOn6 = -1;

m_InOn7 = -1;

m_InOn8 = -1;

m_InOn9 = -1;

m_InputData = 0;

m_CrOn0 = -1;

m_CrOn1 = -1;

//}}AFX_DATA_INIT

// Note that LoadIcon does not require a subsequent DestroyIcon in Win32

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}

void CASHDlg:Big SmileoDataExchange(CDataExchange* pDX)

{

CDialog:Big SmileoDataExchange(pDX);

//{{AFX_DATA_MAP(CASHDlg)

DDX_Radio(pDX, IDC_POLL_ON, m_PollToggle);

DDX_Radio(pDX, IDC_CR_ON_2, m_CrOn2);

DDX_Radio(pDX, IDC_CR_ON_5, m_CrOn5);

DDX_Radio(pDX, IDC_CR_ON_4, m_CrOn4);

DDX_Radio(pDX, IDC_CR_ON_3, m_CrOn3);

DDX_Text(pDX, IDC_ANALOG0, m_AIn0);

DDX_Text(pDX, IDC_ANALOG1, m_AIn1);

DDX_Text(pDX, IDC_ANALOG2, m_AIn2);

DDX_Text(pDX, IDC_ANALOG3, m_AIn3);

DDX_Text(pDX, IDC_ANALOG4, m_AIn4);

DDX_Text(pDX, IDC_ANALOG5, m_AIn5);

DDX_Text(pDX, IDC_ANALOG6, m_AIn6);

DDX_Radio(pDX, IDC_IN_ON_0, m_InOn0);

DDX_Radio(pDX, IDC_IN_ON_1, m_InOn1);

DDX_Radio(pDX, IDC_IN_ON_10, m_InOn10);

DDX_Radio(pDX, IDC_IN_ON_11, m_InOn11);

DDX_Radio(pDX, IDC_IN_ON_12, m_InOn12);

DDX_Radio(pDX, IDC_IN_ON_13, m_InOn13);

DDX_Radio(pDX, IDC_IN_ON_15, m_InOn15);

DDX_Radio(pDX, IDC_IN_ON_14, m_InOn14);

DDX_Radio(pDX, IDC_IN_ON_2, m_InOn2);

DDX_Radio(pDX, IDC_IN_ON_3, m_InOn3);

DDX_Radio(pDX, IDC_IN_ON_4, m_InOn4);

DDX_Radio(pDX, IDC_IN_ON_5, m_InOn5);

DDX_Radio(pDX, IDC_IN_ON_6, m_InOn6);

DDX_Radio(pDX, IDC_IN_ON_7, m_InOn7);

DDX_Radio(pDX, IDC_IN_ON_8, m_InOn8);

DDX_Radio(pDX, IDC_IN_ON_9, m_InOn9);

DDX_Text(pDX, IDC_INPUT_DATA, m_InputData);

DDX_Radio(pDX, IDC_CR_ON_0, m_CrOn0);

DDX_Radio(pDX, IDC_CR_ON_1, m_CrOn1);

//}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CASHDlg, CDialog)

//{{AFX_MSG_MAP(CASHDlg)

ON_WM_SYSCOMMAND()

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

ON_COMMAND(ID_FILE_EXIT, OnFileExit)

ON_COMMAND(ID_HELP_ABOUT, OnHelpAbout)

ON_WM_TIMER()

ON_BN_CLICKED(IDC_READ_DATA, OnReadData)

ON_BN_CLICKED(IDC_POLL_ON, OnPollOn)

ON_BN_CLICKED(IDC_POLL_OFF, OnPollOff)

ON_BN_CLICKED(IDC_CR_ON_0, OnCrOn0)

ON_BN_CLICKED(IDC_CR_OFF_0, OnCrOff0)

ON_BN_CLICKED(IDC_CR_OFF_1, OnCrOff1)

ON_BN_CLICKED(IDC_CR_OFF_2, OnCrOff2)

ON_BN_CLICKED(IDC_CR_OFF_3, OnCrOff3)

ON_BN_CLICKED(IDC_CR_OFF_4, OnCrOff4)

ON_BN_CLICKED(IDC_CR_OFF_5, OnCrOff5)

ON_BN_CLICKED(IDC_CR_ON_1, OnCrOn1)

ON_BN_CLICKED(IDC_CR_ON_2, OnCrOn2)

ON_BN_CLICKED(IDC_CR_ON_3, OnCrOn3)

ON_BN_CLICKED(IDC_CR_ON_4, OnCrOn4)

ON_BN_CLICKED(IDC_CR_ON_5, OnCrOn5)

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CASHDlg message handlers

BOOL CASHDlg:SurprisenInitDialog()

{

CDialog:SurprisenInitDialog();

// Add "About..." menu item to system menu.

// IDM_ABOUTBOX must be in the system command range.

ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);

ASSERT(IDM_ABOUTBOX < 0xF000);

CMenu* pSysMenu = GetSystemMenu(FALSE);

CString strAboutMenu;

strAboutMenu.LoadString(IDS_ABOUTBOX);

if (!strAboutMenu.IsEmpty())

{

pSysMenu->AppendMenu(MF_SEPARATOR);

pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);

}

// Set the icon for this dialog. The framework does this automatically

// when the application's main window is not a dialog

SetIcon(m_hIcon, TRUE); // Set big icon

SetIcon(m_hIcon, FALSE); // Set small icon

//Set radio buttons to off

m_CrOn0=1;

m_CrOn1=1;

m_CrOn2=1;

m_CrOn3=1;

m_CrOn4=1;

m_CrOn5=1;

m_InOn0 = 1;

m_InOn1 = 1;

m_InOn2 = 1;

m_InOn3 = 1;

m_InOn4 = 1;

m_InOn5 = 1;

m_InOn6 = 1;

m_InOn7 = 1;

m_InOn8 = 1;

m_InOn9 = 1;

m_InOn10 = 1;

m_InOn11 = 1;

m_InOn12 = 1;

m_InOn13 = 1;

m_InOn14 = 1;

m_InOn15 = 1;

UpdateData(FALSE);

ClearRelayOutputs();

CLR_STROBE;

CLR_AD_CS;

return TRUE; // return TRUE unless you set the focus to a control

}

void CASHDlg:SurprisenSysCommand(UINT nID, LPARAM lParam)

{

if ((nID & 0xFFF0) == IDM_ABOUTBOX)

{

CAboutDlg dlgAbout;

dlgAbout.DoModal();

}

else

{

CDialog:SurprisenSysCommand(nID, lParam);

}

}

// If you add a minimize button to your dialog, you will need the code below

// to draw the icon. For MFC applications using the document/view model,

// this is automatically done for you by the framework.

void CASHDlg:SurprisenPaint()

{

if (IsIconic())

{

CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

// Center icon in client rectangle

int cxIcon = GetSystemMetrics(SM_CXICON);

int cyIcon = GetSystemMetrics(SM_CYICON);

CRect rect;

GetClientRect(&rect);

int x = (rect.Width() - cxIcon + 1) / 2;

int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon

dc.DrawIcon(x, y, m_hIcon);

}

else

{

CDialog:SurprisenPaint();

}

}

// The system calls this to obtain the cursor to display while the user drags

// the minimized window.

HCURSOR CASHDlg:SurprisenQueryDragIcon()

{

return (HCURSOR) m_hIcon;

}

void CASHDlg:SurprisenFileExit()

{

OnCancel();

}

void CASHDlg:SurprisenHelpAbout()

{

CAboutDlg dlg;

dlg.DoModal();

}

void CASHDlg:SurprisenTimer(UINT nIDEvent) //timer for polling inputs

{

OnReadData();

CDialog:SurprisenTimer(nIDEvent);

}

void CASHDlg:SurprisenReadData() //reads sensor data and displays it

{

ReadAnalogInput();

bitbang_166();

WriteInputToScreen();

UpdateData(FALSE);

}

void CASHDlg:SurprisenPollOn()

{ // Set polling radio button to on

m_PollToggle = 0;

UpdateData(FALSE);

UINT PosActTimer = 1;

if (SetTimer(PosActTimer, 75, NULL) != PosActTimer)

MessageBox("Error creating timer PosActTimer!");

}

void CASHDlg:SurprisenPollOff()

{ // Set polling radio button to off

m_PollToggle = 1;

UpdateData(FALSE);

UINT PosActTimer = 1;

KillTimer(PosActTimer);

}

void CASHDlg::ReadAnalogInput() //

{

m_AIn0 = bitbang_AtoD(0x00); //read analog input ch0

m_AIn1 = bitbang_AtoD(0x01); //read analog input ch1

m_AIn2 = bitbang_AtoD(0x02); //read analog input ch2

m_AIn3 = bitbang_AtoD(0x03); //read analog input ch3

m_AIn4 = bitbang_AtoD(0x04); //read analog input ch4

m_AIn5 = bitbang_AtoD(0x05); //read analog input ch5

m_AIn6 = bitbang_AtoD(0x06); //read analog input ch6

UpdateData(FALSE);

}

void CASHDlg::WriteInputToScreen() //writes digital switch data to screen

{

if (m_InputData & 0x01)

{

m_InOn0 = 0;}

else

{

m_InOn0 = 1;}

if (m_InputData & 0x02)

{

m_InOn1 = 0;}

else

{

m_InOn1 = 1;}

if (m_InputData & 0x04)

{

m_InOn2 = 0;}

else

{

m_InOn2 = 1;}

if (m_InputData & 0x08)

{

m_InOn3 = 0;}

else

{

m_InOn3 = 1;}

if (m_InputData & 0x10)

{

m_InOn4 = 0;}

else

{

m_InOn4 = 1;}

if (m_InputData & 0x20)

{

m_InOn5 = 0;}

else

{

m_InOn5 = 1;}

if (m_InputData & 0x40)

{

m_InOn6 = 0;}

else

{

m_InOn6 = 1;}

if (m_InputData & 0x80)

{

m_InOn7 = 0;}

else

{

m_InOn7 = 1;}

if (m_InputData & 0x100)

{

m_InOn8 = 0;}

else

{

m_InOn8 = 1;}

if (m_InputData & 0x200)

{

m_InOn9 = 0;}

else

{

m_InOn9 = 1;}

if (m_InputData & 0x400)

{

m_InOn10 = 0;}

else

{

m_InOn10 = 1;}

if (m_InputData & 0x800)

{

m_InOn11 = 0;}

else

{

m_InOn11 = 1;}

if (m_InputData & 0x1000)

{

m_InOn12 = 0;}

else

{

m_InOn12 = 1;}

if (m_InputData & 0x2000)

{

m_InOn13 = 0;}

else

{

m_InOn13 = 1;}

if (m_InputData & 0x4000)

{

m_InOn14 = 0;}

else

{

m_InOn14 = 1;}

if (m_InputData & 0x8000)

{

m_InOn15 = 0;}

else

{

m_InOn15 = 1;}

}

void CASHDlg::ClearRelayOutputs()

{

CLR_STROBE; //force strobe low to get ready for rising edge

DATA(relay_data &=0xc0); //put data on data lines

SET_STROBE; //rising edge clocks data to output

}

void CASHDlg:SurprisenCrOn0()

{

CLR_STROBE; //force strobe low to get ready for rising edge

DATA(relay_data |=0x01); //put data on data lines

SET_STROBE; //rising edge clocks data to output

m_CrOn0 = 0;

}

void CASHDlg:SurprisenCrOff0()

{

CLR_STROBE; //force strobe low to get ready for rising edge

DATA(relay_data &=0xfe); //put data on data lines

SET_STROBE; //rising edge clocks data to output

m_CrOn0 = 1;

}

void CASHDlg:SurprisenCrOn1()

{

CLR_STROBE;

DATA(relay_data |=0x02);

SET_STROBE;

m_CrOn1 = 0;

}

void CASHDlg:SurprisenCrOff1()

{

CLR_STROBE;

DATA(relay_data &=0xfd);

SET_STROBE;

m_CrOn1 = 1;

}

void CASHDlg:SurprisenCrOn2()

{

CLR_STROBE;

DATA(relay_data |=0x04);

SET_STROBE;

m_CrOn2 = 0;

}

void CASHDlg:SurprisenCrOff2()

{

CLR_STROBE;

DATA(relay_data &=0xfb);

SET_STROBE;

m_CrOn2 = 1;

}

void CASHDlg:SurprisenCrOn3()

{

CLR_STROBE;

DATA(relay_data |=0x08);

SET_STROBE;

m_CrOn3 = 0;

}

void CASHDlg:SurprisenCrOff3()

{

CLR_STROBE;

DATA(relay_data &=0xf7);

SET_STROBE;

m_CrOn3 = 1;

}

void CASHDlg:SurprisenCrOn4()

{

CLR_STROBE;

DATA(relay_data |=0x10);

SET_STROBE;

m_CrOn4 = 0;

}

void CASHDlg:SurprisenCrOff4()

{

CLR_STROBE;

DATA(relay_data &=0xef);

SET_STROBE;

m_CrOn4 = 1;

}

void CASHDlg:SurprisenCrOn5()

{

CLR_STROBE;

DATA(relay_data |=0x20);

SET_STROBE;

m_CrOn5 = 0;

}

void CASHDlg:SurprisenCrOff5()

{

CLR_STROBE;

DATA(relay_data &=0xdf);

SET_STROBE;

m_CrOn5 = 1;

}

void CASHDlg::bitbang_166() //this routine talks to the 74hct166 chip

{ unsigned char i;

m_InputData=0;

CLR_CLK;

CLR_166_PE; //enable parallel load of data

//SET_CLK; //clock required for parallel load

//CLR_CLK; //clear clock to get ready for data shift

//SET_166_PE; //disable parallel load enable serial shift

for (i=0; i<16; i++)

{

SET_CLK; //data shifted out on rising edge of clk

SET_166_PE; //this here because hdw cs wrong should be above

m_InputData <<=1; //left shift 1 place to get ready for next bit

if (DlPortReadPortUchar(STAT_ADDR)&0x20) //read data and test to see if bit set

m_InputData+=1; //if bit set, set data bit

CLR_CLK; //clear clock to get ready to do it again

}

}

unsigned short CASHDlg:: bitbang_AtoD(unsigned char address) //this routine talks to the TLC1542 A to D chip

{ unsigned short i;

unsigned short ad_data=0;

CLR_CLK;

CLR_AD_CS; //enable A to D chip

//send address

for (i=0;i<10;i++) //address is only 4 bits long but 10 clocks are required for the conversion

{

if (address & 0x08)

{

DATA (0x40);

}

else

{

DATA (0x00);

}

SET_CLK;

address<<=1;

CLR_CLK;

}

while ((!(DlPortReadPortUchar(STAT_ADDR)&0x40)) && (i < 500)) //wait for a to d EOC

{ //the counter is installed in case the

i++; // a to d fails, so it wont hang forever

}

//recieve data

CLR_AD_CS; //enable A to D chip

CLR_CLK;

for (i=0;i<10;i++) //10 clocks are required for the 10 bits of data

{

SET_CLK;

ad_data<<=1;

if (DlPortReadPortUchar(STAT_ADDR)&0x10)

ad_data +=1;

CLR_CLK;

}

SET_AD_CS; //disable A to D chip

return ad_data;

}





Re: C++ to VFP Translation?

dni


You may use dll's direct from vfp...





Re: C++ to VFP Translation?

Cody King

Yes, and I can do that. The problem is addressing the other channels on the port. I was hoping that someone that was sharp in C (pun intended!) would be able to point in the right syntactic direction. This must be a pretty difficult thing to do.......





Re: C++ to VFP Translation?


Re: C++ to VFP Translation?

CChalom

Here's another link that has some good information:

Language Equivalents

http://msdn2.microsoft.com/en-us/library/czz35az4(VS.71).aspx





Re: C++ to VFP Translation?

Cody King

I did look those over pretty well, and they do help in some things. Take this statement for example:

if (DlPortReadPortUchar(STAT_ADDR)&0x20)

I understand that STAT_ADDR is a parameter, but how the heck do you do add/concatenate/mash/smash/plug the "&0x20" so that VFP likes it






Re: C++ to VFP Translation?

CetinBasoz

& is bitand()

| is bitor()

^ is bitxor() in VFP.

if BitAnd( DlPortReadUchar( STAT_ADDR ), 0x20 )





Re: C++ to VFP Translation?

Cody King

Now THAT looks like something that could do the trick! I'll try that tonight!

Thanks in advance!






Re: C++ to VFP Translation?

Cody King

No Joy.....

These three lines of code should work in a little PRG.... I get a "Data Type Mismatch" error. Am I missing something

Declare String DlPortReadPortUchar in dlportio.dll string

#define STAT_ADDR (0x379) &&//status register of LPT1

BitAnd(DlPortReadPortUchar(STAT_ADDR), 0x20) &&//read data and test to see if bit set






Re: C++ to VFP Translation?

CetinBasoz

STAT_CHAR is an integer as I see from this code but in dll declaration you're claiming it is a string. If you mean to get a string from that address then check sys(2600).



Re: C++ to VFP Translation?

Cody King

That isn't working for me either. I wonder if you could take the code snippet and turn it into a DLL






Re: C++ to VFP Translation?

CetinBasoz

Sorry I don't have time to deal with it.



Re: C++ to VFP Translation?

Cody King

Dude.... it was rhetorical question.

I wasn't asking *you* to do anything at all. God forbid I impose on your valuable time.

Thanks for all your help






Re: C++ to VFP Translation?

Tamar E. Granor

Cody - That message sounds awfully sarcastic to me. You do understand that everyone answering questions here is a volunteer, right No one gets paid for doing this.

Tamar




Re: C++ to VFP Translation?

CChalom

Hi Cody,

You can probably do this by yourself.

You can download a free version of Visual C++ express directly from MS, and create your own dlls.

I've already seen some tutorials on the web, teaching how to create DLLs to work with VFP too.

http://msdn.microsoft.com/vstudio/express/downloads/

http://msdn.microsoft.com/vstudio/express/visualc/

Hope this helps

Cesar