added support for Allen Bradley RTD module
This commit is contained in:
+141
-1
@@ -57,6 +57,7 @@
|
||||
#include <boRecord.h>
|
||||
#include <mbbiRecord.h>
|
||||
#include <mbboRecord.h>
|
||||
#include <drvAb.h>
|
||||
|
||||
|
||||
|
||||
@@ -79,7 +80,10 @@ static long linconv_1771Il();
|
||||
static long init_1771Ixe();
|
||||
static long read_1771Ixe();
|
||||
static long linconv_1771Ixe();
|
||||
static int read_1771Ofe();
|
||||
static long init_1771IrPlatinum();
|
||||
static long read_1771IrPlatinum();
|
||||
static long init_1771IrCopper();
|
||||
static long read_1771IrCopper();
|
||||
typedef struct {
|
||||
long number;
|
||||
DEVSUPFUN report;
|
||||
@@ -100,8 +104,13 @@ ABAIDSET devAiAb1771Il= {6, NULL, NULL, init_1771Il, NULL,
|
||||
read_1771Il, linconv_1771Il};
|
||||
ABAIDSET devAiAb1771Ixe= {6, NULL, NULL, init_1771Ixe, NULL,
|
||||
read_1771Ixe, linconv_1771Ixe};
|
||||
ABAIDSET devAiAb1771IrPlatinum= {6, NULL, NULL, init_1771IrPlatinum, NULL,
|
||||
read_1771IrPlatinum, NULL};
|
||||
ABAIDSET devAiAb1771IrCopper= {6, NULL, NULL, init_1771IrCopper, NULL,
|
||||
read_1771IrCopper, NULL};
|
||||
|
||||
static long init_1771Ofe();
|
||||
static int read_1771Ofe();
|
||||
static long write_1771Ofe();
|
||||
static long linconv_1771Ofe();
|
||||
typedef struct {
|
||||
@@ -549,7 +558,138 @@ static long linconv_1771Ixe(struct aiRecord *pai, int after)
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long init_1771IrPlatinum(struct aiRecord *pai)
|
||||
{
|
||||
short value;
|
||||
struct abio *pabio;
|
||||
short conversion;
|
||||
|
||||
/* ai.inp must be an AB_IO */
|
||||
switch (pai->inp.type) {
|
||||
case (AB_IO) :
|
||||
break;
|
||||
default :
|
||||
recGblRecordError(S_db_badField,(void *)pai,
|
||||
"devAiAb1771IrPlatinum (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
pabio = (struct abio *)&(pai->inp.value);
|
||||
if(pabio->parm[0]=='C') {
|
||||
conversion=IR_degC;
|
||||
strcpy(pai->egu,"degC");
|
||||
} else if(pabio->parm[0]=='O') {
|
||||
conversion = IR_Ohms;
|
||||
strcpy(pai->egu,"ohms");
|
||||
} else {
|
||||
conversion = 0;
|
||||
strcpy(pai->egu,"degF");
|
||||
}
|
||||
pai->linr = 0;
|
||||
/* call driver so that it configures card */
|
||||
/* The driver returns error for first call for a card. Ignore it. */
|
||||
ab_aidriver(AB1771IrPlatinum,pabio->link,pabio->adapter,
|
||||
pabio->card,pabio->signal,pabio->plc_flag,&value,conversion);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long read_1771IrPlatinum(struct aiRecord *pai)
|
||||
{
|
||||
struct abio *pabio;
|
||||
long status;
|
||||
short value;
|
||||
short conversion;
|
||||
|
||||
|
||||
pabio = (struct abio *)&(pai->inp.value);
|
||||
if(pabio->parm[0]=='C') conversion=IR_degC;
|
||||
else if(pabio->parm[0]=='O') conversion = IR_Ohms;
|
||||
else conversion = 0;
|
||||
status=ab_aidriver(AB1771IrPlatinum,pabio->link,pabio->adapter,
|
||||
pabio->card,pabio->signal,pabio->plc_flag,&value,conversion);
|
||||
if(status==-2) {
|
||||
recGblSetSevr(pai,HW_LIMIT_ALARM,INVALID_ALARM);
|
||||
status = 0;
|
||||
}
|
||||
if(status==0) {
|
||||
if(conversion==IR_Ohms) pai->val = ((double)value)/100.0;
|
||||
else pai->val = ((double)value)/10.0;
|
||||
pai->udf = FALSE;
|
||||
status=2; /*don't convert*/
|
||||
} else if(status==-1) {
|
||||
if(recGblSetSevr(pai,READ_ALARM,INVALID_ALARM) && errVerbose
|
||||
&& (pai->stat!=READ_ALARM || pai->sevr!=INVALID_ALARM))
|
||||
recGblRecordError(-1,(void *)pai,"ab_aidriver Error");
|
||||
status = 2; /*don't convert*/
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
static long init_1771IrCopper(struct aiRecord *pai)
|
||||
{
|
||||
short value;
|
||||
struct abio *pabio;
|
||||
short conversion;
|
||||
|
||||
/* ai.inp must be an AB_IO */
|
||||
switch (pai->inp.type) {
|
||||
case (AB_IO) :
|
||||
break;
|
||||
default :
|
||||
recGblRecordError(S_db_badField,(void *)pai,
|
||||
"devAiAb1771IrCopper (init_record) Illegal INP field");
|
||||
return(S_db_badField);
|
||||
}
|
||||
pabio = (struct abio *)&(pai->inp.value);
|
||||
if(pabio->parm[0]=='C') {
|
||||
conversion=IR_degC;
|
||||
strcpy(pai->egu,"degC");
|
||||
} else if(pabio->parm[0]=='O') {
|
||||
conversion = IR_Ohms;
|
||||
strcpy(pai->egu,"ohms");
|
||||
} else {
|
||||
conversion = 0;
|
||||
strcpy(pai->egu,"degF");
|
||||
}
|
||||
pai->linr = 0;
|
||||
/* call driver so that it configures card */
|
||||
/* The driver returns error for first call for a card. Ignore it. */
|
||||
ab_aidriver(AB1771IrCopper,pabio->link,pabio->adapter,
|
||||
pabio->card,pabio->signal,pabio->plc_flag,&value,conversion);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static long read_1771IrCopper(struct aiRecord *pai)
|
||||
{
|
||||
struct abio *pabio;
|
||||
long status;
|
||||
short value;
|
||||
short conversion;
|
||||
|
||||
|
||||
pabio = (struct abio *)&(pai->inp.value);
|
||||
if(pabio->parm[0]=='C') conversion=IR_degC;
|
||||
else if(pabio->parm[0]=='O') conversion = IR_Ohms;
|
||||
else conversion = 0;
|
||||
status=ab_aidriver(AB1771IrCopper,pabio->link,pabio->adapter,
|
||||
pabio->card,pabio->signal,pabio->plc_flag,&value,conversion);
|
||||
if(status==-2) {
|
||||
recGblSetSevr(pai,HW_LIMIT_ALARM,INVALID_ALARM);
|
||||
status = 0;
|
||||
}
|
||||
if(status==0) {
|
||||
if(conversion==IR_Ohms) pai->val = ((double)value)/100.0;
|
||||
else pai->val = ((double)value)/10.0;
|
||||
pai->udf = FALSE;
|
||||
status=2; /*don't convert*/
|
||||
} else if(status==-1) {
|
||||
if(recGblSetSevr(pai,READ_ALARM,INVALID_ALARM) && errVerbose
|
||||
&& (pai->stat!=READ_ALARM || pai->sevr!=INVALID_ALARM))
|
||||
recGblRecordError(-1,(void *)pai,"ab_aidriver Error");
|
||||
status = 2; /*don't convert*/
|
||||
}
|
||||
return(status);
|
||||
}
|
||||
|
||||
static long init_1771Ofe(struct aoRecord *pao)
|
||||
{
|
||||
|
||||
|
||||
+79
-10
@@ -384,13 +384,25 @@ int ab_intr (); /* interrupt service routine */
|
||||
* 0x1000 - adapter/plc flag
|
||||
* 0 - adapter
|
||||
* 1 - PLC
|
||||
* 0x0f00 - conversion (from ~gta/dbcon/h/fields.h)
|
||||
* 0x0f00 - conversion
|
||||
* For IXE
|
||||
* 0 - no conversion (use millivolt range)
|
||||
* 1 - linear (use millivolt range)
|
||||
* 2 - k - degrees F
|
||||
* 3 - k - degrees K
|
||||
* 4 - j - degrees F
|
||||
* 5 - j - degrees K
|
||||
* 2 - K_DGF
|
||||
* 3 - K_DGC
|
||||
* 4 - J_DGF
|
||||
* 5 - J_DGC
|
||||
* 6 - E_DGF
|
||||
* 7 - E_DGC
|
||||
* 8 - T_DGF
|
||||
* 9 - T_DGC
|
||||
* 10- R_DGF
|
||||
* 11- R_DGC
|
||||
* 12- S_DGF
|
||||
* 13- S_DGC
|
||||
* For Ir
|
||||
* 0- degF
|
||||
* 1- degC
|
||||
* 0x00e0 - interface type
|
||||
* 0 - Not Assigned
|
||||
* 1 - Binary Input
|
||||
@@ -435,6 +447,7 @@ int abScanId; /* id of the Allen-Bradley scan task */
|
||||
short ab_timers[AB_MAX_LINKS][AB_MAX_ADAPTERS][AB_MAX_CARDS];
|
||||
#define AB_IXE_RATE 5 /* .5 seconds */
|
||||
#define AB_IL_RATE 4 /* .4 seconds */
|
||||
#define AB_IR_RATE 5 /* .5 seconds */
|
||||
#define AB_IFE_RATE 1 /* .1 seconds */
|
||||
#define AB_OFE_RATE 10 /* 1 seconds - written immediately */
|
||||
#define AB_INT_LEVEL 5
|
||||
@@ -577,6 +590,12 @@ register short pass;
|
||||
btq_err = OK; /* assume success */
|
||||
if ((*pcard & AB_INTERFACE_TYPE) == AB_AI_INTERFACE){
|
||||
switch (*pcard&AB_CARD_TYPE){
|
||||
case (AB1771IrPlatinum) :
|
||||
case (AB1771IrCopper) :
|
||||
if ((pass % AB_IR_RATE) == 0) {
|
||||
btq_err = bt_queue(AB_READ,link,adapter,card,8,&msg[0]);
|
||||
}
|
||||
break;
|
||||
case (AB1771IL):
|
||||
if ((pass % AB_IL_RATE) == 0) {
|
||||
btq_err = bt_queue(AB_READ,link,adapter,card,12,&msg[0]);
|
||||
@@ -630,10 +649,19 @@ short link;
|
||||
register short *pab_table;
|
||||
|
||||
bfill(pmsg,64*2,0);
|
||||
|
||||
*pmsg = 0;
|
||||
switch (*pcard & AB_INTERFACE_TYPE){
|
||||
case (AB_AI_INTERFACE):
|
||||
switch (*pcard & AB_CARD_TYPE){
|
||||
case (AB1771IrCopper) :
|
||||
*pmsg = IR_COPPER;
|
||||
case (AB1771IrPlatinum) :
|
||||
i = (*pcard & AB_CONVERSION) >> 8;
|
||||
if(i==IR_degF) *pmsg |= IR_UNITS_DEGF;
|
||||
if(i==IR_Ohms) *pmsg |= IR_UNITS_OHMS;
|
||||
*pmsg |= IR_SIGNED;
|
||||
length = 1;
|
||||
break;
|
||||
case (AB1771IXE): /* millivolt module */
|
||||
/* need to base this on conversion */
|
||||
switch ((*pcard & AB_CONVERSION) >> 8){
|
||||
@@ -987,7 +1015,31 @@ abDoneTask(){
|
||||
/* it was a response to a command */
|
||||
/* analog input response */
|
||||
}else if ((*pcard & AB_INTERFACE_TYPE) == AB_AI_INTERFACE){
|
||||
if ((*pcard & AB_CARD_TYPE) == AB1771IL)
|
||||
if((*pcard & AB_CARD_TYPE) == AB1771IrPlatinum
|
||||
|| (*pcard & AB_CARD_TYPE) == AB1771IrCopper)
|
||||
{
|
||||
struct ab1771ir_read *pmsg = (struct ab1771ir_read *) presponse->data;
|
||||
short under,over,overflow,polarity;
|
||||
|
||||
pab_table = &ab_btdata[link][adapter][card][0];
|
||||
pab_sts = &ab_btsts[link][adapter][card][0];
|
||||
for(i=0, under = 0x1, over=0x100, overflow=0x1, polarity=0x100;
|
||||
i<ai_num_channels[AB1771IrPlatinum];
|
||||
i++, under<<=1, over<<=1, overflow<<=1, polarity<<=1) {
|
||||
*pab_table = pmsg->data[i];
|
||||
if(pmsg->pol_over&polarity) *pab_table = -*pab_table;
|
||||
if((pmsg->status&under) || (pmsg->status&over)
|
||||
|| (pmsg->pol_over&overflow)) {
|
||||
*pab_sts = -3;
|
||||
ab_scaling_error[link][adapter][card]++;
|
||||
}else{
|
||||
*pab_sts = 0;
|
||||
}
|
||||
pab_sts++;
|
||||
pab_table++;
|
||||
}
|
||||
}
|
||||
else if ((*pcard & AB_CARD_TYPE) == AB1771IL)
|
||||
{
|
||||
register struct ab1771il_read *pmsg
|
||||
= (struct ab1771il_read *)presponse->data;
|
||||
@@ -2026,6 +2078,24 @@ ab_io_report(level)
|
||||
if (level > 0){
|
||||
ab_ai_report(type,i,adapter,card,plc_card);
|
||||
}
|
||||
} else if ((ab_config[i][adapter][card] & AB_CARD_TYPE) == AB1771IrPlatinum){
|
||||
printf("\tAI: AB1771IrPlatinum\tadapter %d card %d:\tcto: %d dto: %d sclerr: %d %d",
|
||||
adapter,card,ab_cmd_to[i][adapter][card],
|
||||
ab_data_to[i][adapter][card],
|
||||
ab_scaling_error[i][adapter][card],
|
||||
ab_or_scaling_error[i][adapter][card]);
|
||||
if (level > 0){
|
||||
ab_ai_report(type,i,adapter,card,plc_card);
|
||||
}
|
||||
} else if ((ab_config[i][adapter][card] & AB_CARD_TYPE) == AB1771IrCopper){
|
||||
printf("\tAI: AB1771IrPlatinum\tadapter %d card %d:\tcto: %d dto: %d sclerr: %d %d",
|
||||
adapter,card,ab_cmd_to[i][adapter][card],
|
||||
ab_data_to[i][adapter][card],
|
||||
ab_scaling_error[i][adapter][card],
|
||||
ab_or_scaling_error[i][adapter][card]);
|
||||
if (level > 0){
|
||||
ab_ai_report(type,i,adapter,card,plc_card);
|
||||
}
|
||||
} else if ((ab_config[i][adapter][card] & AB_CARD_TYPE) == AB1771IFE_SE){
|
||||
printf("\tAI: AB1771IFE_SE\tadapter %d card %d:\tcto: %d dto: %d sclerr: %d %d",
|
||||
adapter,card,ab_cmd_to[i][adapter][card],
|
||||
@@ -2116,12 +2186,11 @@ ab_ai_report(type,link,adapter,card,plc_card)
|
||||
short i,num_chans;
|
||||
unsigned short value;
|
||||
|
||||
printf("\n\t");
|
||||
|
||||
num_chans = ai_num_channels[type];
|
||||
for(i=0; i<num_chans; i++) {
|
||||
if(i%8 == 0) printf("\n\t");
|
||||
ab_aidriver(type,link,adapter,card,i,plc_card,&value,0);
|
||||
printf("%4x",value);
|
||||
printf(" %4x",value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -321,4 +321,26 @@ struct ab1771ixe_read {
|
||||
short data[8]; /* current values */
|
||||
unsigned short cjcw; /* cold junction cal word */
|
||||
};
|
||||
|
||||
/*Conversion value passed to abb_ai_driver*/
|
||||
#define IR_degF 0
|
||||
#define IR_degC 1
|
||||
#define IR_Ohms 2
|
||||
/*Register definitions*/
|
||||
#define IR_UNITS_DEGF 0x40
|
||||
#define IR_UNITS_OHMS 0x80
|
||||
#define IR_COPPER 0x100
|
||||
#define IR_SIGNED 0x400
|
||||
/* configuration data transfer to the IR card */
|
||||
struct ab1771ir_config {
|
||||
unsigned short conv_rate; /* conversion and scan rate data */
|
||||
unsigned short resistance; /* 10ohm resiatance @25 degC */
|
||||
unsigned short bias[6]; /* bias */
|
||||
unsigned short calibration[6]; /* */
|
||||
};
|
||||
|
||||
struct ab1771ir_read {
|
||||
unsigned short status; /* status and over/under range */
|
||||
unsigned short pol_over; /* polarity and overflow */
|
||||
short data[6]; /* current values */
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user