//! This module contains standard SCPI errors in the form of the Error enum.
//!
//! Each error variant has a corresponding error/event number as the enum discriminant.
//!
use core::fmt::Display;
/// A SCPI error
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct Error(
/// Error code
ErrorCode,
/// Optional additional error information
Option<&'static [u8]>,
);
impl Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let code = self.get_code();
let msg = core::str::from_utf8(self.get_message()).unwrap_or("<invalid utf8>");
if let Some(ext) = self.get_extended() {
let ext = core::str::from_utf8(ext).unwrap_or("<invalid utf8>");
write!(f, "{code},\"{msg};{ext}\"")
} else {
write!(f, "{code},\"{msg}\"")
}
}
}
impl Default for Error {
fn default() -> Self {
Self::new(ErrorCode::NoError)
}
}
/// Useful alias of Result for SCPI operations
pub type Result<T> = core::result::Result<T, Error>;
impl Error {
/// Create new error with specified error code
pub fn new(code: ErrorCode) -> Self {
Self(code, None)
}
/// Create new error with a custom (unchecked) code
pub fn custom(code: i16, desc: &'static [u8]) -> Self {
Self(ErrorCode::Custom(code, desc), None)
}
/// Create new error with specified error code with an extended message
pub fn extended(mut self, msg: &'static [u8]) -> Self {
self.1 = Some(msg);
self
}
/// Get numeric error code of error
pub fn get_code(&self) -> i16 {
self.0.get_code()
}
/// Get message of error
pub fn get_message(&self) -> &'static [u8] {
self.0.get_message()
}
/// Get extended message of error
pub fn get_extended(&self) -> Option<&'static [u8]> {
self.1
}
/**
* Returns a bitmask for the appropriate bit in the ESR for this event/error.
*/
pub fn esr_mask(&self) -> u8 {
self.0.esr_mask()
}
}
impl PartialEq<ErrorCode> for Error {
fn eq(&self, other: &ErrorCode) -> bool {
&self.0 == other
}
}
impl PartialEq<Error> for ErrorCode {
fn eq(&self, other: &Error) -> bool {
self == &other.0
}
}
impl From<ErrorCode> for Error {
fn from(err: ErrorCode) -> Self {
Error::new(err)
}
}
/// The Error type contains error definitions detected by the parser or commands
///
///> # 21.8.2 Error/Event numbers
///> The system-defined error/event numbers are chosen on an enumerated (“1 of N”) basis. The
///> SCPI-defined error/event numbers and the <error/event_description> portions of the full
///> queue item are listed here. The first error/event described in each class (for example, -100,
///> -200, -300, -400) is a “generic” error. In selecting the proper Error/event number to report,
///> more specific error/event codes are preferred, and the generic error/event is used only if the
///> others are inappropriate.
///
///> Note the organization of the following tables. A “simple-minded” parser might implement
///> only the XX0 errors, and a smarter one might implement all of them. A “smart and friendly”
///> parser might use the instrument-dependent part of the error/event message string to point out
///> the offending part of the command.
///
///
///
#[derive(Debug, PartialEq, Eq, Copy, Clone, scpi_derive::ScpiError)]
pub enum ErrorCode {
///# Custom error
/// Used for custom error in the range`[ -399 , -300 ]` or `[ 1 , 32767 ]`.
/// See **Device-specific error** for closer description.
///
#[error(custom)]
Custom(i16, &'static [u8]),
///# 28.8.3 No error [-99, 0]
///> This message indicates that the device has no errors or events to report.
/// ---
/// `0, "No error"`
///
/// The queue is completely empty. Every error/event in the queue has been read or
/// the queue was purposely cleared by power-on, *CLS, etc
#[error(code = 0, message = b"No error")]
NoError,
///# 28.9.10 Command Errors [-199, -100]
///> An <error/event number> in the range `[ -199 , -100 ]` indicates that an IEEE 488.2 syntax
///> error has been detected by the instrument’s parser. The occurrence of any error in this class
///> shall cause the command error bit (bit 5) in the event status register (IEEE 488.2, section
///> 11.5.1) to be set. One of the following events has occurred:
///> * An IEEE 488.2 syntax error has been detected by the parser. That is, controller-to-device message was received which is in violation of the IEEE 488.2 standard. Possible violations include a data element which violates the devicelistening formats or whose type is unacceptable to the device.
///> * An unrecognized header was received. Unrecognized headers include incorrect device-specific headers and incorrect or unimplemented IEEE 488.2 common commands.
///> * A Group Execute Trigger (GET) was entered into the input buffer inside of an IEEE 488.2 <PROGRAM MESSAGE>.
///> Events that generate command errors shall not generate execution errors, device-specific
///> errors, or query errors; see the other error definitions in this chapter.
/// ---
/// `-100, "Command error"`
///
///This is the generic syntax error for devices that cannot detect more specific
///errors. This code indicates only that a Command Error as defined in IEEE 488.2,
///11.5.1.1.4 has occurred.
#[error(code=-100,message=b"Command error")]
CommandError,
/// `-101, "Invalid character"`
///
/// A syntactic element contains a character which is invalid for that type; for
/// example, a header containing an ampersand, SETUP&. This error might be used
/// in place of errors -114, -121, -141, and perhaps some others.
#[error(code=-101,message=b"Invalid character")]
InvalidCharacter,
/// `-102, "Syntax error"`
///
/// An unrecognized command or data type was encountered; for example, a string
/// was received when the device does not accept strings.
#[error(code=-102,message=b"Syntax error")]
SyntaxError,
/// `-103, "Invalid Separator"`
///
///The parser was expecting a separator and encountered an illegal character; for
///example, the semicolon was omitted after a program message unit,
///*EMC 1:CH1:VOLTS 5
#[error(code=-103,message=b"Invalid separator")]
InvalidSeparator,
/// `-104, "Data type error"`
///
///The parser recognized a data element different than one allowed; for example,
///numeric or string data was expected but block data was encountered
#[error(code=-104,message=b"Data type error")]
DataTypeError,
/// `-105, "GET not allowed"`
///
///A Group Execute Trigger was received within a program message (see IEEE
///488.2, 7.7)
#[error(code=-105,message=b"GET not allowed")]
GetNotAllowed,
/// `-108, "Parameter not allowed"`
///
/// More parameters were received than expected for the header; for example, the
/// *EMC common command only accepts one parameter, so receiving *EMC 0,1 is
/// not allowed.
#[error(code=-108,message=b"Parameter not allowed")]
ParameterNotAllowed,
/// `-109, "Missing parameter"`
///
/// Fewer parameters were recieved than required for the header; for example, the
/// *EMC common command requires one parameter, so receiving *EMC is not
/// allowed.
#[error(code=-109,message=b"Missing parameter")]
MissingParameter,
/// `-110, "Command header error"`
///
/// An error was detected in the header. This error message should be used when the
/// device cannot detect the more specific errors described for errors -111 through
/// -119.
#[error(code=-110,message=b"Command header error")]
CommandHeaderError,
/// `-111, "Header separator error"`
///
/// A character which is not a legal header separator was encountered while parsing
/// the header; for example, no white space followed the header, thus
/// *GMC"MACRO" is an error.
#[error(code=-111,message=b"Header separator error")]
HeaderSeparatorError,
/// `-112, "Program mnemonic too long"`
///
/// The header contains more that twelve characters (see IEEE 488.2, 7.6.1.4.1).
#[error(code=-112,message=b"Program mnemonic too long")]
ProgramMnemonicTooLong,
/// `-113, "Undefined header"`
///
/// The header is syntactically correct, but it is undefined for this specific device; for
/// example, *XYZ is not defined for any device.
#[error(code=-113,message=b"Undefined header")]
UndefinedHeader,
/// `-114, "Header suffix out of range"`
///
/// The value of a numeric suffix attached to a program mnemonic, see Syntax and
/// Style section 6.2.5.2, makes the header invalid.
#[error(code=-114,message=b"Header suffix out of range")]
HeaderSuffixOutOfRange,
/// `-115, "Unexpected number of parameters"`
///
/// The number of parameters received does not correspond to the number of
/// parameters expected. This is typically due an inconsistency with the number of
/// instruments in the selected group (see section on INSTrument:DEFine:GROup).
#[error(code=-115,message=b"Unexpected number of parameters")]
UnexpectedNumberOfParameters,
/// `-120, "Numeric data error"`
///
/// This error, as well as errors -121 through -129, are generated when parsing a data
/// element which apprears to be numeric, including the nondecimal numeric types.
/// This particular error message should be used if the device cannot detect a more
/// specific error.
#[error(code=-120,message=b"Numeric data error")]
NumericDataError,
/// `-121, "Invalid character in number"`
///
/// An invalid character for the data type being parsed was encountered; for
/// example, an alpha in a decimal numeric or a “9" in octal data.
#[error(code=-121,message=b"Invalid character in number")]
InvalidCharacterInNumber,
/// `-123, "Exponent too large"`
///
/// The magnitude of the exponent was larger than 32000 (see IEEE 488.2,
/// 7.7.2.4.1).
#[error(code=-123,message=b"Exponent too large")]
ExponentTooLarge,
/// `-124, "Too many digits"`
///
/// The mantissa of a decimal numeric data element contained more than 255 digits
/// excluding leading zeros (see IEEE 488.2, 7.7.2.4.1).
#[error(code=-124,message=b"Too many digits")]
TooManyDigits,
/// `-128, ""Numeric data not allowed`
///
/// A legal numeric data element was received, but the device does not accept one in
/// this position for the header.
#[error(code=-128,message=b"Numeric data not allowed")]
NumericDataNotAllowed,
/// `-130, "Suffix error"`
///
/// This error, as well as errors -131 through -139, are generated when parsing a
/// suffix. This particular error message should be used if the device cannot detect a
/// more specific error.
#[error(code=-130,message=b"Suffix error")]
SuffixError,
/// `-131, "Invalid suffix"`
///
/// The suffix does not follow the syntax described in IEEE 488.2, 7.7.3.2, or the
/// suffix is inappropriate for this device.]
#[error(code=-131,message=b"Invalid suffix")]
InvalidSuffix,
/// `-134, "Suffix too long"`
///
/// The suffix contained more than 12 characters (see IEEE 488.2, 7.7.3.4).
#[error(code=-134,message=b"Suffix too long")]
SuffixTooLong,
/// `-138, "Suffix not allowed"`
///
/// A suffix was encountered after a numeric element which does not allow suffixes.
#[error(code=-138,message=b"Suffix not allowed")]
SuffixNotAllowed,
/// `-140, "Character data error"`
///
/// This error, as well as errors -141 through -149, are generated when parsing a
/// character data element. This particular error message should be used if the device
/// cannot detect a more specific error.
#[error(code=-140,message=b"Character data error")]
CharacterDataError,
/// `-141, "Invalid character data"`
///
/// Either the character data element contains an invalid character or the particular
/// element received is not valid for the header.
#[error(code=-141,message=b"Invalid character data")]
InvalidCharacterData,
/// `-144, "Character data too long"`
///
/// The character data element contains more than twelve characters (see IEEE
/// 488.2, 7.7.1.4).
#[error(code=-144,message=b"Character data too long")]
CharacterDataTooLong,
/// `-148, "Character data not allowed"`
///
/// A legal character data element was encountered where prohibited by the device.
#[error(code=-148,message=b"Character data not allowed")]
CharacterDataNotAllowed,
/// `-150, "String data error"`
///
/// This error, as well as errors -151 through -159, are generated when parsing a
/// string data element. This particular error message should be used if the device
/// cannot detect a more specific error.
#[error(code=-150,message=b"String data error")]
StringDataError,
/// `-151, "Invalid string data"`
///
/// A string data element was expected, but was invalid for some reason (see IEEE
/// 488.2, 7.7.5.2); for example, an END message was received before the terminal
/// quote character.
#[error(code=-151,message=b"Invalid string data")]
InvalidStringData,
/// `-158, "String data not allowed"`
///
/// A string data element was encountered but was not allowed by the device at this
/// point in parsing.
#[error(code=-158,message=b"String data not allowed")]
StringDataNotAllowed,
/// `-160, "Block data error"`
///
/// This error, as well as errors -161 through -169, are generated when parsing a
/// block data element. This particular error message should be used if the device
/// cannot detect a more specific error.
#[error(code=-160,message=b"Block data error")]
BlockDataError,
/// `-161, "Invalid block data"`
///
/// A block data element was expected, but was invalid for some reason (see IEEE
/// 488.2, 7.7.6.2); for example, an END message was received before the length was
/// satisfied.
#[error(code=-161,message=b"Invalid block data")]
InvalidBlockData,
/// `-168, "Block data not allowed"`
///
/// A legal block data element was encountered but was not allowed by the device at
/// this point in parsing.
#[error(code=-168,message=b"Block data not allowed")]
BlockDataNotAllowed,
/// `-170, "Expression error"`
///
/// This error, as well as errors -171 through -179, are generated when parsing an
/// expression data element. This particular error message should be used if the
/// device cannot detect a more specific error.
#[error(code=-170,message=b"Expression error")]
ExpressionError,
/// `-171, "Invalid expression"`
///
/// The expression data element was invalid (see IEEE 488.2, 7.7.7.2); for example,
/// unmatched parentheses or an illegal character.
#[error(code=-171,message=b"Invalid expression")]
InvalidExpression,
/// `-178, "Expression data not allowed"`
///
/// A legal expression data was encountered but was not allowed by the device at
/// this point in parsing.
#[error(code=-178,message=b"Expression data not allowed")]
ExpressionDataNotAllowed,
/// `-180, "Macro error"`
///
/// This error, as well as errors -181 through -189, are generated when defining a
/// macro or executing a macro. This particular error message should be used if the
/// device cannot detect a more specific error.
#[error(code=-180,message=b"Macro error")]
MacroError,
/// `-181, "Invalid outside macro definition"`
///
/// Indicates that a macro parameter placeholder ($<number) was encountered
/// outside of a macro definition.
#[error(code=-181,message=b"Invalid outside macro definition")]
InvalidOutsideMacroDefinition,
/// `-183, "Invalid inside macro definition"`
///
/// Indicates that the program message unit sequence, sent with a *DDT or *DMC
/// command, is syntactically invalid (see IEEE 488.2, 10.7.6.3).
#[error(code=-183,message=b"Invalid inside macro definition")]
InvalidInsideMacroDefinition,
/// `-184, "Macro parameter error"`
///
/// Indicates that a command inside the macro definition had the wrong number or
/// type of parameters.
#[error(code=-184,message=b"Macro parameter error")]
MacroParameterError,
///# 21.8.10 Execution Errors [-299, -200]
///> An <error/event number> in the range `[ -299 , -200 ]` indicates that an error has been
///> detected by the instrument’s execution control block. The occurrence of any error in this
///> class shall cause the execution error bit (bit 4) in the event status register (IEEE 488.2,
///> section 11.5.1) to be set. One of the following events has occurred:
///> * A \<PROGRAM DATA\> element following a header was evaluated by the device as outside of its legal input range or is otherwise inconsistent with the device’s capabilities.
///> * A valid program message could not be properly executed due to some device condition.
///> Execution errors shall be reported by the device after rounding and expression evaluation
///> operations have taken place. Rounding a numeric data element, for example, shall not be
///> reported as an execution error. Events that generate execution errors shall not generate
///> Command Errors, device-specific errors, or Query Errors; see the other error definitions in
///> this section.
/// ---
/// `-200, "Execution error"`
///
///This is the generic syntax error for devices that cannot detect more specific
///errors. This code indicates only that an Execution Error as defined in IEEE 488.2,
///11.5.1.1.5 has occurred.
#[error(code=-200,message=b"Execution error")]
ExecutionError,
/// `-201, "Invalid while in local"`
///
/// Indicates that a command is not executable while the device is in local due to a
/// hard local control (see IEEE 488.2, 5.6.1.5); for example, a device with a rotary
/// switch receives a message which would change the switches state, but the device
/// is in local so the message can not be executed.
#[error(code=-201,message=b"Invalid while in local")]
InvalidWhileInLocal,
/// `-202, "Settings lost due to rtl"`
///
/// Indicates that a setting associated with a hard local control (see IEEE 488.2,
/// 5.6.1.5) was lost when the device changed to LOCS from REMS or to LWLS
/// from RWLS.
#[error(code=-202,message=b"Settings lost due to rtl")]
SettingsLostDueToRtl,
/// `-203, "Command protected"`
///
/// Indicates that a legal password-protected program command or query could not
/// be executed because the command was disabled.
#[error(code=-203,message=b"Command protected")]
CommandProtected,
/// `-210, "Trigger error"`
///
/// Indicates a trigger error.
#[error(code=-210,message=b"Trigger error")]
TriggerError,
/// `-211, "Trigger ignored"`
///
/// Indicates that a GET, *TRG, or triggering signal was received and recognized by
/// the device but was ignored because of device timing considerations; for example,
/// the device was not ready to respond. Note: a DT0 device always ignores GET and
/// treats *TRG as a Command Error.
#[error(code=-211,message=b"Trigger ignored")]
TriggerIgnored,
/// `-212, "Arm ignored"`
///
/// Indicates that an arming signal was received and recognized by the device but
/// was ignored.
#[error(code=-212,message=b"Arm ignored")]
ArmIgnored,
/// `-213, "Init ignored"`
///
/// Indicates that a request for a measurement initiation was ignored as another
/// measurement was already in progress.
#[error(code=-213,message=b"Init ignored")]
InitIgnored,
/// `-214, "Trigger deadlock"`
///
/// Indicates that the trigger source for the initiation of a measurement is set to GET
/// and subsequent measurement query is received. The measurement cannot be
/// started until a GET is received, but the GET would cause an INTERRUPTED
/// error.
#[error(code=-214,message=b"Trigger deadlock")]
TriggerDeadlock,
/// `-215, "Arm deadlock"`
///
/// Indicates that the arm source for the initiation of a measurement is set to GET
/// and subsequent measurement query is received. The measurement cannot be
/// started until a GET is received, but the GET would cause an INTERRUPTED
/// error.
#[error(code=-215,message=b"Arm deadlock")]
ArmDeadlock,
/// `-220, "Parameter error"`
///
/// Indicates that a program data element related error occurred. This error message
/// should be used when the device cannot detect the more specific errors described
/// for errors -221 through -229.
#[error(code=-220,message=b"Parameter error")]
ParameterError,
/// `-221, "Settings conflict"`
///
/// Indicates that a legal program data element was parsed but could not be executed
/// due to the current device state (see IEEE 488.2, 6.4.5.3 and 11.5.1.1.5.)
#[error(code=-221,message=b"Settings conflict")]
SettingsConflict,
/// `-222, "Data out of range"`
///
/// Indicates that a legal program data element was parsed but could not be executed
/// because the interpreted value was outside the legal range as defined by the device
/// (see IEEE 488.2, 11.5.1.1.5.)
#[error(code=-222,message=b"Data out of range")]
DataOutOfRange,
/// `-223, "Too much data"`
///
/// Indicates that a legal program data element of block, expression, or string type
/// was received that contained more data than the device could handle due to
/// memory or related device-specific requirements.
#[error(code=-223,message=b"Too much data")]
TooMuchData,
/// `-224, "Illegal parameter value"`
///
/// Used where exact value, from a list of possibles, was expected.]
#[error(code=-224,message=b"Illegal parameter value")]
IllegalParameterValue,
/// `-225, "Out of memory"`
///
/// The device has insufficent memory to perform the requested
/// operation.
#[error(code=-225,message=b"Out of memory")]
OutOfMemory,
/// `-226, "Lists not same length"`
///
/// Attempted to use LIST structure having individual LIST’s
/// of unequal lengths.
#[error(code=-226,message=b"Lists not same length")]
ListsNotSameLength,
/// `-230, "Data corrupt or stale"`
///
/// Possibly invalid data; new reading started but not completed since last access.
#[error(code=-230,message=b"Data corrupt or stale")]
DataCorruptOrStale,
/// `-231, "Data questionable"`
///
/// Indicates that measurement accuracy is suspect.
#[error(code=-231,message=b"Data questionable")]
DataQuestionable,
/// `-232, "Invalid format"`
///
/// Indicates that a legal program data element was parsed but could not be executed
/// because the data format or structure is inappropriate. For example when loading
/// memory tables or when sending a SYSTem:SET parameter from an unknown
/// instrument.
#[error(code=-232,message=b"Invalid format")]
InvalidFormat,
/// `-233, "Invalid version"`
///
/// Indicates that a legal program data element was parsed but could not be executed
/// because the version of the data is incorrect to the device. This particular error
/// should be used when file or block data formats are recognized by the instrument
/// but cannot be executed for reasons of version incompatibility. For example, a not
/// supported file version, a not supported instrument version
#[error(code=-233,message=b"Invalid version")]
InvalidVersion,
/// `-240, "Hardware error"`
///
/// Indicates that a legal program command or query could not be executed because
/// of a hardware problem in the device. Definition of what constitutes a hardware
/// problem is completely device-specific. This error message should be used when
/// the device cannot detect the more specific errors described for errors -241 through
/// -249.
#[error(code=-240,message=b"Hardware error")]
HardwareError,
/// `-241, "Hardware missing"`
///
/// Indicates that a legal program command or query could not be executed because
/// of missing device hardware; for example, an option was not installed. Definition
/// of what constitutes missing hardware is completely device-specific.
#[error(code=-241,message=b"Hardware missing")]
HardwareMissing,
/// `-250, "Mass storage error"`
///
/// Indicates that a mass storage error occurred. This error message should be used
/// when the device cannot detect the more specific errors described for errors -251
/// through -259.
#[error(code=-250,message=b"Mass storage error")]
MassStorageError,
/// `-251, "Missing mass storage"`
///
/// Indicates that a legal program command or query could not be executed because
/// of missing mass storage; for example, an option that was not installed. Definition
/// of what constitutes missing mass storage is device-specific.
#[error(code=-251,message=b"Missing mass storage")]
MissingMassStorage,
/// `-252, "Missing media"`
///
/// Indicates that a legal program command or query could not be executed because
/// of a missing media; for example, no disk. The definition of what constitutes
/// missing media is device-specific.
#[error(code=-252,message=b"Missing media")]
MissingMedia,
/// `-253, "Corrupt media"`
///
/// Indicates that a legal program command or query could not be executed because
/// of corrupt media; for example, bad disk or wrong format. The definition of what
/// constitutes corrupt media is device-specific.
#[error(code=-253,message=b"Corrupt media")]
CorruptMedia,
/// `-254, "Media full"`
///
/// Indicates that a legal program command or query could not be executed because
/// the media was full; for example, there is no room on the disk. The definition of
/// what constitutes a full media is device-specific.
#[error(code=-254,message=b"Media full")]
MediaFull,
/// `-255, "Directory full"`
///
/// Indicates that a legal program command or query could not be executed because
/// the media directory was full. The definition of what constitutes a full media
/// directory is device-specific.
#[error(code=-255,message=b"Directory full")]
DirectoryFull,
/// `-256, "File name not found"`
///
/// Indicates that a legal program command or query could not be executed because
/// the file name on the device media was not found; for example, an attempt was
/// made to read or copy a nonexistent file. The definition of what constitutes a file
/// not being found is device-specific.
#[error(code=-256,message=b"Filename not found")]
FileNameNotFound,
/// `-257, "Filename error"`
///
/// Indicates that a legal program command or query could not be executed because
/// the file name on the device media was in error; for example, an attempt was made
/// to copy to a duplicate file name. The definition of what constitutes a file name
/// error is device-specific.
#[error(code=-257,message=b"Filename error")]
FileNameError,
/// `-258, "Media protected"`
///
/// Indicates that a legal program command or query could not be executed because
/// the media was protected; for example, the write-protect tab on a disk was present.
/// The definition of what constitutes protected media is device-specific.
#[error(code=-258,message=b"Media protected")]
MediaProtected,
/// `-260, "Expression error"`
///
/// Indicates that a expression program data element related error occurred. This
/// error message should be used when the device cannot detect the more specific
/// errors described for errors -261 through -269.
#[error(code=-260,message=b"Expression error")]
ExecExpressionError, //Also declared in 170?
/// `-261, "Math error in expression"`
///
/// Indicates that a syntactically legal expression program data element could not be
/// executed due to a math error; for example, a divide-by-zero was attempted. The
/// definition of math error is device-specific.
#[error(code=-261,message=b"Math error in expression")]
MathErrorInExpression,
/// `-270, "Macro error"`
///
/// Indicates that a macro-related execution error occurred. This error message
/// should be used when the device cannot detect the more specific errors described
/// for errors -271 through -279.
#[error(code=-270,message=b"Macro error")]
ExecMacroError,
/// `-271, "Macro syntax error"`
///
/// Indicates that that a syntactically legal macro program data sequence, according
/// to IEEE 488.2, 10.7.2, could not be executed due to a syntax error within the
/// macro definition (see IEEE 488.2, 10.7.6.3.)
#[error(code=-271,message=b"Macro syntax error")]
MacroSyntaxError,
/// `-272, "Macro execution error"`
///
/// Indicates that a syntactically legal macro program data sequence could not be
/// executed due to some error in the macro definition (see IEEE 488.2, 10.7.6.3.)
#[error(code=-272,message=b"Macro execution error")]
MacroExecutionError,
/// `-273, "Illegal macro label"`
///
/// Indicates that the macro label defined in the *DMC command was a legal string
/// syntax, but could not be accepted by the device (see IEEE 488.2, 10.7.3 and
/// 10.7.6.2); for example, the label was too long, the same as a common command
/// header, or contained invalid header syntax.]
#[error(code=-273,message=b"Illegal macro label")]
IllegalMacroLabel,
/// `-274, "Macro parameter error"`
///
/// Indicates that the macro definition improperly used a macro parameter
/// placeholder (see IEEE 488.2, 10.7.3).
#[error(code=-274,message=b"Macro parameter error")]
ExecMacroParameterError,
/// `-275, "Macro definition too long"`
///
/// Indicates that a syntactically legal macro program data sequence could not be
/// executed because the string or block contents were too long for the device to
/// handle (see IEEE 488.2, 10.7.6.1).
#[error(code=-275,message=b"Macro definition too long")]
MacroDefinitionTooLong,
/// `-276, "Macro recursion error"`
///
/// Indicates that a syntactically legal macro program data sequence could not be
/// executed because the device found it to be recursive (see IEEE 488.2, 10.7.6.6).
#[error(code=-276,message=b"Macro recursion error")]
MacroRecursionError,
/// `-277, "Macro redefinition not allowed"`
///
/// Indicates that a syntactically legal macro label in the *DMC command could not
/// be executed because the macro label was already defined (see IEEE 488.2,
/// 10.7.6.4).
#[error(code=-277,message=b"Macro redefinition not allowed")]
MacroRedefinitionNotAllowed,
/// `-278, "Macro header not found"`
///
/// Indicates that a syntactically legal macro label in the *GMC? query could not be
/// executed because the header was not previously defined.
#[error(code=-278,message=b"Macro header not found")]
MacroHeaderNotFound,
/// `-280, "Program error"`
///
/// Indicates that a downloaded program-related execution error occurred. This error
/// message should be used when the device cannot detect the more specific errors
/// described for errors -281 through -289. A downloaded program is used to add
/// algorithmic capability to a device. The syntax used in the program and the
/// mechanism for downloading a program is device-specific.
#[error(code=-280,message=b"Program error")]
ProgramError,
/// `-281, "Cannot create program"`
///
/// Indicates that an attempt to create a program was unsuccessful. A reason for the
/// failure might include not enough memory.
#[error(code=-281,message=b"Cannot create program")]
CannotCreateProgram,
/// `-282, "Illegal program name"`
///
/// The name used to reference a program was invalid; for example, redefining an
/// existing program, deleting a nonexistent program, or in general, referencing a
/// nonexistent program.
#[error(code=-282,message=b"Illegal program name")]
IllegalProgramName,
/// `-283, "Illegal variable name"`
///
/// An attempt was made to reference a nonexistent variable in a program.
#[error(code=-283,message=b"Illegal variable name")]
IllegalVariableName,
/// `-284, "Program currently running"`
///
/// Certain operations dealing with programs may be illegal while the program is
/// running; for example, deleting a running program might not be possible.
#[error(code=-284,message=b"Program currently running")]
ProgramCurrentlyRunning,
/// `-285, "Program syntax error"`
///
/// Indicates that a syntax error appears in a downloaded program. The syntax used
/// when parsing the downloaded program is device-specific.
#[error(code=-285,message=b"Program syntax error")]
ProgramSyntaxError,
/// `-286, "Program runtime error"`
///
///
#[error(code=-286,message=b"Program runtime error")]
ProgramRuntimeError,
/// `-290, "Memory use error"`
///
/// Indicates that a user request has directly or indirectly caused an error related to
/// memory or <data_handle>s, this is not the same as “bad” memory.
#[error(code=-290,message=b"Memory use error")]
MemoryUseError,
/// `-291, "Out of memory"`
///
///
#[error(code=-291,message=b"Out of memory")]
UseOutOfMemory,
/// `-292, "Referenced name does not exist"`
///
///
#[error(code=-292,message=b"Referenced name does not exist")]
ReferencedNameDoesNotExist,
/// `-293, "Referenced name already exists"`
///
///
#[error(code=-293,message=b"Referenced name already exists")]
ReferencedNameAlreadyExists,
/// `-294, "Incompatible type"`
///
/// Indicates that the type or structure of a memory item is inadequate.
#[error(code=-294,message=b"Incompatible type")]
IncompatibleType,
///# Device-specific error `[-399, -300]`
///> An <error/event number> in the range `[ -399 , -300 ]` or `[ 1 , 32767 ]` indicates that the
///> instrument has detected an error which is not a command error, a query error, or an
///> execution error; some device operations did not properly complete, possibly due to an
///> abnormal hardware or firmware condition. These codes are also used for self-test response
///> errors. The occurrence of any error in this class should cause the device-specific error bit (bit
///> 3) in the event status register (IEEE 488.2, section 11.5.1) to be set. The meaning of positive
///> error codes is device-dependent and may be enumerated or bit mapped; the <error message>
///> string for positive error codes is not defined by SCPI and available to the device designer.
///> Note that the string is not optional; if the designer does not wish to implement a string for a
///> particular error, the null string should be sent (for example, 42,""). The occurrence of any
///> error in this class should cause the device-specific error bit (bit 3) in the event status register
///> (IEEE 488.2, section 11.5.1) to be set. Events that generate device-specific errors shall not
///> generate command errors, execution errors, or query errors; see the other error definitions in
///> this section.
/// ---
/// `-300, Device-specific error`
///
/// This is the generic device-dependent error for devices that cannot detect more
/// specific errors. This code indicates only that a Device-Dependent Error as defined
/// in IEEE 488.2, 11.5.1.1.6 has occurred.
#[error(code=-300,message=b"Device-specific error")]
DeviceSpecificError,
/// `-310, "System error"`
///
/// Indicates that some error, termed “system error” by the device, has occurred.
/// This code is device-dependent.
#[error(code=-310,message=b"System error")]
SystemError,
/// `-311, "Memory error"`
///
/// Indicates some physical fault in the device’s memory, such as parity error.
#[error(code=-311,message=b"Memory error")]
MemoryError,
/// `-312, "PUD memory lost"`
///
/// Indicates that the protected user data saved by the *PUD command has been lost.
#[error(code=-312,message=b"PUD memory lost")]
PudMemoryLost,
/// `-313, "Calibration memory lost"`
///
/// Indicates that nonvolatile calibration data used by the *CAL? command has been
/// lost.
#[error(code=-313,message=b"Calibration memory lost")]
CalibrationMemoryLost,
/// `-314, "Save/recall memory lost"`
///
/// Indicates that the nonvolatile data saved by the *SAV? command has been lost.
#[error(code=-314,message=b"Save/recall memory lost")]
SaveRecallMemoryLost,
/// `-315, "Configuration memory lost"`
///
/// Indicates that nonvolatile configuration data saved by the device has been lost.
/// The meaning of this error is device-specific.
#[error(code=-315,message=b"Configuration memory lost")]
ConfigurationMemoryLost,
/// `-320, "Storage fault"`
///
/// Indicates that the firmware detected a fault when using data storage. This error is
/// not an indication of physical damage or failure of any mass storage element.
#[error(code=-320,message=b"Storage fault")]
StorageFault,
/// `-321, "Out of memory"`
///
/// An internal operation needed more memory than was available.
#[error(code=-321,message=b"Out of memory")]
StOutOfMemory,
/// `-330, "Self-test failed"`
///
///
#[error(code=-330,message=b"Self-test failed")]
SelfTestFailed,
/// `-340, "Calibration failed"`
///
///
#[error(code=-340,message=b"Calibration failed")]
CalibrationFailed,
/// `-350, "Queue overflow"`
///
/// A specific code entered into the queue in lieu of the code that caused the error.
/// This code indicates that there is no room in the queue and an error occurred but
/// was not recorded.
#[error(code=-350,message=b"Queue overflow")]
QueueOverflow,
/// `-360, "Communication error"`
///
/// This is the generic communication error for devices that cannot detect the more
/// specific errors described for errors -361 through -363.
#[error(code=-360,message=b"Communication error")]
CommunicationError,
/// `-361, "Parity error in program message"`
///
/// Parity bit not correct when data received for example, on a serial port.
#[error(code=-361,message=b"Parity error in program message")]
ParityErrorInProgramMessage,
/// `-362, "Framing error in program message"`
///
/// A stop bit was not detected when data was received for example, on a serial port
/// (for example, a baud rate mismatch).
#[error(code=-362,message=b"Framing error in program message")]
FramingErrorInProgramMessage,
/// `-363, "Input buffer overrun"`
///
/// Software or hardware input buffer on serial port overflows with data caused by
/// improper or nonexistent pacing.
#[error(code=-363,message=b"Input buffer overrun")]
InputBufferOverrun,
/// `-365, "Time out error"`
///
/// This is a generic device-dependent error.
#[error(code=-365,message=b"Time out error")]
TimeOutError,
///# Query error [-499, -400]
///> An <error/event number> in the range `[ -499 , -400 ]` indicates that the output queue control
///> of the instrument has detected a problem with the message exchange protocol described in
///> IEEE 488.2, chapter 6. The occurrence of any error in this class shall cause the query error
///> bit (bit 2) in the event status register (IEEE 488.2, section 11.5.1) to be set. These errors
///> correspond to message exchange protocol errors described in IEEE 488.2, section 6.5. One
///> of the following is true:
///> * An attempt is being made to read data from the output queue when no output is either present or pending;
///> * Data in the output queue has been lost.
///> Events that generate query errors shall not generate command errors, execution errors, or
///> device-specific errors; see the other error definitions in this section.
/// ---
/// `-400, "Query Error"`
///
/// This is the generic query error for devices that cannot detect more specific errors.
/// This code indicates only that a Query Error as defined in IEEE 488.2, 11.5.1.1.7
/// and 6.3 has occurred.
#[error(code=-400,message=b"Query error")]
QueryError,
/// `-410, "Query INTERRUPTED"`
///
/// Indicates that a condition causing an INTERRUPTED Query error occurred (see
/// IEEE 488.2, 6.3.2.3); for example, a query followed by DAB or GET before a
/// response was completely sent.
#[error(code=-410,message=b"Query INTERRUPTED")]
QueryInterrupted,
/// `-420, "Query UNTERMINATED"`
///
/// Indicates that a condition causing an UNTERMINATED Query error occurred
/// (see IEEE 488.2, 6.3.2.2); for example, the device was addressed to talk and an
/// incomplete program message was received.
#[error(code=-420,message=b"Query UNTERMINATED")]
QueryUnterminated,
/// `-430, "Query DEADLOCKED"`
///
/// Indicates that a condition causing an DEADLOCKED Query error occurred (see
/// IEEE 488.2, 6.3.1.7); for example, both input buffer and output buffer are full and
/// the device cannot continue.
#[error(code=-430,message=b"Query DEADLOCKED")]
QueryDeadlocked,
/// `-440, "Query UNTERMINATED after indefinite response"`
///
/// Indicates that a query was received in the same program message after an query
/// requesting an indefinite response was executed (see IEEE 488.2, 6.5.7.5).
#[error(code=-440,message=b"Query UNTERMINATED after indefinite response")]
QueryUnterminatedAfterIndefiniteResponse,
///# Power on event [-599, -500]
///> An <error/event number> in the range `[-599:-500]` is used when the instrument wishes to
///> report a 488.2 power on event to the event/error queue. This event occurs when the
///> instrument detects an off to on transition in its power supply. This event also sets the power
///> on bit, (bit 7) of the Standard Event Status Register. See IEEE 488.2, section 11.5.1.
/// ---
/// `-500, "Power on"`
///
/// The instrument has detected an off to on transition in its power supply.
#[error(code=-500,message=b"Power on")]
PowerOn,
///# User request event [-699, -600]
///> An <error/event number> in the range `[-699:-600]` is used when the instrument wishes to
///> report a 488.2 user request event. This event occurs when the instrument detects the
///> activation of a user request local control. This event also sets the user request bit (bit 6) of
///> the Standard Event Status Register. See IEEE 488.2, section 11.5.1.
/// ---
/// `-600, "User request"`
///
/// The instrument has detected the activation of a user request local control
#[error(code=-600,message=b"User request")]
UserRequest,
///# Request control event [-799, -700]
///> An <error/event number> in the range `[-799:-700]` is used when the instrument wishes to
///> report a 488.2 request control event to the error/event queue. This event occurs when the
///> instrument requests to become the active IEEE 488.1 controller-in-charge. This event also
///> sets request control bit (bit 1) of the Standard Event Status Register. See IEEE 488.2,
///> section 11.5.1.
/// ---
/// `-700, "Request Control"`
///
/// The instrument requested to become the active IEEE 488.1 controller-in-charge
#[error(code=-700,message=b"Request control")]
RequestControl,
///# Operation complete event [-899, -800]
///> An <error/event number> in the range `[-899:-800]` is used when the instrument wishes to
///> report a 488.2 operation complete event to the error/event queue. This event occurs when
///> instrument’s synchronization protocol, having been enabled by an *OPC command,
///> completes all selected pending operations. This protocol is described in IEEE 488.2, section
///> 12.5.2. This event also sets the operation complete bit (bit 0) of the Standard Event Status
///> Register. See IEEE 488.2, section 11.5.1. Note: *OPC? does not set bit 0 nor does it enter
///> any event in the error/event queue
/// ---
/// `-800, "Operation Complete"`
///
/// The instrument has completed all selected pending operations in accordance with
/// the IEEE 488.2, 12.5.2 synchronization protocol
#[error(code=-800,message=b"Operation complete")]
OperationComplete,
}
impl ErrorCode {
/**
* Returns a bitmask for the appropriate bit in the ESR for this event/error.
*/
pub fn esr_mask(&self) -> u8 {
match self.get_code() {
-99..=0 => 0u8, //No bit
-199..=-100 => 0x20u8, //bit 5
-299..=-200 => 0x10u8, //bit 4
-399..=-300 => 0x08u8, //bit 3
-499..=-400 => 0x04u8, //bit 2
-599..=-500 => 0x80u8, //bit 7
-699..=-600 => 0x40u8, //bit 6
-799..=-700 => 0x02u8, //bit 1
-899..=-800 => 0x01u8, //bit 0
_ => 0x08u8, //bit 3
}
}
pub fn extended(self, msg: &'static [u8]) -> Error {
Error::new(self).extended(msg)
}
}
/// Generic error queue trait
pub trait ErrorQueue {
/// Add a error to the queue.
/// Shall replace last error with a QueueOverflow error if full.
fn push_back_error(&mut self, err: Error);
/// Get a error to the queue
/// Shall return NoError if empty.
fn pop_front_error(&mut self) -> Option<Error>;
/// Current length of queue
fn num_errors(&self) -> usize;
/// Clear queue
fn clear_errors(&mut self);
/// Is queue empty?
fn is_empty(&self) -> bool {
self.num_errors() == 0
}
}
/// Error queue based on a alloc-less [arrayvec::ArrayVec].
#[cfg(feature = "arrayvec")]
pub type ArrayErrorQueue<const CAP: usize> = arrayvec::ArrayVec<Error, CAP>;
#[cfg(feature = "arrayvec")]
impl<const CAP: usize> ErrorQueue for arrayvec::ArrayVec<Error, CAP> {
fn push_back_error(&mut self, err: Error) {
//Try to queue an error, replace last with QueueOverflow if full
if self.try_push(err).is_err() {
let _ = self.pop().unwrap();
self.try_push(ErrorCode::QueueOverflow.into()).unwrap();
}
}
fn pop_front_error(&mut self) -> Option<Error> {
self.pop_at(0)
}
fn num_errors(&self) -> usize {
self.len()
}
fn clear_errors(&mut self) {
self.clear()
}
}
/// Error queue based on [alloc::vec::Vec]
#[cfg(feature = "alloc")]
pub type VecErrorQueue = alloc::vec::Vec<Error>;
#[cfg(feature = "alloc")]
impl ErrorQueue for alloc::vec::Vec<Error> {
fn push_back_error(&mut self, err: Error) {
//Try to queue an error, replace last with QueueOverflow if full
self.push(err)
}
fn pop_front_error(&mut self) -> Option<Error> {
if self.is_empty() {
None
} else {
Some(self.remove(0))
}
}
fn num_errors(&self) -> usize {
self.len()
}
fn clear_errors(&mut self) {
self.clear()
}
}
#[cfg(all(test, feature = "arrayvec"))]
mod test_arrayvec_error_queue {
use super::*;
#[test]
fn test_extended() {
// Check that errorqueue returns NoError when there are no errors
let mut errors = ArrayErrorQueue::<10>::new();
errors.push_back_error(Error::custom(1, b"Error").extended(b"Extended"));
assert_eq!(
errors.pop_front_error(),
Some(Error(ErrorCode::Custom(1, b"Error"), Some(b"Extended")))
);
}
#[test]
fn test_queue_noerror() {
// Check that errorqueue returns NoError when there are no errors
let mut errors = ArrayErrorQueue::<10>::new();
errors.push_back_error(ErrorCode::Custom(1, b"One").into());
errors.push_back_error(ErrorCode::Custom(2, b"Two").into());
assert_eq!(
errors.pop_front_error(),
Some(Error::new(ErrorCode::Custom(1, b"One")))
);
assert_eq!(
errors.pop_front_error(),
Some(Error::new(ErrorCode::Custom(2, b"Two")))
);
assert_eq!(errors.pop_front_error(), None);
}
#[test]
fn test_queue_overflow() {
// Check that errorqueue returns NoError when there are no errors
let mut errors = ArrayErrorQueue::<2>::new();
errors.push_back_error(ErrorCode::Custom(1, b"One").into());
errors.push_back_error(ErrorCode::Custom(2, b"Two").into());
errors.push_back_error(ErrorCode::Custom(3, b"Three").into());
assert_eq!(
errors.pop_front_error(),
Some(Error::new(ErrorCode::Custom(1, b"One")))
);
assert_eq!(
errors.pop_front_error(),
Some(Error::new(ErrorCode::QueueOverflow))
);
}
}