From 401025aebc02eca587474e094fa50b2939f8a147 Mon Sep 17 00:00:00 2001 From: "Michael J. Chudobiak" Date: Fri, 7 Dec 2012 11:39:09 -0500 Subject: modify gpib response sending so it does not hang if read never received --- globals.h | 1 + gpib.c | 223 +++++++++++++++++++++++++++------------------------------ gpib.h | 4 +- instr-daemon.c | 9 ++- 4 files changed, 115 insertions(+), 122 deletions(-) diff --git a/globals.h b/globals.h index 5e5885b..2fa3f17 100644 --- a/globals.h +++ b/globals.h @@ -276,6 +276,7 @@ typedef struct { int avrq_reg; int last_rise_time_relay_setting; char gpib_input_buffer[max_gpib_input_length]; + gchar *pending_output_message; } HWregStruct; diff --git a/gpib.c b/gpib.c index 6007cdf..7711e25 100644 --- a/gpib.c +++ b/gpib.c @@ -296,7 +296,7 @@ void TNT_4882_Status(int status_register,unsigned int byte,int operation) 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 } @@ -349,11 +349,11 @@ static int TNT_INT_STATUS(void) // 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); + |((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); @@ -494,7 +494,7 @@ static void TNT_Setup_IO(int IO_type, unsigned long int cnt, int term) 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 + TNT_Out(R_auxmr,HR_auxrj|0); // B_to is cleared switch(IO_type) { @@ -632,7 +632,13 @@ int GPIB_check_for_device_clear_signal(void) if (TNT_INT_STATUS() & DCAS) { TNT_Out(R_auxmr,F_clrDEC); + + TNT_4882_Status(STB,0x10,CLEAR); // Clear MAV bit + g_free (globals.Registers.pending_output_message); + + TNT_Holdoff_off(); TNT_INT_STATUS(); + return TRUE; } else { return FALSE; @@ -648,7 +654,7 @@ int GPIB_check_for_messages(char *gpib_buf) return FALSE; } - // If the GPIB has requested data, and no output messages + // 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) { @@ -656,7 +662,7 @@ int GPIB_check_for_messages(char *gpib_buf) } // If the TNT4882 is talk addressed, the controller must - // be still reading output data in the TNT4882 FIFOs. + // be still reading output data in the TNT4882 FIFOs. // Wait until this process has completed and the TNT4882 // is listen addressed. @@ -702,8 +708,8 @@ int GPIB_handle_new_input(char *gpib_buf) && !( !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 + && !( !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 @@ -743,12 +749,12 @@ int GPIB_handle_new_input(char *gpib_buf) } if (TNT_update_brq() && !TNT_input_bav() && ib_empty) - // abandon if brq with no commands to process + // 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 + // in idle state return FALSE; } @@ -770,150 +776,141 @@ static void TNT_Holdoff_off() } -int GPIB_send_query_response(gpointer *ignore_this, char *in_string) +void GPIB_start_query_response(gpointer *ignore_this, char *in_string) { g_assert (ignore_this == NULL); g_assert (in_string != NULL); if (!globals.HWDetect.gpib) { - return OK; + return; } - if (GPIB_response_already_pending()) { - // if MAV already, data will be lost. Set QYE bit in STB. + if (globals.Registers.pending_output_message != NULL) { queue_error_for_gpib_only(query_error_interrupted); + g_free (globals.Registers.pending_output_message); } - // needs to be freed - gchar *term_string = g_strdup_printf ("%s\n", in_string); - - // just a pointer - char *out_buffer = term_string; + globals.Registers.pending_output_message = g_strdup_printf ("%s\n", in_string); + TNT_4882_Status(STB,0x10,SET); // Set MAV bit +} - // 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; +void GPIB_finish_query_response() +{ + if (!globals.HWDetect.gpib) { + return; + } - out_cnt = strlen (out_buffer); + if (globals.Registers.pending_output_message == NULL) { + return; + } - TNT_4882_Status(STB,0x10,SET); // Set MAV bit + // just a pointer + char *out_buffer = globals.Registers.pending_output_message; + int i; + unsigned long int out_cnt = strlen (out_buffer); + unsigned long int count_sent; // Local count variable 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)) { + if (!(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(); + if (GPIB_check_for_device_clear_signal()) { + return; - /* 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 + // 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(); + return; + } 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_update_brq(); // update it so that it doesn't get + return; // confused in idle state } - } - - 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 + } else { + // We are talk-addressed. Send some data. - if(out_cnt==0) { - INTERFACE_STATUS|=UCMPL; - return OK; - } + TNT_Setup_IO(OUTPUT,out_cnt,EOI|EOS); - // send data until completed or interrupted - while( !(INTERFACE_STATUS&(DCAS|TIMO|END|ERR|LACS)) - && !(TNT_In(R_isr3)&B_done) - ) { + count_sent=0; + INTERFACE_STATUS=0; // Clear I/O status bits + DATA_COUNT=0; // Clear count global - // 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; + if(out_cnt==0) { + INTERFACE_STATUS|=UCMPL; + return; + } - case (B_nff|B_intsrc2|B_nef): // 8 words in fifo are empty - for(i=0; i<8; i++) { + // 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; } - 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_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 + 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 - g_free (term_string); + INTERFACE_STATUS|=UCMPL; // Set the user complete bit - if (INTERFACE_STATUS&DCAS) { - TNT_4882_Status(STB,0x10,CLEAR); // Clear MAV bit + g_free (globals.Registers.pending_output_message); - // 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 (GPIB_check_for_device_clear_signal()) { + return; + } - 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 ((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; + } - 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 + 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; } @@ -936,16 +933,6 @@ void GPIB_check_remote_status (int *is_remote, int *is_lockout) } -unsigned char GPIB_response_already_pending () -{ - if (!globals.HWDetect.gpib) { - return 0; - } - - return TNT_In(R_spsr) & 0x10; -} - - void GPIB_go_to_local () { if (!globals.HWDetect.gpib) { diff --git a/gpib.h b/gpib.h index 2da0cc1..610d74e 100644 --- a/gpib.h +++ b/gpib.h @@ -12,9 +12,9 @@ int GPIB_check_for_device_clear_signal(void); int GPIB_check_for_device_clear_signal(void); int GPIB_check_for_messages(char *gpib_buf); int GPIB_handle_new_input(char *gpib_buf); -int GPIB_send_query_response(gpointer *ignore_this, char *in_string); +void GPIB_start_query_response(gpointer *ignore_this, char *in_string); +void GPIB_finish_query_response(); void GPIB_check_remote_status (int *is_remote, int *is_lockout); -unsigned char GPIB_response_already_pending (); void GPIB_go_to_local (); void GPIB_clear_events (); unsigned int GPIB_get_ESR (); diff --git a/instr-daemon.c b/instr-daemon.c index 255b294..4924961 100644 --- a/instr-daemon.c +++ b/instr-daemon.c @@ -413,14 +413,19 @@ static gboolean periodic_poll (void) globals.VxiLocks.command_in_progress = TRUE; GPIB_check_for_device_clear_signal(); + if (GPIB_check_for_messages(globals.Registers.gpib_input_buffer)) { if (GPIB_handle_new_input(globals.Registers.gpib_input_buffer)) { - Parser_main(globals.Registers.gpib_input_buffer, 0, GPIB_send_query_response, NULL); + Parser_main(globals.Registers.gpib_input_buffer, 0, GPIB_start_query_response, NULL); } } + + // send response if appropriate + GPIB_finish_query_response(); + GPIB_check_for_device_clear_signal(); - // tell VXI servers that the 4882 subsystem is avilable again + // tell VXI servers that the 4882 subsystem is available again globals.VxiLocks.command_in_progress = FALSE; } -- cgit