Files
sics/site_ansto/hardsup/Digital/hware.c
Douglas Clowes 6928921378 Re-factor device specific code
r1292 | dcl | 2006-11-15 08:41:53 +1100 (Wed, 15 Nov 2006) | 2 lines
2012-11-15 12:53:05 +11:00

549 lines
14 KiB
C

/* vim: ts=8 sts=2 sw=2 cindent
*/
#include "hware.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define DEFAULT_DEVICE "dev2/port0"
#ifdef REGISTER_LEVEL_PROGRAMMING
#define DEVICE_ID_NUMBER "0x7085"
#define DAQmxFailed(e) ((e) != 0)
#define DAQmxGetExtendedErrorInfo(b, l) snprintf(b, l, "BAD")
#include <osiBus.h>
#include <tstaticDIO.h>
typedef unsigned long uInt32;
/**
* This structure contains the data for the PCI-6602 card
*/
typedef struct card_t
{
iBus* bus;
tAddressSpace Bar1;
tstaticDIO *board;
unsigned char dev_mask;
} CARD;
#else
#include <NIDAQmx.h>
#define SAMPLE_COUNT 1
#define PORT_RANGE "Dev2/port0"
#define READ_TIMEOUT 2.0
#define WRITE_TIMEOUT 2.0
#define DAQmxErrChk(functionCall) \
do { if( DAQmxFailed(error=(functionCall)) ) \
goto Error; } while(0)
#endif
#define BUFFER_SIZE 96
/**
* This structure encapsulates the data that is private to
* the implementation of the device
*/
typedef struct device_private_t
{
/** NIDAQ device number of card */
int card_number;
/** NI channel number on card */
int channel_number;
#ifdef REGISTER_LEVEL_PROGRAMMING
HWARE_VALUE value;
CARD* card;
#else
/** NIDAQ opaque task handle */
TaskHandle taskHandle;
/** NIDAQ opaque task handle for digital output */
TaskHandle taskHandle_dout;
/** Actual physical data value, as returned by NIDAQ read function */
uInt8 data[BUFFER_SIZE];
/** previous physical data value */
uInt8 old_data[BUFFER_SIZE];
/** number of samples read */
int32 numRead;
/** number of bytes per sample */
int32 bytesPerSamp;
#endif
} DEVICE_PRIVATE;
#ifdef REGISTER_LEVEL_PROGRAMMING
static void initMite(iBus *bus);
static void initCard(pHWARE ptr);
static void initChan(pHWARE ptr);
static CARD* card[10];
#else
#endif
int hware_ctor(const char* device_name, pHWARE* ptr)
{
pHWARE hware = NULL;
#ifdef REGISTER_LEVEL_PROGRAMMING
CARD* pci = NULL;
#endif
int error = 0;
bool flag = false;
char text_string[] = DEFAULT_DEVICE;
const char *name;
const char *text;
hware = (DEVICE_PRIVATE*) malloc(sizeof(DEVICE_PRIVATE));
*ptr = hware;
memset(hware, 0, sizeof(DEVICE_PRIVATE));
name = device_name;
text = text_string;
while (name && *name)
{
if (isspace(*name))
++name;
else if (*name >= '0' && *name <= '9')
{
if (flag)
{
hware->channel_number = *name - '0';
}
else
{
hware->card_number = *name - '0';
flag = true;
}
}
else if (tolower(*name) != *text)
{
/* TODO error */
printf("Device name error: %s (%d,%d)\n",
device_name,
hware->channel_number,
hware->card_number);
break;
}
++name;
++text;
}
#ifdef REGISTER_LEVEL_PROGRAMMING
if (card[hware->card_number] == NULL)
{
char local_name[40] = "PXI6::1::INSTR";
FILE* fd = fopen("/proc/nirlpk/lsdaq", "r");
if (fd)
{
bool found = false;
int count = 0;
char line[100];
while (fgets(line, 100, fd))
{
if (strstr(line, DEVICE_ID_NUMBER))
{
++count;
name = strstr(line, "PXI");
if (name && count == hware->card_number)
{
found = true;
strcpy(local_name, name);
break;
}
}
if (!found)
{
// TODO error
}
}
fclose(fd);
}
card[hware->card_number] = (CARD*) malloc(sizeof(CARD));
memset(card[hware->card_number], 0, sizeof(CARD));
pci = card[hware->card_number];
hware->card = pci;
pci->bus = acquireBoard((tChar*) local_name /* "PXI6::1::INSTR" */);
if(pci->bus == NULL)
{
printf("Error accessing the PCI device \"%s\". Exiting.\n",
local_name);
error = 1;
goto Error;
}
//Intitialise Mite Chip.
initMite(pci->bus);
initCard(hware);
}
else
{
pci = card[hware->card_number];
hware->card = pci;
}
// Mark the counter on this card as in-use
if (pci->dev_mask & (1 << hware->channel_number))
{
// TODO error
}
pci->dev_mask |= 1 << hware->channel_number;
initChan(hware);
#else
do {
char local_name[40];
/*********************************************/
// Create a DAQmx task
/*********************************************/
DAQmxErrChk (DAQmxCreateTask("",&hware->taskHandle));
DAQmxErrChk (DAQmxCreateTask("",&hware->taskHandle_dout));
/*********************************************/
// Create a DAQmx device within the task
/*********************************************/
snprintf(local_name, sizeof(local_name),
"dev%d/line%d:%d",
hware->card_number,
hware->channel_number * 32,
hware->channel_number * 32 + 23);
DAQmxErrChk (
DAQmxCreateDIChan(hware->taskHandle,
local_name,
"",
DAQmx_Val_ChanForAllLines));
/*********************************************/
// Create the digital output channel within the task
/*********************************************/
snprintf(local_name, sizeof(local_name),
"dev%d/line%d:%d",
hware->card_number,
hware->channel_number * 32 + 24,
hware->channel_number * 32 + 31);
DAQmxErrChk (
DAQmxCreateDOChan(hware->taskHandle_dout,
local_name,
"",
DAQmx_Val_ChanForAllLines));
/*********************************************/
// Start the DAQmx task
/*********************************************/
DAQmxErrChk (DAQmxStartTask(hware->taskHandle));
DAQmxErrChk (DAQmxStartTask(hware->taskHandle_dout));
} while (0);
#endif
hware_write(hware, 0);
return 0;
Error:
free(hware);
*ptr = NULL;
return error;
}
int hware_read(pHWARE hware, HWARE_VALUE* value)
{
int error = 0;
*value = 0;
#ifdef REGISTER_LEVEL_PROGRAMMING
CARD* pci = hware->card;
HWARE_VALUE uPattern;
switch (hware->channel_number)
{
case 0:
uPattern = pci->board->IOPort0Data.readRegister();
uPattern |= pci->board->IOPort1Data.readRegister() << 8;
uPattern |= pci->board->IOPort2Data.readRegister() << 16;
break;
case 1:
uPattern = pci->board->IOPort4Data.readRegister();
uPattern |= pci->board->IOPort5Data.readRegister() << 8;
uPattern |= pci->board->IOPort6Data.readRegister() << 16;
break;
case 2:
uPattern = pci->board->IOPort8Data.readRegister();
uPattern |= pci->board->IOPort9Data.readRegister() << 8;
uPattern |= pci->board->IOPort10Data.readRegister() << 16;
break;
}
*value = uPattern;
#else
/*********************************************/
// DAQmx Read Code
/*********************************************/
hware->numRead = 0;
hware->bytesPerSamp = 0;
error = DAQmxReadDigitalLines (hware->taskHandle,
SAMPLE_COUNT,
READ_TIMEOUT,
DAQmx_Val_GroupByScanNumber,
hware->data,
BUFFER_SIZE,
&hware->numRead,
&hware->bytesPerSamp,
NULL);
#if 0
if (hware->channel_number == 0)
{
int i;
fprintf(stderr, "dev:%d.%d, numRead:%d, bytesPerSamp:%d",
hware->channel_number,
hware->channel_number,
(int) hware->numRead,
(int) hware->bytesPerSamp);
for (i = 0; i < hware->bytesPerSamp; ++i)
fprintf(stderr, ", %02x", hware->data[i]);
fprintf(stderr, "\n");
fflush(stderr);
}
#endif
if (error == DAQmxErrorSamplesNotYetAvailable)
{
printf("Timeout, reading raw data\n");
error = 0;
}
else if (hware_failed(error))
goto Error;
else
{
int i;
HWARE_VALUE uPattern;
uPattern = 0;
for (i = 0; i < hware->bytesPerSamp; ++i)
if (hware->data[i])
uPattern |= 1 << i;
*value = uPattern;
}
return error;
Error:
#endif
return error;
} /* hware_read */
int hware_write(pHWARE hware, HWARE_VALUE value)
{
int error = 0;
#ifdef REGISTER_LEVEL_PROGRAMMING
CARD* pci = hware->card;
switch (hware->channel_number)
{
case 0:
pci->board->IOPort3Data.writeRegister(value & 0xFF);
break;
case 1:
pci->board->IOPort7Data.writeRegister(value & 0xFF);
break;
case 2:
pci->board->IOPort11Data.writeRegister(value & 0xFF);
break;
}
#else
/*********************************************/
// DAQmx Write Code
/*********************************************/
hware->bytesPerSamp = 8;
{
int i;
// copy the data
for (i = 0; i < hware->bytesPerSamp; ++i)
hware->data[i] = (value >> i) & 1;
}
error = DAQmxWriteDigitalLines(hware->taskHandle_dout,
1,
1,
WRITE_TIMEOUT,
DAQmx_Val_GroupByChannel,
hware->data,
NULL,
NULL);
#if 1
if (hware->channel_number == 0)
{
int i;
fprintf(stderr, "dev:%d.%d, Write: %d",
hware->card_number,
hware->channel_number,
(int) hware->bytesPerSamp);
for (i = 0; i < hware->bytesPerSamp; ++i)
fprintf(stderr, ", %02x", hware->data[i]);
fprintf(stderr, "\n");
fflush(stderr);
}
#endif
if (hware_failed(error))
goto Error;
return error;
Error:
#endif
return error;
} /* hware_write */
/*
* Select the source
*/
/*
* Shut down the channel
*/
int hware_dtor(pHWARE* ptr)
{
if (ptr && *ptr)
{
pHWARE hware = *ptr;
#ifdef REGISTER_LEVEL_PROGRAMMING
CARD* pci = hware->card;
switch (hware->channel_number)
{
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
break;
case 5:
break;
}
pci->dev_mask &= ~(1 << hware->channel_number);
if (pci->dev_mask == 0)
{
delete pci->board;
pci->bus->destroyAddressSpace(pci->Bar1);
releaseBoard(pci->bus);
card[hware->card_number] = NULL;
free(pci);
}
#else
if (hware->taskHandle != 0)
{
/*********************************************/
// DAQmx Stop Code
/*********************************************/
DAQmxStopTask(hware->taskHandle);
DAQmxClearTask(hware->taskHandle);
hware->taskHandle = 0;
}
if (hware->taskHandle_dout != 0)
{
/*********************************************/
// DAQmx Stop Code
/*********************************************/
DAQmxStopTask(hware->taskHandle_dout);
DAQmxClearTask(hware->taskHandle_dout);
hware->taskHandle_dout = 0;
}
#endif
/* release the storage */
free(hware);
*ptr = NULL;
}
return 0;
}
bool hware_failed(int error)
{
if (DAQmxFailed(error))
return true;
else
return false;
}
void hware_errmsg(char* buff, int len)
{
*buff = '\0';
DAQmxGetExtendedErrorInfo(buff, len);
}
#ifdef REGISTER_LEVEL_PROGRAMMING
//
//Tell the MITE to link the BAR1 address to the DAQ Board
//You must initialize the MITE before you write to the rest of the PCI board
void initMite(iBus *bus)
{
tAddressSpace Bar0;
u32 physicalBar1;
//Skip MITE initialization for PCMCIA boards
//(which do not have a MITE DMA controller)
if(!bus->get(kIsPciPxiBus,0)) return;
Bar0 = bus->createAddressSpace(kPCI_BAR0);
//Get the physical address of the DAQ board
physicalBar1 = bus->get(kBusAddressPhysical,kPCI_BAR1);
// ***** Generic MITE initialization *****
// Tell the MITE to enable BAR1, where the rest of the board's registers are
Bar0.write32(0xC0, (physicalBar1 & 0xffffff00L) | 0x80);
bus->destroyAddressSpace(Bar0);
}
void initCard(pHWARE hware)
{
CARD* pci = hware->card;
pci->Bar1 = pci->bus->createAddressSpace(kPCI_BAR1);
pci->board = new tstaticDIO(pci->Bar1);
//
// Set All Digital lines as Input so we don't accidentally double drive an IO pin
pci->board->IOSelect0.writeDirection(pci->board->IOSelect0.kDirectionInput);
pci->board->IOSelect1.writeDirection(pci->board->IOSelect1.kDirectionInput);
pci->board->IOSelect2.writeDirection(pci->board->IOSelect2.kDirectionInput);
pci->board->IOSelect3.writeDirection(pci->board->IOSelect3.kDirectionInput);
pci->board->IOSelect4.writeDirection(pci->board->IOSelect4.kDirectionInput);
pci->board->IOSelect5.writeDirection(pci->board->IOSelect5.kDirectionInput);
pci->board->IOSelect6.writeDirection(pci->board->IOSelect6.kDirectionInput);
pci->board->IOSelect7.writeDirection(pci->board->IOSelect7.kDirectionInput);
pci->board->IOSelect8.writeDirection(pci->board->IOSelect8.kDirectionInput);
pci->board->IOSelect9.writeDirection(pci->board->IOSelect9.kDirectionInput);
pci->board->IOSelect10.writeDirection(pci->board->IOSelect10.kDirectionInput);
pci->board->IOSelect11.writeDirection(pci->board->IOSelect11.kDirectionInput);
}
void initChan(pHWARE hware)
{
CARD* pci = hware->card;
/*
* Set up the channel object
*/
switch (hware->channel_number)
{
case 0:
pci->board->IOSelect0.writeDirection(pci->board->IOSelect0.kDirectionInput);
pci->board->IOSelect1.writeDirection(pci->board->IOSelect1.kDirectionInput);
pci->board->IOSelect2.writeDirection(pci->board->IOSelect2.kDirectionInput);
pci->board->IOSelect3.writeDirection(pci->board->IOSelect3.kDirectionOutput);
break;
case 1:
pci->board->IOSelect4.writeDirection(pci->board->IOSelect4.kDirectionInput);
pci->board->IOSelect5.writeDirection(pci->board->IOSelect5.kDirectionInput);
pci->board->IOSelect6.writeDirection(pci->board->IOSelect6.kDirectionInput);
pci->board->IOSelect7.writeDirection(pci->board->IOSelect7.kDirectionOutput);
break;
case 2:
pci->board->IOSelect8.writeDirection(pci->board->IOSelect8.kDirectionInput);
pci->board->IOSelect9.writeDirection(pci->board->IOSelect9.kDirectionInput);
pci->board->IOSelect10.writeDirection(pci->board->IOSelect10.kDirectionInput);
pci->board->IOSelect11.writeDirection(pci->board->IOSelect11.kDirectionOutput);
break;
}
}
#else
#endif