/* devPVME632.c */
/* devPVME632.c - Device Support Routines for VME PVME-632 */
/* 16 bit D/A board (16ch) */
/*
* Original Author: M. Tobiyama
* Current Author: M. Tobiyama
* Date:
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1997, KEKB.
*
*
* Modification Log:
* -----------------
* ver0.0 7/Jun/2000 M.Tobiyama
*/
#include <vxWorks.h>
#include <types.h>
#include <stdioLib.h>
#include <string.h>
#include <iv.h>
#include <vme.h>
#include <dbDefs.h>
#include <dbAccess.h>
#include <recSup.h>
#include <devSup.h>
#include <devCamac.h>
#include <link.h>
#include <module_types.h>
#include <fast_lock.h>
#include <longinRecord.h>
#include <longoutRecord.h>
#include <boRecord.h>
#include <biRecord.h>
#include <mbbiDirectRecord.h>
#include <mbboDirectRecord.h>
#include <waveformRecord.h>
#include <dbScan.h>
/* #define Base_IO 0x20000 */ /* Std. I/O Address */
struct DPvme632 {
unsigned short dac_0;
unsigned short dac_1;
unsigned short dac_2;
unsigned short dac_3;
unsigned short dac_4;
unsigned short dac_5;
unsigned short dac_6;
unsigned short dac_7;
unsigned short dac_8;
unsigned short dac_9;
unsigned short dac_10;
unsigned short dac_11;
unsigned short dac_12;
unsigned short dac_13;
unsigned short dac_14;
unsigned short dac_15;
unsigned short load_reg;
unsigned short sts_reg;
unsigned short zero_reg;
unsigned short dummy[109]
};
/* #define Status Enable */
static long init_all();
static long init_bo_record();
static long init_bi_record();
static long write_bo();
static long read_bi();
static long init_lo_record();
static long write_longout_record();
static unsigned short inpconv();
static int checkLink();
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_lo_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_longout_record;
DEVSUPFUN special_linconv;
}devLoPvme632={
6,
NULL,
NULL,
init_lo_record,
NULL,
write_longout_record,
NULL};
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_bo_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN write_bo;
}devBoPvme632={
5,
NULL,
NULL,
init_bo_record,
NULL,
write_bo
};
struct {
long number;
DEVSUPFUN report;
DEVSUPFUN init;
DEVSUPFUN init_bi_record;
DEVSUPFUN get_ioint_info;
DEVSUPFUN read_bi;
}devBiPvme632={
5,
NULL,
NULL,
init_bi_record,
NULL,
read_bi
};
struct ioCard {
volatile struct DPvme632 *card; /* address of this card */
FAST_LOCK lock; /* semaphore */
};
#define CONST_NUM_LINKS 10
/* #define STATIC */
#define DEBUG_ON
static int debug_flag = 1;
static unsigned long Base_IO;
static int pvme632_num_links;
static struct ioCard cards[CONST_NUM_LINKS];
static int init_flag = 0;
int devPvme632Config(ncards,a24base)
int ncards;
long a24base;
{
pvme632_num_links = ncards;
Base_IO = a24base;
logMsg("Pvme632 NumLink= %d BaseIO= %x\n",pvme632_num_links,Base_IO);
init_all(0);
}
static long init_all(after)
int after;
{
int cardNum, chanNum;
unsigned char probeVal[2];
volatile struct DPvme632 *p;
if (init_flag != 0 )
return(OK);
init_flag = 1;
if (sysBusToLocalAdrs(VME_AM_STD_SUP_DATA,(char *)Base_IO,(char **)&p) == ERROR)
{
logMsg("VmeP632: cannot find A24 address space\n");
return(ERROR);
}
#ifdef DEBUG_ON
if ( CDEBUG)logMsg("PVME632 (init) Called. pass = %d\n", after);
#endif
for (cardNum=0; cardNum< pvme632_num_links; cardNum++)
{
if (vxMemProbe((char*) &(p->sts_reg), READ, 2, &probeVal)< OK)
{
if (debug_flag >0 )
logMsg("No PVME632 with cardNum= %d\n probe= %x\n",cardNum,p);
cards[cardNum].card = NULL;
}
else
{
if (debug_flag >0)
logMsg("Found PVME632 with cardNum= %d\n address= %x\n",cardNum,p);
cards[cardNum].card = p; /* Remember address of the board */
FASTLOCKINIT(&(cards[cardNum].lock));
FASTUNLOCK(&(cards[cardNum].lock)); /* Init the board lock */
p->zero_reg = 0x0001; /* enable output */
}
p++;
}
return(OK);
}
static long init_bi_record(pbi)
struct biRecord *pbi;
{
pbi->mask = 1;
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: /* enable D/A write -- not used */
pbi->rval = cards[cardN].card->sts_reg &pbi->mask;
break;
case 1: /* zero-reset 1: output enable */
pbi->rval = cards[cardN].card->zero_reg & pbi->mask;
break;
}
return(0);
}
static long init_bo_record(pbo)
struct boRecord *pbo;
{
pbo->mask = 1;
return(0);
}
static long write_bo(pbo)
struct boRecord *pbo;
{
short cardN;
cardN = pbo->out.value.vmeio.card;
if (checkLink(cardN) == ERROR)
{
logMsg("Error--- No PVME632 for card %d\n",cardN);
return(ERROR);
}
FASTLOCK(&(cards[cardN].lock));
switch (pbo->out.value.vmeio.signal){
case 0 : /* synchronus output trigger -- not used */
cards[cardN].card->load_reg = pbo->rval & pbo->mask;
break;
case 1: /* enable output = 1 */
cards[cardN].card->zero_reg =pbo ->rval & pbo->mask;
break;
}
FASTUNLOCK(&(cards[cardN].lock));
return(0);
}
static long init_lo_record(plongin)
struct longinRecord *plongin;
{
return(0);
}
static long write_longout_record(plongout)
struct longoutRecord *plongout;
{
short cardN;
cardN = plongout->out.value.vmeio.card;
if (debug_flag >4)
logMsg("write_longout called with card %d\n",cardN);
if (checkLink(cardN) == ERROR)
return(ERROR);
FASTLOCK(&(cards[cardN].lock));
if (debug_flag >4) logMsg("card locked...\n");
switch(plongout->out.value.vmeio.signal){
case 0: /* DAC 0 */
cards[cardN].card->dac_0 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 0 DAC0\n");
break;
case 1: /* DAC 1 */
cards[cardN].card->dac_1 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 1 DAC1\n");
break;
case 2: /* DAC 2 */
cards[cardN].card->dac_2 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 2 DAC2\n");
break;
case 3: /* DAC 3 */
cards[cardN].card->dac_3 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 3 DAC3\n");
break;
case 4: /* DAC 4 */
cards[cardN].card->dac_4 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 4 DAC4\n");
break;
case 5: /* DAC 5 */
cards[cardN].card->dac_5 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 5 DAC5\n");
break;
case 6: /* DAC 6 */
cards[cardN].card->dac_6 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 6 DAC6\n");
break;
case 7: /* DAC 7 */
cards[cardN].card->dac_7 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 7 DAC7\n");
break;
case 8: /* DAC 8 */
cards[cardN].card->dac_8 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 8 DAC8\n");
break;
case 9: /* DAC 9 */
cards[cardN].card->dac_9 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 9 DAC9\n");
break;
case 10: /* DAC 10 */
cards[cardN].card->dac_10 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 10 DAC10\n");
break;
case 11: /* DAC 11 */
cards[cardN].card->dac_11 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 11 DAC11\n");
break;
case 12: /* DAC 12 */
cards[cardN].card->dac_12 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 12 DAC12\n");
break;
case 13: /* DAC 13 */
cards[cardN].card->dac_13 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 13 DAC13\n");
break;
case 14: /* DAC 14 */
cards[cardN].card->dac_14 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 14 DAC14\n");
break;
case 15: /* DAC 15 */
cards[cardN].card->dac_15 = inpconv(plongout->val);
if (debug_flag >4)
logMsg("write_longout signal 15 DAC15\n");
break;
default:
return(-1);
}
FASTUNLOCK(&(cards[cardN].lock));
if (debug_flag >4)
logMsg("unlock card ...\n");
return(CONVERT);
}
static unsigned short inpconv(indata)
long indata;
{
if (indata>32767)
return(65535);
else if (indata <-32768)
return(0);
else
{
return(indata + 32768);
}
}
/**************************************************************************
*
* Make sure card number is valid
*
**************************************************************************/
static int checkLink(cardN)
short cardN;
{
if (cardN >= pvme632_num_links)
return(ERROR);
if (cards[cardN].card == NULL)
{
logMsg("No PVME632 with this number = %d\n",cardN);
return(ERROR);
}
if (debug_flag >5)
logMsg("Yes you have PVME632 with card No= %d\n",cardN);
return(OK);
}