MX_EXPORT mx_status_type mxd_handel_timer_finish_record_initialization( MX_RECORD *record ) { static const char fname[] = "mxd_handel_timer_finish_record_initialization()"; MX_TIMER *timer; MX_HANDEL_TIMER *handel_timer; MX_RECORD *handel_record; const char *handel_driver_name; if ( record == (MX_RECORD *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_RECORD pointer passed was NULL." ); } timer = (MX_TIMER *) record->record_class_struct; if ( timer == (MX_TIMER *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_TIMER pointer for record '%s' is NULL.", record->name ); } timer->mode = MXCM_PRESET_MODE; handel_timer = (MX_HANDEL_TIMER *) record->record_type_struct; if ( handel_timer == (MX_HANDEL_TIMER *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_HANDEL_TIMER pointer for record '%s' is NULL.", record->name ); } handel_record = handel_timer->handel_record; if ( handel_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The handel_record pointer for record '%s' is NULL.", record->name ); } handel_driver_name = mx_get_driver_name( handel_record ); if ( strcmp( handel_driver_name, "handel" ) != 0 ) { return mx_error( MXE_UNSUPPORTED, fname, "Handel timer record '%s' can only be used with a " "Handel record of type 'handel'. Instead, Handel record '%s' " "is of type '%s'.", record->name, handel_record->name, handel_driver_name ); } return mx_timer_finish_record_initialization( record ); }
static mx_status_type mxv_spec_get_pointers( MX_VARIABLE *variable, MX_SPEC_PROPERTY **spec_property, MX_SPEC_SERVER **spec_server, const char *calling_fname ) { static const char fname[] = "mxv_spec_get_pointers()"; MX_RECORD *spec_server_record; MX_SPEC_PROPERTY *spec_property_ptr; if ( variable == (MX_VARIABLE *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_VARIABLE pointer passed by '%s' was NULL.", calling_fname ); } if ( variable->record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_RECORD pointer for MX_VARIABLE pointer passed by '%s' was NULL.", calling_fname ); } spec_property_ptr = (MX_SPEC_PROPERTY *) variable->record->record_type_struct; if ( spec_property != (MX_SPEC_PROPERTY **) NULL ) { *spec_property = spec_property_ptr; } spec_server_record = spec_property_ptr->spec_server_record; if ( spec_server_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "spec_server_record pointer for record '%s' passed by '%s' is NULL.", variable->record->name, calling_fname ); } if ( spec_server_record->mx_type != MXN_SPEC_SERVER ) { return mx_error( MXE_TYPE_MISMATCH, fname, "spec_server_record '%s' for SPEC variable '%s' is not a SPEC server. " "Instead, it is a '%s' record.", spec_server_record->name, variable->record->name, mx_get_driver_name( spec_server_record ) ); } if ( spec_server != (MX_SPEC_SERVER **) NULL ) { *spec_server = (MX_SPEC_SERVER *) spec_server_record->record_type_struct; } return MX_SUCCESSFUL_RESULT; }
MX_EXPORT mx_status_type mxd_icplus_get_offset( MX_AMPLIFIER *amplifier ) { static const char fname[] = "mxd_icplus_get_offset()"; MX_ICPLUS *icplus; char command[40]; char response[40]; int num_items, offset_percentage; mx_status_type mx_status; icplus = NULL; if ( amplifier == ( MX_AMPLIFIER *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "The MX_AMPLIFIER pointer passed is NULL." ); } mx_status = mxd_icplus_get_pointers( amplifier->record, NULL, &icplus, fname ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; snprintf( command, sizeof(command), ":CONF%ld:CURR:OFFS?", icplus->address ); mx_status = mxd_icplus_command( icplus, command, response, sizeof response, MXD_ICPLUS_DEBUG ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; num_items = sscanf( response, "%d", &offset_percentage ); if ( num_items != 1 ) { return mx_error( MXE_DEVICE_IO_ERROR, fname, "Unrecognizable response to a Get Input Offset command '%s' " "by %s '%s'. Response = '%s'.", command, mx_get_driver_name( icplus->record ), amplifier->record->name, response ); } amplifier->offset = 0.1 * (double) offset_percentage; return MX_SUCCESSFUL_RESULT; }
static mx_status_type mxd_itc503_aoutput_get_pointers( MX_ANALOG_OUTPUT *aoutput, MX_ITC503_AOUTPUT **itc503_aoutput, MX_ITC503 **itc503, MX_ISOBUS **isobus, const char *calling_fname ) { static const char fname[] = "mxd_itc503_aoutput_get_pointers()"; MX_ITC503_AOUTPUT *itc503_aoutput_ptr; MX_RECORD *controller_record, *isobus_record; MX_ITC503 *itc503_ptr; if ( aoutput == (MX_ANALOG_OUTPUT *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "The MX_ANALOG_OUTPUT pointer passed was NULL." ); } if ( aoutput->record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_RECORD pointer for the MX_ANALOG_OUTPUT pointer passed was NULL." ); } itc503_aoutput_ptr = (MX_ITC503_AOUTPUT *) aoutput->record->record_type_struct; if ( itc503_aoutput_ptr == (MX_ITC503_AOUTPUT *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_ITC503_AOUTPUT pointer for analog output '%s' is NULL", aoutput->record->name ); } if ( itc503_aoutput != (MX_ITC503_AOUTPUT **) NULL ) { *itc503_aoutput = itc503_aoutput_ptr; } controller_record = itc503_aoutput_ptr->controller_record; if ( controller_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "controller_record pointer for analog output '%s' is NULL.", aoutput->record->name ); } switch( controller_record->mx_type ) { case MXI_CTRL_ITC503: case MXI_CTRL_CRYOJET: break; default: return mx_error( MXE_TYPE_MISMATCH, fname, "controller_record '%s' for ITC503 control record '%s' " "is not an 'itc503' or a 'cryojet' record. Instead, " "it is of type '%s'.", controller_record->name, aoutput->record->name, mx_get_driver_name( controller_record ) ); break; } itc503_ptr = (MX_ITC503 *) controller_record->record_type_struct; if ( itc503_ptr == (MX_ITC503 *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_ITC503 pointer for ITC503 controller '%s' " "used by ITC503 status record '%s' is NULL.", controller_record->name, aoutput->record->name ); } if ( itc503 != (MX_ITC503 **) NULL ) { *itc503 = itc503_ptr; } if ( isobus != (MX_ISOBUS **) NULL ) { isobus_record = itc503_ptr->isobus_record; if ( isobus_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The isobus_record pointer for %s " "controller record '%s' is NULL.", itc503_ptr->label, controller_record->name ); } *isobus = isobus_record->record_type_struct; if ( (*isobus) == (MX_ISOBUS *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_ISOBUS pointer for ISOBUS record '%s' " "is NULL.", isobus_record->name ); } } return MX_SUCCESSFUL_RESULT; }
MX_EXPORT mx_status_type mxi_isobus_open( MX_RECORD *record ) { static const char fname[] = "mxi_isobus_open()"; MX_ISOBUS *isobus; MX_RECORD *interface_record; unsigned long isobus_flags, read_terminator; mx_status_type mx_status; if ( record == (MX_RECORD *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_RECORD pointer passed is NULL."); } isobus = (MX_ISOBUS *) record->record_type_struct; if ( isobus == (MX_ISOBUS *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_ISOBUS pointer for record '%s' is NULL.", record->name); } isobus_flags = isobus->isobus_flags; #if MXI_ISOBUS_DEBUG MX_DEBUG(-2,("%s invoked for record '%s', isobus_flags = %#lx.", fname, record->name, isobus_flags )); #endif interface_record = isobus->isobus_interface.record; switch( interface_record->mx_class ) { case MXI_RS232: /* Verify that the RS-232 port has the right settings. */ if ( isobus_flags & MXF_ISOBUS_READ_TERMINATOR_IS_LINEFEED ) { read_terminator = MX_LF; } else { read_terminator = MX_CR; } mx_status = mx_rs232_verify_configuration( interface_record, 9600, 8, 'N', 1, 'N', read_terminator, 0x0d ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; /* Reinitialize the serial port. */ mx_status = mx_resynchronize_record( interface_record ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; mx_msleep(1000); /* Discard any characters waiting to be sent or received. */ mx_status = mx_rs232_discard_unwritten_output( interface_record, MXI_ISOBUS_DEBUG ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; mx_status = mx_rs232_discard_unread_input( interface_record, MXI_ISOBUS_DEBUG ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; break; case MXI_GPIB: /* GPIB does not require any initialization. */ break; default: return mx_error( MXE_TYPE_MISMATCH, fname, "Only RS-232 and GPIB interfaces are supported for " "ISOBUS interface '%s'. Interface record '%s' is " "of unsupported type '%s'.", record->name, interface_record->name, mx_get_driver_name( interface_record ) ); break; } return MX_SUCCESSFUL_RESULT; }
static mx_status_type mxd_smartmotor_ain_get_pointers( MX_ANALOG_INPUT *ainput, MX_SMARTMOTOR_AINPUT **smartmotor_ainput, MX_SMARTMOTOR **smartmotor, const char *calling_fname ) { static const char fname[] = "mxd_smartmotor_ain_get_pointers()"; MX_RECORD *smartmotor_record; if ( ainput == (MX_ANALOG_INPUT *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_ANALOG_INPUT pointer passed by '%s' was NULL.", calling_fname ); } if ( smartmotor_ainput == (MX_SMARTMOTOR_AINPUT **) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_SMARTMOTOR_AINPUT pointer passed by '%s' was NULL.", calling_fname ); } if ( smartmotor == (MX_SMARTMOTOR **) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_SMARTMOTOR pointer passed by '%s' was NULL.", calling_fname ); } if ( ainput->record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_RECORD pointer for MX_ANALOG_INPUT pointer passed by '%s' was NULL.", calling_fname ); } *smartmotor_ainput = (MX_SMARTMOTOR_AINPUT *) ainput->record->record_type_struct; if ( *smartmotor_ainput == (MX_SMARTMOTOR_AINPUT *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_SMARTMOTOR_AINPUT pointer for record '%s' passed by '%s' is NULL.", ainput->record->name, calling_fname ); } smartmotor_record = (*smartmotor_ainput)->smartmotor_record; if ( smartmotor_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_SMARTMOTOR pointer for SMARTMOTOR analog input " "record '%s' passed by '%s' is NULL.", ainput->record->name, calling_fname ); } if ( smartmotor_record->mx_type != MXT_MTR_SMARTMOTOR ) { return mx_error( MXE_TYPE_MISMATCH, fname, "smartmotor_record '%s' for SmartMotor analog input '%s' " "is not a SmartMotor record. Instead, it is a '%s' record.", smartmotor_record->name, ainput->record->name, mx_get_driver_name( smartmotor_record ) ); } *smartmotor = (MX_SMARTMOTOR *) smartmotor_record->record_type_struct; if ( *smartmotor == (MX_SMARTMOTOR *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_SMARTMOTOR pointer for SmartMotor record '%s' used by " "SmartMotor analog input record '%s' and passed by '%s' is NULL.", smartmotor_record->name, ainput->record->name, calling_fname ); } return MX_SUCCESSFUL_RESULT; }
MX_EXPORT mx_status_type mxd_icplus_command( MX_ICPLUS *icplus, char *command, char *response, size_t response_buffer_length, int debug_flag ) { static const char fname[] = "mxd_icplus_command()"; char c; int i, max_attempts; unsigned long sleep_ms, num_input_bytes_available; mx_status_type mx_status, mx_status2; if ( icplus == (MX_ICPLUS *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "NULL MX_ICPLUS pointer passed." ); } if ( command == NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "NULL command buffer pointer passed." ); } if ( debug_flag ) { MX_DEBUG(-2,("%s: sending '%s' to '%s'", fname, command, icplus->record->name )); } /* Send the command string. */ mx_status = mx_rs232_putline( icplus->rs232_record, command, NULL, 0 ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; /* The IC PLUS always sends an ACK character to acknowledge receipt * of the LF terminator for the command that we just sent. Even if * we expect no other response, we must still read and discard this * ACK character. */ mx_status = mx_rs232_getchar( icplus->rs232_record, &c, MXF_232_WAIT ); if ( mx_status.code == MXE_NOT_READY ) { return mx_error( MXE_NOT_READY, fname, "No response received from %s amplifier '%s' " "for command '%s'. Are you sure it is plugged in " "and turned on?", mx_get_driver_name( icplus->record ), icplus->record->name, command ); } if ( mx_status.code != MXE_SUCCESS ) return mx_status; if ( c != MX_ACK ) { (void) mx_rs232_discard_unread_input( icplus->rs232_record, MXD_ICPLUS_DEBUG ); return mx_error( MXE_DEVICE_IO_ERROR, fname, "Did not receive an ACK acknowledgement character from " "%s interface '%s' in response to the command '%s'. " "Instead, saw a %#x (%c) character.", mx_get_driver_name( icplus->record ), icplus->record->name, command, c, c ); } /* If we expect a response, then read it in. */ if ( response != NULL ) { mx_status = mx_rs232_getline( icplus->rs232_record, response, response_buffer_length, NULL, 0 ); if ( debug_flag & (mx_status.code == MXE_SUCCESS) ) { MX_DEBUG(-2,("%s: received '%s' from '%s'", fname, response, icplus->record->name )); } } else { if ( debug_flag ) { MX_DEBUG(-2,("%s complete.", fname)); } } /* If the IC PLUS echoes the command line back to us, then we must * throw this away. */ if ( icplus->discard_echoed_command_line ) { max_attempts = 100; sleep_ms = 1; for ( i = 0; i < max_attempts; i++ ) { mx_status2 = mx_rs232_num_input_bytes_available( icplus->rs232_record, &num_input_bytes_available ); if ( mx_status2.code != MXE_SUCCESS ) break; if ( num_input_bytes_available > 0 ) break; mx_msleep( sleep_ms ); } if ( i >= max_attempts ) { mx_status = mx_error( MXE_TIMED_OUT, fname, "Timed out waiting for %s record '%s' to echo " "the command line '%s' back to us.", mx_get_driver_name( icplus->record ), icplus->record->name, command ); } (void) mx_rs232_discard_unread_input( icplus->rs232_record, FALSE ); } return mx_status; }
MX_EXPORT mx_status_type mxd_icplus_get_gain( MX_AMPLIFIER *amplifier ) { static const char fname[] = "mxd_icplus_get_gain()"; MX_ICPLUS *icplus; char command[40]; char response[40]; int num_items; long exponent; mx_status_type mx_status; icplus = NULL; if ( amplifier == ( MX_AMPLIFIER *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "The MX_AMPLIFIER pointer passed is NULL." ); } mx_status = mxd_icplus_get_pointers( amplifier->record, NULL, &icplus, fname ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; snprintf( command, sizeof(command), ":CONF%ld:CURR:RANG?", icplus->address ); mx_status = mxd_icplus_command( icplus, command, response, sizeof response, MXD_ICPLUS_DEBUG ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; num_items = sscanf( response, "%ld", &(icplus->range) ); if ( num_items != 1 ) { return mx_error( MXE_DEVICE_IO_ERROR, fname, "Unrecognizable response to a Get Input Range command '%s' " "by %s record '%s'. Response = '%s'.", command, mx_get_driver_name( icplus->record ), amplifier->record->name, response ); } if ( (icplus->qbpm_flags & MXF_QBPM_USE_NEW_GAINS) == 0 ) { /* Use power of 10 gains. */ exponent = 11 - icplus->range; amplifier->gain = pow( 10.0, (double) exponent ); } else { /* Use new irregular gain pattern. */ switch( icplus->range ) { case 1: amplifier->gain = 1.4e9; break; case 2: amplifier->gain = 7.0e8; break; case 3: amplifier->gain = 3.5e8; break; case 4: amplifier->gain = 7.0e7; break; case 5: amplifier->gain = 7.0e6; break; case 6: amplifier->gain = 7.0e5; break; default: amplifier->gain = -1.0; break; } } return MX_SUCCESSFUL_RESULT; }
MX_EXPORT mx_status_type mxd_icplus_open( MX_RECORD *record ) { static const char fname[] = "mxd_icplus_open()"; MX_AMPLIFIER *amplifier; MX_ICPLUS *icplus; MX_RS232 *rs232; char command[40]; char response[80]; int timed_out; unsigned long i, max_attempts, wait_ms, num_input_bytes_available; mx_status_type mx_status; amplifier = NULL; icplus = NULL; mx_status = mxd_icplus_get_pointers( record, &lifier, &icplus, fname ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; mx_status = mx_rs232_get_pointers( icplus->rs232_record, &rs232, NULL, fname ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; MX_DEBUG( 2,("%s invoked for record '%s'.", fname, record->name)); /* The ICPLUS driver does not use the QBPM flags. */ if ( record->mx_type == MXT_AMP_ICPLUS ) { icplus->qbpm_flags = 0; } /* See if the serial port is configured correctly. */ if( record->mx_type == MXT_AMP_ICPLUS ) { mx_status = mx_rs232_verify_configuration( icplus->rs232_record, 9600, 8, 'N', 1, 'N', 0x0a, 0x0a, rs232->timeout ); } else { mx_status = mx_rs232_verify_configuration( icplus->rs232_record, 19200, 8, 'N', 1, 'N', 0x0a, 0x0a, rs232->timeout ); } if ( mx_status.code != MXE_SUCCESS ) return mx_status; /* Throw away any leftover characters. */ mx_status = mx_rs232_discard_unwritten_output( icplus->rs232_record, MXD_ICPLUS_DEBUG ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; mx_status = mx_rs232_discard_unread_input( icplus->rs232_record, MXD_ICPLUS_DEBUG ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; /* If the RS-232 port does not have a timeout specified, set * the timeout to 1 second. */ if ( rs232->timeout < 0.0 ) { rs232->timeout = 1.0; MX_DEBUG( 2,("%s: forcing the timeout to 1 second.", fname)); } /* See if the IC PLUS is available by trying to read * the input current. */ if ( icplus->record->mx_type == MXT_AMP_ICPLUS ) { snprintf( command, sizeof(command), ":READ%ld:CURR?", icplus->address ); } else { snprintf( command, sizeof(command), ":READ%ld:CURR1?", icplus->address ); } wait_ms = 100; max_attempts = 5; timed_out = FALSE; for ( i = 0; i < max_attempts; i++ ) { mx_status = mxd_icplus_command( icplus, command, response, sizeof response, MXD_ICPLUS_DEBUG ); switch( mx_status.code ) { case MXE_SUCCESS: timed_out = FALSE; break; case MXE_NOT_READY: case MXE_TIMED_OUT: timed_out = TRUE; break; default: return mx_status; break; } if ( timed_out == FALSE ) break; /* Exit the for() loop. */ /* Resynchronize the serial port. This will cause * the serial port to be closed and then reopened. */ #if MXD_ICPLUS_DEBUG MX_DEBUG(-2,("%s: resynchronizing the serial port.", fname)); #endif mx_status = mx_resynchronize_record( icplus->rs232_record ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; mx_msleep( wait_ms ); } /* If there are still characters available from the RS-232 port, * then the serial port is echoing back part of the transmitted * command. This means that the RS-232 cable is incorrectly * wired, but we will attempt to continue anyway. */ mx_status = mx_rs232_num_input_bytes_available( icplus->rs232_record, &num_input_bytes_available ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; if ( num_input_bytes_available > 0 ) { icplus->discard_echoed_command_line = TRUE; (void) mx_rs232_discard_unread_input( icplus->rs232_record, FALSE ); mx_warning( "Some or all of the command string transmitted to '%s' device '%s' " "was echoed back to the serial port. This means that the RS-232 " "cable is incorrectly wired, but we will attempt to continue by " "discarding the echoed characters. However, this slows down the " "driver, so it would be better to fix the wiring.", mx_get_driver_name( icplus->record ), record->name ); } /* Set the gain, offset, and peaking time. */ mx_status = mx_amplifier_set_gain( record, amplifier->gain ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; mx_status = mx_amplifier_set_offset( record, amplifier->offset ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; mx_status = mx_amplifier_set_time_constant( record, amplifier->time_constant ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; /* If this is a QBPM controller, set the initial averaging. */ if ( record->mx_type == MXT_AMP_QBPM ) { if ( icplus->default_averaging > 100 ) { return mx_error( MXE_WOULD_EXCEED_LIMIT, fname, "The requested averaging size of %ld for record '%s' is " "outside the allowed range of 1 to 100.", icplus->default_averaging, record->name ); } else if ( icplus->default_averaging >= 1 ) { snprintf( command, sizeof(command), ":READ%ld:AVGCURR %ld", icplus->address, icplus->default_averaging ); } else if ( icplus->default_averaging > -1 ) { snprintf( command, sizeof(command), ":READ%ld:SINGLE", icplus->address ); } else if ( icplus->default_averaging >= -100 ) { snprintf( command, sizeof(command), ":READ%ld:WDWCURR %ld", icplus->address, -(icplus->default_averaging) ); } else { return mx_error( MXE_WOULD_EXCEED_LIMIT, fname, "The requested moving average size of %ld for record '%s' is " "outside the allowed range of -1 to -100.", icplus->default_averaging, record->name ); } mx_status = mxd_icplus_command( icplus, command, NULL, 0, MXD_ICPLUS_DEBUG ); } MX_DEBUG( 2,("%s complete.", fname)); return MX_SUCCESSFUL_RESULT; }
static mx_status_type mxd_bluice_motor_get_pointers( MX_MOTOR *motor, MX_BLUICE_MOTOR **bluice_motor, MX_BLUICE_SERVER **bluice_server, MX_BLUICE_FOREIGN_DEVICE **foreign_motor, mx_bool_type skip_foreign_device_check, const char *calling_fname ) { static const char fname[] = "mxd_bluice_motor_get_pointers()"; MX_RECORD *bluice_motor_record; MX_BLUICE_MOTOR *bluice_motor_ptr; MX_RECORD *bluice_server_record; MX_BLUICE_SERVER *bluice_server_ptr; MX_BLUICE_FOREIGN_DEVICE *foreign_motor_ptr; mx_status_type mx_status; long mx_status_code; /* In this section, we do standard MX ..._get_pointers() logic. */ if ( motor == (MX_MOTOR *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "The MX_MOTOR pointer passed by '%s' was NULL.", calling_fname ); } bluice_motor_record = motor->record; if ( bluice_motor_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_RECORD pointer for the MX_MOTOR pointer %p " "passed was NULL.", motor ); } bluice_motor_ptr = bluice_motor_record->record_type_struct; if ( bluice_motor_ptr == (MX_BLUICE_MOTOR *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_BLUICE_MOTOR pointer for record '%s' is NULL.", bluice_motor_record->name ); } if ( bluice_motor != (MX_BLUICE_MOTOR **) NULL ) { *bluice_motor = bluice_motor_ptr; } bluice_server_record = bluice_motor_ptr->bluice_server_record; if ( bluice_server_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The 'bluice_server_record' pointer for record '%s' " "is NULL.", bluice_motor_record->name ); } bluice_server_ptr = bluice_server_record->record_class_struct; if ( bluice_server_ptr == (MX_BLUICE_SERVER *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_BLUICE_SERVER pointer for Blu-Ice server " "record '%s' used by record '%s' is NULL.", bluice_server_record->name, bluice_motor_record->name ); } if ( bluice_server != (MX_BLUICE_SERVER **) NULL ) { *bluice_server = bluice_server_ptr; } if ( skip_foreign_device_check ) { return MX_SUCCESSFUL_RESULT; } /* In this section, we check to see if the pointer to the Blu-Ice * foreign device structure has been set up yet. */ if ( foreign_motor != (MX_BLUICE_FOREIGN_DEVICE **) NULL ) { *foreign_motor = NULL; } foreign_motor_ptr = bluice_motor_ptr->foreign_device; if ( foreign_motor_ptr == (MX_BLUICE_FOREIGN_DEVICE *) NULL ) { double timeout; /* If not, wait a while for the pointer to be set up. */ switch( bluice_server_record->mx_type ) { case MXN_BLUICE_DCSS_SERVER: timeout = 5.0; break; case MXN_BLUICE_DHS_SERVER: timeout = 0.1; break; default: return mx_error( MXE_TYPE_MISMATCH, fname, "Blu-Ice server record '%s' should be either of type " "'bluice_dcss_server' or 'bluice_dhs_server'. " "Instead, it is of type '%s'.", bluice_server_record->name, mx_get_driver_name( bluice_server_record ) ); } #if BLUICE_MOTOR_DEBUG MX_DEBUG(-2,("%s: About to wait for device pointer " "initialization of motor '%s' for function '%s'.", fname, bluice_motor_record->name, calling_fname)); #endif mx_status_code = mx_mutex_lock( bluice_server_ptr->foreign_data_mutex ); if ( mx_status_code != MXE_SUCCESS ) { return mx_error( mx_status_code, fname, "An attempt to lock the foreign data mutex for " "Blu-ice server '%s' failed.", bluice_server_record->name ); } mx_status = mx_bluice_wait_for_device_pointer_initialization( bluice_server_ptr, bluice_motor_ptr->bluice_name, MXT_BLUICE_FOREIGN_MOTOR, &(bluice_server_ptr->motor_array), &(bluice_server_ptr->num_motors), &foreign_motor_ptr, timeout ); if ( mx_status.code != MXE_SUCCESS ) { mx_mutex_unlock(bluice_server_ptr->foreign_data_mutex); return mx_status; } foreign_motor_ptr->u.motor.mx_motor = motor; bluice_motor_ptr->foreign_device = foreign_motor_ptr; mx_mutex_unlock( bluice_server_ptr->foreign_data_mutex ); #if BLUICE_MOTOR_DEBUG MX_DEBUG(-2,("%s: Successfully waited for device pointer " "initialization of motor '%s'.", fname, bluice_motor_record->name)); #endif } if ( foreign_motor != (MX_BLUICE_FOREIGN_DEVICE **) NULL ) { *foreign_motor = foreign_motor_ptr; } return MX_SUCCESSFUL_RESULT; }
MX_EXPORT mx_status_type mxd_si9650_status_read( MX_ANALOG_INPUT *ainput ) { static const char fname[] = "mxd_si9650_status_read()"; MX_SI9650_STATUS *si9650_status; MX_SI9650_MOTOR *si9650_motor; MX_RECORD *si9650_motor_record; MX_DRIVER *driver; char driver_name[ MXU_DRIVER_NAME_LENGTH+1 ]; char command[80]; char response[80]; int num_items; double status_value; mx_status_type mx_status; /* Find and check a bunch of pointers. */ if ( ainput == (MX_ANALOG_INPUT *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "The MX_ANALOG_INPUT pointer passed was NULL." ); } if ( ainput->record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_RECORD pointer for the MX_ANALOG_INPUT pointer passed was NULL." ); } si9650_status = (MX_SI9650_STATUS *) ainput->record->record_type_struct; if ( si9650_status == (MX_SI9650_STATUS *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_SI9650_STATUS pointer for analog input '%s' is NULL", ainput->record->name ); } si9650_motor_record = si9650_status->si9650_motor_record; if ( si9650_motor_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "si9650_motor_record pointer for analog input '%s' is NULL.", ainput->record->name ); } if ( si9650_motor_record->mx_type != MXT_MTR_SI9650 ) { driver = mx_get_driver_by_type( MXT_MTR_SI9650 ); if ( driver == (MX_DRIVER *) NULL ) { strlcpy( driver_name, "unknown", MXU_DRIVER_NAME_LENGTH ); } else { strlcpy( driver_name, driver->name, MXU_DRIVER_NAME_LENGTH ); } return mx_error( MXE_TYPE_MISMATCH, fname, "si9650_motor_record '%s' for SI 9650 status record '%s' " "is not of type '%s'. Instead, it is of type '%s'.", si9650_motor_record->name, ainput->record->name, driver_name, mx_get_driver_name( si9650_motor_record ) ); } si9650_motor = (MX_SI9650_MOTOR *) si9650_motor_record->record_type_struct; if ( si9650_motor == (MX_SI9650_MOTOR *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_SI9650_MOTOR pointer for SI 9650 motor '%s' " "used by SI 9650 status record '%s' is NULL.", si9650_motor_record->name, ainput->record->name ); } /* Request the status of the controller. */ switch( si9650_status->parameter_type ) { case MXT_SI9650_TEMPERATURE_SENSOR1: strlcpy( command, "T", sizeof(command) ); break; case MXT_SI9650_TEMPERATURE_SENSOR2: strlcpy( command, "t", sizeof(command) ); break; default: return mx_error( MXE_ILLEGAL_ARGUMENT, fname, "Unrecognized parameter type %ld for 'si9650_status' record '%s'. " "The allowed values are in the range (1-2).", si9650_status->parameter_type, ainput->record->name ); } mx_status = mxd_si9650_motor_command( si9650_motor, command, response, sizeof(response), SI9650_STATUS_DEBUG ); if ( mx_status.code != MXE_SUCCESS ) return mx_status; num_items = sscanf( response, "%lg", &status_value ); if ( num_items != 1 ) { return mx_error( MXE_DEVICE_IO_ERROR, fname, "Unrecognizable response returned by SI 9650 controller '%s' " "to command '%s'. Response = '%s'.", ainput->record->name, command, response ); } ainput->raw_value.double_value = 0.1 * status_value; return MX_SUCCESSFUL_RESULT; }
static mx_status_type mxd_compumotor_din_get_pointers( MX_DIGITAL_INPUT *dinput, MX_COMPUMOTOR_DINPUT **compumotor_dinput, MX_COMPUMOTOR_INTERFACE **compumotor_interface, const char *calling_fname ) { static const char fname[] = "mxd_compumotor_din_get_pointers()"; MX_RECORD *compumotor_interface_record; if ( dinput == (MX_DIGITAL_INPUT *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_DIGITAL_INPUT pointer passed by '%s' was NULL.", calling_fname ); } if (compumotor_dinput == NULL) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_COMPUMOTOR_DINPUT pointer passed by '%s' was NULL.", calling_fname ); } if (compumotor_interface == NULL) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_COMPUMOTOR_INTERFACE pointer passed by '%s' was NULL.", calling_fname ); } if ( dinput->record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_RECORD pointer for MX_DIGITAL_INPUT pointer passed by '%s' was NULL.", calling_fname ); } *compumotor_dinput = (MX_COMPUMOTOR_DINPUT *) dinput->record->record_type_struct; if ( *compumotor_dinput == (MX_COMPUMOTOR_DINPUT *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_COMPUMOTOR_DINPUT pointer for record '%s' passed by '%s' is NULL.", dinput->record->name, calling_fname ); } compumotor_interface_record = (*compumotor_dinput)->compumotor_interface_record; if ( compumotor_interface_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "compumotor_interface_record pointer for Compumotor digital input " "record '%s' passed by '%s' is NULL.", dinput->record->name, calling_fname ); } if ( compumotor_interface_record->mx_type != MXI_CTRL_COMPUMOTOR ) { return mx_error( MXE_TYPE_MISMATCH, fname, "compumotor_interface_record '%s' for Compumotor digital " "input '%s' is not a Compumotor interface record. " "Instead, it is a '%s' record.", compumotor_interface_record->name, dinput->record->name, mx_get_driver_name( compumotor_interface_record ) ); } *compumotor_interface = (MX_COMPUMOTOR_INTERFACE *) compumotor_interface_record->record_type_struct; if ( *compumotor_interface == (MX_COMPUMOTOR_INTERFACE *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_COMPUMOTOR_INTERFACE pointer for Compumotor record '%s' used " "by Compumotor digital input record '%s' and passed by '%s' is NULL.", compumotor_interface_record->name, dinput->record->name, calling_fname ); } return MX_SUCCESSFUL_RESULT; }
static mx_status_type mxd_mdrive_din_get_pointers( MX_DIGITAL_INPUT *dinput, MX_MDRIVE_DINPUT **mdrive_dinput, MX_MDRIVE **mdrive, const char *calling_fname ) { static const char fname[] = "mxd_mdrive_din_get_pointers()"; MX_RECORD *mdrive_record; if ( dinput == (MX_DIGITAL_INPUT *) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_DIGITAL_INPUT pointer passed by '%s' was NULL.", calling_fname ); } if ( mdrive_dinput == (MX_MDRIVE_DINPUT **) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_MDRIVE_DINPUT pointer passed by '%s' was NULL.", calling_fname ); } if ( mdrive == (MX_MDRIVE **) NULL ) { return mx_error( MXE_NULL_ARGUMENT, fname, "MX_MDRIVE pointer passed by '%s' was NULL.", calling_fname ); } if ( dinput->record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_RECORD pointer for MX_DIGITAL_INPUT pointer passed by '%s' was NULL.", calling_fname ); } *mdrive_dinput = (MX_MDRIVE_DINPUT *) dinput->record->record_type_struct; if ( *mdrive_dinput == (MX_MDRIVE_DINPUT *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_MDRIVE_DINPUT pointer for record '%s' passed by '%s' is NULL.", dinput->record->name, calling_fname ); } mdrive_record = (*mdrive_dinput)->mdrive_record; if ( mdrive_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "MX_MDRIVE pointer for MDRIVE digital input " "record '%s' passed by '%s' is NULL.", dinput->record->name, calling_fname ); } if ( mdrive_record->mx_type != MXT_MTR_MDRIVE ) { return mx_error( MXE_TYPE_MISMATCH, fname, "mdrive_record '%s' for MDrive digital input '%s' " "is not a MDrive record. Instead, it is a '%s' record.", mdrive_record->name, dinput->record->name, mx_get_driver_name( mdrive_record ) ); } *mdrive = (MX_MDRIVE *) mdrive_record->record_type_struct; if ( *mdrive == (MX_MDRIVE *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "The MX_MDRIVE pointer for MDrive record '%s' used by " "MDrive digital input record '%s' and passed by '%s' is NULL.", mdrive_record->name, dinput->record->name, calling_fname ); } return MX_SUCCESSFUL_RESULT; }
MX_EXPORT mx_status_type mxd_powerpmac_simultaneous_start( long num_motor_records, MX_RECORD **motor_record_array, double *position_array, unsigned long flags ) { static const char fname[] = "mxd_powerpmac_simultaneous_start()"; MX_RECORD *powerpmac_interface_record = NULL; MX_RECORD *motor_record; MX_MOTOR *motor; MX_POWERPMAC_MOTOR *powerpmac_motor = NULL; MX_POWERPMAC *powerpmac = NULL; char command_buffer[500]; char *ptr; const char *driver_name; double raw_position; long i, raw_steps; size_t length, buffer_left; mx_status_type mx_status; if ( num_motor_records <= 0 ) return MX_SUCCESSFUL_RESULT; /* Construct the move command to send to the POWERPMAC. */ ptr = command_buffer; *ptr = '\0'; for ( i = 0; i < num_motor_records; i++ ) { motor_record = motor_record_array[i]; motor = (MX_MOTOR *) motor_record->record_class_struct; driver_name = mx_get_driver_name( motor_record ); if ( strcmp( driver_name, "powerpmac_motor" ) != 0 ) { return mx_error( MXE_TYPE_MISMATCH, fname, "Cannot perform a simultaneous start since motors " "'%s' and '%s' are not the same type of motors.", motor_record_array[0]->name, motor_record->name ); } powerpmac_motor = (MX_POWERPMAC_MOTOR *) motor_record->record_type_struct; if ( powerpmac_interface_record == (MX_RECORD *) NULL ) { powerpmac_interface_record = powerpmac_motor->powerpmac_record; powerpmac = (MX_POWERPMAC *) powerpmac_interface_record->record_type_struct; } /* Verify that the POWERPMAC motor records all belong * to the same PowerPMAC controller. */ if ( powerpmac_interface_record != powerpmac_motor->powerpmac_record ) { return mx_error( MXE_UNSUPPORTED, fname, "Cannot perform a simultaneous start for motors '%s' and '%s' " "since they are controlled by different POWERPMAC interfaces, " "namely '%s' and '%s'.", motor_record_array[0]->name, motor_record->name, powerpmac_interface_record->name, powerpmac_motor->powerpmac_record->name ); } /* Compute the new position in raw units. */ raw_position = mx_divide_safely( position_array[i] - motor->offset, motor->scale ); raw_steps = mx_round( raw_position ); /* Append the part of the command referring to this motor. */ length = strlen( command_buffer ); buffer_left = sizeof(command_buffer) - length; ptr = command_buffer + length; snprintf( ptr, buffer_left, "#%ldJ=%ld ", powerpmac_motor->motor_number, raw_steps ); } if ( powerpmac_interface_record == (MX_RECORD *) NULL ) { return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname, "No powerpmac interface record pointer was found for " "record '%s'.", motor_record_array[0]->name ); } /* Send the command to the POWERPMAC. */ MX_DEBUG( 2,("%s: command = '%s'", fname, command_buffer)); mx_status = mxi_powerpmac_command( powerpmac, command_buffer, NULL, 0, POWERPMAC_DEBUG ); return mx_status; }
int motor_start_fn( int argc, char *argv[] ) { MX_RECORD *record; mx_status_type mx_status; if ( argc != 3 ) { fprintf(output, "Usage: start 'devicename' - starts moving or counting for 'devicename'\n" ); return FAILURE; } record = mx_get_record( motor_record_list, argv[2] ); if ( record == (MX_RECORD *) NULL ) { fprintf( output, "Record '%s' does not exist.\n", argv[2] ); return FAILURE; } /* Find out what kind of record this is. */ switch( record->mx_superclass ) { case MXR_DEVICE: switch( record->mx_class ) { case MXC_MULTICHANNEL_ANALYZER: mx_status = mx_mca_start( record ); break; case MXC_MULTICHANNEL_SCALER: mx_status = mx_mcs_start( record ); break; case MXC_PULSE_GENERATOR: mx_status = mx_pulse_generator_start( record ); break; default: fprintf(output, "Start is not supported for '%s' records.\n", mx_get_driver_name( record ) ); return FAILURE; break; } break; case MXR_OPERATION: mx_status = mx_operation_start( record ); break; default: fprintf(output, "Start is only supported for device and operation records.\n"); return FAILURE; } if ( mx_status.code == MXE_SUCCESS ) { return SUCCESS; } else { return FAILURE; } }