diff options
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | bus.c | 65 | ||||
-rw-r--r-- | bus.h | 1 | ||||
-rw-r--r-- | dummy_functions.c | 26 | ||||
-rw-r--r-- | dummy_functions.h | 14 | ||||
-rw-r--r-- | error_utils.c | 3 | ||||
-rw-r--r-- | error_utils.h | 1 | ||||
-rw-r--r-- | globals.c | 3 | ||||
-rw-r--r-- | globals.h | 14 | ||||
-rw-r--r-- | gpib.c | 981 | ||||
-rw-r--r-- | gpib.h | 25 | ||||
-rw-r--r-- | instr-daemon.c | 23 | ||||
-rw-r--r-- | menus.c | 3 | ||||
-rw-r--r-- | parser.c | 3 |
14 files changed, 1081 insertions, 82 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e4656a4..5ba415d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,6 +23,7 @@ add_executable(instr-daemon instr-daemon.c monitor.c menus.c dummy_functions.c + gpib.c ) add_executable(instr-client instr-client.c) @@ -151,15 +151,6 @@ static void gpmc_printinfo() } -// The shift amounts - -#define CSWROFFTIME 16 -#define CSRDOFFTIME 8 -#define OEOFFTIME 8 -#define RDACCESSTIME 16 -#define WRCYCLETIME 8 -#define RDCYCLETIME 0 -#define WRACCESSTIME 24 #define BIDIR 0x20 #define PULL_UP 0x10 @@ -175,9 +166,42 @@ static void gpmc_printinfo() #define MODE_7 0x07 -static void gpmc_setup(int chipselect, int accesscycles, int size, bool enablecs, int baseaddress) -{ +// multiply by 10 ns +#define TOTAL_IO_CYCLE 25; // 250 ns cycle +#define CS_DELAY 2; // CS low 20ns after address valid +#define DELAY_TO_WR_RD 4; // RD/WR lines low 50ns after address valid +#define WR_RD_WIDTH 20; // stay low for until 200 ns after address valid +#define DATA_READY 15; // data ready 150ns after address valid + +static void gpmc_setup(void) +{ + int chipselect = 0; + int size = GPMC_SIZE_16MB; + bool enablecs = true; + int baseaddress = 1; + + + int CSWROFFTIME = TOTAL_IO_CYCLE - CS_DELAY; + int CSRDOFFTIME = TOTAL_IO_CYCLE - CS_DELAY; + int CSONTIME = CS_DELAY; + int config2 = (CSWROFFTIME << 16) | (CSRDOFFTIME << 8) | CSONTIME; + + int WEOFFTIME = DELAY_TO_WR_RD + WR_RD_WIDTH; + int WEONTIME = DELAY_TO_WR_RD; + int OEOFFTIME = DELAY_TO_WR_RD + WR_RD_WIDTH; + int OEONTIME = DELAY_TO_WR_RD; + int config4 = (WEOFFTIME << 24) | (WEONTIME << 16) | (OEOFFTIME << 8) | OEONTIME; + + int RDACCESSTIME = DATA_READY; + int WRCYCLETIME = TOTAL_IO_CYCLE; + int RDCYCLETIME = TOTAL_IO_CYCLE; + int config5 = (RDACCESSTIME << 16) | (WRCYCLETIME << 8) | RDCYCLETIME; + + int WRACCESSTIME = DATA_READY; + int config6 = WRACCESSTIME << 24; + + pinmux_configurepin("gpmc_csn0", PULL_UP | MODE_0); pinmux_configurepin("gpmc_oen_ren", PULL_UP | MODE_0); pinmux_configurepin("gpmc_wen", PULL_UP | MODE_0); @@ -209,12 +233,11 @@ static void gpmc_setup(int chipselect, int accesscycles, int size, bool enablecs *(registers + displacement + GPMC_CONFIG7) = 0x0; *(registers + displacement + GPMC_CONFIG1) = 0x0; - *(registers + displacement + GPMC_CONFIG2) = (accesscycles << CSWROFFTIME) | (accesscycles << CSRDOFFTIME); + *(registers + displacement + GPMC_CONFIG2) = config2; *(registers + displacement + GPMC_CONFIG3) = 0x0; // not using ADV so we can ignore this guy - *(registers + displacement + GPMC_CONFIG4) = (accesscycles << OEOFFTIME); - *(registers + displacement + GPMC_CONFIG5) = (accesscycles << RDACCESSTIME) | (accesscycles << WRCYCLETIME) - | (accesscycles << RDCYCLETIME); - *(registers + displacement + GPMC_CONFIG6) = (accesscycles << WRACCESSTIME); + *(registers + displacement + GPMC_CONFIG4) = config4; + *(registers + displacement + GPMC_CONFIG5) = config5; + *(registers + displacement + GPMC_CONFIG6) = config6; *(registers + displacement + GPMC_CONFIG7) = size << 8 | (enablecs ? 1 << 6 : 0) | baseaddress; gpmc_unmapregisters(); @@ -326,7 +349,7 @@ static unsigned gpio_pins[] = { GPIO0_X + 22, // i.e., GPIO0_22 GPIO1_X + 15, // i.e., GPIO1_15 GPIO1_X + 14, GPIO0_X + 27, - GPIO1_X + 12 + GPIO1_X + 12 }; @@ -343,7 +366,7 @@ void bus_init() } if (isbb) { - gpmc_setup(0, GPMCACCESSTIME, GPMC_SIZE_16MB, true, 1); + gpmc_setup(); extbus = (uint8_t*) util_mapmemoryblock(0x01000000, 0x100); @@ -367,9 +390,9 @@ void bus_init() int bus_getpin(int pin) { - if (isbb) { - return gpio_readvalue(gpio_pins[pin]); - } else { + if (isbb) { + return gpio_readvalue(gpio_pins[pin]); + } else { return 0; } } @@ -25,7 +25,6 @@ #define Octal_DACportCS_high 0x20 #define TNT_Port 0x40 -#define GPMCACCESSTIME 0x07 void bus_init(void); // call this before doing anything diff --git a/dummy_functions.c b/dummy_functions.c index 8f10b94..71d6b59 100644 --- a/dummy_functions.c +++ b/dummy_functions.c @@ -1,31 +1,5 @@ #include "dummy_functions.h" #include "globals.h" -void GPIB_Set_Command_Error() {} -void GPIB_Set_Query_Error() {} -void GPIB_Set_Device_Dependent_Error() {} -void GPIB_Set_Execution_Error() {} -unsigned int GPIB_get_ESR () -{ - return 0; -} -unsigned int GPIB_get_SRE () -{ - return 0; -} -unsigned int GPIB_get_ESE () -{ - return 0; -} -unsigned int GPIB_get_STB () -{ - return 0; -} -void GPIB_set_ESR (unsigned int byte,int operation) {} -void GPIB_set_SRE (unsigned int byte,int operation) {} -void GPIB_set_ESE (unsigned int byte,int operation) {} -void GPIB_clear_events () {} -void GPIB_change_address(int new_address) {} - void Main_return_to_local() {} diff --git a/dummy_functions.h b/dummy_functions.h index 15cfb1b..5f9ba2e 100644 --- a/dummy_functions.h +++ b/dummy_functions.h @@ -3,20 +3,6 @@ #include "globals.h" -void GPIB_Set_Command_Error(); -void GPIB_Set_Query_Error(); -void GPIB_Set_Device_Dependent_Error(); -void GPIB_Set_Execution_Error(); -unsigned int GPIB_get_ESR (); -unsigned int GPIB_get_SRE (); -unsigned int GPIB_get_ESE (); -unsigned int GPIB_get_STB (); -void GPIB_set_ESR (unsigned int byte,int operation); -void GPIB_set_SRE (unsigned int byte,int operation); -void GPIB_set_ESE (unsigned int byte,int operation); -void GPIB_clear_events (); -void GPIB_change_address(int new_address); - void Main_return_to_local(); #endif diff --git a/error_utils.c b/error_utils.c index 32ea779..8681808 100644 --- a/error_utils.c +++ b/error_utils.c @@ -20,6 +20,7 @@ END DESCRIPTION **********************************************************/ #include "lcd.h" #include "error_utils.h" #include "menus.h" +#include "gpib.h" /*** EndHeader */ @@ -120,8 +121,6 @@ void queue_error_from_parser(gchar** response, int error_num) } -void queue_error_for_gpib_only(int error_num); - void queue_error_for_gpib_only(int error_num) { if (error_num == OK) { diff --git a/error_utils.h b/error_utils.h index ac03fd9..a331b18 100644 --- a/error_utils.h +++ b/error_utils.h @@ -11,5 +11,6 @@ void Error_Remove_From_Queue(void); int Error_check(ChannelStruct ChannelStateToTest[max_channels]); void queue_and_broadcast_sensor_alarm(int error_num); void queue_error_and_display_on_LCD(int error_num); +void queue_error_for_gpib_only(int error_num); #endif @@ -11,8 +11,9 @@ GlobalStruct globals = { .Registers.last_relay_driver_settings[0] = -1, .Registers.last_relay_driver_settings[1] = -1, - .Registers.last_relay_driver_settings[2] = -1 + .Registers.last_relay_driver_settings[2] = -1, + .Registers.gpib_buffer[0] = 0 }; @@ -273,18 +273,8 @@ long sec_timer (void); unsigned long long ms_timer (void); -typedef struct { - int PRIMARY_ADDRESS; /* GPIB chip's GPIB primary address */ - 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; -} GpibStruct; +#define max_gpib_input_length 512 typedef struct { int parallel_DAC_reg[8]; @@ -294,6 +284,7 @@ typedef struct { int ques_enable_register; /* for stat:enable command */ int avrq_reg; int last_rise_time_relay_setting; + char gpib_buffer[max_gpib_input_length]; } HWregStruct; @@ -795,7 +786,6 @@ typedef struct { ConstraintsStruct Constraints; ChannelStruct ChannelState[max_channels]; FlashStruct Flash; - GpibStruct GPIB; HWregStruct Registers; ChangeStruct Changes; ErrorStruct Errors; @@ -0,0 +1,981 @@ +#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 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) +{ + 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); +} + @@ -0,0 +1,25 @@ +/* define macros */ + +void GPIB_Set_Execution_Error(void); +void GPIB_Set_Command_Error(void); +void GPIB_Set_Query_Error(void); +void GPIB_Set_Device_Dependent_Error(void); +void GPIB_initialize(void); +void GPIB_change_address(int new_address); +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(char *out_buffer); +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 (); +unsigned int GPIB_get_SRE (); +unsigned int GPIB_get_ESE (); +unsigned int GPIB_get_STB (); +void GPIB_set_ESR (unsigned int byte,int operation); +void GPIB_set_SRE (unsigned int byte,int operation); +void GPIB_set_ESE (unsigned int byte,int operation); + diff --git a/instr-daemon.c b/instr-daemon.c index 7ee36d3..8ffd2b7 100644 --- a/instr-daemon.c +++ b/instr-daemon.c @@ -8,6 +8,9 @@ #include "nicutils.h" #include "monitor.h" #include "menus.h" +#include "gpib.h" +#include "parser.h" + #include <stdlib.h> #include <ctype.h> #include <glib.h> @@ -193,6 +196,8 @@ int main(int argc, char **argv) g_type_init (); + bus_init(); + LCD_initialize(); LCD_write(0,0,"Starting..."); @@ -223,7 +228,7 @@ int main(int argc, char **argv) LCD_write(2,0,message); g_free (message); - // FIXME - init RS232 +// GPIB_initialize(); IO_Setup_RS232( globals.Flash.baud, globals.Flash.parity, @@ -245,8 +250,6 @@ int main(int argc, char **argv) } LCD_write(3,27,"OK"); - bus_init(); - I2C_Setup_Monitor(); Main_Rst(); @@ -319,5 +322,19 @@ static gboolean periodic_poll (void) Menu_Check_Buttons (); + // FIXME - gpib input - should have it's own thread? + // + // FIXME - comment out everything up to "return TRUE" if this section + // is crashing due to non-functional bus + GPIB_check_for_device_clear_signal(); + if (GPIB_check_for_messages(globals.Registers.gpib_buffer)) { + if (GPIB_handle_new_input(globals.Registers.gpib_buffer)) { + // FIXME check_for_ctrl_mode_changes(); /* update rem/loc settings */ + Parser_main(globals.Registers.gpib_buffer, 0, NULL, NULL); + } + } + GPIB_check_for_device_clear_signal(); + + return TRUE; } @@ -9,6 +9,7 @@ #include "flash.h" #include "nicutils.h" #include "menus.h" +#include "gpib.h" #include <glib.h> #include <math.h> @@ -1217,7 +1218,7 @@ static void Display_Number_on_LCD(int Is_Item_Visible,int LCD_row,int LCD_col,ch break; case Show_gpib_address: - Submenu_Value=(float) globals.GPIB.PRIMARY_ADDRESS; + Submenu_Value=(float) globals.Flash.gpib_address; significant_digits=0; units = g_strdup(""); show_plus_sign=NO; @@ -18,6 +18,7 @@ END DESCRIPTION **********************************************************/ #include "i2c.h" #include "lcd.h" #include "menus.h" +#include "gpib.h" #include <glib/gprintf.h> @@ -2715,7 +2716,7 @@ static int Go_gpib_addr_59(gchar** response, int channel, char *parameter,char * break; case query_simple: - return query_int (response, globals.GPIB.PRIMARY_ADDRESS); + return query_int (response, globals.Flash.gpib_address); break; case query_param: |