Пример #1
0
static mx_status_type
child_function( MX_THREAD *thread, void *args )
{
	mx_status_type mx_status;

	fprintf( stderr, "Child: Child thread starting.\n" );

	fprintf( stderr, "Child: Installing stop request handler.\n" );

	mx_status = mx_thread_set_stop_request_handler( thread,
							stop_request_handler,
							NULL );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	while(1) {
		fprintf( stderr, "Child: Checking for stop request.\n" );

		mx_status = mx_thread_check_for_stop_request( thread );

		if ( mx_status.code != MXE_SUCCESS )
			return mx_status;

		mx_msleep(500);
	}

	/* We should never get here. */
}
Пример #2
0
int
main( int argc, char *argv[] )
{
	MX_THREAD *child_thread;
	long thread_exit_status;
	mx_status_type mx_status;

	fprintf( stderr, "Parent: Creating child thread.\n" );

	mx_status = mx_thread_create( &child_thread, child_function, NULL );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

	fprintf( stderr, "Parent: Hit any key to stop the child thread.\n" );

	while(1) {
		if ( mx_kbhit() ) {
			break;		/* Exit the while() loop. */
		}

		mx_msleep(100);
	}

	fprintf( stderr, "Parent: Asking the child thread to stop.\n" );

	mx_status = mx_thread_stop( child_thread );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

	fprintf( stderr, "Parent: Waiting for the child thread to stop.\n" );

	mx_status = mx_thread_wait( child_thread,
					&thread_exit_status,
					MX_THREAD_INFINITE_WAIT );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

	fprintf( stderr, "Parent: Child thread exit status = %ld.\n",
						thread_exit_status );

	fprintf( stderr, "Parent: Freeing child data structures.\n" );

	mx_status = mx_thread_free_data_structures( child_thread );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

	/* Announce to the user that the test is over. */

	fprintf( stderr, "Parent: Thread test completed successfully.\n" );

	exit(0);
}
Пример #3
0
MX_EXPORT mx_status_type
mxd_uglide_soft_abort( MX_MOTOR *motor )
{
	static const char fname[] = "mxd_uglide_soft_abort()";

	MX_UGLIDE_MOTOR *uglide_motor;
	MX_UGLIDE *uglide;
	mx_status_type mx_status;

	mx_status = mxd_uglide_get_pointers( motor,
					&uglide_motor, &uglide, fname );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	MX_DEBUG( 2,("%s invoked for motor '%s'.", fname, motor->record->name));

	/* Send the single character 's' to the controller. */

#if UGLIDE_DEBUG
	MX_DEBUG(-2,("%s: sending soft abort character 's' to '%s'",
			fname, uglide->record->name ));
#endif

	mx_status = mx_rs232_putline( uglide->rs232_record, "s", NULL, 0 );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Wait a moment for the move to stop and then discard all
	 * existing responses from the controller.
	 */

	mx_msleep(500);

	mx_status = mx_rs232_discard_unread_input( uglide->rs232_record,
							UGLIDE_DEBUG );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Tell the controller record that the last command executed was
	 * a position report.
	 */

	uglide->last_response_code = MXF_UGLIDE_POSITION_REPORT;

	/* Refresh the position of the motors. */

	mx_status = mxi_uglide_command( uglide, "q", UGLIDE_DEBUG );

	return mx_status;
}
Пример #4
0
MX_EXPORT mx_status_type
mx_bluice_wait_for_device_pointer_initialization(
			MX_BLUICE_SERVER *bluice_server,
			char *name,
			long bluice_foreign_type,
			MX_BLUICE_FOREIGN_DEVICE ***foreign_device_array_ptr,
			long *num_foreign_devices_ptr,
			MX_BLUICE_FOREIGN_DEVICE **foreign_device_ptr,
			double timeout_in_seconds )
{
	static const char fname[] =
			"mx_bluice_wait_for_device_pointer_initialization()";

	unsigned long i, wait_ms, max_attempts;
	mx_status_type mx_status;

	/* Wait for the Blu-Ice server thread to assign a value to the pointer.
	 */
	
	wait_ms = 100;

	max_attempts = 
		mx_round( (1000.0 * timeout_in_seconds) / (double) wait_ms );

	for ( i = 0; i < max_attempts; i++ ) {

		mx_status = mx_bluice_device_pointer_fn( bluice_server,
						name,
						foreign_device_array_ptr,
						num_foreign_devices_ptr,
						FALSE,
						foreign_device_ptr );

		if ( mx_status.code == MXE_NOT_FOUND ) {
			mx_msleep( wait_ms );
		} else {
			if ( mx_status.code != MXE_SUCCESS )
				return mx_status;

			if ( (*foreign_device_ptr) == NULL ) {
				mx_msleep( wait_ms );
			} else {
				break;		/* Exit the for() loop. */
			}
		}
	}

	if ( i >= max_attempts ) {
		return mx_error( MXE_TIMED_OUT, fname,
		"Timed out after waiting %g seconds for Blu-Ice server '%s' "
		"to initialize Blu-Ice device '%s'.", timeout_in_seconds,
					bluice_server->record->name, name );
	}

	if ( bluice_foreign_type != (*foreign_device_ptr)->foreign_type ) {
		return mx_error( MXE_TYPE_MISMATCH, fname,
		"The type (%ld) of Blu-Ice server device '%s' does not "
		"match the expected type of %ld.  Perhaps you have specified "
		"an incorrect device name?",
			(*foreign_device_ptr)->foreign_type,
			name, bluice_foreign_type );
	}

	return MX_SUCCESSFUL_RESULT;
}
Пример #5
0
MX_EXPORT mx_status_type
mx_bluice_receive_message( MX_RECORD *bluice_server_record,
				char *data_buffer,
				long data_buffer_length,
				long *actual_data_length,
				double timeout_in_seconds )
{
	static const char fname[] = "mx_bluice_receive_message()";

	MX_BLUICE_SERVER *bluice_server;
	MX_SOCKET *bluice_server_socket;
	char message_header[MX_BLUICE_MSGHDR_LENGTH+1];
	long text_data_length, binary_data_length, total_data_length;
	long maximum_length;
	size_t actual_bytes_received;
	long num_bytes_available;
	unsigned long i, wait_ms, max_attempts;
	char *data_pointer;
	mx_status_type mx_status;

	bluice_server = NULL;
	bluice_server_socket = NULL;

	mx_status = mx_bluice_get_pointers( bluice_server_record,
				&bluice_server, &bluice_server_socket, fname );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Wait for a new message to come in.
	 *
	 * A negative timeout means wait forever, so we only need to loop
	 * if the timeout is >= 0.
	 */

	if ( timeout_in_seconds >= 0.0 ) {
		wait_ms = 10;
		max_attempts =
		    mx_round((1000.0 * timeout_in_seconds) / (double) wait_ms);

		for ( i = 0; i < max_attempts; i++ ) {
			mx_status = mx_socket_num_input_bytes_available(
					bluice_server->socket,
					&num_bytes_available );

			if ( mx_status.code != MXE_SUCCESS )
				return mx_status;

			if ( num_bytes_available != 0 ) {
				break;		/* Exit the for() loop. */
			}

			mx_msleep( wait_ms );
		}

		if ( i >= max_attempts ) {
			return mx_error( MXE_TIMED_OUT, fname,
			"Timed out after %g seconds of waiting for "
			"Blu-Ice server '%s' to send a message.",
				timeout_in_seconds,
				bluice_server_record->name );
		}
	}

	/* Read in the header from the Blu-Ice server. */

	mx_status = mx_socket_receive( bluice_server_socket,
					message_header,
					MX_BLUICE_MSGHDR_LENGTH,
					NULL, NULL, 0, 0 );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Make sure the message header is null terminated. */

	message_header[MX_BLUICE_MSGHDR_LENGTH-1] = '\0';

	/* Get the length of the binary data. */

	binary_data_length = atol( &message_header[MX_BLUICE_MSGHDR_BINARY] );

	if ( binary_data_length != 0 ) {
		mx_warning( "The binary data length for the message being "
		"received from Blu-Ice server '%s' is not 0.  "
		"Instead, it is %lu.",
			bluice_server_record->name,
			(unsigned long) binary_data_length );
	}

	/* Get the length of the text data. */

	message_header[MX_BLUICE_MSGHDR_BINARY] = '\0'; /* Null terminate it. */

	text_data_length = atol( message_header );

	total_data_length = text_data_length + binary_data_length;

#if 0
	MX_DEBUG(-2,("%s: text = %lu, binary = %lu, total = %lu",
		fname, (unsigned long) text_data_length,
		(unsigned long) binary_data_length,
		(unsigned long) total_data_length));
#endif

	if ( data_buffer == NULL ) {
		data_pointer = bluice_server->receive_buffer;
		maximum_length = bluice_server->receive_buffer_length;
	} else {
		data_pointer = data_buffer;
		maximum_length = data_buffer_length;
	}

	if ( total_data_length > maximum_length ) {
		mx_warning( "Truncating a %lu byte message body from "
		"Blu-Ice server '%s' to %lu bytes.",
			(unsigned long) total_data_length,
			bluice_server_record->name,
			(unsigned long) maximum_length );

		total_data_length = maximum_length;
	}

	/* Now receive the data for the message. */

	mx_status = mx_socket_receive( bluice_server_socket,
					data_pointer,
					total_data_length,
					&actual_bytes_received,
					NULL, 0, 0 );

#if BLUICE_DEBUG_MESSAGE
	MX_DEBUG(-3,("%s: received '%s' from server '%s'.",
		fname, data_pointer, bluice_server_record->name));
#endif

	*actual_data_length = (long) actual_bytes_received;

	if ( actual_bytes_received < maximum_length ) {
		data_pointer[actual_bytes_received] = '\0';
	}

	return mx_status;
}
Пример #6
0
int
motor_gpib_fn( int argc, char *argv[] )
{
	static const char cname[] = "gpib";

	MX_RECORD *record;
	int cmd_type, status, address;
	size_t length;
	mx_status_type mx_status;

	static char usage[] =
		"\n"
		"Usage: gpib 'record_name' address getline\n"
		"       gpib 'record_name' address putline \"text to send\"\n"
		"       gpib 'record_name' address command \"text to send\"\n"
		"       gpib 'record_name' address cmd \"text to send\"\n\n";

	if ( argc <= 4 ) {
		fputs( usage, output );
		return FAILURE;
	}

	record = mx_get_record( motor_record_list, argv[2] );

	if ( record == NULL ) {
		fprintf( output, "\n%s: There is no record named '%s'.\n\n",
				cname, argv[2] );
		return FAILURE;
	}

	if ( ( record->mx_superclass != MXR_INTERFACE )
	  || ( record->mx_class != MXI_GPIB ) )
	{
		fprintf( output, "\n%s: Record '%s' is not an GPIB port.\n\n",
				cname, argv[2] );
		return FAILURE;
	}

	address = atoi( argv[3] );

	length = strlen( argv[4] );

	if ( strncmp( "getline", argv[4], max(4,length) ) == 0 ) {
		cmd_type = GPIB_GETLINE_CMD;

	} else if ( strncmp( "putline", argv[4], max(1,length) ) == 0 ) {
		cmd_type = GPIB_PUTLINE_CMD;

	} else if ( strncmp( "command", argv[4], max(1,length) ) == 0 ) {
		cmd_type = GPIB_COMMAND_CMD;

	} else if ( strncmp( "cmd", argv[4], max(1,length) ) == 0 ) {
		cmd_type = GPIB_COMMAND_CMD;

	} else {
		fputs( usage, output );
		return FAILURE;
	}

	if ( cmd_type == GPIB_GETLINE_CMD ) {
		if ( argc != 5 ) {
			fputs( usage, output );
			return FAILURE;
		}
	} else {
		if ( argc != 6 ) {
			fputs( usage, output );
			return FAILURE;
		}
	}

	/* Both putline and command send a string here. */

	if ( ( cmd_type == GPIB_PUTLINE_CMD )
	  || ( cmd_type == GPIB_COMMAND_CMD ) )
	{
		mx_status = mx_gpib_putline( record, address,
					argv[5], NULL, GPIB_DEBUG );

		if ( mx_status.code != MXE_SUCCESS )
			return FAILURE;
	}

	switch( cmd_type ) {
	case GPIB_PUTLINE_CMD:

		/* Putline is done at this point. */

		return SUCCESS;

	case GPIB_GETLINE_CMD:

		status = motor_gpib_readline( record, address );

		if ( status == FAILURE ) {
			fprintf( output,
			"gpib: No new response is available.\n" );

			return FAILURE;
		}
		break;

	case GPIB_COMMAND_CMD:

		mx_msleep(500);

		status = motor_gpib_readline( record, address );

		if ( status == FAILURE ) {
			fprintf( output,
			"gpib: No response is available.\n" );

			return FAILURE;
		}
		break;
	default:
		fprintf( output,
		"gpib: Unrecognized command line.\n" );
		return FAILURE;
	}
	return SUCCESS;
}
Пример #7
0
MX_EXPORT mx_status_type
mxi_compumotor_open( MX_RECORD *record )
{
	static const char fname[] = "mxi_compumotor_open()";

	MX_COMPUMOTOR_INTERFACE *compumotor_interface;
	MX_RECORD *rs232_record;
	MX_RS232 *rs232;
	long i;
	unsigned long interface_flags;
	mx_status_type mx_status;

	if ( record == (MX_RECORD *) NULL ) {
		return mx_error( MXE_NULL_ARGUMENT, fname,
			"MX_RECORD pointer passed is NULL.");
	}

	compumotor_interface = (MX_COMPUMOTOR_INTERFACE *)
					(record->record_type_struct);

	if ( compumotor_interface == (MX_COMPUMOTOR_INTERFACE *) NULL ) {
		return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname,
		"MX_COMPUMOTOR_INTERFACE pointer for record '%s' is NULL.",
		record->name);
	}

	/* Are the line terminators set correctly? */

	rs232_record = compumotor_interface->rs232_record;

	if ( rs232_record == (MX_RECORD *) NULL ) {
		return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname,
		"rs232_record pointer for Compumotor interface '%s' is NULL.",
			record->name );
	}

	rs232 = (MX_RS232 *) rs232_record->record_class_struct;

	if ( rs232 == (MX_RS232 *) NULL ) {
		return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname,
		"MX_RS232 pointer for RS-232 record '%s' is NULL.",
			compumotor_interface->rs232_record->name );
	}

#if 0
	if ( (rs232->read_terminators != 0x0d0a)
	  || (rs232->write_terminators != 0x0d0a) )
	{
		return mx_error( MXE_ILLEGAL_ARGUMENT, fname,
	"The Compumotor interface '%s' requires that the line terminators "
	"of RS-232 record '%s' be a carriage return followed by a line feed.  "
	"Instead saw read terminator %#x and write terminator %#x.",
		record->name, compumotor_interface->rs232_record->name,
		rs232->read_terminators, rs232->write_terminators );
	}
#endif

	/* If requested, attempt to automatically configure the parameter
	 * settings needed for correct communication handshaking with the
	 * Compumotor controller.  The most important ones are
	 *     EOT13,10,0
	 *     ERRLVL1
	 *     ECHO1
	 *     MA11111111
	 */

	interface_flags = compumotor_interface->interface_flags;

	if ( interface_flags & MXF_COMPUMOTOR_AUTO_COMMUNICATION_CONFIG ) {

#if MXI_COMPUMOTOR_INTERFACE_DEBUG
		MX_DEBUG(-2,
	  ("%s: Attempting automatic communication config for controller '%s'.",
			fname, record->name));
#endif

		/* Since we do not necessarily have correct handshaking set up
		 * yet, we send the first three commands in the blind.
		 */

		(void) mx_rs232_discard_unwritten_output( rs232_record,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

		(void) mx_rs232_discard_unread_input( rs232_record,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

		mx_status = mx_rs232_putline( rs232_record,
					"!EOT13,10,0", NULL,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

		mx_status = mx_rs232_putline( rs232_record,
					"!ERRLVL1", NULL,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

		mx_status = mx_rs232_putline( rs232_record,
					"!ECHO1", NULL,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

		mx_status = mx_rs232_putline( rs232_record,
					"!MA11111111", NULL,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

		if ( interface_flags & MXF_COMPUMOTOR_KILL_ON_STARTUP ) {
			mx_status = mx_rs232_putline( rs232_record,
					"!K", NULL,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

		}

		/* If all went well, the controllers have been configured
		 * to handshake correctly with the MX driver.  We discard
		 * any responses from the controller so far.
		 */

		mx_msleep(100);

		mx_status = mx_rs232_discard_unread_input( rs232_record,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

		if ( mx_status.code != MXE_SUCCESS )
			return mx_status;
	}

	/* If requested, send an '!ADDR1' command to automatically configure
	 * unit addresses.  This will not do the right thing for an RS-485
	 * multi-drop configuration, so it must be optional.
	 */

	if ( compumotor_interface->interface_flags
		& MXF_COMPUMOTOR_AUTO_ADDRESS_CONFIG )
	{
		/* If we are using autoaddressing, the controllers must be 
		 * numbered from 1 to num_controllers in the controller_number
		 * array for consistency.  If they are not, generate an
		 * error message.
		 */

		for ( i = 0; i < compumotor_interface->num_controllers; i++ ) {
			if ( compumotor_interface->controller_number[i] != i+1 )
			{
				return mx_error( MXE_ILLEGAL_ARGUMENT, fname,
"If MXF_COMPUMOTOR_AUTO_ADDRESS_CONFIG is set for record '%s', then the "
"controller addresses in the database must be in order from 1 to %ld.",
				compumotor_interface->record->name,
				compumotor_interface->num_controllers );
			}
		}

		/* Send the automatic configuration command. */

		(void) mx_rs232_discard_unwritten_output( rs232_record,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

		mx_status = mx_rs232_putline( rs232_record,
					"!ADDR1", NULL,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

		switch( mx_status.code ) {
		case MXE_SUCCESS:
			break;
		case MXE_NOT_READY:
		case MXE_INTERFACE_IO_ERROR:
			return mx_error( MXE_INTERFACE_IO_ERROR, fname,
"Cannot set addresses for Compumotor interface '%s' on RS-232 port '%s'.  "
"Is it turned on?", record->name, compumotor_interface->rs232_record->name );
		default:
			return mx_status;
		}
	}

	/* Synchronize with the controllers. */

	mx_status = mxi_compumotor_resynchronize( record );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* If a startup program is defined, then run it. */

	if ( strlen( compumotor_interface->startup_program ) > 0 ) {
		mx_status = mxi_compumotor_run_program(
				compumotor_interface,
				"startup",
				compumotor_interface->startup_program );
	}

	return mx_status;
}
Пример #8
0
static mx_status_type
child_function( MX_THREAD *thread, void *args )
{
	mutex_pair_t *mutex_pair;
	long status, exit_status;
	int exit_loop;

	fprintf(stderr, "Child: Child thread starting.\n");

#if 0
	mx_show_thread_info( thread, "Child thread:" );
#endif

	if ( args == NULL ) {
		fprintf(stderr, "Child: args pointer was NULL.  Exiting...\n");
		exit(1);
	}

	mutex_pair = (mutex_pair_t *) args;

	/* Lock the child mutex. */

	fprintf( stderr, "Child: Locking child mutex.\n" );

	status = mx_mutex_lock( mutex_pair->child_mutex );

	if ( status != MXE_SUCCESS ) {
		fprintf( stderr,
"Child: Attempt to lock the child mutex failed with MX status code = %ld.\n",
			status );
		exit( status );
	}

	/* Busy wait for the parent mutex. */

	fprintf( stderr, "Child: Waiting to lock the parent mutex.\n" );

	exit_loop = FALSE;

	while( exit_loop == FALSE ) {
		status = mx_mutex_trylock( mutex_pair->parent_mutex );

		switch( status ) {
		case MXE_SUCCESS:
			exit_loop = TRUE;
			break;
		case MXE_NOT_AVAILABLE:
			fprintf(stderr, "Child: Parent mutex not available.\n");
			break;
		default:
			fprintf( stderr,
"Child: Attempt to lock the parent mutex failed with MX status code = %ld.\n",
				status );
			exit( status );
			break;
		}
		mx_msleep(500);
	}

	/* Once we have acquired the parent mutex, release it. */

	fprintf( stderr,
		"Child: Parent mutex locked.  It will now be unlocked.\n");

	status = mx_mutex_unlock( mutex_pair->parent_mutex );

	if ( status != MXE_SUCCESS ) {
		fprintf( stderr,
"Child: Attempt to unlock the parent mutex failed with MX status code = %ld.\n",
			status );
		exit( status );
	}

	/* Sleep for 5 seconds. */

	fprintf( stderr, "Child: Sleeping for 5 seconds.\n" );

	mx_msleep(5000);

	/* Unlock the child mutex. */

	fprintf( stderr, "Child: Unlocking the child mutex.\n" );

	status = mx_mutex_unlock( mutex_pair->child_mutex );

	if ( status != MXE_SUCCESS ) {
		fprintf( stderr,
"Child: Attempt to unlock the child mutex failed with MX status code = %ld.\n",
			status );
		exit( status );
	}

	exit_status = 456;

	fprintf( stderr,
	"Child: Child thread will now terminate with exit status = %ld.\n",
		exit_status );

	(void) mx_thread_exit( thread, exit_status );

	/* We should never get here. */

	return MX_SUCCESSFUL_RESULT;
}
Пример #9
0
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;
}
Пример #10
0
int
motor_home_fn( int argc, char *argv[] )
{
	static const char cname[] = "home";

	MX_RECORD *record;
	char *endptr;
	int direction;
	double position;
	unsigned long motor_status;
	mx_bool_type busy, home_search_succeeded, limit_hit;
	mx_status_type mx_status;

	static char usage[] =
"Usage:  home 'motorname' 'direction' -  Perform a home search on 'motorname'\n"
"\n"
"  Normally, direction > 0 causes a search in the positive direction,\n"
"  while direction < 0 causes a search in the negative direction.  Some\n"
"  drivers that can't do a home search will perform some other operation\n"
"  related to position calibration.  You must examine the individual driver\n"
"  to see exactly what it will do.  In all cases, direction == 0 is performs\n"
"  some driver specific function.\n";

	if ( argc != 4 ) {
		fprintf(output, "%s\n", usage);
		return FAILURE;
	}

	record = mx_get_record( motor_record_list, argv[2] );

	if ( record == (MX_RECORD *) NULL ) {
		fprintf(output,"%s: invalid motor name '%s'\n",cname,argv[2]);
		return FAILURE;
	}

	/* Is this a motor? */

	if ( record->mx_class != MXC_MOTOR ) {
		fprintf(output,"%s: '%s' is not a motor.\n",cname,argv[2]);
		return FAILURE;
	}

	direction = (int) strtol( argv[3], &endptr, 10 );

	if ( *endptr != '\0' ) {
		fprintf(output,
			"%s: specified direction '%s' is not a number.\n",
			cname, argv[3] );
		return FAILURE;
	}

	/* Start the home search. */

	fprintf(output,"*** Home search in progress ***\n");

	mx_status = mx_motor_home_search( record,
				direction, MXF_MTR_SHOW_MOVE );

	if ( mx_status.code != MXE_SUCCESS )
		return FAILURE;

	/* Wait for the home search to complete. */

	for (;;) {
		mx_status = mx_motor_get_extended_status( record,
						&position, &motor_status );

		if ( mx_status.code != MXE_SUCCESS )
			return FAILURE;

		fprintf(output, "  %g\n", position);

		if ( mx_user_requested_interrupt() ) {
			fprintf(output, "*** Home search interrupted ***\n");

			(void) mx_motor_soft_abort( record );

			break;		/* Exit the for(;;) loop. */
		}

		busy = (mx_bool_type) (motor_status & MXSF_MTR_IS_BUSY);

		if ( busy == FALSE ) {

			/* The motor has stopped, so exit the for(;;) loop. */

			break;
		}

		mx_msleep(1000);
	}

	mx_status = mx_motor_home_search_succeeded( record,
						&home_search_succeeded );

	if ( mx_status.code != MXE_SUCCESS )
		return FAILURE;

	if ( home_search_succeeded ) {
		fprintf(output,
		"*** Home search for motor '%s' completed successfully. ***\n",
			record->name );

		return SUCCESS;
	} else {
		/* Check to see if the limit switches are tripped. */

		(void) mx_motor_positive_limit_hit( record, &limit_hit );

		if ( limit_hit ) {
			fprintf(output,
			"*** Positive limit hit for motor '%s'. ***\n",
				record->name);
		}

		(void) mx_motor_negative_limit_hit( record, &limit_hit );

		if ( limit_hit ) {
			fprintf(output,
			"*** Negative limit hit for motor '%s'. ***\n",
				record->name);
		}

		fprintf(output,
"\007*** Home search failed.  Motor '%s' is not at the home switch. ***\n",
			record->name );

		return FAILURE;
	}
}
Пример #11
0
MX_EXPORT mx_status_type
mxd_u500_set_parameter( MX_MOTOR *motor )
{
	static const char fname[] = "mxd_u500_set_parameter()";

	MX_U500_MOTOR *u500_motor = NULL;
	MX_U500 *u500 = NULL;
	int board_number;
	char axis_name;
	double double_value;
	long long_value;
	char command[200];
	AERERR_CODE wapi_status;
	mx_status_type mx_status;

	mx_status = mxd_u500_get_pointers( motor, &u500_motor, &u500, fname );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	board_number = u500_motor->board_number;
	axis_name = u500_motor->axis_name;

	switch( motor->parameter_type ) {
	case MXLV_MTR_SPEED:
		/* Just store the value for later use by the INDEX
		 * and FREERUN commands.
		 */
		break;
	case MXLV_MTR_RAW_ACCELERATION_PARAMETERS:

		/* The acceleration must be specified in counts/msec**2 */

		sprintf( command, "AC %c%ld",
			u500_motor->axis_name,
			1.0e-6 * motor->raw_acceleration_parameters[0] );

		mx_status = mxi_u500_command( u500, board_number, command );
		break;
	case MXLV_MTR_AXIS_ENABLE:
		if ( motor->axis_enable ) {
			motor->axis_enable = 1;

			snprintf( command, sizeof(command),
				"EN %c", u500_motor->axis_name );
		} else {
			snprintf( command, sizeof(command),
				"DI %c", u500_motor->axis_name );
		}

		mx_status = mxi_u500_command( u500, board_number, command );
		break;
#if 0
	case MXLV_MTR_CLOSED_LOOP:
		if ( motor->closed_loop ) {
		} else {
		}
		break;
#endif
	case MXLV_MTR_FAULT_RESET:
		/* First send an abort command. */

		mx_status = mxi_u500_command( u500, board_number, "AB" );

		/* FIXME: Do we need to insert a delay here for it to
		 * respond to the abort?
		 */

		mx_msleep(1000);

#if U500_DEBUG
		MX_DEBUG(-2,("%s: Invoking WAPIAerFaultAck()", fname));
#endif

		wapi_status = WAPIAerFaultAck();

		if ( wapi_status != 0 ) {
			return mxi_u500_error( wapi_status, fname,
			"Attempt to acknowledge a fault for motor '%s' failed.",
				motor->record->name );
		}
		break;
	case MXLV_MTR_PROPORTIONAL_GAIN:
		long_value = mx_round( motor->proportional_gain );

		sprintf( command, "GA %c KPOS%ld", axis_name, long_value );

		mx_status = mxi_u500_command( u500, board_number, command );
		break;
	case MXLV_MTR_INTEGRAL_GAIN:
		long_value = mx_round( motor->integral_gain );

		sprintf( command, "GA %c KI%ld", axis_name, long_value );

		mx_status = mxi_u500_command( u500, board_number, command );
		break;
	case MXLV_MTR_DERIVATIVE_GAIN:
		long_value = mx_round( motor->derivative_gain );

		sprintf( command, "GA %c KP%ld", axis_name, long_value );

		mx_status = mxi_u500_command( u500, board_number, command );
		break;
	case MXLV_MTR_VELOCITY_FEEDFORWARD_GAIN:
		long_value = mx_round( motor->velocity_feedforward_gain );

		sprintf( command, "GA %c VFF%ld", axis_name, long_value );

		mx_status = mxi_u500_command( u500, board_number, command );
		break;
	case MXLV_MTR_ACCELERATION_FEEDFORWARD_GAIN:
		long_value = mx_round( motor->acceleration_feedforward_gain );

		sprintf( command, "GA %c AFF%ld", axis_name, long_value );

		mx_status = mxi_u500_command( u500, board_number, command );
		break;
	default:
		mx_status = mx_motor_default_set_parameter_handler( motor );
		break;
	}

	return mx_status;
}
Пример #12
0
static mx_status_type
mxd_bluice_area_detector_collect_thread( MX_THREAD *thread, void *args )
{
	static const char fname[] = "mxd_bluice_area_detector_collect_thread()";

	MX_AREA_DETECTOR *ad;
	MX_BLUICE_AREA_DETECTOR *bluice_area_detector;
	MX_BLUICE_SERVER *bluice_server;
	MX_BLUICE_FOREIGN_DEVICE *collect_operation;
	MX_BLUICE_FOREIGN_DEVICE *transfer_operation;
	MX_BLUICE_FOREIGN_DEVICE *oscillation_ready_operation;
	int num_items;
	int current_collect_state, commanded_collect_state;
	int current_transfer_state, current_oscillation_ready_state;
	char command[200];
	char start_oscillation_format[40];
	char prepare_for_oscillation_format[40];
	char request_name[40];
	char motor_name[MXU_BLUICE_NAME_LENGTH+1];
	double oscillation_time, new_motor_position;
	unsigned long client_number;
	int32_t operation_counter;
	mx_status_type mx_status;

	if ( args == NULL ) {
		return mx_error( MXE_NULL_ARGUMENT, fname,
			"The MX_AREA_DETECTOR pointer passed was NULL." );
	}

	ad = (MX_AREA_DETECTOR *) args;

	mx_status = mxd_bluice_area_detector_get_pointers( ad,
		&bluice_area_detector, &bluice_server, NULL, fname );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

#if MXD_BLUICE_AREA_DETECTOR_DEBUG
	MX_DEBUG(-2,("%s invoked for Blu-Ice detector '%s'",
		fname, ad->record->name ));
#endif
	collect_operation = bluice_area_detector->collect_operation;

	if ( collect_operation == (MX_BLUICE_FOREIGN_DEVICE *) NULL ) {
		return mx_error( MXE_INITIALIZATION_ERROR, fname,
	    "No collect operation has been configured for area detector '%s'.",
	    		ad->record->name );
	}

	transfer_operation = bluice_area_detector->transfer_operation;

	if ( transfer_operation == (MX_BLUICE_FOREIGN_DEVICE *) NULL ) {
		return mx_error( MXE_INITIALIZATION_ERROR, fname,
	    "No transfer operation has been configured for area detector '%s'.",
	    		ad->record->name );
	}

	oscillation_ready_operation =
		bluice_area_detector->oscillation_ready_operation;

	if ( oscillation_ready_operation == (MX_BLUICE_FOREIGN_DEVICE *) NULL )
	{
		return mx_error( MXE_INITIALIZATION_ERROR, fname,
"No oscillation_ready operation has been configured for area detector '%s'.",
	    		ad->record->name );
	}

	snprintf( start_oscillation_format,
		sizeof(start_oscillation_format),
			"%%%ds %%%ds %%lg",
			(int) sizeof(request_name)+1,
			(int) sizeof(motor_name)+1 );

	snprintf( prepare_for_oscillation_format,
		sizeof(prepare_for_oscillation_format),
			"%%%ds %%lg",
			(int) sizeof(request_name)+1 );

	/*-------------------------------------------*/

	/* Send the collect command which was formatted in the main thread
	 * in the function mxd_bluice_area_detector_trigger().
	 */

	commanded_collect_state = MXSF_BLUICE_OPERATION_STARTED;

	mx_bluice_set_operation_state( collect_operation,
						commanded_collect_state );

	mx_status = mx_bluice_send_message( bluice_server->record,
				bluice_area_detector->collect_command, NULL, 0);

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* The Collect operation may perform multiple exposures,
	 * so we loop over the exposures here.
	 */

	while (1) {
		/*-------------------------------------------*/

		/* Wait until the Collect operation changes its state. */

		current_collect_state = mx_bluice_get_operation_state(
							collect_operation );

		while ( current_collect_state == commanded_collect_state ) {
			mx_msleep(1);

			current_collect_state = mx_bluice_get_operation_state(
							collect_operation );
		}

		if ( current_collect_state != MXSF_BLUICE_OPERATION_UPDATED ) {
			return mx_error( MXE_UNKNOWN_ERROR, fname,
			"Unexpected operation state %d seen for the collect "
			"operation of Blu-Ice area detector '%s'.",
				current_collect_state, ad->record->name );
		}

		/*-------------------------------------------*/

		/* We should have received a start_oscillation request here.
		 * Try to parse it.
		 */

		num_items = sscanf(
			collect_operation->u.operation.arguments_buffer,
			start_oscillation_format,
			request_name, motor_name, &oscillation_time );

		if ( num_items != 3 ) {
			return mx_error( MXE_UNPARSEABLE_STRING, fname,
			"The operation update string '%s' for operation '%s' "
			"of area detector '%s' could not be parsed into a "
			"request name, motor name, and oscillation time.",
				collect_operation->u.operation.arguments_buffer,
				collect_operation->name,
				ad->record->name );
		}

#if MXD_BLUICE_AREA_DETECTOR_DEBUG
		MX_DEBUG(-2,
	("%s: request_name = '%s', motor_name = '%s', oscillation_time = %f",
			fname, request_name, motor_name, oscillation_time));
#endif

		if ( strcmp( request_name, "start_oscillation" ) != 0 ) {
			return mx_error( MXE_NETWORK_IO_ERROR, fname,
			"Unexpected '%s' request seen in update '%s' for "
			"operation '%s' of area detector '%s'.  "
			"We expected to see 'start_oscillation' here.",
				request_name,
				collect_operation->u.operation.arguments_buffer,
				collect_operation->name,
				ad->record->name );
		}

		/*-------------------------------------------*/

		/* Acknowledge the update. */

		commanded_collect_state =
			MXSF_BLUICE_OPERATION_UPDATE_ACKNOWLEDGED;

		mx_bluice_set_operation_state( collect_operation,
						commanded_collect_state );

		/*-------------------------------------------*/

		/* FIXME: Here we either invoke an 'expose' operation or the
		 * 'stoh_start_oscillation' command.
		 */

		mx_warning( "FIXME FIXME FIXME!\n"
	"****** This is where we would do the 'expose' operation. ******\n"
	"FIXME FIXME FIXME!" );

		/* FIXME: Now we claim that the oscillation is over. */

		/*-------------------------------------------*/

		/* Send 'detector_transfer_image' to the area detector to tell
		 * it to read out the image.
		 */

		client_number = mx_bluice_get_client_number( bluice_server );

		operation_counter = mx_bluice_update_operation_counter(
							bluice_server );

		snprintf( command, sizeof(command),
			"stoh_start_operation detector_transfer_image %lu.%lu",
			client_number, (unsigned long) operation_counter );

		mx_bluice_set_operation_state( transfer_operation,
						MXSF_BLUICE_OPERATION_STARTED );

		mx_status = mx_bluice_send_message( bluice_server->record,
						command, NULL, 0);

		if ( mx_status.code != MXE_SUCCESS )
			return mx_status;

		/*-------------------------------------------*/

		/* Wait until the Transfer operation changes its state. */

		current_transfer_state =
			mx_bluice_get_operation_state( transfer_operation );

		while (current_transfer_state == MXSF_BLUICE_OPERATION_STARTED)
		{
			mx_msleep(1);

			current_transfer_state = mx_bluice_get_operation_state(
							transfer_operation );
		}

		if ( current_transfer_state != MXSF_BLUICE_OPERATION_COMPLETED )		{
			return mx_error( MXE_UNKNOWN_ERROR, fname,
			"Unexpected operation state %d seen for the transfer "
			"operation of Blu-Ice area detector '%s'.",
				current_transfer_state, ad->record->name );
		}

		/*-------------------------------------------*/

		/* Wait until the Command operation changes its state. */

		current_collect_state =
			mx_bluice_get_operation_state( collect_operation );

		while ( current_collect_state == commanded_collect_state )
		{
			mx_msleep(1);

			current_collect_state = mx_bluice_get_operation_state(
							collect_operation );
		}

		switch( current_collect_state ) {
		case MXSF_BLUICE_OPERATION_UPDATED:
			/* We will be acquiring another frame. */
			break;
		case MXSF_BLUICE_OPERATION_COMPLETED:
			
#if MXD_BLUICE_AREA_DETECTOR_DEBUG
			MX_DEBUG(-2,
			("%s: COLLECT HAS SUCCEEDED! for detector '%s'.  "
			"This thread will exit now.",
				fname, ad->record->name ));
#endif

			/* We have acquired the LAST frame, so the collect
			 * operation is over.  We can now exit this thread.
			 */

			return MX_SUCCESSFUL_RESULT;

			break;
		default:
			return mx_error( MXE_UNKNOWN_ERROR, fname,
			"Unexpected operation state %d seen for the collect "
			"operation of Blu-Ice area detector '%s'.",
				current_collect_state, ad->record->name );
		}

		/*-------------------------------------------*/

		/* We should have received a prepare_for_oscillation request
		 * here.  Try to parse it.
		 */

		num_items = sscanf(
			collect_operation->u.operation.arguments_buffer,
			prepare_for_oscillation_format,
			request_name, &new_motor_position );

		if ( num_items != 2 ) {
			return mx_error( MXE_UNPARSEABLE_STRING, fname,
			"The operation update string '%s' for operation '%s' "
			"of area detector '%s' could not be parsed into a "
			"request name and a new motor position.",
				collect_operation->u.operation.arguments_buffer,
				collect_operation->name,
				ad->record->name );
		}

#if MXD_BLUICE_AREA_DETECTOR_DEBUG
		MX_DEBUG(-2,("%s: request_name = '%s', new_motor_position = %f",
			fname, request_name, new_motor_position));
#endif

		if ( strcmp( request_name, "prepare_for_oscillation" ) != 0 ) {
			return mx_error( MXE_NETWORK_IO_ERROR, fname,
			"Unexpected '%s' request seen in update '%s' for "
			"operation '%s' of area detector '%s'.  "
			"We expected to see 'prepare_for_oscillation' here.",
				request_name,
				collect_operation->u.operation.arguments_buffer,
				collect_operation->name,
				ad->record->name );
		}

		/*-------------------------------------------*/

		/* Acknowledge the update. */

		commanded_collect_state =
			MXSF_BLUICE_OPERATION_UPDATE_ACKNOWLEDGED;

		mx_bluice_set_operation_state( collect_operation,
						commanded_collect_state );

		/*-------------------------------------------*/

		/* FIXME: Here we would move the motor to a new position. */

		mx_warning( "FIXME FIXME FIXME!\n"
	"****** This is where we would do the 'move' operation. ******\n"
	"FIXME FIXME FIXME!" );

		/* FIXME: Now we claim that the move is over. */

		/*-------------------------------------------*/

		/* Send 'detector_oscillation_ready' to the area detector
		 * to tell it that the motor has reached its new position.
		 */

		client_number = mx_bluice_get_client_number( bluice_server );

		operation_counter = mx_bluice_update_operation_counter(
							bluice_server );

		snprintf( command, sizeof(command),
		"stoh_start_operation detector_oscillation_ready %lu.%lu",
			client_number, (unsigned long) operation_counter );

		mx_bluice_set_operation_state( oscillation_ready_operation,
						MXSF_BLUICE_OPERATION_STARTED );

		mx_status = mx_bluice_send_message( bluice_server->record,
						command, NULL, 0);

		if ( mx_status.code != MXE_SUCCESS )
			return mx_status;

		/*-------------------------------------------*/

		/* Wait until the Oscillation_ready operation changes
		 * its state.
		 */

		current_oscillation_ready_state =
		    mx_bluice_get_operation_state(oscillation_ready_operation);

		while ( current_oscillation_ready_state
				== MXSF_BLUICE_OPERATION_STARTED )
		{
			mx_msleep(1);

			current_oscillation_ready_state =
				mx_bluice_get_operation_state(
					oscillation_ready_operation );
		}

		if ( current_oscillation_ready_state
				!= MXSF_BLUICE_OPERATION_COMPLETED )
		{
			return mx_error( MXE_UNKNOWN_ERROR, fname,
			"Unexpected operation state %d seen for the "
			"oscillation_ready operation of Blu-Ice "
			"area detector '%s'.",
				current_oscillation_ready_state,
				ad->record->name );
		}

		/*-------------------------------------------*/

		/* Go back to the top of the loop for another pass. */

#if MXD_BLUICE_AREA_DETECTOR_DEBUG
		MX_DEBUG(-2,
		("%s: Going back to the top of the loop for another frame.",
			fname));
#endif
	}

}
Пример #13
0
MX_EXPORT mx_status_type
mxi_compumotor_command( MX_COMPUMOTOR_INTERFACE *compumotor_interface,
		char *command, char *response, size_t response_buffer_length,
		int command_flags )
{
	static const char fname[] = "mxi_compumotor_command()";

	MX_RS232 *rs232;
	unsigned long interface_flags;
	unsigned long sleep_ms, num_bytes_available;
	long num_command_attempts;
	long i, max_response_attempts;
	size_t command_length, response_length;
	char c;
	char echoed_command_string[200];
	mx_bool_type debug_flag, debug_getchar_flag;
	mx_status_type mx_status;
#if MXI_COMPUMOTOR_INTERFACE_DEBUG_TIMING	
	MX_HRT_RS232_TIMING command_timing, response_timing;
#endif

	debug_flag = FALSE;

	MX_DEBUG(2,("%s invoked.", fname));

	if ( compumotor_interface == NULL ) {
		return mx_error( MXE_NULL_ARGUMENT, fname,
		"MX_COMPUMOTOR_INTERFACE pointer passed was NULL." );
	}
	if ( command == NULL ) {
		return mx_error( MXE_NULL_ARGUMENT, fname,
		"'command' buffer pointer passed was NULL.  No command sent.");
	}
	if ( compumotor_interface->rs232_record == (MX_RECORD *) NULL ) {
		return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname,
		"The rs232_record pointer for record '%s' is NULL.",
			compumotor_interface->record->name );
	}

	rs232 = (MX_RS232 *)
			compumotor_interface->rs232_record->record_class_struct;

	if ( rs232 == (MX_RS232 *) NULL ) {
		return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname,
		"The MX_RS232 pointer for record '%s' used by '%s' is NULL.",
			compumotor_interface->rs232_record->name,
			compumotor_interface->record->name );
	}

	interface_flags = compumotor_interface->interface_flags;

	if ( interface_flags & MXF_COMPUMOTOR_ECHO_ON ) {

		command_length = strlen( command );

		if ( command_length > ( sizeof(echoed_command_string) - 1 ) ) {
			return mx_error( MXE_WOULD_EXCEED_LIMIT, fname,
	"Compumotor interface record '%s' has ECHO set to 1.  When ECHO is "
	"set to 1, commands are limited to a maximum of %ld characters, but "
	"the command string passed is %ld characters long.  command = '%s'",
			compumotor_interface->record->name,
			(long) sizeof( echoed_command_string ) - 1L,
			(long) command_length, command );
		}
	}

	if ( command_flags & MXI_COMPUMOTOR_INTERFACE_DEBUG ) {
		debug_flag = TRUE;
	} else
	if ( interface_flags & MXF_COMPUMOTOR_DEBUG_SERIAL ) {
	} else {
		debug_flag = FALSE;
	}

	if ( command_flags & MXF_COMPUMOTOR_NO_RECURSION ) {
		num_command_attempts = 1;
	} else
	if ( interface_flags & MXF_COMPUMOTOR_AUTOMATIC_RESYNCHRONIZE ) {
		num_command_attempts = 2;
	} else {
		num_command_attempts = 1;
	}

	if ( interface_flags & MXF_COMPUMOTOR_DEBUG_SERIAL_GETCHAR ) {
		if ( interface_flags & MXF_COMPUMOTOR_DEBUG_SERIAL ) {
			debug_getchar_flag = TRUE;
		} else
		if ( rs232->rs232_flags & MXF_232_DEBUG_SERIAL ) {
			debug_getchar_flag = TRUE;
		} else
		if ( rs232->rs232_flags & MXF_232_DEBUG_SERIAL_HEX ) {
			debug_getchar_flag = TRUE;
		} else {
			debug_getchar_flag = FALSE;
		}
	} else {
		debug_getchar_flag = FALSE;
	}

	/* Send the command string. */

	if ( debug_flag ) {
		MX_DEBUG(-2,("%s: sending '%s' to '%s'",
			fname, command, compumotor_interface->record->name));
	}

	while ( num_command_attempts > 0 ) {

	    num_command_attempts--;

#if MXI_COMPUMOTOR_INTERFACE_DEBUG_TIMING	
	    MX_HRT_RS232_START_COMMAND( command_timing, 2 + strlen(command) );
#endif

	    mx_status = mx_rs232_putline( compumotor_interface->rs232_record,
					command, NULL, 0 );

#if MXI_COMPUMOTOR_INTERFACE_DEBUG_TIMING
	    MX_HRT_RS232_END_COMMAND( command_timing );
#endif

	    if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

#if MXI_COMPUMOTOR_INTERFACE_DEBUG_TIMING
	MX_HRT_RS232_COMMAND_RESULTS( command_timing, command, fname );
#endif

	    if ( interface_flags & MXF_COMPUMOTOR_ECHO_ON ) {

		/* If the Compumotor is configured to echo commands,
		 * read the echoed command string.
		 */

#if MXI_COMPUMOTOR_INTERFACE_DEBUG_TIMING
		MX_HRT_RS232_START_RESPONSE( response_timing,
					compumotor_interface->rs232_record );
#endif

		mx_status = mx_rs232_getline(compumotor_interface->rs232_record,
					echoed_command_string,
					sizeof( echoed_command_string ) - 1L,
					NULL, 0 );

#if MXI_COMPUMOTOR_INTERFACE_DEBUG_TIMING
		MX_HRT_RS232_END_RESPONSE( response_timing,
					strlen(echoed_command_string) );

		MX_HRT_RS232_RESPONSE_RESULTS( response_timing,
					echoed_command_string, fname );
#endif

		if ( mx_status.code != MXE_SUCCESS )
			return mx_status;
	    }

	    /* Get the response, if one is expected. */

	    i = 0;

	    max_response_attempts = 1000;
	    sleep_ms = 1;

	    if ( response == NULL ) {

		/* If we are not checking for a response, then we have no
		 * way to tell whether or not the command succeeded.  That
		 * means that we have no justification for retrying a
		 * command, so we suppress command retries.
		 */

		num_command_attempts = 0;

	    } else {
		/* If we get here, a response is expected. */

#if MXI_COMPUMOTOR_INTERFACE_DEBUG_TIMING
#if 0
		MX_HRT_RS232_START_RESPONSE( response_timing,
					compumotor_interface->rs232_record );
#else
		MX_HRT_RS232_START_RESPONSE( response_timing, NULL );
#endif
#endif

		/* Any text sent by the Compumotor controller should
		 * be prefixed by an asterisk character, so to begin
		 * with, we try to read and discard characters until
		 * we see an asterisk.
		 */

		c = '\0';

		for ( i = 0; i < max_response_attempts; i++ ) {

			mx_status = mx_rs232_num_input_bytes_available(
					compumotor_interface->rs232_record,
					&num_bytes_available );

			if ( mx_status.code != MXE_SUCCESS )
				return mx_status;

			if ( num_bytes_available == 0 ) {
				/* Sleep and then go back to the top
				 * of the for() loop.
				 */

				mx_msleep(sleep_ms);
				continue;
			}

			mx_status = mx_rs232_getchar(
					compumotor_interface->rs232_record,
					&c, MXF_232_WAIT );

			if ( debug_getchar_flag ) {
				MX_DEBUG(-2,
				("%s: mx_rs232_getchar() = '%c' %#x",
					fname, c, c));
			}

			if ( mx_status.code != MXE_SUCCESS ) {
				response[0] = '\0';

				if ( debug_flag ) {
					MX_DEBUG(-2,
		("%s failed while waiting for an asterisk character from '%s'.",
				fname, compumotor_interface->record->name));
				}
				return mx_status;
			}

			/* Did we see the asterisk character? */

			if ( c != '*' ) {
				/* If not, sleep and then go back to
				 * the top of the for() loop.
				 */

				mx_msleep(sleep_ms);
				continue;	
			}

			/* Read in the Compumotor response. */

			mx_status = mx_rs232_getline(
					compumotor_interface->rs232_record,
					response, response_buffer_length,
					NULL, 0 );

			if ( mx_status.code == MXE_SUCCESS ) {
				break;		/* Exit the for() loop. */

			} else if ( mx_status.code != MXE_NOT_READY ) {
				MX_DEBUG(-2,
		("*** Exiting with status = %ld for Compumotor interface '%s'.",
			mx_status.code, compumotor_interface->record->name));

				return mx_status;
			}
			mx_msleep(sleep_ms);

		}   /* End of response attempt loop (i) */

		if ( i >= max_response_attempts ) {

		    if ( num_command_attempts > 0 ) {
			mx_warning( "Resynchronizing '%s'.",
					compumotor_interface->record->name );

			mx_status = mxi_compumotor_resynchronize(
					compumotor_interface->record );

			if ( mx_status.code != MXE_SUCCESS )
				return mx_status;

			mx_warning( "Resynchronization of '%s' complete.",
					compumotor_interface->record->name );
		    } else {
			mx_status = mx_rs232_discard_unread_input(
					compumotor_interface->rs232_record,
					debug_flag );

			if ( mx_status.code != MXE_SUCCESS ) {
				mx_error( MXE_INTERFACE_IO_ERROR, fname,
"Failed at attempt to discard unread characters in buffer for record '%s'",
					compumotor_interface->record->name );
			}

			return mx_error( MXE_TIMED_OUT, fname,
				"No response seen to '%s' command after "
				"%ld attempts to read from Compumotor "
				"interface '%s'.",
					command, max_response_attempts,
					compumotor_interface->record->name );
		    }
		} else {

		    /* Successfully got a response. */

		    num_command_attempts = 0;    /* No more attempts needed. */

		    /* Sometimes, the response string after the asterisk '*'
		     * character starts with a newline character.  If this
		     * has happened, strip off the leading newline.
		     */

		    if ( response[0] == MX_LF ) {
			response_length = strlen(response);

			memmove( response, response+1, response_length );
		    }

#if MXI_COMPUMOTOR_INTERFACE_DEBUG_TIMING
		    MX_HRT_RS232_END_RESPONSE( response_timing,
						strlen(response) );

		    MX_HRT_TIME_BETWEEN_MEASUREMENTS( command_timing,
						response_timing, fname );

		    MX_HRT_RS232_RESPONSE_RESULTS( response_timing,
						response, fname);
#endif

		    if ( debug_flag ) {
			MX_DEBUG(-2,("%s: received '%s' from '%s'",
				fname, response,
				compumotor_interface->record->name));
		    }
#if 0
		    {
			long j;

			response_length = strlen(response);

			for ( j = 0; j < response_length; j++ ) {
				MX_DEBUG(-2,("%s: response[%ld] = %#x '%c'",
				fname, j, response[j], response[j]));
			}
		    }
#endif
		}

	    } /* End of ( response != NULL ) block */

	} /* End of while() command attempt loop. */

	MX_DEBUG(2,("%s complete.", fname));

	return MX_SUCCESSFUL_RESULT;
}
Пример #14
0
MX_EXPORT mx_status_type
mxi_compumotor_resynchronize( MX_RECORD *record )
{
	static const char fname[] = "mxi_compumotor_resynchronize()";

	MX_COMPUMOTOR_INTERFACE *compumotor_interface = NULL;
	char command[80], response[80];
	char version_string[80], type_string[80];
	long i, j;
	int num_items, command_flags;
	mx_status_type mx_status;

	mx_status = mxi_compumotor_get_pointers( record,
				&compumotor_interface, fname );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Throw away any pending input and output on the 
	 * Compumotor RS-232 port.
	 */

	mx_status = mx_rs232_discard_unwritten_output(
					compumotor_interface->rs232_record,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

	switch( mx_status.code ) {
	case MXE_SUCCESS:
	case MXE_UNSUPPORTED:
		break;		/* Continue on. */
	default:
		return mx_status;
	}

	mx_status = mx_rs232_discard_unread_input(
					compumotor_interface->rs232_record,
					MXI_COMPUMOTOR_INTERFACE_DEBUG);

	/* Verify that each of the controllers are there by asking them
	 * for their revision number.
	 */

	command_flags = MXI_COMPUMOTOR_INTERFACE_DEBUG
			| MXF_COMPUMOTOR_NO_RECURSION;

	for ( i = 0; i < compumotor_interface->num_controllers; i++ ) {

		snprintf( command, sizeof(command), "%ld_!TREV",
				compumotor_interface->controller_number[i] );
	
		mx_status = mxi_compumotor_command( compumotor_interface,
				command, response, sizeof response,
				command_flags );

		switch( mx_status.code ) {
		case MXE_SUCCESS:
			break;
		case MXE_NOT_READY:
		case MXE_INTERFACE_IO_ERROR:
			return mx_error( MXE_INTERFACE_IO_ERROR, fname,
"Cannot communicate with Compumotor controller %ld on RS-232 port '%s'.  "
"Is it turned on?", i+1, compumotor_interface->rs232_record->name );
			break;
		default:
			return mx_status;
			break;
		}

		/* Attempt to determine the model of each type of
		 * controller.  The effectiveness of this logic is
		 * limited by the fact that I only have access to
		 * 6K and Zeta 6104 controllers.  (W. Lavender)
		 */

		compumotor_interface->controller_type[i]
						= MXT_COMPUMOTOR_UNKNOWN;

		num_items = sscanf( response, "%s %s",
					version_string, type_string );

		if ( num_items == 1 ) {
			compumotor_interface->controller_type[i]
						= MXT_COMPUMOTOR_6000_SERIES;

		} else if ( num_items == 2 ) {
			if ( strcmp( type_string, "6K" ) == 0 ) {

				compumotor_interface->controller_type[i]
						= MXT_COMPUMOTOR_6K;
			} else
			if ( strcmp( type_string, "ZETA6000" ) == 0 ) {

				compumotor_interface->controller_type[i]
						= MXT_COMPUMOTOR_ZETA_6000;
			} else
			if ( strcmp( type_string, "6104" ) == 0 ) {

				compumotor_interface->controller_type[i]
						= MXT_COMPUMOTOR_ZETA_6000;
			} else {
				compumotor_interface->controller_type[i]
						= MXT_COMPUMOTOR_6000_SERIES;
			}
		}

		if ( compumotor_interface->controller_type[i]
				== MXT_COMPUMOTOR_UNKNOWN )
		{
			(void) mx_error( MXE_UNPARSEABLE_STRING, fname,
	"Compumotor interface '%s' had an unrecognized response to "
	"the TREV command.  TREV response = '%s'",
			record->name, response );
		}
	}

	/* Try to enable all of the axes for each controller. */

	for ( i = 0; i < compumotor_interface->num_controllers; i++ ) {

		snprintf( command, sizeof(command), "%ld_!DRIVE",
				compumotor_interface->controller_number[i] );

		for ( j = 0; j < compumotor_interface->num_axes[i]; j++ ) {

			strlcat( command, "1", sizeof(command) );
		}

		(void) mxi_compumotor_command( compumotor_interface,
					command, NULL, 0,
					command_flags );
	}

	/* Discard any unread output from the controller. */

	mx_msleep(100);

	mx_status = mx_rs232_discard_unread_input(
					compumotor_interface->rs232_record,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

	return mx_status;
}
Пример #15
0
MX_EXPORT mx_status_type
mx_bluice_check_for_master( MX_BLUICE_SERVER *bluice_server )
{
	static const char fname[] = "mx_bluice_check_for_master()";

	MX_BLUICE_DCSS_SERVER *bluice_dcss_server;
	mx_bool_type master_flag;
	unsigned long i, wait_ms, max_attempts, auto_take_master;
	mx_status_type mx_status;

	mx_status = mx_bluice_is_master( bluice_server, &master_flag );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	if ( master_flag ) {
		return MX_SUCCESSFUL_RESULT;
	} else {
		/* We can only get here for DCSS servers. */

		bluice_dcss_server = (MX_BLUICE_DCSS_SERVER *)
				bluice_server->record->record_type_struct;

		auto_take_master = bluice_dcss_server->bluice_dcss_flags
					& MXF_BLUICE_DCSS_AUTO_TAKE_MASTER;

		if ( auto_take_master ) {
			mx_status = mx_bluice_take_master(bluice_server, TRUE);

			if ( mx_status.code != MXE_SUCCESS )
				return mx_status;

			/* Wait to become master. */

			wait_ms = 100;
			max_attempts = 50;

			for ( i = 0; i < max_attempts; i++ ) {
				mx_status = mx_bluice_is_master( bluice_server,
								&master_flag );

				if ( mx_status.code != MXE_SUCCESS )
					return mx_status;

				if ( master_flag ) {
					return MX_SUCCESSFUL_RESULT;
				}

				mx_msleep( wait_ms );
			}

			return mx_error( MXE_TIMED_OUT, fname,
			"Timed out after waiting %g seconds to become master "
			"for Blu-Ice server '%s'.",
				0.001 * (double)( wait_ms * max_attempts ),
				bluice_server->record->name );
		} else {
			return mx_error( MXE_NOT_VALID_FOR_CURRENT_STATE, fname,
			"Your client is not currently master for "
			"Blu-Ice server '%s'.",
				bluice_server->record->name );
		}
	}
}
Пример #16
0
int
main( int argc, char *argv[] )
{
	MX_RECORD *record_list;

	MX_RECORD *energy_motor_record;
	MX_RECORD *i_zero_record;
	MX_RECORD *i_trans_record;
	MX_RECORD *timer_record;

	double start, step_size, measurement_time, energy;
	int i, num_steps, error, busy;
	long i_zero_value, i_trans_value;

	mx_status_type status;

	/* Read in the MX database used by this example. */

	status = mx_setup_database( &record_list, DATABASE_FILENAME );

	if ( status.code != MXE_SUCCESS ) {
		fprintf( stderr, "Cannot setup the MX database '%s'.\n",
				DATABASE_FILENAME );
		exit(1);
	}

	/* Find the devices to be used by the scan. */

	energy_motor_record = mx_get_record( record_list, "energy" );

	if ( energy_motor_record == (MX_RECORD *) NULL ) {
		fprintf( stderr, "Cannot find the motor 'energy'.\n" );
		exit(1);
	}

	i_zero_record = mx_get_record( record_list, "Io" );

	if ( i_zero_record == (MX_RECORD *) NULL ) {
		fprintf( stderr, "Cannot find the scaler 'Io'.\n" );

		exit(1);
	}

	i_trans_record = mx_get_record( record_list, "It" );

	if ( i_trans_record == (MX_RECORD *) NULL ) {
		fprintf( stderr, "Cannot find the scaler 'It'.\n" );

		exit(1);
	}

	timer_record = mx_get_record( record_list, "timer1" );

	if ( timer_record == (MX_RECORD *) NULL ) {
		fprintf( stderr, "Cannot find the timer 'timer1'.\n" );
		exit(1);
	}

	/* Setup the scan parameters for a copper K edge scan. */

	start = 8950;			/* in eV */
	step_size = 1.0;		/* in eV */
	num_steps = 101;
	measurement_time = 1.0;		/* in seconds */

	/* Perform the scan. */

	error = FALSE;

	printf( "Moving to start position.\n" );

	for ( i = 0; i < num_steps; i++ ) {

		/* Clear the scalers. */

		status = mx_scaler_clear( i_zero_record );

		if ( status.code != MXE_SUCCESS ) {
			error = TRUE;
			break;
		}

		status = mx_scaler_clear( i_trans_record );

		if ( status.code != MXE_SUCCESS ) {
			error = TRUE;
			break;
		}

		/* Compute the energy for the next step. */

		energy = start + step_size * (double) i;

		/* Move to the new energy. */

		status = mx_motor_move_absolute( energy_motor_record,
							energy, 0 );

		if ( status.code != MXE_SUCCESS ) {
			error = TRUE;
			break;
		}

		/* Wait for the motor to stop moving. */

		busy = TRUE;

		while ( busy ) {
			mx_msleep(10);       /* Wait for 10 milliseconds */

			status = mx_motor_is_busy( energy_motor_record, &busy );

			if ( status.code != MXE_SUCCESS ) {
				error = TRUE;
				break;
			}
		}

		/* Start the measurement timer. */

		status = mx_timer_start( timer_record, measurement_time );

		if ( status.code != MXE_SUCCESS ) {
			error = TRUE;
			break;
		}

		/* Wait until the timer stops counting. */

		busy = TRUE;

		while ( busy ) {
			mx_msleep(10);       /* Wait for 10 milliseconds */

			status = mx_timer_is_busy( timer_record, &busy );

			if ( status.code != MXE_SUCCESS ) {
				error = TRUE;
				break;
			}
		}

		/* Read out the scalers. */

		status = mx_scaler_read( i_zero_record, &i_zero_value );

		if ( status.code != MXE_SUCCESS ) {
			error = TRUE;
			break;
		}

		status = mx_scaler_read( i_trans_record, &i_trans_value );

		if ( status.code != MXE_SUCCESS ) {
			error = TRUE;
			break;
		}

		/* Print out the values. */

		printf( "%10.3f  %10lu  %10lu\n",
			energy, i_zero_value, i_trans_value );
	}

	if ( error ) {
		fprintf(stderr, "The scan aborted abnormally.\n" );
		exit(1);
	}

	exit(0);
}
Пример #17
0
static mx_status_type
mxp_wedge_scan_take_frame( MX_SCAN *scan,
			MX_AREA_DETECTOR_SCAN *ad_scan,
			MX_WEDGE_SCAN *wedge_scan )
{
#if MXS_WEDGE_SCAN_DEBUG
	static const char fname[] = "mxp_wedge_scan_take_frame()";
#endif

	MX_RECORD *ad_record;
	MX_AREA_DETECTOR *ad;
	MX_RECORD *motor_record;
	MX_MOTOR *motor;
	MX_RECORD *shutter_record;
	double delta, oscillation_time;
	unsigned long ad_status;
	mx_status_type mx_status;

#if MXS_WEDGE_SCAN_DEBUG
	MX_DEBUG(-2,("%s invoked for scan '%s'", fname, scan->record->name));
#endif

	ad_record = scan->input_device_array[0];

	ad = ad_record->record_class_struct;

	MXW_UNUSED( ad );

	shutter_record = scan->input_device_array[1];

	delta = ad_scan->step_size[0];

	mx_status = mx_get_last_measurement_time( &(scan->measurement),
							&oscillation_time );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	motor_record = scan->motor_record_array[0];

	motor = motor_record->record_class_struct;

	MXW_UNUSED( motor );

#if MXS_WEDGE_SCAN_DEBUG
	MX_DEBUG(-2,("%s: Starting oscillation of '%s' for %f seconds "
	"using shutter '%s' with an oscillation distance of '%s' for %f %s",
		fname, ad_record->name, exposure_time,
		shutter_record->name, motor_record->name,
		delta, motor->units ));
#endif

	/* FIXME - Move this call to mx_area_detector_setup_oscillation()
	 * to somewhere else, so that we are not doing it for each frame.
	 */

	mx_status = mx_area_detector_setup_oscillation( ad_record,
						motor_record,
						shutter_record,
						NULL,
						delta,
						oscillation_time );
	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Trigger the oscillation. */

	mx_status = mx_area_detector_trigger_oscillation( ad_record );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Wait for the oscillation to finish. */

	while(1) {
		mx_status = mx_area_detector_get_status( ad_record,
							&ad_status );

		if ( mx_status.code != MXE_SUCCESS )
			return mx_status;

		if ( ( ad_status & MXSF_AD_IS_BUSY ) == 0 ) {
			break;		/* Exit the for() loop. */
		}

		mx_msleep(1);
	}

	mx_status = mx_add_measurement_to_datafile( &(scan->datafile) );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

#if MXS_WEDGE_SCAN_DEBUG
	MX_DEBUG(-2,("%s: frame complete.", fname));
#endif

	return MX_SUCCESSFUL_RESULT;
}
Пример #18
0
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,
					&amplifier, &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;
}
Пример #19
0
MX_EXPORT mx_status_type
mxi_numato_gpio_open( MX_RECORD *record )
{
	static const char fname[] = "mxi_numato_gpio_open()";

	MX_NUMATO_GPIO *numato_gpio = NULL;
	unsigned long flags;
	mx_bool_type debug_rs232;
	mx_status_type mx_status;

#if MXI_NUMATO_GPIO_DEBUG
	MX_DEBUG(-2,("%s invoked for record '%s'.", fname, record->name ));
#endif

	numato_gpio = (MX_NUMATO_GPIO *) record->record_type_struct;

	if ( numato_gpio == (MX_NUMATO_GPIO *) NULL ) {
		return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname,
		"MX_NUMATO_GPIO pointer for record '%s' is NULL.",
			record->name);
	}

	flags = numato_gpio->numato_gpio_flags;

	if ( flags & MXF_NUMATO_GPIO_DEBUG_RS232 ) {
		debug_rs232 = TRUE;
	} else {
		debug_rs232 = FALSE;
	}

	/* Make sure that the RS232 line terminators are set correctly.  The
	 * write terminator must be set to 0x0d, while the read terminators
	 * must be set to 0x3e0d (or '>\r').
	 */

#if 0
	{
		MX_RS232 *rs232 = (MX_RS232 *)
			numato_gpio->rs232_record->record_class_struct;

		rs232->read_terminators = 0x3e0d;
		rs232->write_terminators = 0x0d;

		mx_status = mx_rs232_convert_terminator_characters(
						numato_gpio->rs232_record );

		if ( mx_status.code != MXE_SUCCESS )
			return mx_status;
	}
#endif
	/* Send a <CR> to make sure that any partial commands or junk data
	 * have been discarded.
	 */

	mx_status = mx_rs232_putline( numato_gpio->rs232_record, "",
							NULL, debug_rs232 );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	mx_msleep(1000);

	/* Discard any leftover bytes in the serial port. */

	mx_status = mx_rs232_discard_unwritten_output(
				numato_gpio->rs232_record, debug_rs232 );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	mx_status = mx_rs232_discard_unread_input( numato_gpio->rs232_record,
								 debug_rs232 );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Read the version number of the Numato firmware. */

	mx_breakpoint();

	mx_status = mxi_numato_gpio_command( numato_gpio, "ver",
					numato_gpio->version,
					sizeof(numato_gpio->version),
					debug_rs232 );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Read the id number of the Numato device. */

	mx_status = mxi_numato_gpio_command( numato_gpio, "id",
					numato_gpio->id,
					sizeof(numato_gpio->id),
					debug_rs232 );

	return mx_status;
}
Пример #20
0
int
main( int argc, char *argv[] )
{
	mutex_pair_t mutex_pair;
	MX_THREAD *parent_thread, *child_thread;
	long status, thread_exit_status;
	int exit_loop;
	mx_status_type mx_status;

	mx_set_debug_level(0);

	fprintf(stderr, "Parent: child_function = %p\n", child_function);

	mx_status = mx_get_current_thread( &parent_thread );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

#if 0
	mx_show_thread_info( parent_thread, "Parent thread:" );
#endif

	fprintf(stderr, "Parent: Creating parent mutex.\n");

	mx_status = mx_mutex_create( &(mutex_pair.parent_mutex) );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

	fprintf(stderr, "Parent: Creating child mutex.\n");

	mx_status = mx_mutex_create( &(mutex_pair.child_mutex) );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

	fprintf(stderr, "Parent: Locking parent mutex.\n");

	status = mx_mutex_lock( mutex_pair.parent_mutex );

	if ( status != MXE_SUCCESS ) {
		fprintf(stderr,
"Parent: Attempt to lock the parent mutex failed with MX status code = %ld.\n",
			status );
		exit( status );
	}

	fprintf(stderr, "Parent: Creating child thread.\n" );

	mx_status = mx_thread_create( &child_thread,
					child_function,
					&mutex_pair );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

	/* Give the child long enough to lock the child mutex. */

	fprintf(stderr, "Parent: Sleeping for 5 seconds.\n");

	mx_msleep(5000);

	/* Unlock the parent mutex so that the child can proceed. */

	fprintf(stderr, "Parent: Unlocking parent mutex.\n");

	status = mx_mutex_unlock( mutex_pair.parent_mutex );

	if ( status != MXE_SUCCESS ) {
		fprintf( stderr,
		"Parent: Attempt to unlock the parent mutex failed "
			"with MX status code = %ld.\n", status );
		exit( status );
	}

	/* Wait for the child to unlock its mutex. */

	fprintf(stderr, "Parent: Waiting to lock the child mutex.\n");

	exit_loop = FALSE;

	while( exit_loop == FALSE ) {
		status = mx_mutex_trylock( mutex_pair.child_mutex );

		switch( status ) {
		case MXE_SUCCESS:
			exit_loop = TRUE;
			break;
		case MXE_NOT_AVAILABLE:
			fprintf(stderr, "Parent: Child mutex not available.\n");
			break;
		default:
			fprintf( stderr,
"Parent: Attempt to lock the child mutex failed with MX status code = %ld.\n",
				status );
			exit( status );
			break;
		}
		mx_msleep(500);
	}

	fprintf(stderr,
		"Parent: Child mutex locked.  It will now be unlocked.\n" );

	status = mx_mutex_unlock( mutex_pair.child_mutex );

	if ( status != MXE_SUCCESS ) {
		fprintf( stderr,
"Parent: Attempt to unlock the child mutex failed with MX status code = %ld.\n",
			status );
		exit( status );
	}

	/* Wait for the child to finish executing. */

	fprintf(stderr, "Parent: Waiting for the child to exit.\n" );

	mx_status = mx_thread_wait( child_thread,
					&thread_exit_status,
					MX_THREAD_INFINITE_WAIT );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

	fprintf(stderr, "Parent: Child thread exit status = %ld.\n",
					thread_exit_status );

	/* Free the data structures used by the child thread. */

	fprintf( stderr, "Parent: Freeing child data structures.\n" );

	mx_status = mx_thread_free_data_structures( child_thread );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );
	
	/* Destroy the parent and child mutexes. */

	fprintf( stderr, "Parent: Destroying parent mutex.\n" );

	mx_status = mx_mutex_destroy( mutex_pair.parent_mutex );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

	fprintf( stderr, "Parent: Destroying child mutex.\n" );

	mx_status = mx_mutex_destroy( mutex_pair.child_mutex );

	if ( mx_status.code != MXE_SUCCESS )
		exit( mx_status.code );

	/* Announce to the user that the test is over. */

	fprintf(stderr, "Parent: Mutex test completed successfully.\n");

	exit(0);
}
Пример #21
0
static mx_status_type
mxd_am9513_motor_move_single_step( MX_AM9513_MOTOR *am9513_motor,
					MX_AM9513 *low_am9513, int m )
{
	uint16_t saved_counter_mode_register, saved_load_register;

	mx_status_type mx_status;

	saved_counter_mode_register = low_am9513->counter_mode_register[m];
	saved_load_register = low_am9513->load_register[m];

	/* Turn off gating and the count repetitively settings. */

	low_am9513->counter_mode_register[m]
				= saved_counter_mode_register & 0x1fcf;

	mx_status = mxi_am9513_set_counter_mode_register( low_am9513, m );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Load a 4 into the counter.  A 0 here will not put out any
	 * steps at all.  A 1 or 2 results in an anomalously long step
	 * pulse (not known why!) and 3 or more gives the desired short
	 * step pulse.  (CUS 050615) */

	low_am9513->load_register[m] = 4;

	mx_status = mxi_am9513_load_counter( low_am9513, m );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Arm the counter.  This should cause the step to occur. */

	mx_status = mxi_am9513_arm_counter( low_am9513, m );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Wait for the step pulse to complete.  Unless the delay is
	 * present, a fast computer could reset the Load and Command
	 * registers before the step pulse is complete, resulting in
	 * flaky behavior.  It is not clear that the 10ms delay is
	 * optimal but it works and is not too long ;). (CUS 050615) */

	mx_msleep( 10 );

	/* Now restore the counter parameters. */

	low_am9513->counter_mode_register[m] = saved_counter_mode_register;

	mx_status = mxi_am9513_set_counter_mode_register( low_am9513, m );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	low_am9513->load_register[m] = saved_load_register;

	mx_status = mxi_am9513_load_counter( low_am9513, m );

	if ( mx_status.code != MXE_SUCCESS )
		return mx_status;

	/* Modify the recorded position of the motor. */

	if ( am9513_motor->last_direction < 0 ) {
		am9513_motor->last_destination--;
	} else {
		am9513_motor->last_destination++;
	}

	return MX_SUCCESSFUL_RESULT;
}
Пример #22
0
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;
}
Пример #23
0
static mx_status_type
mxi_compumotor_run_program( MX_COMPUMOTOR_INTERFACE *compumotor_interface,
				char *program_type,
				char *program_filename )
{
	static const char fname[] = "mxi_compumotor_run_program()";

	int saved_errno;
	FILE *program_file;
	char program_line[200];
	char *ptr;
	long i, length;
	mx_bool_type suppress_comments;
	mx_status_type mx_status;

	if ( compumotor_interface->interface_flags
			& MXF_COMPUMOTOR_SUPPRESS_COMMENTS )
	{
		suppress_comments = TRUE;
	} else {
		suppress_comments = FALSE;
	}

	/* Try to open the startup program file. */

	program_file = mx_cfn_fopen( MX_CFN_CONFIG, program_filename, "r" );

	if ( program_file == ( FILE * ) NULL ) {
		saved_errno = errno;

		return mx_error( MXE_FILE_IO_ERROR, fname,
		"The attempt by record '%s' to open %s program "
		"file '%s' failed.  Errno = %d, error message = '%s'.",
			compumotor_interface->record->name,
			program_type, program_filename,
			saved_errno, strerror(saved_errno) );
	}

	/* Read the startup program one line at a time
	 * and send it to the Compumotor controller.
	 */

	while (1) {
		mx_fgets( program_line, sizeof(program_line),
						program_file );

		if ( feof(program_file) ) {
			fclose( program_file );
			program_file = NULL;
			break;		/* Exit the while() loop. */
		} else
		if ( ferror(program_file) ) {
			saved_errno = errno;
			fclose( program_file );

			return mx_error( MXE_FILE_IO_ERROR, fname,
			"An error occurred while reading from "
			"%s program file '%s' for record '%s'.  "
			"Errno = %d, error message = '%s'.",
				program_type, program_filename,
				compumotor_interface->record->name,
				saved_errno, strerror(saved_errno) );
		}

		if ( suppress_comments ) {
			/* Look for the comment character ';'. */

			ptr = strchr( program_line, ';' );

			if ( ptr != NULL ) {
				*ptr = '\0';
			}

			/* Suppress trailing spaces or tabs. */

			length = strlen( program_line );

			for ( i = length-1; i >= 0; i-- ) {

				if ( program_line[i] == ' ' ) {
					program_line[i] = '\0';
				} else
				if ( program_line[i] == '\t' ) {
					program_line[i] = '\0';
				} else {
					break;	/* Exit the for() loop. */
				}
			}

			if ( strlen( program_line ) == 0 ) {
				/* If we have an empty line, do not send it
				 * to the controller and go back to the top
				 * of the while() loop.
				 */

				continue;
			}
		}

		mx_status = mxi_compumotor_command(
				compumotor_interface,
				program_line,
				NULL, 0,
				MXI_COMPUMOTOR_INTERFACE_DEBUG );

		if ( mx_status.code != MXE_SUCCESS ) {
			fclose( program_file );
			return mx_status;
		}
	}

	/* This should never happen, but we check anyway. */

	if ( program_file != NULL ) {
		fclose( program_file );

		return mx_error( MXE_CORRUPT_DATA_STRUCTURE, fname,
		"The FILE pointer for file '%s' used by record '%s' "
		"was not NULL at a time when the file should "
		"already be closed.",
			program_filename,
			compumotor_interface->record->name );
	}

	/* If the commands we sent generated any output,
	 * we throw the output away now.
	 */

	mx_msleep(100);

	mx_status = mx_rs232_discard_unread_input(
					compumotor_interface->rs232_record,
					MXI_COMPUMOTOR_INTERFACE_DEBUG );

	return mx_status;
}