#include "gpib.h" #include "globals.h" #include "flash.h" #include "error_utils.h" #include "bus.h" /* TNT Configuration --------------------------------------------------------*/ /* I/O */ #define max_gpib_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 char 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) { bus_writebyte ((uint8_t) (TNT_Port + reg), (uint8_t) byte); } static unsigned char TNT_In(int reg) { return (unsigned char) bus_readbyte ((uint8_t) (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_gpib_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); }