Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Jack H.Integration and automation of manufacturing systems.2001.pdf
Скачиваний:
80
Добавлен:
23.08.2013
Размер:
3.84 Mб
Скачать

page 459

operating systems, but it is relatively easy to add. When it is not a real-time process, it common for another process to monopolize the processor and cause erratic delays. When this happens the control program may not respond to a control event for a second or more. This would generally be a bad thing in a time critical system.

-need to be able to specify how often a process runs.

-RTLinux

-system clock for slower processes.

16.5 DISCRETE IO

16.6 COUNTERS AND TIMERS

16.7 ACCESSING DAQ CARDS FROM LINUX

Listing 16.1 - DAS08 Driver Header File (das08_io.h)

#include "../include/global.h"

#ifndef _DAS08__ #define _DAS08__

 

 

page 460

#define CARDBASE

0x300

 

#define ADCHIGH

0

// AD Data Registers

#define ADCLOW

1

 

/* A/D Status and Control Register */

#define ADCSTATUS2

 

 

/* Auxiliary port on analog bus */

#define PORTAUX

 

2

/* Programmable Gain Register */

#define GAIN

3

 

/* Counter Load & Read Registers */ #define LOADREAD14

#define LOADREAD25 #define LOADREAD36

#define CCONFIGPORT7// Counter Control Register

/* D/A 0 Control Registers */ #define DAC0LOW 8

#define DAC0HIGH9

/* D/A 1 Control Registers */ #define DAC1LOW 10

#define DAC1HIGH11

/* 82C55 Digital I/O Registers */

#define PORTA

12

 

#define PORTB

13

 

#define PORTC

14

 

#define PORTCL

12345

/* real port is 0x30e bits 0-3 */

#define PORTCH

6789

/* real port is 0x30e bits 4-7 */

/* 82C55 Control Register */

 

#define DCONFIGPORT15

 

#define DIGITALOUT

1

 

#define DIGITALIN

2

 

#define HIGHONLASTCOUNT 0

 

#define ONESHOT

1

 

#define RATEGENERATOR2 #define SQUAREWAVE3 #define SOFTWARESTROBE4 #define HARDWARESTROBE5

/* Range Codes */ #define BIP10VOLTS0x08 #define BIP5VOLTS0x00 #define BIP2PT5VOLTS0x02

#define BIP1PT25VOLTS0x04 #define BIPPT625VOLTS0x06 #define UNI10VOLTS0x01 #define UNI5VOLTS0x03 #define UNI2PT5VOLTS0x05 #define UNI1PT25VOLTS0x07

class das08{ protected: public:

int

base;

// card setup information

page 461

int

chan0;

 

int

chan1;

 

int

portA;

// port data directions

int

portB;

 

int

portCL;

 

int

portCH;

 

int

*data_portA;// hooks to global values

int

*data_portB;

int

*data_portCL;

int

*data_portCH;

int

*data_portXI;

int

*data_portXO;

int

*data_AI0;

int

*data_AI1;

int

*data_AI2;

int

*data_AI3;

int

*data_AI4;

int

*data_AI5;

int

*data_AI6;

int

*data_AI7;

int

*data_AO0;

int

*data_AO1;

 

das08();

 

 

~das08();

 

int

configure(char*);

int

connect();

int

scan();

 

int

disconnect();

int

DConfigPort(int, int);

int

DIn(int, int*);

int

DBitIn(int, int, int*);

int

DOut(int, int);

int

DBitOut(int, int, int);

int

C8254Config(int, int);

int

CLoad(int, int);

int

CIn(int, int*);

int

AIn(int, int*);

int

AOut(int, int);

};

#endif

Listing 16.2 - DAS08 Driver File (das08_io.cpp)

#include <errno.h> #include <signal.h> #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/wait.h> #include <netinet/in.h>

page 462

#include <netdb.h> #include <sys/time.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <unistd.h> #include <sys/io.h>

#include "das08_io.h"

#include "../include/process.h"

int bits[]={0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};

das08::das08(){

base = CARDBASE;// default cardbase chan0 = BIP10VOLTS;// default AD ranges chan1 = BIP10VOLTS;

portA = DIGITALIN; portB = DIGITALIN; portCH = DIGITALIN; portCL = DIGITALIN;

}

das08::~das08(){

}

int das08::configure(char *file_name){

int

error;

FILE

*fp_in;

char

params[200];

error = NO_ERROR;

if((fp_in = fopen(file_name, "r")) != NULL){ fgets(params, 200, fp_in); while(feof(fp_in) == 0){

if((params[0] != ’#’) && (strlen(params) > 3)){ if(params[0] == ’B’){

base = atoi(&(params[1]));

} else if(strncmp("A0", params, 2) == 0){ if(strncmp("BIP10VOLTS", &(params[2]), 10) == 0){

chan0 = BIP10VOLTS;

} else if(strncmp("BIP5VOLTS", &(params[2]), 9) ==

0){ chan0 = BIP5VOLTS;

} else if(strncmp("BIP2PT5VOLTS", &(params[2]), 12)

== 0){ chan0 = BIP2PT5VOLTS;

} else if(strncmp("BIP1PT25VOLTS", &(params[2]),

13) == 0){ chan0 = BIP1PT25VOLTS;

} else if(strncmp("BIPPT625VOLTS", &(params[2]),

13) == 0){ chan0 = BIPPT625VOLTS;

} else if(strncmp("UNI10VOLTS", &(params[2]), 10)

== 0){ chan0 = UNI10VOLTS;

} else if(strncmp("UNI5VOLTS", &(params[2]), 9) ==

0){ chan0 = UNI5VOLTS;

} else if(strncmp("UNI2PT5VOLTS", &(params[2]), 12)

== 0){ chan0 = UNI2PT5VOLTS;

} else if(strncmp("UNI1PT25VOLTS", &(params[2]),

13) == 0){ chan0 = UNI1PT25VOLTS;

page 463

} else {

error_log(MINOR, "Unrecognized DAS08

analog A0 output range");

error = ERROR;

}

} else if(strncmp("A1", params, 2) == 0){ if(strncmp("BIP10VOLTS", &(params[2]), 10) == 0){

chan1 = BIP10VOLTS;

} else if(strncmp("BIP5VOLTS", &(params[2]), 9) ==

0){ chan1 = BIP5VOLTS;

} else if(strncmp("BIP2PT5VOLTS", &(params[2]), 12)

== 0){ chan1 = BIP2PT5VOLTS;

} else if(strncmp("BIP1PT25VOLTS", &(params[2]),

13) == 0){ chan1 = BIP1PT25VOLTS;

} else if(strncmp("BIPPT625VOLTS", &(params[2]),

13) == 0){ chan1 = BIPPT625VOLTS;

} else if(strncmp("UNI10VOLTS", &(params[2]), 10)

== 0){ chan1 = UNI10VOLTS;

} else if(strncmp("UNI5VOLTS", &(params[2]), 9) ==

0){ chan1 = UNI5VOLTS;

} else if(strncmp("UNI2PT5VOLTS", &(params[2]), 12)

== 0){ chan1 = UNI2PT5VOLTS;

} else if(strncmp("UNI1PT25VOLTS", &(params[2]),

13) == 0){ chan1 = UNI1PT25VOLTS;

} else {

error_log(MINOR, "Unrecognized DAS08

analog A1 output range");

error = ERROR;

}

} else if(strncmp("PAI", params, 3) == 0){ portA =

DIGITALIN;

} else if(strncmp("PAO", params, 3) == 0){ portA =

DIGITALOUT;

} else if(strncmp("PBI", params, 3) == 0){ portB =

DIGITALIN;

} else if(strncmp("PBO", params, 3) == 0){ portB =

DIGITALOUT;

} else if(strncmp("PCLI", params, 4) == 0){ portCL =

DIGITALIN;

} else if(strncmp("PCLO", params, 4) == 0){ portCL =

DIGITALOUT;

} else if(strncmp("PCHI", params, 4) == 0){ portCH =

DIGITALIN;

} else if(strncmp("PCHO", params, 4) == 0){ portCH =

DIGITALOUT;

} else {

error_log(MINOR, "DAS08 argument not recognized"); error = ERROR;

}

}

fgets(params, 200, fp_in);

}

fclose(fp_in);

}

return error;

}

int das08::connect(){

int error;

error = NO_ERROR; if(ioperm(base, 16, 1) == 0){

page 464

DConfigPort(PORTA, portA);

DConfigPort(PORTB, portB);

DConfigPort(PORTCL, portCL);

DConfigPort(PORTCH, portCH);

} else {

error = ERROR;

error_log(MINOR, "Could not connect to DAS08 board - memory is probably in

use");

}

return error;

}

int das08::scan(){

int error;

error = NO_ERROR;

// update digital ports

if(portA == DIGITALIN){DIn(PORTA, data_portA); } else {DOut(PORTA, data_portA[0]);}

if(portB == DIGITALIN){DIn(PORTB, data_portB); } else {DOut(PORTB, data_portB[0]);}

if(portCL == DIGITALIN){DIn(PORTCL, data_portCL); } else {DOut(PORTCL, data_portCL[0]);}

if(portCH == DIGITALIN){DIn(PORTCH, data_portCH); } else {DOut(PORTCH, data_portCH[0]);} DOut(PORTAUX, data_portXO[0]);

DIn(PORTAUX, data_portXI);

//Update analog inputs AIn(0, data_AI0); AIn(1, data_AI1); AIn(2, data_AI2); AIn(3, data_AI3); AIn(4, data_AI4); AIn(5, data_AI5); AIn(6, data_AI6); AIn(7, data_AI7);

//Update analog outputs AOut(0, data_AO0[0]); AOut(1, data_AO1[0]);

return error;

}

int das08::disconnect(){

int error;

error = NO_ERROR; if(ioperm(base, 16, 0) != 0){

error = ERROR;

error_log(MINOR, "Could not release the DAS08 board - memory is probably in

use");

}

return error;

}

int das08::DConfigPort(int Port, int Direction){

page 465

//This command configures a port as an input or output.

//The Direction field can be either DIGITALIN or DIGITALOUT

//depending on whether the port is to be configured as an

//input or output. Valid ports are PORTA, PORTB, PORTCL and

//PORTCH. Direction bit can be either DIGITALIN or DIGITALOUT.

int

error,

 

mask, OldByte, NewByte;

//printf("Configuring port %d with direction %d \n", Port, Direction); error = NO_ERROR;

OldByte = inb(DCONFIGPORT + base); /*read the current register*/ if(Direction == DIGITALIN){ /* determine mask for DIGITALIN */

if(Port == PORTA){ mask = 0x10;

}else if(Port == PORTB){ mask = 0x02;

}else if(Port == PORTC){ mask = 0x09;

}else if(Port == PORTCL){ mask = 0x01; Port = PORTC;

}else if(Port == PORTCH){ mask = 0x08; Port = PORTC;

}else {

error_log(MINOR, "Digital port must be PORTA, PORTB, PORTC,

PORTCL or PORTCH");

error = ERROR; mask = 0;

}

NewByte = OldByte | mask; /* new data for register */ } else if(Direction == DIGITALOUT){ /* determine mask for DIGITALOUT */

if(Port == PORTA){ mask = 0xef;

}else if(Port == PORTB){ mask = 0xfd;

}else if(Port == PORTC){ mask = 0xf6;

}else if(Port == PORTCL){ mask = 0xfe; Port = PORTC;

}else if(Port == PORTCH){ mask = 0xf7; Port = PORTC;

}else {

error_log(MINOR, "Digital port must be PORTA, PORTB, PORTC,

PORTCL or PORTCH");

error = ERROR;

}

NewByte = OldByte & mask; /* new value for register */

} else {

error_log(MINOR, "Direction must be set to DIGITALIN or DIGITALOUT"); error = ERROR;

}

if(error == NO_ERROR){

//printf("port thingy %d %d \n", NewByte, DCONFIGPORT);

outb(NewByte, DCONFIGPORT + base); /* write config data to register */

}

return error; /* no errors detected */

}

int das08::DBitIn(int Port, int BitNum, int *BitData){

//This function determines whether a bit within the

//requested port is set. The value (1 or 0) is returned

//in the variable pointer sent to the function. Port may

//be PORTA, PORTB, PORTCL or PORTCH. BitNum must be in the

//range 0-7.

int

error,

 

 

mask =

0, data;

error = NO_ERROR;

if((Port == PORTCL) || (Port == PORTCH)){ data = inb(PORTC + base); } else { data = inb(Port + base);}

//printf("GOT %d %d %d %d \n", Port, data, BitNum, BitData[0]);

page 466

if((Port == PORTA) || (Port == PORTB) || (Port == PORTC)){ if((BitNum >= 0) && (BitNum <= 7)){

mask = bits[BitNum];

} else {

error_log(MINOR, "Bit numbers should be between 0 and 7"); error = ERROR;

}

} else if((Port == PORTCL) || (Port == PORTAUX)) { if((BitNum >= 0) && (BitNum <= 3)){

mask = bits[BitNum];

} else {

error_log(MINOR, "Bit numbers should be between 0 and 3"); error = ERROR;

}

} else if(Port == PORTCH) {

if((BitNum >= 4) && (BitNum <= 7)){ mask = bits[BitNum];

} else {

error_log(MINOR, "Bit numbers should be between 4 and 7"); error = ERROR;

}

}else if(Port == DCONFIGPORT) { mask = bits[BitNum];

}else {

error_log(MINOR, "Input port not recognized"); error = ERROR;

}

if(error == NO_ERROR){ BitData[0] = 0;

if((mask & data) != 0) BitData[0] = 1;

}

return error;

}

int das08::DBitOut(int Port, int BitNum, int BitValue){

//This function sets a bit of the requested port to either

//a zero or a one. Port may be PORTA, PORTB, PORTCL or

//PORTCH. BitNum must be in the range 0 - 7. BitValue

//must be 1 or 0.

int

error,

 

mask, NewByte, OldByte;

error = NO_ERROR;

if((Port == PORTCL) || (Port == PORTCH)){ OldByte = inb(PORTC + base);

} else {

OldByte = inb(Port + base);

}

if((Port == PORTAUX) && (BitValue == 1)){

mask = bits[BitNum+4];

 

NewByte = OldByte

| mask;

//printf("ddo %x

%x

\n", mask, OldByte);

}else if((Port == PORTAUX) && (BitValue == 0)) { mask = bits[BitNum+4];

NewByte = OldByte & ~mask;

}else if(((Port==PORTA) || (Port==PORTB) || (Port == PORTC)) && (BitValue==1)){ mask = bits[BitNum];

NewByte = OldByte | mask;

}else if(((Port==PORTA) || (Port==PORTB) || (Port==PORTC)) && (BitValue == 0)){

mask = bits[BitNum];

page 467

NewByte = OldByte & ~mask;

}else if((Port == PORTCL) && (BitValue == 1)){ mask = bits[BitNum];

NewByte = OldByte | mask;

}else if((Port == PORTCL) && (BitValue == 0)){ mask = bits[BitNum];

NewByte = OldByte & ~mask;

}else if((Port == PORTCH) && (BitValue == 1)){ mask = bits[BitNum];

NewByte = OldByte | mask;

}else if((Port == PORTCH) && (BitValue == 0)){ mask = bits[BitNum];

NewByte = OldByte & ~mask;

}else {

error = ERROR;

}

if((Port == PORTCL) || (Port == PORTCH)) Port = PORTC;

//printf("OUT %d %d\n", NewByte, Port + base); if(error == NO_ERROR) outb(NewByte, Port + base);

return error;

}

int das08::DIn(int Port, int *Value){

 

// This function reads the byte value of the specified port

 

// and returns the result in the variable pointer sent to the

 

// function. Valid ports are PORTA, PORTB, PORTCL and PORTCH.

 

int

error;

//

int

result;

//

int

BitData;

 

int

temp;

error = NO_ERROR;

//if(Port == PORTA){

//result = DBitIn(DCONFIGPORT, 4, &BitData);

//} else if(Port == PORTB){

//result = DBitIn(DCONFIGPORT, 1, &BitData);

//} else if(Port == PORTC){

//result = DBitIn(DCONFIGPORT, 0, &BitData)

//

+ DBitIn(DCONFIGPORT, 3, &BitData);

//} else if(Port == PORTCL){

//result = DBitIn(DCONFIGPORT, 0, &BitData);

//} else if(Port == PORTCH){

//result = DBitIn(DCONFIGPORT, 3, &BitData);

//} else if(Port == PORTAUX){

//} else {

//error_log(MINOR, "ERROR: Port not recognized");

//error = ERROR;

//}

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

//printf("sss %d %d \n", Port, result);

//if((error == NO_ERROR) && (BitData == 0)){

//error_log("ERROR: Port not configured for read");

//error = ERROR;

//}

if(error == NO_ERROR){ if(Port == PORTCL){

temp = inb(PORTC + base);/* read the port data */ Value[0] = (temp & 0x0f);/* mask off the high bits */

} else if(Port == PORTCH){

// int

page 468

temp = inb(PORTC + base);/* read the port data */ Value[0] = (temp & 0xf0);/* mask off the low bits */

} else if(Port == PORTAUX){

Value[0] = 0x7 & (int)((inb(Port + base) / 16));

} else {

Value[0] = 0xff & inb(Port + base);/* read the port data */

}

}

return error;

}

int das08::DOut(int Port, int ByteValue){

//This function writes the byte value to the specified port.

//Valid ports are PORTA, PORTB, PORTCL and PORTCH.

int error;

error = NO_ERROR; if(Port == PORTAUX){

ByteValue = (0x07 & inb(Port+base)) | (ByteValue * 16);

}

if((ByteValue > 255) || (ByteValue < 0)){ error = ERROR;

}

//printf("Writing byte %d to port %d\n", ByteValue, Port); if(error == NO_ERROR){

if(Port == PORTCL){

outb((ByteValue & 0x0f), PORTC + base); } else if(Port == PORTCH){

outb((ByteValue & 0xf0), PORTC + base);

} else {

outb(ByteValue, Port + base); /* write the port data */

}

}

return error; /* no errors detected */

}

int das08::C8254Config(int CounterNum, int Config){ int error,

NewByte,

//TempByte,

BCD, mask, counter;

temp;

error = NO_ERROR;

/* BCD = 0xfe - 16-bit binary count

BCD = 0xf1 - 4 decade Binary Coded Decimal */

BCD = 0xfe; switch (Config){

case HIGHONLASTCOUNT:mask = 0xf1; break;

case ONESHOT: mask = 0xf3; break;

case RATEGENERATOR:mask = 0xf5; break; case SQUAREWAVE: mask = 0xf7; break; case SOFTWARESTROBE:mask = 0xf9; break; case HARDWARESTROBE:mask = 0xfb; break; default: error = ERROR;; break;

}

switch (CounterNum){

page 469

case 1: counter = 0x3f; break; case 2: counter = 0x7f; break; case 3: counter = 0xbf; break; default: error = ERROR; break;

}

if(error == NO_ERROR){

NewByte = (BCD & mask) & counter;

//printf("The value of TempByte & mask is --> %x.\n", NewByte); outb(NewByte, CCONFIGPORT + base);

}

return error;

}

int das08::CLoad(int CounterNum, int value)

{

 

char

LoadValue[6];

int

error;

int TempByte, TempByte1, Register, CounterMask; int WriteLowByteMask1 = 0x20;/* RL1 | */

int WriteLowByteMask2 = 0xef;/* RL0 & */ int WriteHighByteMask1 = 0xdf;/* RL1 & */ int WriteHighByteMask2 = 0x10;/* RL0 | */ char LowByte[5];

char HighByte[5];

long HighByteValue, LowByteValue; int test;

error = NO_ERROR; switch (CounterNum){

case 1: Register = LOADREAD1; CounterMask = 0x3f; break; case 2: Register = LOADREAD2; CounterMask = 0x7f; break; case 3: Register = LOADREAD3; CounterMask = 0xbf; break; default: error = ERROR; break;

}

HighByte[0] = LoadValue[0];

HighByte[1] = LoadValue[1];

HighByte[2] = LoadValue[2];

HighByte[3] = LoadValue[3];

LowByte[0] = ’0’;

LowByte[1] = ’x’;

LowByte[2] = LoadValue[4];

LowByte[3] = LoadValue[5];

if(error == NO_ERROR){

HighByteValue = (int)strtol(HighByte, NULL, 0);

LowByteValue = (int)strtol(LowByte, NULL, 0);

TempByte = (CounterMask | WriteLowByteMask1) & WriteLowByteMask2; TempByte1 = TempByte & 0xf0;

//printf("The value in config low is --> %x.\n", TempByte1); outb(TempByte1, CCONFIGPORT + base);

outb(LowByteValue, Register + base);

//printf("The register chosen is --> %x.\n", Register); test = inb(Register + base);

//printf("The value read in counter low is --> %x.\n", test); TempByte = (0x30 & WriteHighByteMask1) | WriteHighByteMask2; //printf("The value in config high is --> %x.\n", TempByte); outb(TempByte, CCONFIGPORT + base);

outb(HighByteValue, Register + base); outb(TempByte, CCONFIGPORT + base); test = inb(Register + base);

page 470

//printf("The value in counter high is --> %x.\n", test);

}

return error;

}

int das08::CIn(int CounterNum, int *CountValue){

int

error;

int

TempByte, Register;

int ReadLowByteMask1 = 0x20;/* RL1 | */ int ReadLowByteMask2 = 0xef;/* RL0 & */ int ReadHighByteMask1 = 0xdf;/* RL1 & */ int ReadHighByteMask2 = 0x10;/* RL0 | */ int CountValue1, CountValue2;

error = NO_ERROR; switch (CounterNum){

case 1: Register = LOADREAD1; break; case 2: Register = LOADREAD2; break; case 3: Register = LOADREAD3; break; default: error = ERROR; break;

}

if(error == NO_ERROR){

TempByte = (0x3f | ReadLowByteMask1) & ReadLowByteMask2; outb(TempByte, CCONFIGPORT + base);

CountValue1 = inb(Register + base);

//printf("The low value is --> %x.\n", CountValue1); TempByte = (0x3f & ReadHighByteMask1) | ReadHighByteMask2; outb(TempByte, CCONFIGPORT + base);

CountValue2 = inb(Register + base);

//printf("The high value is --> %x.\n", CountValue2);

}

return error;

}

int das08::AIn(int ADChannel, int *Value){

//This function requires three arguments to perform the

//analog to digital conversion. ADChannel must be in the

//range 0-7 and Range must be a valid range code

//i.e. BIP5VOLTS. The value of the conversion will be

//returned to the address specificed through the pointer

//variable. This value will be in the range 0-4095.

int error;

int value1, value2, value3, curr_status, new_status, ADbusy; int ADCmask1, ADCmask2;

int ADValue_low, ADValue_low1, ADValue_low2, ADValue_high; int EOC = 1;

error = NO_ERROR;

curr_status = inb(ADCSTATUS + base); /* current value in status */

switch(ADChannel){

case 0:ADCmask1 = 0xf8;ADCmask2 = 0x00;break; case 1:ADCmask1 = 0xf9;ADCmask2 = 0x01;break; case 2:ADCmask1 = 0xfa;ADCmask2 = 0x02;break; case 3:ADCmask1 = 0xfb;ADCmask2 = 0x03;break; case 4:ADCmask1 = 0xfc;ADCmask2 = 0x04;break; case 5:ADCmask1 = 0xfd;ADCmask2 = 0x05;break;

page 471

case 6:ADCmask1 = 0xfe;ADCmask2 = 0x06;break; case 7:ADCmask1 = 0xff;ADCmask2 = 0x07;break; default:error = ERROR;; break; /* error */

}

if(error == NO_ERROR){

outb(chan0, GAIN + base); /* set the gain/range value */ new_status = (curr_status & ADCmask1) | ADCmask2; outb(new_status, ADCSTATUS + base); /* set the channel number */ outb(0x00, ADCLOW + base); /* start a 12 bit A/D conversion */

}

while((error == NO_ERROR) && (EOC == 1)){ /* check for end of conversion */ ADbusy = inb(ADCSTATUS + base); /* read status register */ if(ADbusy >= 128){

EOC = 1; /* A/D still converting */

} else {

EOC = 0; /* A/D done converting */

}

}

if(error == NO_ERROR){

ADValue_low = inb(ADCLOW + base); /* get the lower eight bits */ ADValue_high = inb(ADCHIGH + base); /* get the upper four bits */

switch(ADValue_high){

case 0x00:value1 = 0;break; case 0x80:value1 = 1;break; case 0x40:value1 = 2;break; case 0xc0:value1 = 3;break; case 0x20:value1 = 4;break; case 0xa0:value1 = 5;break; case 0x60:value1 = 6;break; case 0xe0:value1 = 7;break; case 0x10:value1 = 8;break; case 0x90:value1 = 9;break; case 0x50:value1 = 10;break; case 0xd0:value1 = 11;break; case 0x30:value1 = 12;break; case 0xb0:value1 = 13;break; case 0x70:value1 = 14;break; case 0xf0:value1 = 15;break; default:error = ERROR;break;

}

ADValue_low1 = (ADValue_low & 0x0f); /* mask off bits 4-7 */ switch(ADValue_low1){

case 0x00:value2 = 0;break; case 0x01:value2 = 16;break; case 0x02:value2 = 32;break; case 0x03:value2 = 48;break; case 0x04:value2 = 64;break; case 0x05:value2 = 80;break; case 0x06:value2 = 96;break; case 0x07:value2 = 112;break; case 0x08:value2 = 128;break; case 0x09:value2 = 144;break; case 0x0a:value2 = 160;break; case 0x0b:value2 = 176;break; case 0x0c:value2 = 192;break; case 0x0d:value2 = 208;break; case 0x0e:value2 = 224;break; case 0x0f:value2 = 240;break; default:error = ERROR;break;

}

page 472

ADValue_low2 = (ADValue_low & 0xf0); /* mask off bits 0-3 */ switch(ADValue_low2){

case 0x00:value3 = 0;break; case 0x10:value3 = 256;break; case 0x20:value3 = 512;break; case 0x30:value3 = 768;break; case 0x40:value3 = 1024;break; case 0x50:value3 = 1280;break; case 0x60:value3 = 1536;break; case 0x70:value3 = 1792;break; case 0x80:value3 = 2048;break; case 0x90:value3 = 2304;break; case 0xa0:value3 = 2560;break; case 0xb0:value3 = 2816;break; case 0xc0:value3 = 3072;break; case 0xd0:value3 = 3328;break; case 0xe0:value3 = 3584;break; case 0xf0:value3 = 3840;break;

default: error = ERROR; /* error - unknown conversion result */

}

*Value = value1+value2+value3; /* total value for conversion */

}

return error; /* no errors detected */

}

int das08::AOut(int DAChannel, int DAValue){

//This function performs a digital to analog conversion

//routine. The DAChannel must be either 0 or 1 and the

//digital value must be in the range 0-4095.

int

error;

int

low, high, DACLOW, DACHIGH;

error = NO_ERROR; switch(DAChannel){

case 0:DACLOW = DAC0LOW;DACHIGH = DAC0HIGH;break; case 1:DACLOW = DAC1LOW;DACHIGH = DAC1HIGH;break; default:error = ERROR;break;

}

/* The following table converts the digital value into three hex values encompassing two 8-bit registers. The layout of the registers follow:

low

- DA7

DA6

DA5

DA4

DA3

DA2 DA1

DA0

 

high -

x

x

x

x

DA11

DA10 DA9

DA8

*/

if(DAValue <= 255){

 

 

 

 

 

 

 

low

= DAValue;

 

 

 

 

 

 

high =

0x00;

 

 

 

 

 

 

 

}else if((DAValue >= 256) && (DAValue <= 511)){ low = DAValue - 256;

high = 0x01;

}else if((DAValue >= 512) && (DAValue <= 767)) { low = DAValue - 512;

high = 0x02;

}else if((DAValue >= 768) && (DAValue <= 1023)) { low = DAValue - 768;

high = 0x03;

}else if((DAValue >= 1024) && (DAValue <= 1279)) {

page 473

low = DAValue - 1024; high = 0x04;

}else if((DAValue >= 1280) && (DAValue <= 1535)) { low = DAValue - 1280;

high = 0x05;

}else if((DAValue >= 1536) && (DAValue <= 1791)) { low = DAValue - 1536;

high = 0x06;

}else if((DAValue >= 1792) && (DAValue <= 2047)) { low = DAValue - 1792;

high = 0x07;

}else if((DAValue >= 2048) && (DAValue <= 2303)){ low = DAValue - 2048;

high = 0x08;

}else if((DAValue >= 2304) && (DAValue <= 2559)){ low = DAValue - 2304;

high = 0x09;

}else if((DAValue >= 2560) && (DAValue <= 2815)){ low = DAValue - 2560;

high = 0x0a;

}else if((DAValue >= 2816) && (DAValue <= 3071)){ low = DAValue - 2816;

high = 0x0b;

}else if((DAValue >= 3072) && (DAValue <= 3327)){ low = DAValue - 3072;

high = 0x0c;

}else if((DAValue >= 3328) && (DAValue <= 3583)){ low = DAValue - 3328;

high = 0x0d;

}else if((DAValue >= 3584) && (DAValue <= 3839)){ low = DAValue - 3584;

high = 0x0e;

}else if((DAValue >= 3840) && (DAValue <= 4095)){ low = DAValue - 3840;

high = 0x0f;

}else{

error = ERROR; /* error - D/A value must be 0-4095 */

}

if(error == NO_ERROR){

outb(low, DACLOW + base); /* write the low byte value */ outb(high, DACHIGH + base); /* write the high byte value */

}

return error; /* no errors detected */

}

Listing 16.1 - DAS08 Driver Test File (testdaq.cpp)

#include <stdio.h> #include <stdlib.h> #include <string.h>

#include "das08_io.h"

int ChooseCounter(); int ChooseConfig();

int ChooseDir(int DirectNum);

page 474

#define QUERY

350

#defineCHOOSE_PORT

351

#defineCHOOSE_COUNTER352

 

#define CHOOSE_CONFIG353 #defineCHOOSE_DIRECTION 354

int query(int, char*, int);

int main(){

 

 

 

 

int

choice;

 

 

 

das08

*A;

 

 

 

int

value;

 

 

 

A = new das08();

 

 

 

A->configure("das08.conf");

 

 

A->connect();

 

 

 

do{

 

 

 

 

 

printf("\n\n------------ DAS08 Test Harness Menu --------------\n");

 

printf("1.

Digital

Configure\n");

 

printf("2.

Digital

Input

Bit\n");

 

printf("3.

Digital

Input

Word\n");

 

printf("4.

Digital

Output

Bit\n");

 

printf("5.

Digital

Output

Word\n\n");

 

printf("6.

Counter

Configure\n");

 

printf("7.

Counter

Load

Value\n");

 

printf("8.

Counter

Input

Value\n\n");

 

printf("9.

Analog

Input

Value\n");

 

printf("10. Analog

Output

Value\n\n");

 

printf("11. Quit\n\n");

 

 

printf("Select: ");

 

 

 

scanf("%d", &choice);

 

 

 

if(choice == 1){

 

 

 

A->DConfigPort(query(CHOOSE_PORT, NULL, 0),

 

 

 

 

query(CHOOSE_DIRECTION, NULL,

0));

 

 

 

 

 

} else if(choice == 2){

 

 

A->DBitIn(query(CHOOSE_PORT, NULL, 0),

 

 

 

 

query(QUERY, "Choose a bit (0-7): ", 0),

&value);

 

 

 

 

 

printf("The Bit Value is [%d] \n", value);

 

} else if(choice == 3){

 

 

A->DIn(

 

query(CHOOSE_PORT, NULL, 0), &value);

 

printf("The Value is [%d] or [%d]hex\n", value, value);

 

} else if(choice == 4){

 

A->DBitOut(query(CHOOSE_PORT, NULL, 0),

query(QUERY, "Choose a bit (0-7): ", 0), query(QUERY, "Choose a value (0 or 1): ",

0));

} else if(choice == 5){

A->DOut( query(CHOOSE_PORT, NULL, 0),

query(QUERY, "Choose a value (-128 to

127): ", 0));

} else if(choice == 6){ A->C8254Config(query(CHOOSE_COUNTER, NULL, 0),

query(CHOOSE_CONFIG, NULL, 0));

} else if(choice == 7){

A->CLoad( query(CHOOSE_COUNTER, NULL, 0),

page 475

query(QUERY, "Enter a value in the form

0x____ : ", 0));

} else if(choice == 8){

A->CIn( query(CHOOSE_COUNTER, NULL, 0), &value);

printf("The Counter value was [%d]\n", value);

} else if(choice == 9){

A->AIn( query(QUERY, "Enter Channel Number (0-7): ", 0),

&value);

printf("The value is [%d]\n", value); } else if(choice == 10){

A->AOut( query(QUERY, "Enter Channel Number (0-1): ", 0), query(QUERY, "Enter Value (0- 4095): ",

0));

}else if(choice == 11){

}else {

printf("ERROR: Choice not recognized\n");

}

} while(choice != 11); A->disconnect(); delete A;

}

 

 

 

 

int

query(int type, char *text, int def){

 

char

work[20];

 

 

 

int

value;

 

 

 

if(type == QUERY){

 

 

 

 

printf("%s [%d]: ", text, def);

 

 

scanf("%s",

work);

printf("<%s>\n", work);

 

 

 

 

if(strlen(work) == 0){

 

 

return def;

 

 

} else {

 

 

 

 

return atoi(work);

 

 

}

 

 

 

} else if(type == CHOOSE_PORT){

 

 

printf("Which port (1=A, 2=B, 3=C, 4=CH, 5=CL, 6=AUX): ");

 

 

scanf("%d",

&value);

 

 

if(value ==

1)

return PORTA;

 

 

if(value ==

2)

return PORTB;

 

 

if(value ==

3)

return PORTC;

 

 

if(value ==

4)

return PORTCL;

 

 

if(value ==

5)

return PORTCH;

 

 

if(value ==

6)

return PORTAUX;

return ERROR;

}else if(type == CHOOSE_COUNTER){ printf("Which counter (1, 2, 3): "); scanf("%d", &value);

if((value >= 1) || (value <= 3)) return value; return ERROR;

}else if(type == CHOOSE_CONFIG){

printf("Which mode (1=HighOnLastCount, 2=OneShot, 3=RateGenerator, 4=SquareWave, 5=SoftwareStrobe, 6=HardwareStrobe): ");

scanf("%d", &value);

if(value == 1) return HIGHONLASTCOUNT; if(value == 2) return ONESHOT; if(value == 3) return RATEGENERATOR; if(value == 4) return SQUAREWAVE; if(value == 5) return SOFTWARESTROBE; if(value == 6) return HARDWARESTROBE; return ERROR;

} else if(type == CHOOSE_DIRECTION){

printf("Which direction (1=In, 2=Out): ");