Initial revision
This commit is contained in:
404
src/drv/drvKscV215.c
Normal file
404
src/drv/drvKscV215.c
Normal file
@@ -0,0 +1,404 @@
|
||||
/*
|
||||
* KscV215_driver.c
|
||||
*
|
||||
* driver for KscV215 VXI module
|
||||
*
|
||||
* Author: Jeff Hill
|
||||
* Date: 052192
|
||||
*
|
||||
* Experimental Physics and Industrial Control System (EPICS)
|
||||
*
|
||||
* Copyright 1991, the Regents of the University of California,
|
||||
* and the University of Chicago Board of Governors.
|
||||
*
|
||||
* This software was produced under U.S. Government contracts:
|
||||
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
|
||||
* and (W-31-109-ENG-38) at Argonne National Laboratory.
|
||||
*
|
||||
* Initial development by:
|
||||
* The Controls and Automation Group (AT-8)
|
||||
* Ground Test Accelerator
|
||||
* Accelerator Technology Division
|
||||
* Los Alamos National Laboratory
|
||||
*
|
||||
* Co-developed with
|
||||
* The Controls and Computing Group
|
||||
* Accelerator Systems Division
|
||||
* Advanced Photon Source
|
||||
* Argonne National Laboratory
|
||||
*
|
||||
* Modification Log:
|
||||
* -----------------
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <vxWorks.h>
|
||||
#ifdef V5_vxWorks
|
||||
# include <68k/iv.h>
|
||||
#else
|
||||
# include <iv68k.h>
|
||||
#endif
|
||||
#include <types.h>
|
||||
#include <module_types.h>
|
||||
#include <task_params.h>
|
||||
#include <fast_lock.h>
|
||||
#include <epvxiLib.h>
|
||||
|
||||
#define LOCAL
|
||||
|
||||
#define VXI_MODEL_KSCV215 (0x215)
|
||||
|
||||
#define MAXTRIES 100
|
||||
|
||||
#define KSCV215_PCONFIG(LA) \
|
||||
epvxiPConfig((LA), KscV215DriverId, struct KscV215_config *)
|
||||
|
||||
#define ChannelEnable(PCSR) ((PCSR)->dir.w.dd.reg.ddx08)
|
||||
#define ModuleStatus(PCSR) ((PCSR)->dir.r.status)
|
||||
|
||||
#define ALL_SWITCHES_OPEN 0
|
||||
|
||||
struct KscV215_config{
|
||||
FAST_LOCK lock; /* mutual exclusion */
|
||||
};
|
||||
|
||||
#define KSCV215_INT_LEVEL 1
|
||||
#define KscV215Handshake (0x0040)
|
||||
#define KscV215csrInit (0x9000)
|
||||
|
||||
LOCAL
|
||||
int KscV215DriverId;
|
||||
|
||||
void KscV215_int_service();
|
||||
void KscV215_init_card();
|
||||
void KscV215_stat();
|
||||
int KscV215WriteSync();
|
||||
|
||||
|
||||
struct KscV215_A24{
|
||||
unsigned short diag;
|
||||
unsigned short isr;
|
||||
unsigned short pad1[7];
|
||||
unsigned short channels[64]; /* odd access causes a bus error ? */
|
||||
unsigned short controlMemoryAddr;
|
||||
unsigned short pad2;
|
||||
unsigned short controlMemoryDataWrite;
|
||||
unsigned short pad3;
|
||||
unsigned short controlMemoryDataRead;
|
||||
unsigned short pad4;
|
||||
unsigned short lastChannel;
|
||||
unsigned short pad5;
|
||||
unsigned short singleScan;
|
||||
unsigned short pad6;
|
||||
unsigned short stopScan;
|
||||
unsigned short pad7;
|
||||
unsigned short clearControlMemoryAddr;
|
||||
unsigned short pad8;
|
||||
unsigned short enableContinuousScanning;
|
||||
unsigned short pad9;
|
||||
unsigned short disableContinuousScanning;
|
||||
unsigned short pad10;
|
||||
unsigned short enableDoneInt;
|
||||
unsigned short pad11;
|
||||
unsigned short disbaleDoneInt;
|
||||
unsigned short pad12;
|
||||
unsigned short clearDoneInt;
|
||||
unsigned short pad13;
|
||||
unsigned short testDoneInt;
|
||||
unsigned short pad14;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* KscV215_init
|
||||
*
|
||||
* initialize all KscV215 cards
|
||||
*
|
||||
*/
|
||||
KscV215Init()
|
||||
{
|
||||
int r0;
|
||||
|
||||
/*
|
||||
* do nothing on crates without VXI
|
||||
*/
|
||||
if(!epvxiResourceMangerOK){
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
KscV215DriverId = vxiUniqueDriverID();
|
||||
|
||||
{
|
||||
epvxiDeviceSearchPattern dsp;
|
||||
|
||||
dsp.flags = VXI_DSP_make | VXI_DSP_model;
|
||||
dsp.make = VXI_MAKE_KSC;
|
||||
dsp.model = VXI_MODEL_KSCV215;
|
||||
r0 = epvxiLookupLA(&dsp, KscV215_init_card, (void *)NULL);
|
||||
if(r0<0){
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* KSCV215_INIT_CARD
|
||||
*
|
||||
* initialize single at5vxi card
|
||||
*
|
||||
*/
|
||||
LOCAL void
|
||||
KscV215_init_card(la)
|
||||
unsigned la;
|
||||
{
|
||||
int status;
|
||||
int i;
|
||||
struct KscV215_config *pc;
|
||||
struct KscV215_A24 *pA24;
|
||||
struct vxi_csr *pcsr;
|
||||
|
||||
status = epvxiOpen(
|
||||
la,
|
||||
KscV215DriverId,
|
||||
(unsigned long) sizeof(*pc),
|
||||
KscV215_stat);
|
||||
if(status<0){
|
||||
logMsg("KscV215: device open failed %d\n", la);
|
||||
return;
|
||||
}
|
||||
|
||||
pc = KSCV215_PCONFIG(la);
|
||||
if(pc == NULL){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
return;
|
||||
}
|
||||
|
||||
pA24 = epvxiA24Base(la);
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pcsr->dir.w.control = KscV215csrInit;
|
||||
|
||||
status = KscV215WriteSync(pA24, &pA24->controlMemoryAddr, 0);
|
||||
if(status<0){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
logMsg("KscV215 init failed\n");
|
||||
return;
|
||||
}
|
||||
for(i=0; i<(NELEMENTS(pA24->channels)/2); i++){
|
||||
status = KscV215WriteSync(
|
||||
pA24,
|
||||
&pA24->controlMemoryDataWrite,
|
||||
0);
|
||||
if(status<0){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
logMsg("KscV215 init failed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* turn on continuous scan mode
|
||||
*/
|
||||
status = KscV215WriteSync(
|
||||
pA24,
|
||||
&pA24->enableContinuousScanning,
|
||||
0);
|
||||
if(status<0){
|
||||
epvxiClose(la, KscV215DriverId);
|
||||
logMsg("KscV215 init failed- device left open\n");
|
||||
return;
|
||||
}
|
||||
|
||||
FASTLOCKINIT(&pc->lock);
|
||||
|
||||
#ifdef INTERRUPTS
|
||||
r0 = intConnect(
|
||||
(unsigned char) INUM_TO_IVEC(la),
|
||||
KscV215_int_service,
|
||||
(void *) la);
|
||||
if(r0 == ERROR)
|
||||
return;
|
||||
sysIntEnable(KSCV215_INT_LEVEL);
|
||||
#endif
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* KscV215WriteSync
|
||||
*
|
||||
*
|
||||
*/
|
||||
LOCAL int
|
||||
KscV215WriteSync(pA24, preg, val)
|
||||
struct KscV215_A24 *pA24;
|
||||
unsigned short *preg;
|
||||
unsigned short val;
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<MAXTRIES; i++){
|
||||
*preg = val;
|
||||
if(pA24->diag & KscV215Handshake){
|
||||
return OK;
|
||||
}
|
||||
taskDelay(1);
|
||||
}
|
||||
|
||||
logMsg("KscV215 timed out\n");
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* KscV215_int_service()
|
||||
*
|
||||
*
|
||||
* This device interrupts once the
|
||||
* switches have settled
|
||||
*
|
||||
*/
|
||||
#ifdef INTERRUPTS
|
||||
LOCAL void
|
||||
KscV215_int_service(la)
|
||||
unsigned la;
|
||||
{
|
||||
struct KscV215_config *pc;
|
||||
|
||||
pc = KSCV215_PCONFIG(la);
|
||||
if(pc == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* operation completed so we can update
|
||||
* the shadow value
|
||||
*/
|
||||
|
||||
/*
|
||||
* tell them that the switches have settled
|
||||
*/
|
||||
io_scanner_wakeup(IO_AI, KSCV215_BI, la);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* KSCV215_STAT
|
||||
*
|
||||
* initialize single at5vxi card
|
||||
*
|
||||
*/
|
||||
LOCAL void
|
||||
KscV215_stat(la,level)
|
||||
unsigned la;
|
||||
int level;
|
||||
{
|
||||
struct KscV215_config *pc;
|
||||
struct vxi_csr *pcsr;
|
||||
struct KscV215_A24 *pA24;
|
||||
int i;
|
||||
|
||||
pc = KSCV215_PCONFIG(la);
|
||||
if(pc == NULL){
|
||||
return;
|
||||
}
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pA24 = (struct KscV215_A24 *) epvxiA24Base(la);
|
||||
|
||||
if(level>0){
|
||||
printf ("KSC V215 32 CHANNEL 16 BIT ADC.\n");
|
||||
}
|
||||
if (level > 1) {
|
||||
for (i = 0; i < 32; i++)
|
||||
printf ("Channel %d Value %d\n",
|
||||
i,
|
||||
pA24->channels[i*2]);
|
||||
}
|
||||
if (level > 2) {
|
||||
printf ("\nGain Setting (Control Memory Data Register\n");
|
||||
pA24->controlMemoryAddr = 0;
|
||||
for (i = 0; i < 32; i++) {
|
||||
switch (pA24->controlMemoryAddr) {
|
||||
case 0:
|
||||
printf ("+- 10V");
|
||||
break;
|
||||
case 1:
|
||||
printf ("+- 5V");
|
||||
break;
|
||||
case 3:
|
||||
printf ("+- 2.5V");
|
||||
break;
|
||||
case 5:
|
||||
printf ("+- 1.25V");
|
||||
break;
|
||||
case 6:
|
||||
printf ("+- 625mV");
|
||||
break;
|
||||
default:
|
||||
printf ("Unknown Gain Setting.");
|
||||
}
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
* AT5VXI_AI_DRIVER
|
||||
*
|
||||
* analog input driver
|
||||
*/
|
||||
int
|
||||
KscV215_ai_driver(la,chan,prval)
|
||||
register unsigned short la;
|
||||
unsigned short chan;
|
||||
register unsigned short *prval;
|
||||
{
|
||||
struct KscV215_config *pc;
|
||||
struct vxi_csr *pcsr;
|
||||
struct KscV215_A24 *pA24;
|
||||
long tmp;
|
||||
int i;
|
||||
|
||||
pc = KSCV215_PCONFIG(la);
|
||||
if(pc == NULL){
|
||||
return ERROR;
|
||||
}
|
||||
pcsr = VXIBASE(la);
|
||||
|
||||
pA24 = epvxiA24Base(la);
|
||||
|
||||
if(chan >= NELEMENTS(pA24->channels)/2)
|
||||
return ERROR;
|
||||
|
||||
for(i=0; i<MAXTRIES; i++){
|
||||
tmp = pA24->channels[chan<<1];
|
||||
if(pA24->diag & KscV215Handshake){
|
||||
tmp = tmp + 0xffff;
|
||||
tmp = tmp >> 4;
|
||||
tmp &= 0xfff;
|
||||
*prval = tmp;
|
||||
return OK;
|
||||
}
|
||||
taskDelay(1);
|
||||
}
|
||||
|
||||
return ERROR;
|
||||
}
|
||||
Reference in New Issue
Block a user