summaryrefslogtreecommitdiff
path: root/gpib.c
diff options
context:
space:
mode:
Diffstat (limited to 'gpib.c')
-rw-r--r--gpib.c982
1 files changed, 982 insertions, 0 deletions
diff --git a/gpib.c b/gpib.c
new file mode 100644
index 0000000..7ef84f9
--- /dev/null
+++ b/gpib.c
@@ -0,0 +1,982 @@
+#include "gpib.h"
+#include "globals.h"
+#include "flash.h"
+#include "error_utils.h"
+
+
+/* TNT Configuration --------------------------------------------------------*/
+
+/* I/O */
+
+#define max_input_length 512
+
+#define READ_EOS_BYTE 0x00 /* EOS byte for reads/inputs/receives*/
+#define WRITE_EOS_BYTE 0x00 /* EOS byte for writes/outputs/sends */
+#define USE_EIGHT_BIT_EOS_COMPARE NO /* Compare EOS byte 7 or 8 bits */
+#define USE_TRANSMIT_EOI_WITH_EOS NO /* Send EOI with EOS byte (writes) */
+#define USE_HIGH_SPEED_T1 NO /* Short T1 delay while doing three wire handshaking */
+
+
+/* Miscellaneous Handlers */
+#define USE_SPOLL_BIT NO /* STBO (SPOLL) - Serial Poll */
+
+/* TNT Hardware Parameters */
+#define TNT_BASE_ADDRESS 0x4100 /* Board Base I/O address */
+
+
+/* TNT Constants ------------------------------------------------------------*/
+
+#define YES 1
+#define ENABLE 1
+#define SET 1
+#define NO 0
+#define NONE 0
+#define DISABLE 0
+#define CLEAR 0
+#define INPUT 4
+#define INPUT_BYTE 16
+#define OUTPUT 2
+#define INTERFACE 1
+
+/* Interface Status Constants */
+#define ERR (1<<15)
+#define TIMO (1<<14)
+#define END (1<<13)
+#define EOS (1<<12)
+#define RQS (1<<11)
+#define IFC (1<<10)
+#define SPOLL (1<<9)
+#define UCMPL (1<<8)
+#define LOK (1<<7)
+#define REM (1<<6)
+#define ASYNC (1<<5)
+#define DTAS (1<<4)
+#define DCAS (1<<3)
+#define LACS (1<<2)
+#define TACS (1<<1)
+#define NACS (1<<0)
+#define SYNC 0
+#define NONE 0
+#define EOI END
+
+
+/* Error Codes */
+#define ENOL 1
+#define EARG 2
+#define EABO 3
+
+
+/* 488.2 Status Registers */
+#define STB 0
+#define SRE 1
+#define ESE 2
+#define ESR 3
+#define IST 4
+
+
+/****************************************************************************
+ *
+ * Define TNT register map and TL related bits and functions
+ *
+ * FORMAT:
+ * register address
+ * B_bits value
+ * F_function value (F_field)
+ *
+ ****************************************************************************/
+
+/* Interrupt Mask and Status Registers */
+
+#define R_imr0 0x1d
+#define B_glint (1<<7)
+
+#define R_isr0 0x1d
+#define B_stbo (1<<6)
+#define B_eos (1<<4)
+#define B_ifc (1<<3)
+#define B_to (1<<1)
+
+#define R_imr1 0x02
+#define R_isr1 0x02
+#define B_det (1<<5)
+#define B_end (1<<4)
+#define B_dec (1<<3)
+#define B_err (1<<2)
+#define B_do (1<<1)
+
+#define R_isr2 0x04
+#define B_int (1<<7)
+#define B_lok (1<<5)
+#define B_rem (1<<4)
+
+#define R_isr3 0x1a
+#define B_x (1<<7)
+#define B_intsrc2 (1<<6)
+#define B_nff (1<<3)
+#define B_nef (1<<2)
+#define B_done (1<<0)
+
+/* Serial Poll Status and Mode Registers */
+
+#define R_spsr 0x06
+#define B_pend (1<<6)
+#define R_spmr 0x06
+
+/* Address Mode, Status and Control Registers */
+
+#define R_adsr 0x08
+#define B_natn (1<<6)
+#define B_spms (1<<5)
+#define B_la (1<<2)
+#define B_ta (1<<1)
+
+#define R_admr 0x08
+
+#define F_noaddress 0x30
+#define F_normalprimary 0x31
+
+#define R_adr 0x0c
+#define B_ars (1<<7)
+#define B_dt (1<<6)
+#define B_dl (1<<5)
+
+/* Data Count Registers */
+
+#define R_cnt0 0x14
+#define R_cnt1 0x16
+#define R_cnt2 0x09
+#define R_cnt3 0x0b
+
+/* Auxillary and Hidden Registers */
+#define R_auxmr 0x0a
+#define F_pon 0x00
+#define F_chrst 0x02
+#define F_rhdf 0x03
+#define F_ist0 0x01
+#define F_ist1 0x09
+#define F_lut 0x0b
+#define F_lul 0x0c
+#define F_reqt 0x18
+#define F_reqf 0x19
+#define F_hldi 0x51
+
+/* Clear Interrupt Flags */
+#define F_clrEND 0x55
+#define F_clrDEC 0x56
+#define F_clrERR 0x57
+
+/* Hidden Auxillary Registers */
+#define B_u (1<<4)
+#define B_s (1<<3)
+
+#define HR_auxra 0x80
+#define F_normal 0x00
+#define F_hlda 0x01
+#define F_hlde 0x02
+#define B_endoneos (1<<2)|((USE_EIGHT_BIT_EOS_COMPARE)? (1<<4):0)
+
+#if(!(USE_TRANSMIT_EOI_WITH_EOS))
+#define B_xeoiweos (1<<3)|((USE_EIGHT_BIT_EOS_COMPARE)? (1<<4):0)
+#else
+#define B_xeoiweos 0x00
+#endif
+
+#define HR_auxrb 0xa0
+#define B_hst1 (1<<2)
+
+#define HR_auxre 0xc0
+#define B_dhdc (1<<0)
+
+#define HR_auxri 0xe0
+#define B_ustd (1<<3)
+
+#define HR_auxrj 0xf0
+
+#define R_hier 0x13
+#define B_dga (1<<7)
+#define B_dgb (1<<6)
+
+#define R_eosr 0x0e
+
+#define R_misc 0x15
+
+#define R_sts1 0x10
+#define B_halt (1<<1)
+
+#define R_cfg 0x10
+#define B_in (1<<5)
+#define B_ccen (1<<3)
+#define B_tmoe (1<<2)
+#define B_timbytn (1<<1)
+#define B_16bit (1<<0)
+#define B_8bit (0)
+#define F_input_config (B_in|B_tmoe|B_timbytn|B_ccen|B_8bit)
+#define F_output_config (B_tmoe|B_timbytn|B_8bit)
+
+#define R_dsr 0x11
+
+#define R_hssel 0x0d
+#define B_go2sids (1<<5)
+#define F_onechip 0x01
+
+#define R_keyrg 0x17
+
+/* TNTs FIFOs */
+#define R_fifob 0x18
+
+#define R_sasr 0x1b
+
+#define R_cmdr 0x1c
+#define F_softreset 0x22
+#define F_resetfifo 0x10
+#define F_stop 0x08
+#define F_go 0x04
+
+#define R_bsr 0x1f
+
+/* --------------------------------------------------------------------------*/
+
+
+/* TNT4882 GLOBAL VARIABLES -------------------------------------------------*/
+
+int INTERFACE_ERROR; /* Error Code */
+int INTERFACE_STATUS; /* Interface Status */
+unsigned int MR_4882_status[5]; /* 4882 status memory registers */
+
+unsigned long int DATA_COUNT; /* Transfer count */
+unsigned long int Requested_Count; /* Requested transfer count */
+unsigned long int cnt;
+int prev_brq;
+int spoll_count;
+
+
+static int TNT_INT_STATUS(void);
+static void TNT_Adr_Mode();
+static void TNT_Gen_Error(int code);
+static void TNT_Setup_IO(int IO_type, unsigned long int cnt, int term);
+static void TNT_DONE_Handler(int IO_type,unsigned long int *count_sent);
+static unsigned long int TNT_DATA_COUNT();
+static void TNT_Out(int reg, unsigned int byte);
+static unsigned char TNT_In(int reg);
+static int TNT_input_bav(void);
+static int TNT_update_brq(void);
+static void TNT_RFD_Holdoff();
+static void TNT_Holdoff_off();
+
+
+void TNT_4882_Status(int status_register,unsigned int byte,int operation)
+{
+ int set_srq;
+
+ MR_4882_status[STB] = TNT_In(R_spsr); /* Get STB */
+
+ switch (operation) {
+ case SET:
+ /* Cannot set SRQ directly */
+ if((status_register==STB)||(status_register==SRE)) {
+ byte&=~0x40;
+ }
+
+ MR_4882_status[status_register]|= byte;/* OR in new register value */
+
+ if(status_register==IST) {
+ TNT_Out(R_auxmr,F_ist1); /* if IST set IST bit */
+ }
+
+ break;
+
+ case CLEAR:
+ MR_4882_status[status_register]&=~byte; /* ~AND requested bits */
+ if(status_register==IST) {
+ TNT_Out(R_auxmr,F_ist0); /* if IST clear IST bit */
+ }
+ break;
+
+ default:
+ TNT_Gen_Error(EARG); /* Neither SET/CLEAR then EARG */
+ break;
+ }
+ /* If ESE&ESR set ESB bit */
+ MR_4882_status[STB]|=(MR_4882_status[ESE]&MR_4882_status[ESR])? 0x20 : 0;
+
+ /* If STB&SRE set RQS bit */
+ set_srq = (MR_4882_status[STB]&MR_4882_status[SRE])? TRUE : FALSE;
+
+ if(set_srq) { /* If SRQ desired */
+ TNT_Out(R_auxmr,F_reqt); /* Set request true */
+ } else { /* Else */
+ TNT_Out(R_auxmr,F_reqf); /* Set request false */
+ }
+
+ TNT_Out(R_spmr,MR_4882_status[STB]); /* Set new serial poll byte */
+}
+
+
+/****************************************************************************
+ *
+ * TNT_INT_STATUS(): Used to update INTERFACE_STATUS word by reading
+ * R_isr0,R_isr1,R_isr2,R_isr3,R_adsr,R_spmr and
+ * updating the appropriate INTERFACE_STATUS bits.
+ *
+ * INTERFACE_STATUS bits:
+ *
+ * ERR (1<<15) Error - Check INTERFACE_ERROR for error
+ * TIMO (1<<14) Timeout - If timeouts are used
+ * END (1<<13) End/EOI/EOS - End of transmition received
+ * EOS (1<<12) End of String - End of string received
+ * RQS (1<<11) Requesting Service - TNT asserting SRQ line
+ * IFC (1<<10) Interface Clear - Interface Clear Asserted
+ * SPOLL (1<<9) Serial Poll Active - Serial Poll Byte STB is requested
+ * UCMPL (1<<8) User Complete - User I/O function terminated
+ *
+ * LOK (1<<7) Local Lockout - Lockout front panel controls
+ * REM (1<<6) Remote Programming - TNT in remote programming state
+ * ASYNC (1<<5) Asyncronous I/O - NOT USED IN NON-INT ESP
+ * DTAS (1<<4) Trigger Active State - Requested Device Trigger
+ * DCAS (1<<3) Clear Active State - Requested Device Clear
+ * LACS (1<<2) Listener Active - TNT listen addressed
+ * TACS (1<<1) Talker Active - TNT talk addressed
+ * NACS (1<<0) Not Active State - TNT not addressed
+ *
+ *
+ ****************************************************************************/
+
+/*----------------------------------------------------------------------------------------------------------*/
+static int TNT_INT_STATUS(void)
+{
+ int mr_isr0,mr_isr1,mr_isr2,mr_spsr,mr_adsr;
+
+ mr_isr1=TNT_In(R_isr1); /* Read status register isr1 */
+ mr_isr2=TNT_In(R_isr2); /* Read status register isr2 */
+ mr_isr0=TNT_In(R_isr0); /* Read status register isr0 */
+ mr_spsr=TNT_In(R_spsr); /* Read status register spsr */
+ mr_adsr=TNT_In(R_adsr); /* Read status register adsr */
+
+ INTERFACE_STATUS&=(UCMPL|END|EOS|TIMO|ERR); /* Maintain I/O bits */
+ /* These are cleared at the */
+ /* beginning of a new I/O call */
+
+ /* Get new status */
+ INTERFACE_STATUS|=((mr_isr0&B_to) ?TIMO :0)|((mr_isr2&B_rem) ?REM :0)
+ |((mr_isr1&B_end) ?END :0)|((mr_isr0&B_eos) ?EOS :0)
+ |((mr_spsr&B_pend)?RQS :0)|((mr_isr0&B_ifc) ?IFC :0)
+ |((mr_isr0&B_stbo)?SPOLL:0)|((mr_isr2&B_lok) ?LOK :0)
+ |((mr_isr1&B_det) ?DTAS :0)|((mr_isr1&B_dec) ?DCAS:0)
+ |((mr_adsr&B_ta) ?TACS :0)|((mr_adsr&B_la) ?LACS:0);
+
+ INTERFACE_STATUS|=((INTERFACE_STATUS&(LACS|TACS)) ? 0:NACS);
+
+ return INTERFACE_STATUS; /* Return status */
+}
+
+
+/****************************************************************************
+ *
+ * TNT_Gen_Error(): Used to Update INTERFACE_ERROR. INTERFACE_ERROR is
+ * only valid when ERR is set in INTERFACE_STATUS.
+ *
+ * INTERFACE_ERROR values:
+ *
+ * xxxx 0 - No Error
+ * ENOL 1 - No Listeners I/O aborted because no listeners on bus.
+ * EARG 2 - Bad Argument in parameter list.
+ * EABO 3 - I/O Aborted due to timeout.
+ *
+ * Related Functions: None
+ *
+ * Valid Parameters: code = 1,2..7
+ *
+ * Note: This is a system function.
+ *
+ ****************************************************************************/
+
+/*----------------------------------------------------------------------------------------------------------*/
+static void TNT_Gen_Error(int code)
+{
+ INTERFACE_STATUS|=ERR; /* Set error bit & enter code */
+ INTERFACE_ERROR=code; /* Set error code */
+}
+
+
+/**************************** INITIALIZATION ********************************
+ *
+ * GPIB_initialize(): Sets the TNT into a known initialized state,
+ * clears global values (mask registers,status words),
+ * and loads current addressing setup.
+ *
+ * Normally, this function is executed once at power
+ * up, however it may be used to reinitialize the
+ * interface during operation.
+ *
+ ****************************************************************************/
+
+/*----------------------------------------------------------------------------------------------------------*/
+void GPIB_initialize(void)
+{
+ int i;
+
+ for(i=0; i<5; ++i) {
+ MR_4882_status[i]=0; /* do this because these variable are 2-byte integers */
+ }
+ /* but Nat Inst code assumes they are one-byte */
+
+ INTERFACE_STATUS=0; /* Initialize Globals to zero */
+ INTERFACE_ERROR=0;
+ DATA_COUNT=0;
+ Requested_Count=0;
+
+ TNT_Out(R_cmdr,F_softreset); /* Reset FIFOS */
+
+ TNT_Out(R_spmr ,0x80); /* This sequence of commands */
+ TNT_Out(R_auxmr,0x80); /* insures that the TNT */
+ TNT_Out(R_auxmr,0x99); /* will be in the normal 7210 */
+ TNT_Out(R_keyrg,0); /* mode and not 9914 */
+
+ TNT_Out(R_hssel,F_onechip); /* Set TNT to one chip WINK mode */
+ TNT_Out(R_misc,0); /* Disable HS mode */
+ TNT_Out(R_hier,B_dga|B_dgb); /* Set deglitching circuits to */
+
+ TNT_Out(R_auxmr,F_chrst); /* Reset TNT */
+
+ TNT_4882_Status(STB,0xff,CLEAR); /* Initialize Serial Poll Byte */
+ TNT_4882_Status(SRE,0xff,CLEAR); /* Initialize SRE memory register */
+ TNT_4882_Status(ESR,0xff,CLEAR); /* Initialize ESR memory register */
+ TNT_4882_Status(ESR,0x80,SET); /* Indicate power on */
+ TNT_4882_Status(ESE,0xff,CLEAR); /* Initialize ESE memory register */
+
+ TNT_Adr_Mode();
+ GPIB_change_address(globals.Flash.gpib_address);
+ /* Set auxri for non-static bits and */
+ /* possibly ultra short t1 delay*/
+ TNT_Out(R_auxmr,HR_auxri|((USE_HIGH_SPEED_T1)? B_ustd : 0));
+
+ /* If not using HS488 set only hst1*/
+ TNT_Out(R_auxmr,HR_auxrb|((USE_HIGH_SPEED_T1)? B_hst1 : 0));
+
+ TNT_Out(R_auxmr,F_hldi); /* Issue hold off immediately */
+ TNT_Out(R_auxmr,F_pon); /* Clear Power On */
+
+ TNT_Out(R_imr0,B_glint); /* Enable setting of tlcint */
+}
+
+
+static void TNT_Adr_Mode()
+{
+ TNT_Out(R_admr,F_noaddress); /* Clear address mode */
+ TNT_Out(R_adr,B_dt|B_dl); /* Disable talk & listener */
+ TNT_Out(R_adr,B_ars|B_dt|B_dl); /* capabilities */
+ TNT_Out(R_auxmr,F_lut); /* Untalk TNT4882 */
+ TNT_Out(R_auxmr,F_lul); /* Unlisten TNT4882 */
+ TNT_Out(R_admr,F_normalprimary); /* Set single primary address mode*/
+}
+
+
+void GPIB_change_address(int new_address)
+{
+ int eprom_loc;
+
+ TNT_Out(R_adr,new_address); /* Load new address setting */
+
+ globals.Flash.gpib_address=new_address;
+ eprom_loc = (char *) &(globals.Flash.gpib_address) - (char *) &(globals.Flash.flash_start);
+ writeUserBlock(&globals.Flash, eprom_loc, sizeof(globals.Flash.gpib_address));
+}
+
+
+static void TNT_Setup_IO(int IO_type, unsigned long int cnt, int term)
+{
+ unsigned long int twos_cnt; /* Obtain the twos compliment cnt */
+
+ twos_cnt=-cnt;
+
+ Requested_Count=cnt; /* Save requested transfer cnt */
+
+ TNT_Out(R_cmdr,F_resetfifo); /* Reset TNT fifos */
+
+ TNT_Out(R_cnt0, (char)(twos_cnt)); /* Load twos compliment count */
+ TNT_Out(R_cnt1, (char)(twos_cnt>>8)); /* into TNT count registers */
+ TNT_Out(R_cnt2, (char)(twos_cnt>>16));
+ TNT_Out(R_cnt3, (char)(twos_cnt>>24));
+
+ TNT_Out(R_imr0,B_glint); /* Set write to imr0 to be sure */
+ TNT_Out(R_auxmr,HR_auxrj|0); /* B_to is cleared */
+
+ switch(IO_type) {
+
+ case INPUT_BYTE:
+ TNT_Out(R_imr1, B_end); /* End transfer on eoi or eos */
+
+ TNT_Out(R_eosr, READ_EOS_BYTE); /* Set eos byte */
+ TNT_Out(R_auxmr,HR_auxra|F_hlde|((term&EOS)?B_endoneos:0));
+ /* Configure for byte input */
+ TNT_Out(R_cfg , F_input_config&~B_16bit);
+ /* Holdoff on end & enable eos */
+ TNT_Out(R_auxmr,F_rhdf); /* Release holdoff */
+ TNT_Out(R_cmdr, F_go); /* Start transfer state machine */
+ break;
+
+ case INPUT:
+ TNT_Out(R_imr1, B_end); /* End transfer on eoi or eos */
+ TNT_Out(R_eosr, READ_EOS_BYTE); /* Set eos byte */
+ TNT_Out(R_auxmr,HR_auxra|F_hlde|((term&EOS)?B_endoneos:0));
+ TNT_Out(R_cfg , F_input_config); /* Configure for *byte* input */
+ /* Holdoff on end & enable eos */
+ TNT_Out(R_auxmr,F_rhdf); /* Release holdoff */
+ TNT_Out(R_cmdr, F_go); /* Start transfer state machine */
+ break;
+
+ case OUTPUT:
+ TNT_Out(R_imr1, B_err); /* End transfer on err */
+ TNT_Out(R_eosr, WRITE_EOS_BYTE); /* Set EOS byte */
+ /* Holdoff on all & enable EOS */
+ TNT_Out(R_auxmr,HR_auxra|F_hlda|((term&EOS)?B_xeoiweos:0));
+ /* Configure for *byte* output */
+ TNT_Out(R_cfg , F_output_config|((term)?B_ccen:0));
+ TNT_Out(R_auxmr,F_hldi); /* Hold off immediately */
+ TNT_Out(R_cmdr, F_go); /* Start transfer state machine */
+ break;
+
+ default:
+ TNT_Gen_Error(EARG); /* If IO_type incorrect issue EARG*/
+ break;
+ }
+}
+
+
+static void TNT_DONE_Handler(int IO_type,unsigned long int *count_sent)
+{
+ TNT_Out(R_cmdr,F_stop); /* Stop fifos */
+ TNT_Out(R_cmdr,F_resetfifo); /* Reset the fifos */
+
+ if(TNT_In(R_isr1)&B_end) { /* If we received an END */
+ TNT_Out(R_auxmr,F_clrEND); /* Clear status bit */
+ }
+
+ if(TNT_In(R_isr1)&B_err) {
+ TNT_Gen_Error(ENOL); /* No listeners */
+ TNT_Out(R_auxmr,F_clrERR); /* Clear error bit */
+
+ if(IO_type==OUTPUT) {
+ TNT_Out(R_hssel,F_onechip|B_go2sids); /* if error set to idle state. */
+ TNT_Out(R_hssel,F_onechip);
+ }
+ }
+
+ *count_sent = TNT_DATA_COUNT(); /* Obtain transfer count */
+}
+
+
+static unsigned long int TNT_DATA_COUNT()
+{
+ unsigned long int return_value;
+
+ return_value=(unsigned long int) TNT_In(R_cnt0);
+ return_value|=((unsigned long int) TNT_In(R_cnt1)) << 8;
+ return_value|=((unsigned long int) TNT_In(R_cnt2)) << 16;
+ return_value|=((unsigned long int) TNT_In(R_cnt3)) << 24;
+ return_value+=(unsigned long int) Requested_Count;
+
+ return( (unsigned long int) return_value );
+}
+
+
+static void TNT_Out(int reg, unsigned int byte)
+{
+ ;
+ // FIXME WrPortE(TNT_Port + reg, NULL, byte);
+}
+
+
+static unsigned char TNT_In(int reg)
+{
+ return 0;
+ // FIXME return RdPortE(TNT_Port + reg);
+}
+
+
+static int TNT_input_bav(void)
+{
+ /* is a byte available (bav) in the TNT4882 FIFOs? Used mostly for GPIB reads */
+ return (int) TNT_In(R_isr3)&B_nef;
+}
+
+
+static int TNT_update_brq(void)
+{
+ /* is the GPIB requesting data from the TNT4882? */
+ int state_SGNS;
+ int state_TACS;
+
+ state_TACS = (TNT_In(R_adsr)&B_ta) && (TNT_In(R_adsr)&B_natn) && !(TNT_In(R_adsr)&B_spms);
+ state_SGNS = state_TACS && !(TNT_In(R_sasr)&0x02) && !(TNT_In(R_sasr)&0x01);
+
+ /* the IEEE488.2 standard says that this signal should be set only for for
+ each data request, so some memory is required to avoid generating multiple,
+ stateless brq messages. */
+
+ if (!prev_brq) { /* prev_brq=0 */
+ prev_brq=state_SGNS;
+ return state_SGNS;
+ } else {
+ prev_brq=state_SGNS;
+ return 0;
+ }
+}
+
+
+int GPIB_check_for_device_clear_signal(void)
+{
+ /* added by MJC - June 20/06 */
+ /* reset interface if a device clear is received */
+
+ if (TNT_INT_STATUS() & DCAS) {
+ TNT_Out(R_auxmr,F_clrDEC);
+ TNT_INT_STATUS();
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+
+int GPIB_check_for_messages(char *gpib_buf)
+{
+#define ib_empty (!(strlen(gpib_buf)))
+
+ /* If the GPIB has requested data, and no output messages are in the TNT4882 FIFOs, generate a query error */
+ if (TNT_update_brq() && !TNT_input_bav() && ib_empty) {
+ queue_error_for_gpib_only(query_error_unterminated);
+ }
+
+ /* If the TNT4882 is talk addressed, the controller must be still reading output data in the TNT4882
+ FIFOs. Wait until this process has completed and the TNT4882 is listen addressed. */
+ if ( (TNT_In(R_adsr)&B_ta) && (TNT_In(R_isr3)&B_nef) && !(TNT_In(R_cfg)&B_in)) {
+ return OK; /* exit if not listen addressed */
+ }
+
+
+ /* if no I/O is begin done, set up for input. Note that TLCHLTE must be set to zero, so that the */
+ /* HALT signal is set only by the STOP and GO commands. */
+ if (TNT_In(R_sts1)&B_halt) {
+ cnt=max_input_length-8;
+ gpib_buf[0]=0;
+ INTERFACE_STATUS=0;
+ TNT_Setup_IO(INPUT,cnt,EOI|EOS);
+ }
+
+ /* is data available to read? */
+ return (TNT_In(R_isr3)&B_nef) && (TNT_In(R_cfg)&B_in);
+}
+
+
+int GPIB_handle_new_input(char *gpib_buf)
+{
+ /* read until done or buffers empty. Then reset DAC holdoff */
+
+ unsigned long int count_sent; /* Local count variable */
+ int i;
+ char *buffer_pos;
+
+ buffer_pos = gpib_buf;
+
+ count_sent=0; /* Clear I/O status bits */
+ DATA_COUNT=0; /* Clear count global */
+
+ /* read FIFOs until transaction completed or interrupted */
+ while( !( INTERFACE_STATUS & DCAS) /* device clear */
+ && !( !TNT_input_bav() && (INTERFACE_STATUS & END)) /* proper transaction end */
+ && !( !TNT_input_bav() && TNT_In(R_isr3)&B_done) /* proper transaction end */
+ && !( !TNT_input_bav() && (INTERFACE_STATUS & TIMO)) /* improper timeout */
+ && !( !TNT_input_bav() && TNT_update_brq() && ib_empty) /* brq message true, GPIB requesting data */
+ ) {
+
+ /* choose the most efficient fifo-emptying method based on FIFO flags */
+ switch(TNT_In(R_isr3)&(B_nff|B_intsrc2|B_nef)) {
+ case (B_nef):
+ case (B_nef|B_intsrc2):
+ for(i=0; i<15; i++) {
+ *(buffer_pos++)=TNT_In(R_fifob);
+ }
+ break;
+
+ case (B_nff|B_intsrc2|B_nef):
+ for(i=0; i<8; i++) {
+ *(buffer_pos++)=TNT_In(R_fifob);
+ }
+ break;
+
+ case (B_nff|B_nef):
+ *(buffer_pos++)=TNT_In(R_fifob);
+ break;
+ }
+
+ TNT_INT_STATUS(); /* Update to get current status */
+
+ }
+
+ TNT_DONE_Handler(INPUT,&count_sent); /* Finish up and get count */
+ DATA_COUNT+=count_sent; /* Update total transfer count */
+ cnt-=count_sent; /* Update total requested count */
+ buffer_pos=buffer_pos+((int) count_sent); /* Update buffer pointer */
+
+
+ INTERFACE_STATUS|=UCMPL; /* Set the user complete bit */
+
+ if (GPIB_check_for_device_clear_signal()) {
+ return FALSE; /* abandon if SDC, DCL */
+ }
+
+ if (TNT_update_brq() && !TNT_input_bav() && ib_empty)
+ /* abandon if brq with no commands to process */
+ {
+ queue_error_for_gpib_only(query_error_unterminated);
+ prev_brq=1; /* reset brq */
+ TNT_update_brq(); /* update it so that it doesn't get confused in idle state */
+ return FALSE;
+ }
+
+ gpib_buf[(int) DATA_COUNT]=0;
+ return TRUE;
+}
+
+
+static void TNT_RFD_Holdoff()
+{
+ /* holdoff accepting data until software has checked the state of the TNT4882 */
+ TNT_Out(R_auxmr,F_hldi); /* set immediate RFD holdoff */
+}
+
+
+static void TNT_Holdoff_off()
+{
+ TNT_Out(R_auxmr,F_rhdf); /* cancel immediate RFD holdoff */
+}
+
+
+int GPIB_send_query_response(char *out_buffer)
+{
+ /* message must be available if this function has been called */
+
+ unsigned long int out_cnt;
+ unsigned long int count_sent; /* Local count variable */
+ int i;
+
+ out_cnt = strlen (out_buffer);
+
+ TNT_4882_Status(STB,0x10,SET); /* Set MAV bit */
+
+ TNT_INT_STATUS();
+
+ /* if the TNT4882 isn't talk addressed, wait until it is, or until the GPIB sends a clear signal,
+ or until the GPIB writes more data to the TNT4882, generating a query error. */
+ while (!(INTERFACE_STATUS&TACS)) {
+ TNT_RFD_Holdoff();
+ if (INTERFACE_STATUS&DCAS) {
+ /* device has been cleared. return to idle state */
+ TNT_4882_Status(STB,0x10,CLEAR); /* Clear MAV bit */
+ TNT_Holdoff_off();
+
+ /* added by MJC - June 20/06 */
+ /* reset interface if a device clear is received */
+ TNT_Out(R_auxmr,F_clrDEC);
+ TNT_INT_STATUS();
+
+ return OK;
+ } else if (!TNT_input_bav()) {
+ /* if no bytes are available, we're still waiting for the GPIB to request data. Repeat loop. */
+ TNT_Setup_IO(INPUT,out_cnt,EOI|EOS);
+ TNT_INT_STATUS();
+ TNT_Holdoff_off();
+ } else {
+ /* abandon if input bytes available, and generate query error */
+ TNT_Holdoff_off();
+ queue_error_for_gpib_only(query_error_interrupted);
+ TNT_4882_Status(STB,0x10,CLEAR); /* Clear MAV bit */
+ prev_brq=1; /* reset brq */
+ TNT_update_brq(); /* update it so that it doesn't get confused in idle state */
+ return OK;
+ }
+ }
+
+ TNT_Setup_IO(OUTPUT,out_cnt,EOI|EOS);
+
+ count_sent=0;
+ INTERFACE_STATUS=0; /* Clear I/O status bits */
+ DATA_COUNT=0; /* Clear count global */
+
+ if(out_cnt==0) {
+ INTERFACE_STATUS|=UCMPL;
+ return OK;
+ }
+
+ /* send data until completed or interrupted */
+ while( !(INTERFACE_STATUS&(DCAS|TIMO|END|ERR|LACS))
+ && !(TNT_In(R_isr3)&B_done)
+ ) {
+
+ /* choose the most efficient fifo-filling method based on flags */
+ switch(TNT_In(R_isr3)&(B_nff|B_intsrc2|B_nef)) {
+ case (B_nff):
+ case (B_nff|B_intsrc2): /* 16 words in fifo are empty */
+ for(i=0; i<16; i++) {
+ TNT_Out(R_fifob,*((char *)(out_buffer++)));
+ }
+ break;
+
+ case (B_nff|B_intsrc2|B_nef): /* 8 words in fifo are empty */
+ for(i=0; i<8; i++) {
+ TNT_Out(R_fifob,*((char *)(out_buffer++)));
+ }
+ break;
+
+ case (B_nff|B_nef): /* 1 word in fifo is empty */
+ TNT_Out(R_fifob,*((char *)(out_buffer++)));
+ break;
+ }
+
+ TNT_INT_STATUS(); /* Get current status */
+ }
+
+ TNT_DONE_Handler(OUTPUT,&count_sent); /* Finish up and get count */
+ DATA_COUNT+=count_sent; /* Update total transfer count */
+ out_cnt-=count_sent; /* Update total requested count */
+ out_buffer=out_buffer+((int) count_sent); /* Update buffer pointer */
+
+ INTERFACE_STATUS|=UCMPL; /* Set the user complete bit */
+
+ if (INTERFACE_STATUS&DCAS) {
+ TNT_4882_Status(STB,0x10,CLEAR); /* Clear MAV bit */
+
+ /* added by MJC - June 20/06 */
+ /* reset interface if a device clear is received */
+ TNT_Out(R_auxmr,F_clrDEC);
+ TNT_INT_STATUS();
+
+ return OK; /* abandon if SDC or DCL */
+ }
+
+ if ((INTERFACE_STATUS&LACS) && (TNT_In(R_isr3)&B_nef)) {
+ /* abandon gracefully if listen-addressed with data in buffer */
+ queue_error_for_gpib_only(query_error_interrupted);
+ TNT_4882_Status(STB,0x10,CLEAR); /* Clear MAV bit */
+ prev_brq=1; /* reset brq */
+ TNT_update_brq(); /* update it so that it doesn't get confused in idle state */
+ TNT_Setup_IO(INPUT,cnt,EOI|EOS);
+ return OK;
+ }
+
+ if(DATA_COUNT>0) {
+ TNT_4882_Status(STB,0x10,CLEAR); /* Clear MAV bit */
+ prev_brq=1; /* brq was active during send */
+ TNT_update_brq(); /* update it so that it doesn't get confused in idle state */
+ }
+
+ return OK;
+}
+
+
+void GPIB_check_remote_status (int *is_remote, int *is_lockout)
+{
+ *is_remote = *is_lockout = 0;
+
+ TNT_INT_STATUS(); /* Update to get current status */
+ if ((INTERFACE_STATUS&REM) == REM) {
+ *is_remote = 1;
+ }
+ if ((INTERFACE_STATUS&LOK) == LOK) {
+ *is_lockout = 1;
+ }
+
+ return;
+}
+
+
+unsigned char GPIB_response_already_pending ()
+{
+ return TNT_In(R_spsr) & 0x10;
+}
+
+
+void GPIB_go_to_local ()
+{
+ TNT_Out(R_auxmr,0x05); /* issue TNT rtl command */
+ return;
+}
+
+
+void GPIB_clear_events ()
+{
+ TNT_4882_Status(ESR,0xff,CLEAR); /* Clear ESR register */
+ TNT_4882_Status(STB,0x20,CLEAR); /* Clear ESB bit in STB */
+ return;
+}
+
+
+unsigned int GPIB_get_ESR ()
+{
+ return MR_4882_status[ESR];
+}
+
+
+unsigned int GPIB_get_SRE ()
+{
+ return MR_4882_status[SRE];
+}
+
+
+unsigned int GPIB_get_ESE ()
+{
+ return MR_4882_status[ESE];
+}
+
+
+unsigned int GPIB_get_STB ()
+{
+ return (TNT_In(R_spsr)&0xbf) | (((TNT_In(R_spsr)&0xbf) & MR_4882_status[SRE])?0x40:0);
+}
+
+
+void GPIB_set_ESR (unsigned int byte,int operation)
+{
+ TNT_4882_Status(ESR,byte,operation);
+ return;
+}
+
+
+void GPIB_set_SRE (unsigned int byte,int operation)
+{
+ TNT_4882_Status(SRE,byte,operation);
+ return;
+}
+
+
+void GPIB_set_ESE (unsigned int byte,int operation)
+{
+ TNT_4882_Status(ESE,byte,operation);
+ return;
+}
+
+
+void GPIB_Set_Execution_Error ()
+{
+ TNT_4882_Status(3,0x10,1);
+}
+
+
+void GPIB_Set_Command_Error ()
+{
+ TNT_4882_Status(3,0x20,1);
+}
+
+
+void GPIB_Set_Query_Error ()
+{
+ TNT_4882_Status(3,0x04,1);
+}
+
+
+void GPIB_Set_Device_Dependent_Error ()
+{
+ TNT_4882_Status(3,0x08,1);
+}
+