diff options
Diffstat (limited to 'gpib.c')
-rw-r--r-- | gpib.c | 982 |
1 files changed, 982 insertions, 0 deletions
@@ -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); +} + |