From d2a20872d516c6ab4ed60fd0113e831cfc908011 Mon Sep 17 00:00:00 2001 From: emfoumoune Date: Wed, 3 Apr 2024 16:44:46 +0200 Subject: [PATCH 1/3] see #ICATHALES-582 : Sommation d'images par accumulation - IHM accuMode et ExpoAccuTime --- specifics/Lambda/Lambda.cpp | 79 +++++++++++++++++++++-- specifics/Lambda/Lambda.h | 18 ++++++ specifics/Lambda/Lambda.xmi | 28 +++++++- specifics/Lambda/LambdaClass.cpp | 50 ++++++++++++++ specifics/Lambda/LambdaClass.h | 26 ++++++++ specifics/Lambda/LambdaStateMachine.cpp | 86 ++++++++++++++++++++----- 6 files changed, 263 insertions(+), 24 deletions(-) diff --git a/specifics/Lambda/Lambda.cpp b/specifics/Lambda/Lambda.cpp index dcece7c..ab3ea5c 100755 --- a/specifics/Lambda/Lambda.cpp +++ b/specifics/Lambda/Lambda.cpp @@ -84,6 +84,8 @@ namespace Lambda_ns // chargeSumming | Tango::DevBoolean Scalar // lowerThreshold | Tango::DevDouble Scalar // upperThreshold | Tango::DevDouble Scalar +// hwAccumulation | Tango::DevBoolean Scalar +// exposureAccuTime | Tango::DevDouble Scalar //================================================================ namespace Lambda_ns @@ -366,6 +368,7 @@ void Lambda::get_device_property() //-------------------------------------------------------- void Lambda::always_executed_hook() { + DEBUG_STREAM << "Lambda::always_executed_hook() " << device_name << endl; /*----- PROTECTED REGION ID(Lambda::always_executed_hook) ENABLED START -----*/ // code always executed before all requests @@ -419,6 +422,7 @@ void Lambda::always_executed_hook() //-------------------------------------------------------- void Lambda::read_attr_hardware(TANGO_UNUSED(vector &attr_list)) { + DEBUG_STREAM << "Lambda::read_attr_hardware(vector &attr_list) entering... " << endl; /*----- PROTECTED REGION ID(Lambda::read_attr_hardware) ENABLED START -----*/ // Add your own code @@ -433,6 +437,7 @@ void Lambda::read_attr_hardware(TANGO_UNUSED(vector &attr_list)) //-------------------------------------------------------- void Lambda::write_attr_hardware(TANGO_UNUSED(vector &attr_list)) { + DEBUG_STREAM << "Lambda::write_attr_hardware(vector &attr_list) entering... " << endl; /*----- PROTECTED REGION ID(Lambda::write_attr_hardware) ENABLED START -----*/ // Add your own code @@ -655,7 +660,7 @@ void Lambda::read_linearityCorrection(Tango::Attribute &attr) //-------------------------------------------------------- void Lambda::write_linearityCorrection(Tango::WAttribute &attr) { - INFO_STREAM << "Lambda::write_linearityCorrection(Tango::WAttribute &attr) entering... " << endl; + DEBUG_STREAM << "Lambda::write_linearityCorrection(Tango::WAttribute &attr) entering... " << endl; // Retrieve write value Tango::DevBoolean w_val; attr.get_write_value(w_val); @@ -720,7 +725,7 @@ void Lambda::read_saturationFlag(Tango::Attribute &attr) //-------------------------------------------------------- void Lambda::write_saturationFlag(Tango::WAttribute &attr) { - INFO_STREAM << "Lambda::write_saturationFlag(Tango::WAttribute &attr) entering... " << endl; + DEBUG_STREAM << "Lambda::write_saturationFlag(Tango::WAttribute &attr) entering... " << endl; // Retrieve write value Tango::DevBoolean w_val; attr.get_write_value(w_val); @@ -785,7 +790,7 @@ void Lambda::read_saturationThreshold(Tango::Attribute &attr) //-------------------------------------------------------- void Lambda::write_saturationThreshold(Tango::WAttribute &attr) { - INFO_STREAM << "Lambda::write_saturationThreshold(Tango::WAttribute &attr) entering... " << endl; + DEBUG_STREAM << "Lambda::write_saturationThreshold(Tango::WAttribute &attr) entering... " << endl; // Retrieve write value Tango::DevLong w_val; attr.get_write_value(w_val); @@ -870,7 +875,7 @@ void Lambda::read_lowerThreshold(Tango::Attribute &attr) //-------------------------------------------------------- void Lambda::write_lowerThreshold(Tango::WAttribute &attr) { - INFO_STREAM << "Lambda::write_lowerThreshold(Tango::WAttribute &attr) entering... " << endl; + DEBUG_STREAM << "Lambda::write_lowerThreshold(Tango::WAttribute &attr) entering... " << endl; // Retrieve write value Tango::DevDouble w_val; attr.get_write_value(w_val); @@ -938,7 +943,7 @@ void Lambda::read_upperThreshold(Tango::Attribute &attr) //-------------------------------------------------------- void Lambda::write_upperThreshold(Tango::WAttribute &attr) { - INFO_STREAM << "Lambda::write_upperThreshold(Tango::WAttribute &attr) entering... " << endl; + DEBUG_STREAM << "Lambda::write_upperThreshold(Tango::WAttribute &attr) entering... " << endl; // Retrieve write value Tango::DevDouble w_val; attr.get_write_value(w_val); @@ -960,6 +965,70 @@ void Lambda::write_upperThreshold(Tango::WAttribute &attr) /*----- PROTECTED REGION END -----*/ // Lambda::write_upperThreshold } +//-------------------------------------------------------- +/** + * Write attribute hwAccumulation related method + * Description: + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ +//-------------------------------------------------------- +void Lambda::write_hwAccumulation(Tango::WAttribute &attr) +{ + DEBUG_STREAM << "Lambda::write_hwAccumulation(Tango::WAttribute &attr) entering... " << endl; + // Retrieve write value + Tango::DevBoolean w_val; + attr.get_write_value(w_val); + /*----- PROTECTED REGION ID(Lambda::write_hwAccumulation) ENABLED START -----*/ + try + { + m_camera->setAccumulationMode(w_val); + //- Memorize the write value + yat4tango::PropertyHelper::set_memorized_attribute(this, "hwAccumulation", w_val); + } + catch(Tango::DevFailed& df) + { + manage_devfailed_exception(df, "Lambda::write_hwAccumulation"); + } + catch(Exception& e) + { + manage_lima_exception(e, "Lambda::write_hwAccumulation"); + } + /*----- PROTECTED REGION END -----*/ // Lambda::write_hwAccumulation +} +//-------------------------------------------------------- +/** + * Write attribute exposureAccuTime related method + * Description: + * + * Data type: Tango::DevDouble + * Attr type: Scalar + */ +//-------------------------------------------------------- +void Lambda::write_exposureAccuTime(Tango::WAttribute &attr) +{ + DEBUG_STREAM << "Lambda::write_exposureAccuTime(Tango::WAttribute &attr) entering... " << endl; + // Retrieve write value + Tango::DevDouble w_val; + attr.get_write_value(w_val); + /*----- PROTECTED REGION ID(Lambda::write_exposureAccuTime) ENABLED START -----*/ + try + { + m_camera->setExposureAccuTime(w_val); + //- Memorize the write value + yat4tango::PropertyHelper::set_memorized_attribute(this, "exposureAccuTime", w_val); + } + catch(Tango::DevFailed& df) + { + manage_devfailed_exception(df, "Lambda::write_exposureAccuTime"); + } + catch(Exception& e) + { + manage_lima_exception(e, "Lambda::write_exposureAccuTime"); + } + /*----- PROTECTED REGION END -----*/ // Lambda::write_exposureAccuTime +} //-------------------------------------------------------- /** diff --git a/specifics/Lambda/Lambda.h b/specifics/Lambda/Lambda.h index 68ea898..ca936b3 100755 --- a/specifics/Lambda/Lambda.h +++ b/specifics/Lambda/Lambda.h @@ -298,6 +298,24 @@ class Lambda : public TANGO_BASE_CLASS virtual void read_upperThreshold(Tango::Attribute &attr); virtual void write_upperThreshold(Tango::WAttribute &attr); virtual bool is_upperThreshold_allowed(Tango::AttReqType type); +/** + * Attribute hwAccumulation related methods + * Description: + * + * Data type: Tango::DevBoolean + * Attr type: Scalar + */ + virtual void write_hwAccumulation(Tango::WAttribute &attr); + virtual bool is_hwAccumulation_allowed(Tango::AttReqType type); +/** + * Attribute exposureAccuTime related methods + * Description: + * + * Data type: Tango::DevDouble + * Attr type: Scalar + */ + virtual void write_exposureAccuTime(Tango::WAttribute &attr); + virtual bool is_exposureAccuTime_allowed(Tango::AttReqType type); //-------------------------------------------------------- diff --git a/specifics/Lambda/Lambda.xmi b/specifics/Lambda/Lambda.xmi index 4117d5f..ae44b7f 100755 --- a/specifics/Lambda/Lambda.xmi +++ b/specifics/Lambda/Lambda.xmi @@ -1,7 +1,7 @@ - + @@ -167,6 +167,30 @@ FAULT RUNNING + + + + + + + + FAULT + RUNNING + FAULT + RUNNING + + + + + + + + + FAULT + RUNNING + FAULT + RUNNING + @@ -176,6 +200,6 @@ - + diff --git a/specifics/Lambda/LambdaClass.cpp b/specifics/Lambda/LambdaClass.cpp index d144652..a5109e9 100755 --- a/specifics/Lambda/LambdaClass.cpp +++ b/specifics/Lambda/LambdaClass.cpp @@ -663,6 +663,56 @@ void LambdaClass::attribute_factory(vector &att_list) // Not Memorized att_list.push_back(upperthreshold); + // Attribute : hwAccumulation + hwAccumulationAttrib *hwaccumulation = new hwAccumulationAttrib(); + Tango::UserDefaultAttrProp hwaccumulation_prop; + // description not set for hwAccumulation + // label not set for hwAccumulation + // unit not set for hwAccumulation + // standard_unit not set for hwAccumulation + // display_unit not set for hwAccumulation + // format not set for hwAccumulation + // max_value not set for hwAccumulation + // min_value not set for hwAccumulation + // max_alarm not set for hwAccumulation + // min_alarm not set for hwAccumulation + // max_warning not set for hwAccumulation + // min_warning not set for hwAccumulation + // delta_t not set for hwAccumulation + // delta_val not set for hwAccumulation + + hwaccumulation->set_default_properties(hwaccumulation_prop); + // Not Polled + hwaccumulation->set_disp_level(Tango::OPERATOR); + hwaccumulation->set_memorized(); + hwaccumulation->set_memorized_init(true); + att_list.push_back(hwaccumulation); + + // Attribute : exposureAccuTime + exposureAccuTimeAttrib *exposureaccutime = new exposureAccuTimeAttrib(); + Tango::UserDefaultAttrProp exposureaccutime_prop; + // description not set for exposureAccuTime + // label not set for exposureAccuTime + // unit not set for exposureAccuTime + // standard_unit not set for exposureAccuTime + // display_unit not set for exposureAccuTime + // format not set for exposureAccuTime + // max_value not set for exposureAccuTime + // min_value not set for exposureAccuTime + // max_alarm not set for exposureAccuTime + // min_alarm not set for exposureAccuTime + // max_warning not set for exposureAccuTime + // min_warning not set for exposureAccuTime + // delta_t not set for exposureAccuTime + // delta_val not set for exposureAccuTime + + exposureaccutime->set_default_properties(exposureaccutime_prop); + // Not Polled + exposureaccutime->set_disp_level(Tango::OPERATOR); + exposureaccutime->set_memorized(); + exposureaccutime->set_memorized_init(true); + att_list.push_back(exposureaccutime); + // Create a list of static attributes create_static_attribute_list(get_class_attr()->get_attr_list()); diff --git a/specifics/Lambda/LambdaClass.h b/specifics/Lambda/LambdaClass.h index c22578c..41066f1 100755 --- a/specifics/Lambda/LambdaClass.h +++ b/specifics/Lambda/LambdaClass.h @@ -225,6 +225,32 @@ class upperThresholdAttrib: public Tango::Attr {return (static_cast(dev))->is_upperThreshold_allowed(ty);} }; +// Attribute hwAccumulation class definition +class hwAccumulationAttrib: public Tango::Attr +{ +public: + hwAccumulationAttrib():Attr("hwAccumulation", + Tango::DEV_BOOLEAN, Tango::WRITE) {}; + ~hwAccumulationAttrib() {}; + virtual void write(Tango::DeviceImpl *dev,Tango::WAttribute &att) + {(static_cast(dev))->write_hwAccumulation(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast(dev))->is_hwAccumulation_allowed(ty);} +}; + +// Attribute exposureAccuTime class definition +class exposureAccuTimeAttrib: public Tango::Attr +{ +public: + exposureAccuTimeAttrib():Attr("exposureAccuTime", + Tango::DEV_DOUBLE, Tango::WRITE) {}; + ~exposureAccuTimeAttrib() {}; + virtual void write(Tango::DeviceImpl *dev,Tango::WAttribute &att) + {(static_cast(dev))->write_exposureAccuTime(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast(dev))->is_exposureAccuTime_allowed(ty);} +}; + /** * The LambdaClass singleton definition diff --git a/specifics/Lambda/LambdaStateMachine.cpp b/specifics/Lambda/LambdaStateMachine.cpp index 2215e57..b3b9ca5 100755 --- a/specifics/Lambda/LambdaStateMachine.cpp +++ b/specifics/Lambda/LambdaStateMachine.cpp @@ -60,7 +60,7 @@ bool Lambda::is_configFile_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if (get_state()==Tango::FAULT && !is_device_initialized()) + if (get_state()==Tango::FAULT) { /*----- PROTECTED REGION ID(Lambda::configFileStateAllowed_READ) ENABLED START -----*/ @@ -85,7 +85,7 @@ bool Lambda::is_distortionCorrection_allowed(TANGO_UNUSED(Tango::AttReqType type if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if (get_state()==Tango::FAULT && !is_device_initialized()) + if (get_state()==Tango::FAULT) { /*----- PROTECTED REGION ID(Lambda::distortionCorrectionStateAllowed_READ) ENABLED START -----*/ @@ -110,7 +110,7 @@ bool Lambda::is_libraryVersion_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if (get_state()==Tango::FAULT && !is_device_initialized()) + if (get_state()==Tango::FAULT) { /*----- PROTECTED REGION ID(Lambda::libraryVersionStateAllowed_READ) ENABLED START -----*/ @@ -135,7 +135,7 @@ bool Lambda::is_highVoltage_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::highVoltageStateAllowed_READ) ENABLED START -----*/ @@ -161,7 +161,7 @@ bool Lambda::is_humidity_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::humidityStateAllowed_READ) ENABLED START -----*/ @@ -187,7 +187,7 @@ bool Lambda::is_temperature_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::temperatureStateAllowed_READ) ENABLED START -----*/ @@ -212,7 +212,7 @@ bool Lambda::is_linearityCorrection_allowed(TANGO_UNUSED(Tango::AttReqType type) if ( type!=Tango::READ_REQ ) { // Compare device state with not allowed states for WRITE - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::linearityCorrectionStateAllowed_WRITE) ENABLED START -----*/ @@ -228,7 +228,7 @@ bool Lambda::is_linearityCorrection_allowed(TANGO_UNUSED(Tango::AttReqType type) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::linearityCorrectionStateAllowed_READ) ENABLED START -----*/ @@ -253,7 +253,7 @@ bool Lambda::is_saturationFlag_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type!=Tango::READ_REQ ) { // Compare device state with not allowed states for WRITE - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::saturationFlagStateAllowed_WRITE) ENABLED START -----*/ @@ -269,7 +269,7 @@ bool Lambda::is_saturationFlag_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::saturationFlagStateAllowed_READ) ENABLED START -----*/ @@ -294,7 +294,7 @@ bool Lambda::is_saturationThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type) if ( type!=Tango::READ_REQ ) { // Compare device state with not allowed states for WRITE - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::saturationThresholdStateAllowed_WRITE) ENABLED START -----*/ @@ -310,7 +310,7 @@ bool Lambda::is_saturationThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::saturationThresholdStateAllowed_READ) ENABLED START -----*/ @@ -336,7 +336,7 @@ bool Lambda::is_chargeSumming_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if (get_state()==Tango::FAULT && !is_device_initialized()) + if (get_state()==Tango::FAULT) { /*----- PROTECTED REGION ID(Lambda::chargeSummingStateAllowed_READ) ENABLED START -----*/ @@ -360,7 +360,7 @@ bool Lambda::is_lowerThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type!=Tango::READ_REQ ) { // Compare device state with not allowed states for WRITE - if ((get_state()==Tango::FAULT && !is_device_initialized()) || + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::lowerThresholdStateAllowed_WRITE) ENABLED START -----*/ @@ -376,7 +376,7 @@ bool Lambda::is_lowerThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized()) || + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::lowerThresholdStateAllowed_READ) ENABLED START -----*/ @@ -401,7 +401,7 @@ bool Lambda::is_upperThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type!=Tango::READ_REQ ) { // Compare device state with not allowed states for WRITE - if ((get_state()==Tango::FAULT && !is_device_initialized()) || + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::upperThresholdStateAllowed_WRITE) ENABLED START -----*/ @@ -417,7 +417,7 @@ bool Lambda::is_upperThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized()) || + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::upperThresholdStateAllowed_READ) ENABLED START -----*/ @@ -430,6 +430,58 @@ bool Lambda::is_upperThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type)) return true; } +//-------------------------------------------------------- +/** + * Method : Lambda::is_hwAccumulation_allowed() + * Description : Execution allowed for hwAccumulation attribute + */ +//-------------------------------------------------------- +bool Lambda::is_hwAccumulation_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + // Check access type. + if ( type!=Tango::READ_REQ ) + { + // Compare device state with not allowed states for WRITE + if (get_state()==Tango::FAULT || + get_state()==Tango::RUNNING) + { + /*----- PROTECTED REGION ID(Lambda::hwAccumulationStateAllowed_WRITE) ENABLED START -----*/ + + /*----- PROTECTED REGION END -----*/ // Lambda::hwAccumulationStateAllowed_WRITE + return false; + } + return true; + } + + return true; +} + +//-------------------------------------------------------- +/** + * Method : Lambda::is_exposureAccuTime_allowed() + * Description : Execution allowed for exposureAccuTime attribute + */ +//-------------------------------------------------------- +bool Lambda::is_exposureAccuTime_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + // Check access type. + if ( type!=Tango::READ_REQ ) + { + // Compare device state with not allowed states for WRITE + if (get_state()==Tango::FAULT || + get_state()==Tango::RUNNING) + { + /*----- PROTECTED REGION ID(Lambda::exposureAccuTimeStateAllowed_WRITE) ENABLED START -----*/ + + /*----- PROTECTED REGION END -----*/ // Lambda::exposureAccuTimeStateAllowed_WRITE + return false; + } + return true; + } + + return true; +} + //================================================= // Commands Allowed Methods From 82811fa1e8612f0b63def37b24b8a2a5fcb596eb Mon Sep 17 00:00:00 2001 From: emfoumoune Date: Thu, 4 Apr 2024 14:29:33 +0200 Subject: [PATCH 2/3] see #ICATHALES-586 : Ajout mode d'acquisition d'images 1 et 6 bits --- specifics/Lambda/Lambda.cpp | 84 +++++++++++++++++++++++-- specifics/Lambda/Lambda.h | 19 ++++++ specifics/Lambda/Lambda.xmi | 14 ++++- specifics/Lambda/LambdaClass.cpp | 33 ++++++++++ specifics/Lambda/LambdaClass.h | 17 +++++ specifics/Lambda/LambdaStateMachine.cpp | 54 +++++++++++----- 6 files changed, 198 insertions(+), 23 deletions(-) diff --git a/specifics/Lambda/Lambda.cpp b/specifics/Lambda/Lambda.cpp index dcece7c..029f4c4 100755 --- a/specifics/Lambda/Lambda.cpp +++ b/specifics/Lambda/Lambda.cpp @@ -84,6 +84,7 @@ namespace Lambda_ns // chargeSumming | Tango::DevBoolean Scalar // lowerThreshold | Tango::DevDouble Scalar // upperThreshold | Tango::DevDouble Scalar +// hwAcquisitionMode | Tango::DevEnum Scalar //================================================================ namespace Lambda_ns @@ -154,6 +155,7 @@ void Lambda::delete_device() m_is_device_initialized = false; /*----- PROTECTED REGION END -----*/ // Lambda::delete_device + delete[] attr_hwAcquisitionMode_read; } //-------------------------------------------------------- @@ -175,6 +177,7 @@ void Lambda::init_device() // Get the device properties from database get_device_property(); + attr_hwAcquisitionMode_read = new hwAcquisitionModeEnum[1]; /*----- PROTECTED REGION ID(Lambda::init_device) ENABLED START -----*/ // Initialize device CREATE_SCALAR_ATTRIBUTE(attr_distortionCorrection_read); @@ -366,6 +369,7 @@ void Lambda::get_device_property() //-------------------------------------------------------- void Lambda::always_executed_hook() { + DEBUG_STREAM << "Lambda::always_executed_hook() " << device_name << endl; /*----- PROTECTED REGION ID(Lambda::always_executed_hook) ENABLED START -----*/ // code always executed before all requests @@ -419,6 +423,7 @@ void Lambda::always_executed_hook() //-------------------------------------------------------- void Lambda::read_attr_hardware(TANGO_UNUSED(vector &attr_list)) { + DEBUG_STREAM << "Lambda::read_attr_hardware(vector &attr_list) entering... " << endl; /*----- PROTECTED REGION ID(Lambda::read_attr_hardware) ENABLED START -----*/ // Add your own code @@ -433,6 +438,7 @@ void Lambda::read_attr_hardware(TANGO_UNUSED(vector &attr_list)) //-------------------------------------------------------- void Lambda::write_attr_hardware(TANGO_UNUSED(vector &attr_list)) { + DEBUG_STREAM << "Lambda::write_attr_hardware(vector &attr_list) entering... " << endl; /*----- PROTECTED REGION ID(Lambda::write_attr_hardware) ENABLED START -----*/ // Add your own code @@ -655,7 +661,7 @@ void Lambda::read_linearityCorrection(Tango::Attribute &attr) //-------------------------------------------------------- void Lambda::write_linearityCorrection(Tango::WAttribute &attr) { - INFO_STREAM << "Lambda::write_linearityCorrection(Tango::WAttribute &attr) entering... " << endl; + DEBUG_STREAM << "Lambda::write_linearityCorrection(Tango::WAttribute &attr) entering... " << endl; // Retrieve write value Tango::DevBoolean w_val; attr.get_write_value(w_val); @@ -720,7 +726,7 @@ void Lambda::read_saturationFlag(Tango::Attribute &attr) //-------------------------------------------------------- void Lambda::write_saturationFlag(Tango::WAttribute &attr) { - INFO_STREAM << "Lambda::write_saturationFlag(Tango::WAttribute &attr) entering... " << endl; + DEBUG_STREAM << "Lambda::write_saturationFlag(Tango::WAttribute &attr) entering... " << endl; // Retrieve write value Tango::DevBoolean w_val; attr.get_write_value(w_val); @@ -785,7 +791,7 @@ void Lambda::read_saturationThreshold(Tango::Attribute &attr) //-------------------------------------------------------- void Lambda::write_saturationThreshold(Tango::WAttribute &attr) { - INFO_STREAM << "Lambda::write_saturationThreshold(Tango::WAttribute &attr) entering... " << endl; + DEBUG_STREAM << "Lambda::write_saturationThreshold(Tango::WAttribute &attr) entering... " << endl; // Retrieve write value Tango::DevLong w_val; attr.get_write_value(w_val); @@ -870,7 +876,7 @@ void Lambda::read_lowerThreshold(Tango::Attribute &attr) //-------------------------------------------------------- void Lambda::write_lowerThreshold(Tango::WAttribute &attr) { - INFO_STREAM << "Lambda::write_lowerThreshold(Tango::WAttribute &attr) entering... " << endl; + DEBUG_STREAM << "Lambda::write_lowerThreshold(Tango::WAttribute &attr) entering... " << endl; // Retrieve write value Tango::DevDouble w_val; attr.get_write_value(w_val); @@ -938,7 +944,7 @@ void Lambda::read_upperThreshold(Tango::Attribute &attr) //-------------------------------------------------------- void Lambda::write_upperThreshold(Tango::WAttribute &attr) { - INFO_STREAM << "Lambda::write_upperThreshold(Tango::WAttribute &attr) entering... " << endl; + DEBUG_STREAM << "Lambda::write_upperThreshold(Tango::WAttribute &attr) entering... " << endl; // Retrieve write value Tango::DevDouble w_val; attr.get_write_value(w_val); @@ -960,6 +966,74 @@ void Lambda::write_upperThreshold(Tango::WAttribute &attr) /*----- PROTECTED REGION END -----*/ // Lambda::write_upperThreshold } +//-------------------------------------------------------- +/** + * Read attribute hwAcquisitionMode related method + * Description: + * + * Data type: Tango::DevEnum (hwAcquisitionModeEnum) + * Attr type: Scalar + */ +//-------------------------------------------------------- +void Lambda::read_hwAcquisitionMode(Tango::Attribute &attr) +{ + DEBUG_STREAM << "Lambda::read_hwAcquisitionMode(Tango::Attribute &attr) entering... " << endl; + /*----- PROTECTED REGION ID(Lambda::read_hwAcquisitionMode) ENABLED START -----*/ + // Set the attribute value + int acqMode = -1; + m_camera->getAcquisitionMode(acqMode); + switch(acqMode) { + case 1: *attr_hwAcquisitionMode_read = Lambda_ns::_1_BIT; break; + case 6: *attr_hwAcquisitionMode_read = Lambda_ns::_6_BITS; break; + case 12: *attr_hwAcquisitionMode_read = Lambda_ns::_12_BITS; break; + case 24: *attr_hwAcquisitionMode_read = Lambda_ns::_24_BITS; break; + default: break; + } + attr.set_value(attr_hwAcquisitionMode_read); + + /*----- PROTECTED REGION END -----*/ // Lambda::read_hwAcquisitionMode +} +//-------------------------------------------------------- +/** + * Write attribute hwAcquisitionMode related method + * Description: + * + * Data type: Tango::DevEnum (hwAcquisitionModeEnum) + * Attr type: Scalar + */ +//-------------------------------------------------------- +void Lambda::write_hwAcquisitionMode(Tango::WAttribute &attr) +{ + DEBUG_STREAM << "Lambda::write_hwAcquisitionMode(Tango::WAttribute &attr) entering... " << endl; + // Retrieve write value + hwAcquisitionModeEnum w_val; + attr.get_write_value(w_val); + /*----- PROTECTED REGION ID(Lambda::write_hwAcquisitionMode) ENABLED START -----*/ + try + { + int acqMode = 24; + switch(w_val) { + case Lambda_ns::_1_BIT: acqMode = 1; break; + case Lambda_ns::_6_BITS: acqMode = 6; break; + case Lambda_ns::_12_BITS: acqMode = 12; break; + case Lambda_ns::_24_BITS: acqMode = 24; break; + default: break; + } + m_camera->setAcquisitionMode(acqMode); + //- Memorize the write value + yat4tango::PropertyHelper::set_memorized_attribute(this, "hwAcquisitionMode", w_val); + } + catch (Tango::DevFailed& df) + { + manage_devfailed_exception(df, "write_hwAcquisitionMode"); + } + catch (lima::Exception& le) + { + manage_lima_exception(le, "write_hwAcquisitionMode"); + } + + /*----- PROTECTED REGION END -----*/ // Lambda::write_hwAcquisitionMode +} //-------------------------------------------------------- /** diff --git a/specifics/Lambda/Lambda.h b/specifics/Lambda/Lambda.h index 68ea898..a4f7bba 100755 --- a/specifics/Lambda/Lambda.h +++ b/specifics/Lambda/Lambda.h @@ -64,6 +64,14 @@ namespace Lambda_ns { +enum _hwAcquisitionModeEnum { + _24_BITS, + _12_BITS, + _6_BITS, + _1_BIT, +} ; +typedef _hwAcquisitionModeEnum hwAcquisitionModeEnum; + /*----- PROTECTED REGION ID(Lambda::Additional Class Declarations) ENABLED START -----*/ // Additional Class Declarations @@ -106,6 +114,7 @@ class Lambda : public TANGO_BASE_CLASS Tango::DevBoolean *attr_chargeSumming_read; Tango::DevDouble *attr_lowerThreshold_read; Tango::DevDouble *attr_upperThreshold_read; + hwAcquisitionModeEnum *attr_hwAcquisitionMode_read; // Constructors and destructors public: @@ -298,6 +307,16 @@ class Lambda : public TANGO_BASE_CLASS virtual void read_upperThreshold(Tango::Attribute &attr); virtual void write_upperThreshold(Tango::WAttribute &attr); virtual bool is_upperThreshold_allowed(Tango::AttReqType type); +/** + * Attribute hwAcquisitionMode related methods + * Description: + * + * Data type: Tango::DevEnum + * Attr type: Scalar + */ + virtual void read_hwAcquisitionMode(Tango::Attribute &attr); + virtual void write_hwAcquisitionMode(Tango::WAttribute &attr); + virtual bool is_hwAcquisitionMode_allowed(Tango::AttReqType type); //-------------------------------------------------------- diff --git a/specifics/Lambda/Lambda.xmi b/specifics/Lambda/Lambda.xmi index 4117d5f..6f05911 100755 --- a/specifics/Lambda/Lambda.xmi +++ b/specifics/Lambda/Lambda.xmi @@ -1,7 +1,7 @@ - + @@ -167,6 +167,18 @@ FAULT RUNNING + + + + + + + + 24 Bits + 12 Bits + 6 Bits + 1 Bit + diff --git a/specifics/Lambda/LambdaClass.cpp b/specifics/Lambda/LambdaClass.cpp index d144652..8c1585e 100755 --- a/specifics/Lambda/LambdaClass.cpp +++ b/specifics/Lambda/LambdaClass.cpp @@ -663,6 +663,39 @@ void LambdaClass::attribute_factory(vector &att_list) // Not Memorized att_list.push_back(upperthreshold); + // Attribute : hwAcquisitionMode + hwAcquisitionModeAttrib *hwacquisitionmode = new hwAcquisitionModeAttrib(); + Tango::UserDefaultAttrProp hwacquisitionmode_prop; + // description not set for hwAcquisitionMode + // label not set for hwAcquisitionMode + // unit not set for hwAcquisitionMode + // standard_unit not set for hwAcquisitionMode + // display_unit not set for hwAcquisitionMode + // format not set for hwAcquisitionMode + // max_value not set for hwAcquisitionMode + // min_value not set for hwAcquisitionMode + // max_alarm not set for hwAcquisitionMode + // min_alarm not set for hwAcquisitionMode + // max_warning not set for hwAcquisitionMode + // min_warning not set for hwAcquisitionMode + // delta_t not set for hwAcquisitionMode + // delta_val not set for hwAcquisitionMode + + { + vector labels; + labels.push_back("24 Bits"); + labels.push_back("12 Bits"); + labels.push_back("6 Bits"); + labels.push_back("1 Bit"); + hwacquisitionmode_prop.set_enum_labels(labels); + } + hwacquisitionmode->set_default_properties(hwacquisitionmode_prop); + // Not Polled + hwacquisitionmode->set_disp_level(Tango::OPERATOR); + hwacquisitionmode->set_memorized(); + hwacquisitionmode->set_memorized_init(true); + att_list.push_back(hwacquisitionmode); + // Create a list of static attributes create_static_attribute_list(get_class_attr()->get_attr_list()); diff --git a/specifics/Lambda/LambdaClass.h b/specifics/Lambda/LambdaClass.h index c22578c..f5f0e4d 100755 --- a/specifics/Lambda/LambdaClass.h +++ b/specifics/Lambda/LambdaClass.h @@ -225,6 +225,23 @@ class upperThresholdAttrib: public Tango::Attr {return (static_cast(dev))->is_upperThreshold_allowed(ty);} }; +// Attribute hwAcquisitionMode class definition +class hwAcquisitionModeAttrib: public Tango::Attr +{ +public: + hwAcquisitionModeAttrib():Attr("hwAcquisitionMode", + Tango::DEV_ENUM, Tango::READ_WRITE) {}; + ~hwAcquisitionModeAttrib() {}; + virtual void read(Tango::DeviceImpl *dev,Tango::Attribute &att) + {(static_cast(dev))->read_hwAcquisitionMode(att);} + virtual void write(Tango::DeviceImpl *dev,Tango::WAttribute &att) + {(static_cast(dev))->write_hwAcquisitionMode(att);} + virtual bool is_allowed(Tango::DeviceImpl *dev,Tango::AttReqType ty) + {return (static_cast(dev))->is_hwAcquisitionMode_allowed(ty);} + virtual bool same_type(const type_info &in_type) {return typeid(hwAcquisitionModeEnum) == in_type;} + virtual string get_enum_type() {return string("hwAcquisitionModeEnum");} +}; + /** * The LambdaClass singleton definition diff --git a/specifics/Lambda/LambdaStateMachine.cpp b/specifics/Lambda/LambdaStateMachine.cpp index 2215e57..328b1e7 100755 --- a/specifics/Lambda/LambdaStateMachine.cpp +++ b/specifics/Lambda/LambdaStateMachine.cpp @@ -60,7 +60,7 @@ bool Lambda::is_configFile_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if (get_state()==Tango::FAULT && !is_device_initialized()) + if (get_state()==Tango::FAULT) { /*----- PROTECTED REGION ID(Lambda::configFileStateAllowed_READ) ENABLED START -----*/ @@ -85,7 +85,7 @@ bool Lambda::is_distortionCorrection_allowed(TANGO_UNUSED(Tango::AttReqType type if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if (get_state()==Tango::FAULT && !is_device_initialized()) + if (get_state()==Tango::FAULT) { /*----- PROTECTED REGION ID(Lambda::distortionCorrectionStateAllowed_READ) ENABLED START -----*/ @@ -110,7 +110,7 @@ bool Lambda::is_libraryVersion_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if (get_state()==Tango::FAULT && !is_device_initialized()) + if (get_state()==Tango::FAULT) { /*----- PROTECTED REGION ID(Lambda::libraryVersionStateAllowed_READ) ENABLED START -----*/ @@ -135,7 +135,7 @@ bool Lambda::is_highVoltage_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::highVoltageStateAllowed_READ) ENABLED START -----*/ @@ -161,7 +161,7 @@ bool Lambda::is_humidity_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::humidityStateAllowed_READ) ENABLED START -----*/ @@ -187,7 +187,7 @@ bool Lambda::is_temperature_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::temperatureStateAllowed_READ) ENABLED START -----*/ @@ -212,7 +212,7 @@ bool Lambda::is_linearityCorrection_allowed(TANGO_UNUSED(Tango::AttReqType type) if ( type!=Tango::READ_REQ ) { // Compare device state with not allowed states for WRITE - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::linearityCorrectionStateAllowed_WRITE) ENABLED START -----*/ @@ -228,7 +228,7 @@ bool Lambda::is_linearityCorrection_allowed(TANGO_UNUSED(Tango::AttReqType type) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::linearityCorrectionStateAllowed_READ) ENABLED START -----*/ @@ -253,7 +253,7 @@ bool Lambda::is_saturationFlag_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type!=Tango::READ_REQ ) { // Compare device state with not allowed states for WRITE - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::saturationFlagStateAllowed_WRITE) ENABLED START -----*/ @@ -269,7 +269,7 @@ bool Lambda::is_saturationFlag_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::saturationFlagStateAllowed_READ) ENABLED START -----*/ @@ -294,7 +294,7 @@ bool Lambda::is_saturationThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type) if ( type!=Tango::READ_REQ ) { // Compare device state with not allowed states for WRITE - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::saturationThresholdStateAllowed_WRITE) ENABLED START -----*/ @@ -310,7 +310,7 @@ bool Lambda::is_saturationThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized())|| + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::saturationThresholdStateAllowed_READ) ENABLED START -----*/ @@ -336,7 +336,7 @@ bool Lambda::is_chargeSumming_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if (get_state()==Tango::FAULT && !is_device_initialized()) + if (get_state()==Tango::FAULT) { /*----- PROTECTED REGION ID(Lambda::chargeSummingStateAllowed_READ) ENABLED START -----*/ @@ -360,7 +360,7 @@ bool Lambda::is_lowerThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type!=Tango::READ_REQ ) { // Compare device state with not allowed states for WRITE - if ((get_state()==Tango::FAULT && !is_device_initialized()) || + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::lowerThresholdStateAllowed_WRITE) ENABLED START -----*/ @@ -376,7 +376,7 @@ bool Lambda::is_lowerThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized()) || + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::lowerThresholdStateAllowed_READ) ENABLED START -----*/ @@ -401,7 +401,7 @@ bool Lambda::is_upperThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type!=Tango::READ_REQ ) { // Compare device state with not allowed states for WRITE - if ((get_state()==Tango::FAULT && !is_device_initialized()) || + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::upperThresholdStateAllowed_WRITE) ENABLED START -----*/ @@ -417,7 +417,7 @@ bool Lambda::is_upperThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type)) if ( type==Tango::READ_REQ ) { // Compare device state with not allowed states for READ - if ((get_state()==Tango::FAULT && !is_device_initialized()) || + if (get_state()==Tango::FAULT || get_state()==Tango::RUNNING) { /*----- PROTECTED REGION ID(Lambda::upperThresholdStateAllowed_READ) ENABLED START -----*/ @@ -430,6 +430,26 @@ bool Lambda::is_upperThreshold_allowed(TANGO_UNUSED(Tango::AttReqType type)) return true; } +//-------------------------------------------------------- +/** + * Method : Lambda::is_hwAcquisitionMode_allowed() + * Description : Execution allowed for hwAcquisitionMode attribute + */ +//-------------------------------------------------------- +bool Lambda::is_hwAcquisitionMode_allowed(TANGO_UNUSED(Tango::AttReqType type)) +{ + // Not any excluded states for hwAcquisitionMode attribute in Write access. + /*----- PROTECTED REGION ID(Lambda::hwAcquisitionModeStateAllowed_WRITE) ENABLED START -----*/ + + /*----- PROTECTED REGION END -----*/ // Lambda::hwAcquisitionModeStateAllowed_WRITE + + // Not any excluded states for hwAcquisitionMode attribute in read access. + /*----- PROTECTED REGION ID(Lambda::hwAcquisitionModeStateAllowed_READ) ENABLED START -----*/ + + /*----- PROTECTED REGION END -----*/ // Lambda::hwAcquisitionModeStateAllowed_READ + return true; +} + //================================================= // Commands Allowed Methods From 1f737e581f2c21b44292e07794dd3df44d8cd97e Mon Sep 17 00:00:00 2001 From: emfoumoune Date: Fri, 5 Apr 2024 14:53:16 +0200 Subject: [PATCH 3/3] see #ICATHALES-586 : Ajout mode d'acquisition d'images 1 et 6 bits - maj detector --- src/LimaDetector.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/LimaDetector.cpp b/src/LimaDetector.cpp index 201eae9..d6aa25b 100755 --- a/src/LimaDetector.cpp +++ b/src/LimaDetector.cpp @@ -4350,14 +4350,22 @@ void LimaDetector::configure_image_type(void) { HwDetInfoCtrlObj *hw_det_info; m_hw->getHwCtrlObj(hw_det_info); - if(detectorPixelDepth == "2") + if(detectorPixelDepth == "1") + { + hw_det_info->setCurrImageType(Bpp1); + } + else if(detectorPixelDepth == "2") { hw_det_info->setCurrImageType(Bpp2); } else if(detectorPixelDepth == "4") { hw_det_info->setCurrImageType(Bpp4); - } + } + else if(detectorPixelDepth == "6") + { + hw_det_info->setCurrImageType(Bpp6); + } else if(detectorPixelDepth == "8") { hw_det_info->setCurrImageType(Bpp8); @@ -4818,7 +4826,11 @@ void LimaDetector::add_image_dynamic_attribute(const std::string& attr_name) dai.tai.max_dim_x = 100000; //- arbitrary big value dai.tai.max_dim_y = 100000; //- arbitrary big value - if(detectorPixelDepth == "8" || detectorPixelDepth == "4" || detectorPixelDepth == "2") + if(detectorPixelDepth == "1" || detectorPixelDepth == "6") + { + dai.tai.data_type = Tango::DEV_UCHAR; + } + else if(detectorPixelDepth == "8" || detectorPixelDepth == "4" || detectorPixelDepth == "2") { dai.tai.data_type = Tango::DEV_UCHAR; }