From 18eca2c71b4f54045299580cb692e048c870cea1 Mon Sep 17 00:00:00 2001
From: Gunther <core-talk@aps.anl.gov>
Date: Fri, 26 Jun 1992 10:17:23 +0000
Subject: [PATCH] combined drvStc.c and stcdriver.c

---
 src/drv/drvStc.c | 268 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 268 insertions(+)

diff --git a/src/drv/drvStc.c b/src/drv/drvStc.c
index 2880b5919..ba44460f0 100644
--- a/src/drv/drvStc.c
+++ b/src/drv/drvStc.c
@@ -1,6 +1,51 @@
 
 /* drvStc.c */
 /* share/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
+ *  bg  062692  force all edge 0 delays less than two to two
+ */
 
 /* drvStc.c -  Driver Support Routines for Stc */
 #include	<vxWorks.h>
@@ -37,3 +82,226 @@ static long init()
 
     return(0);
 }
+
+#define CHANONCHIP		5
+#define CHIPCHAN		(channel%CHANONCHIP)
+#define CHIPNUM			(channel/CHANONCHIP)
+
+#define STC_RESET		*pcmd = 0xff
+#define STC_BUS16		*pcmd = 0xef
+#define STC_SET_MASTER_MODE(D)	{*pcmd = 0x17; *pdata=(D);}
+#define STC_MASTER_MODE		(*pcmd = 0x17, *pdata)
+
+#define STC_CTR_INIT(MODE,LOAD,HOLD)\
+{*pcmd = CHIPCHAN+1; *pdata = (MODE); *pdata = (LOAD); *pdata= (HOLD);}
+
+#define STC_CTR_READ(MODE,LOAD,HOLD)\
+{*pcmd = CHIPCHAN+1; (MODE) = *pdata; (LOAD) = *pdata; (HOLD) = *pdata;}
+
+#define STC_SET_TC(D)		*pcmd = 0xe0 | ((D)?8:0)|(CHIPCHAN+1)
+
+#define STC_LOAD		*pcmd = 0x40 | 1<<(CHIPCHAN)
+#define STC_STEP		*pcmd = 0xf0 | (CHIPCHAN+1)
+#define STC_ARM			*pcmd = 0x20 | 1<<CHIPCHAN
+#define STC_DISARM		*pcmd = 0xc0 | 1<<CHIPCHAN
+
+stc_io_report(pcmd,pdata)
+register unsigned char 	*pcmd;
+register unsigned short *pdata;
+{
+  int	cmd, data;
+
+  if(vxMemProbe(pcmd, READ, sizeof(*pcmd), &cmd) != OK)
+    return ERROR;
+  if(vxMemProbe(pdata, READ, sizeof(*pdata), &data) != OK)
+    return ERROR;
+
+  return OK;
+}
+
+
+stc_init(pcmd, pdata, master_mode)
+register unsigned char 	*pcmd;
+register unsigned short *pdata;
+unsigned short		master_mode;
+{
+  int	dummy;
+  int 	channel;
+
+  if(vxMemProbe(pcmd, READ, sizeof(*pcmd), &dummy) != OK)
+    return ERROR;
+  if(vxMemProbe(pdata, READ, sizeof(*pdata), &dummy) != OK)
+    return ERROR;
+/*  
+    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 OK;
+}
+
+
+stc_one_shot_read(preset, edge0_count, edge1_count, pcmd, pdata, channel,int_source)
+unsigned int	*preset;
+unsigned short	*edge0_count;
+unsigned short	*edge1_count;
+unsigned char	*pcmd;
+unsigned short	*pdata;
+unsigned int 	channel;
+unsigned int	*int_source;
+{
+  int			dummy;
+  unsigned short	mode;
+  unsigned short	edge0;
+  unsigned short	edge1;
+
+  if(vxMemProbe(pcmd, READ, sizeof(*pcmd), &dummy) != OK)
+    return ERROR;
+  if(vxMemProbe(pdata, READ, sizeof(*pdata), &dummy) != OK)
+    return ERROR;
+
+  if(channel>=CHANONCHIP)
+    return ERROR;
+
+  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 ERROR;
+
+  return OK;
+}
+
+
+stc_one_shot(preset, edge0_count, edge1_count, pcmd, pdata, channel,int_source)
+unsigned int	preset;
+unsigned short	edge0_count;
+unsigned short	edge1_count;
+unsigned char	*pcmd;
+unsigned short	*pdata;
+unsigned int 	channel;
+int		int_source;
+{
+  int		dummy;
+
+  if(vxMemProbe(pcmd, READ, sizeof(*pcmd), &dummy) != OK)
+    return ERROR;
+  if(vxMemProbe(pdata, READ, sizeof(*pdata), &dummy) != OK)
+    return ERROR;
+  if(channel>=CHANONCHIP)
+    return ERROR;
+
+  /*
+   * 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 OK;
+}
+   
+
+
