From 5d3e47a92240f7a3c1224de62746ee8c2c2b01bf Mon Sep 17 00:00:00 2001 From: Marty Kraimer Date: Thu, 26 May 1994 12:55:19 +0000 Subject: [PATCH] added support for Allen Bradley RTD module --- src/dev/devAllenBradley.c | 142 +++++++++++++++++++++++++++++++++++++- src/drv/drvAb.c | 89 +++++++++++++++++++++--- src/drv/drvAb.h | 22 ++++++ 3 files changed, 242 insertions(+), 11 deletions(-) diff --git a/src/dev/devAllenBradley.c b/src/dev/devAllenBradley.c index 8eb41c0e4..84e180136 100644 --- a/src/dev/devAllenBradley.c +++ b/src/dev/devAllenBradley.c @@ -57,6 +57,7 @@ #include #include #include +#include @@ -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) { diff --git a/src/drv/drvAb.c b/src/drv/drvAb.c index 2a7db8f68..2b07293f6 100644 --- a/src/drv/drvAb.c +++ b/src/drv/drvAb.c @@ -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; + idata[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