/* devVme18k14.c */
/* devVme18k14.c - Device Support Routines for VME 64 ch adc board */
/*
*
* Original Author: Makoto Tobiyama
* Current Author:
* Date: 10/Sep/2013
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1997, KEKB.
*
*
* Modification Log:
* -----------------
*/
#include <vxLib.h>#include <logLib.h>
#include <sysLib.h>
/* #include <memLib.h> */
#include <intLib.h>
#include <stdio.h>
| #include | <stdioLib.h> |
| #include | <string.h> |
/* #include <sys/time.h> */
| #include | <vme.h> |
| #include | <dbDefs.h> |
| #include | <dbAccess.h> |
| #include | <recSup.h> |
| #include | <devSup.h> |
#include <iv.h>
| #include | <module_types.h> |
| #include | <longinRecord.h> |
| #include | <longoutRecord.h> |
| #include | <boRecord.h> |
| #include | <biRecord.h> |
| #include | <mbbiDirectRecord.h> |
| #include | <mbboDirectRecord.h> |
| #include | <waveformRecord.h> |
#include <stringoutRecord.h>
#include <epicsMutex.h>#include <epicsExport.h>
#include <vxLib.h>
#include <time.h>
struct D18k14 {
unsigned long mean[32];
unsigned long peak[32];
unsigned long mini[32];
unsigned long curr[32];
unsigned long math_enb;
unsigned long math_size;
unsigned long math_single;
unsigned long math_end;
unsigned long status;
unsigned long adc_sw;
unsigned long irq_id;
unsigned long irq_no;
unsigned long irqenb;
unsigned long sync;
unsigned long dum2;
unsigned long dum3;
unsigned long res1;
unsigned long ave_mode;
unsigned long res2;
unsigned long fpga_ver;
unsigned long dum4[112];
};
static long init_all();
static long init_bo_record();
static long write_bo();
static long init_bi_record();
static long read_bi();
static long init_wf_record();
static long read_wf_record();
static long init_lo_record();
static long write_longout();
static long init_li_record();
static long read_longin();
static int checkLink();
/* Create the dset for devBo18k14 */
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_bo;
}devBo18k14={
5,
NULL,
NULL,
init_bo_record,
NULL,
write_bo
};
epicsExportAddress(dset,devBo18k14);
/* Create the dset for devBi18k14 */
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_bi;
}devBi18k14={
5,
NULL,
NULL,
init_bi_record,
NULL,
read_bi
};
epicsExportAddress(dset,devBi18k14);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_write;
DEVSUPFUN conv;
}devWf18k14 ={
6,
NULL,
NULL,
init_wf_record,
NULL,
read_wf_record,
NULL
};
epicsExportAddress(dset,devWf18k14);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_longout;
DEVSUPFUN special_linconv;
}devLo18k14={
6,
NULL,
NULL,
init_lo_record,
NULL,
write_longout,
NULL
};
epicsExportAddress(dset,devLo18k14);
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_longin;
DEVSUPFUN special_linconv;
}devLi18k14={
6,
NULL,
NULL,
init_li_record,
NULL,
read_longin,
NULL};
epicsExportAddress(dset,devLi18k14);
struct ioCard {
volatile struct D18k14 *card; /* address of this card */
epicsMutexId lock; /* semaphore */
};
#define CONST_NUM_LINKS 10
/* #define STATIC */
#define DEBUG_ON
static int debug_flag = 5;
static unsigned long Base_IO;
static int D18k14_num_links;
static struct ioCard cards[CONST_NUM_LINKS];
static int init_flag = 0;
int dev18k14Config(ncards,a32base)
int ncards;
long a32base;
{
D18k14_num_links = ncards;
Base_IO = a32base;
logMsg("dev18k14 NumLink= %d BaseIO= %x\n",D18k14_num_links,Base_IO,0,0,0,0);
init_all(0);
return 0;
}
static long init_all(after)
int after;
{
int cardNum;
unsigned char probeVal[4];
volatile struct D18k14 *p;
if (init_flag != 0 )
return(OK);
init_flag = 1;
if (sysBusToLocalAdrs(VME_AM_EXT_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
{
logMsg("18k14: cannot find extended address space\n",0,0,0,0,0,0);
return(ERROR);
}
/* if (debug_flag >0) logMsg("18k14 address %x\n",(int)p,0,0,0,0,0); */
for (cardNum=0; cardNum< D18k14_num_links; cardNum++)
{
if (vxMemProbe((char*) &(p->status), READ, 4, (char *)&probeVal[0])!= OK)
{
if (debug_flag >0 )
logMsg("No 18k14 with cardNum= %d\n probe= %x\n",cardNum,(int)p,0,0,0,0);
cards[cardNum].card = NULL;
} else
{
if (debug_flag >0)
logMsg("Found 18k14 with cardNum= %d\n address= %x\n",cardNum,(int)p,0,0,0,0);
cards[cardNum].card = p; /* Remember address of the board */
}
cards[cardNum].lock = epicsMutexMustCreate();
epicsMutexUnlock((cards[cardNum].lock)); /* Init the board lock */
p++;
}
return(OK);
}
/**************************************************************************
*
* BO Initialization (Called one time for each BO PowerUT card record)
*
**************************************************************************/
static long init_bo_record(pbo)
struct boRecord *pbo;
{
pbo->mask = 1;
return(0);
}
/**************************************************************************
*
* Perform a write operation from a BO record
*
**************************************************************************/
static long write_bo(pbo)
struct boRecord *pbo;
{
short cardN;
cardN = pbo->out.value.vmeio.card;
if (checkLink(cardN) == ERROR)
{
logMsg("Error--- No 18k14 for card %d\n",cardN,0,0,0,0,0);
return(ERROR);
}
if (debug_flag>5) logMsg("BO\n",0,0,0,0,0,0);
epicsMutexMustLock((cards[cardN].lock));
switch(pbo->out.value.vmeio.signal){
case 0 : /* math enable 1: enable */
cards[cardN].card->math_enb = pbo->val & 0x1;
break;
case 1 : /* math_single 1: for debug */
cards[cardN].card->math_single = pbo->val & 0x1;
break;
case 2 : /* irqenb 1 : enable */
cards[cardN].card->irqenb = pbo->val &0x1;
break;
case 3 : /* ave_mode 1: round, 0 : cut */
cards[cardN].card->ave_mode = pbo->val &0x1;
break;
case 4 : /* soft sync */
cards[cardN].card->sync = 0x1;
break;
default :
break;
}
epicsMutexUnlock((cards[cardN].lock));
return(0);
}
static long init_bi_record(pbi)
struct biRecord *pbi;
{
pbi->mask=0x1;
return(0);
}
static long read_bi(pbi)
struct biRecord *pbi;
{
short cardN;
cardN = pbi->inp.value.vmeio.card;
if (checkLink(cardN) == ERROR)
return(ERROR);
switch(pbi->inp.value.vmeio.signal){
case 0:
pbi->rval = cards[cardN].card->math_enb & pbi->mask;
break;
case 1:
pbi->rval = cards[cardN].card->math_single & pbi->mask;
break;
case 2:
pbi->rval = cards[cardN].card->math_end & pbi->mask;
break;
case 3:
pbi->rval = cards[cardN].card->irqenb & pbi->mask;
break;
case 4:
pbi->rval = cards[cardN].card->ave_mode & pbi->mask;
break;
default:
break;
}
return(0);
}
static long init_lo_record(plongout)
struct longoutRecord *plongout;
{
return(0);
}
static long write_longout(plongout)
struct longoutRecord *plongout;
{
short cardN;
cardN = plongout->out.value.vmeio.card;
if (debug_flag >10)
logMsg("write_lo called with card %d\n",cardN,0,0,0,0,0);
if (checkLink(cardN) == ERROR)
return(ERROR);
epicsMutexMustLock((cards[cardN].lock));
switch(plongout->out.value.vmeio.signal){
case 0 : /* math size */
cards[cardN].card->math_size = 0x3 & (plongout->val);
break;
default: break; }
epicsMutexUnlock((cards[cardN].lock));
return(0);
}
static long init_li_record(plongin)
struct longinRecord *plongin;
{
return(0);
}
static long read_longin(plongin)
struct longinRecord *plongin;
{
short cardN;
if (debug_flag >10)
logMsg("read_longin called...\n",0,0,0,0,0,0);
cardN = plongin->inp.value.vmeio.card;
if (checkLink(cardN) == ERROR)
return(ERROR);
switch(plongin->inp.value.vmeio.signal){
case 0: /* math size */
plongin->val = (cards[cardN].card->math_size) & 0x3;
break;
case 1: /* status */
plongin->val = (cards[cardN].card->status) & 0x7;
break;
case 2: /* adc_switch */
plongin->val = (cards[cardN].card->adc_sw) & 0xff;
break;
case 3 : /* irq_id */
plongin->val = (cards[cardN].card->irq_id) & 0xff;
break;
case 4: /* IRQ_NO */
plongin->val = (cards[cardN].card->irq_no) & 0x7;
default: break;
}
return(OK);
}
static long init_wf_record(pwf)
| struct waveformRecord | *pwf; |
{ /*
short cardNum;
cardNum = pwf->inp.value.vmeio.card;
if (intConnect(INUM_TO_IVEC(INT_VEC_BASE + cardNum),
(VOIDFUNCPTR)vme18k14_isr,
(int)pwf) != OK)
logMsg("devVme18k14: Interrupt connect failed for card %d\n",pwf->inp.value.vmeio.card); logMsg("intConnect 0x%x\n",pwf);
sysIntEnable(int_level); logMsg("devVme18k14 int set for int 0x%x\n",int_level);
*/
return(0);
}
static long read_wf_record(pwf)
| struct waveformRecord | *pwf; |
{ short cardN;
unsigned long a1;
long ii;
short* s_thing = (short*)pwf->bptr;
cardN = pwf->inp.value.vmeio.card;
if (debug_flag >5)
logMsg("read_wf_record called with card number of %d\n",cardN,0,0,0,0,0);
if (checkLink(cardN) == ERROR)
return(ERROR);
switch(pwf->inp.value.vmeio.signal){
case 0: { /* avarage channel */
for (ii=0;ii<32;ii++)
{
a1 = (unsigned long)(cards[cardN].card->mean[ii]);
s_thing[ii*2] = (short)((a1>>16) & 0xffff);
s_thing[ii*2+1] = (short)(a1 & 0xffff);
}
pwf->nord = 64;
break;
}
case 1: { /* peak */
for (ii=0;ii<32;ii++)
{
a1 = (unsigned long)(cards[cardN].card->peak[ii]);
s_thing[ii*2] = (short)((a1>>16) & 0xffff);
s_thing[ii*2+1] = (short)(a1 & 0xffff);
}
pwf->nord = 64;
break;
}
case 2: { /* mini */
for (ii=0;ii<32;ii++)
{
a1 = (unsigned long)(cards[cardN].card->mini[ii]);
s_thing[ii*2] = (short)((a1>>16) & 0xffff);
s_thing[ii*2+1] = (short)(a1 & 0xffff);
}
pwf->nord = 64;
break;
}
case 3: { /* curr */
for (ii=0;ii<32;ii++)
{
a1 = (unsigned long)(cards[cardN].card->curr[ii]);
s_thing[ii*2] = (short)((a1>>16) & 0xffff);
s_thing[ii*2+1] = (short)(a1 & 0xffff);
}
pwf->nord = 64;
break;
}
default : logMsg("Invalid Signal\n",0,0,0,0,0,0);
}
if (debug_flag >5) logMsg("18k14 card %d end of read\n",cardN,0,0,0,0,0);
return(0);
}
/*
static long get_wf_int_info(cmd,pwf,ppvt)
int cmd;
struct waveformRecord *pwf;
IOSCANPVT *ppvt;
{
short cardN;
unsigned char stat;
cardN = pwf->inp.value.vmeio.card;
*ppvt = cards[cardN].ioscanpvt;
if (debug_flag >5) logMsg("wf_INT CALLED\n");
return(0);
}
*/
/**************************************************************************
*
* Make sure card number is valid
*
**************************************************************************/
static int checkLink(cardN)
short cardN;
{
if (cardN >= D18k14_num_links)
return(ERROR);
if (cards[cardN].card == NULL)
{
logMsg("No 18K14 with this number = %d\n",cardN,0,0,0,0,0);
return(ERROR);
}
if (debug_flag >10)
logMsg("Yes you have 18k14 with card No= %d\n",cardN,0,0,0,0,0);
return(OK);
}