291 lines
6.3 KiB
C
291 lines
6.3 KiB
C
/* drvStc.c */
|
||
/* base/src/drv $Id$ */
|
||
/*
|
||
* The following are specific driver routines for the AMD STC
|
||
*
|
||
* NOTE: if multiple threads use these routines at once you must provide locking
|
||
* so command/data sequences are gauranteed. See mz8310_driver.c for examples.
|
||
*
|
||
*
|
||
* Author: Jeff Hill
|
||
* Date: Feb 89
|
||
*
|
||
* 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:
|
||
* -----------------
|
||
*
|
||
* joh 022089 Init Release
|
||
* joh 042889 Added read back
|
||
* joh 111789 Fixed reset goes to byte mode bug
|
||
* joh 121090 Fixed confusion about the polarity of internal/external
|
||
* clock between DB and the drivers.
|
||
* joh 110791 Prevent the stc from generating tc prior to the trigger
|
||
* in delayed pulse mode by forcing edge 0 delays of zero to be
|
||
* a delay of one instead.
|
||
* joh 010491 force all edge 0 delays less than two to two
|
||
* joh 082493 ANSI C and EPICS return codes
|
||
*/
|
||
|
||
#include <vxWorks.h>
|
||
#include <stdioLib.h>
|
||
#include <vxLib.h>
|
||
|
||
#include <dbDefs.h>
|
||
#include <drvSup.h>
|
||
#include <module_types.h>
|
||
#include <drvStc.h>
|
||
#include <devLib.h>
|
||
|
||
|
||
|
||
/*
|
||
* stc_io_report()
|
||
*/
|
||
stcStat stc_io_report(
|
||
volatile uint8_t *pcmd,
|
||
volatile uint16_t *pdata
|
||
)
|
||
{
|
||
uint8_t cmd;
|
||
uint16_t data;
|
||
|
||
if(vxMemProbe((char *)pcmd, READ, sizeof(cmd), (char *)&cmd) != OK)
|
||
return S_dev_noDevice;
|
||
if(vxMemProbe((char *)pdata, READ, sizeof(data), (char *)&data) != OK)
|
||
return S_dev_noDevice;
|
||
|
||
/*
|
||
* addd AMD STC status here
|
||
*/
|
||
|
||
return STC_SUCCESS;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* stc_init()
|
||
*/
|
||
stcStat stc_init(
|
||
volatile uint8_t *pcmd,
|
||
volatile uint16_t *pdata,
|
||
unsigned master_mode
|
||
)
|
||
{
|
||
uint8_t cmd;
|
||
uint16_t data;
|
||
unsigned channel;
|
||
|
||
if(vxMemProbe((char *)pcmd, READ, sizeof(cmd), (char *)&cmd) != OK)
|
||
return S_dev_noDevice;
|
||
if(vxMemProbe((char *)pdata, READ, sizeof(data), (char *)&data) != OK)
|
||
return S_dev_noDevice;
|
||
|
||
/*
|
||
* go to 16 bit mode in order to test the master mode register
|
||
*/
|
||
STC_BUS16;
|
||
if(master_mode != STC_MASTER_MODE){
|
||
|
||
/*
|
||
* start in a known state
|
||
*/
|
||
STC_RESET;
|
||
|
||
/*
|
||
* required since the reset puts it in byte mode
|
||
*/
|
||
STC_BUS16;
|
||
STC_SET_MASTER_MODE(master_mode);
|
||
for(channel=0; channel<CHANONCHIP; channel++)
|
||
STC_LOAD;
|
||
}
|
||
|
||
return STC_SUCCESS;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* stc_one_shot_read()
|
||
*/
|
||
stcStat stc_one_shot_read(
|
||
unsigned *preset,
|
||
unsigned short *edge0_count,
|
||
unsigned short *edge1_count,
|
||
volatile uint8_t *pcmd,
|
||
volatile uint16_t *pdata,
|
||
unsigned channel,
|
||
unsigned *int_source
|
||
)
|
||
{
|
||
uint8_t cmd;
|
||
uint16_t data;
|
||
uint16_t mode;
|
||
uint16_t edge0;
|
||
uint16_t edge1;
|
||
|
||
if(vxMemProbe((char *)pcmd, READ, sizeof(cmd), (char *)&cmd) != OK)
|
||
return S_dev_noDevice;
|
||
if(vxMemProbe((char *)pdata, READ, sizeof(data), (char *)&data) != OK)
|
||
return S_dev_noDevice;
|
||
|
||
if(channel>=CHANONCHIP)
|
||
return S_dev_badSignalNumber;
|
||
|
||
STC_CTR_READ(mode, edge0, edge1);
|
||
|
||
/*
|
||
* Only return values if the counter is in the proper mode
|
||
* see stc_one_shot() for info on conversions and functions selected
|
||
* by these bit fields
|
||
*/
|
||
if(mode == 0xc16a){
|
||
*int_source = FALSE;
|
||
*preset = TRUE;
|
||
*edge0_count = ~edge0;
|
||
*edge1_count = ~edge1+1;
|
||
}
|
||
else if(mode == 0xc162){
|
||
*int_source = FALSE;
|
||
*preset = FALSE;
|
||
*edge0_count = edge0-1;
|
||
*edge1_count = edge1;
|
||
}
|
||
else if(mode == 0xcb6a){
|
||
*int_source = TRUE;
|
||
*preset = TRUE;
|
||
*edge0_count = ~edge0;
|
||
*edge1_count = ~edge1+1;
|
||
}
|
||
else if(mode == 0xcb62){
|
||
*int_source = TRUE;
|
||
*preset = FALSE;
|
||
*edge0_count = edge0-1;
|
||
*edge1_count = edge1;
|
||
}
|
||
else
|
||
return S_dev_internal;
|
||
|
||
return STC_SUCCESS;
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* stc_one_shot()
|
||
*/
|
||
stcStat stc_one_shot(
|
||
unsigned preset,
|
||
unsigned edge0_count,
|
||
unsigned edge1_count,
|
||
volatile uint8_t *pcmd,
|
||
volatile uint16_t *pdata,
|
||
unsigned channel,
|
||
unsigned int_source
|
||
)
|
||
{
|
||
uint8_t cmd;
|
||
uint16_t data;
|
||
|
||
if(vxMemProbe((char *)pcmd, READ, sizeof(cmd), (char *)&cmd) != OK)
|
||
return S_dev_noDevice;
|
||
if(vxMemProbe((char *)pdata, READ, sizeof(data), (char *)&data) != OK)
|
||
return S_dev_noDevice;
|
||
if(channel>=CHANONCHIP)
|
||
return S_dev_badSignalNumber;
|
||
|
||
/*
|
||
* joh 110791
|
||
* Prevent the stc from generating tc prior to the trigger
|
||
* in delayed pulse mode by forcing edge 0 delays of zero to be
|
||
* a delay of one instead.
|
||
*
|
||
* 010492
|
||
* Strange extra edges occur when the delay is 0 or 1
|
||
* and the counter is reinitialized to a width of
|
||
* zero so I have disabled a delay of one also
|
||
*
|
||
* These extra edges occur when TC is set
|
||
*/
|
||
|
||
if(edge0_count < 2)
|
||
edge0_count = 2;
|
||
|
||
STC_DISARM;
|
||
|
||
/*
|
||
* active positive going edge (gate input)
|
||
* count on the rising edge of source
|
||
* ctr source: (F1- internal) (SRC1- external)
|
||
* mode L - Hardware triggered delayed pulse one-shot
|
||
* binary count
|
||
* count down (count up if preset is TRUE)
|
||
* TC toggled output
|
||
*
|
||
* see chapter 7 of the Am9513 STC tech man concerning count + 1
|
||
*
|
||
*/
|
||
|
||
/*
|
||
* NOTE: I must be able to read back the state of the preset later
|
||
* so I encode this information in the count down/up bit.
|
||
* count up on TRUE preset
|
||
* count down on FALSE preset
|
||
*
|
||
* see stc_one_shot_read() above
|
||
*/
|
||
if(int_source){
|
||
if(preset)
|
||
STC_CTR_INIT(0xcb6a, ~edge0_count, ~edge1_count+1)
|
||
else
|
||
STC_CTR_INIT(0xcb62, edge0_count+1, edge1_count);
|
||
}else{
|
||
if(preset)
|
||
STC_CTR_INIT(0xc16a, ~edge0_count, ~edge1_count+1)
|
||
else
|
||
STC_CTR_INIT(0xc162, edge0_count+1, edge1_count);
|
||
}
|
||
|
||
STC_LOAD;
|
||
/*
|
||
*see chapter 7 of the Am9513 STC tech man concerning this step
|
||
*/
|
||
|
||
STC_STEP;
|
||
|
||
STC_SET_TC(preset);
|
||
|
||
/*
|
||
* Only arm counter if the pulse has a finite duration
|
||
*/
|
||
if(edge1_count != 0){
|
||
STC_ARM;
|
||
}
|
||
|
||
return STC_SUCCESS;
|
||
}
|
||
|
||
|
||
|