diff --git a/camerad/CMakeLists.txt b/camerad/CMakeLists.txt index c17b7b4..e8642be 100644 --- a/camerad/CMakeLists.txt +++ b/camerad/CMakeLists.txt @@ -97,6 +97,7 @@ endif() # ---------------------------------------------------------------------------- list (APPEND INTERFACE_SOURCES ${CAMERAD_DIR}/camera_interface.cpp + ${CAMERAD_DIR}/deinterlace_modes.cpp ) add_library(${INTERFACE_TARGET} ${INTERFACE_SOURCES}) target_link_libraries(${INTERFACE_TARGET} diff --git a/camerad/archon_controller.cpp b/camerad/archon_controller.cpp index bc2f2b3..22efe3c 100644 --- a/camerad/archon_controller.cpp +++ b/camerad/archon_controller.cpp @@ -11,10 +11,14 @@ namespace Camera { Controller::Controller() : - interface(nullptr), is_connected(false), is_busy(false), is_firmwareloaded(false) + interface(nullptr), framebuf(nullptr), framebuf_bytes(0), is_connected(false), is_busy(false), is_firmwareloaded(false) { } + Controller::~Controller() { + delete[] framebuf; + } + /***** Camera::Controller::set_interface ************************************/ /** * @brief initialize pointer to parent interface @@ -28,6 +32,32 @@ namespace Camera { /***** Camera::Controller::set_interface ************************************/ + /***** Camera::Controller::allocate_framebuf ********************************/ + /** + * @brief allocate memory for frame buffer + * @param[in] reqsz size in bytes of Archon frame buffer + * @return ERROR | NO_ERROR + * + */ + long Controller::allocate_framebuf(uint32_t reqsz) { + const std::string function("Camera::Controller::allocate_framebuf"); + try { + if (reqsz>0) { + delete[] this->framebuf; + this->framebuf = new char[reqsz]; + this->framebuf_bytes = reqsz; + } + else throw std::runtime_error("invalid requested size"); + } + catch(const std::exception &e) { + logwrite(function, "ERROR allocating framebuf: "+std::string(e.what())); + this->framebuf_bytes = 0; + } + return (this->framebuf_bytes>0 ? NO_ERROR : ERROR); + } + /***** Camera::Controller::allocate_framebuf ********************************/ + + /***** Camera::Controller::write_config_key *********************************/ /** * @brief write a configuration KEY=VALUE pair to the Archon controller diff --git a/camerad/archon_controller.h b/camerad/archon_controller.h index 43d373e..64985a7 100644 --- a/camerad/archon_controller.h +++ b/camerad/archon_controller.h @@ -34,13 +34,16 @@ namespace Camera { public: Controller(); - ~Controller() = default; + ~Controller(); private: ArchonInterface* interface; //!< pointer back to the parent interface void set_interface(ArchonInterface* _interface); + char* framebuf; //!< local frame buffer read from Archon + uint32_t framebuf_bytes; //!< size of framebuf in bytes + bool is_connected; //!< true if controller connected bool is_busy; bool is_firmwareloaded; @@ -58,6 +61,7 @@ namespace Camera { Network::TcpSocket sock; network_details archon_network_details; + long allocate_framebuf(uint32_t reqsz); long write_config_key(const char* key, const char* newvalue, bool &changed); long write_config_key(const char* key, int newvalue, bool &changed); diff --git a/camerad/archon_exposure_modes.cpp b/camerad/archon_exposure_modes.cpp index da1d4f9..f1becfa 100644 --- a/camerad/archon_exposure_modes.cpp +++ b/camerad/archon_exposure_modes.cpp @@ -5,6 +5,7 @@ */ #include "archon_exposure_modes.h" +#include "archon_interface.h" namespace Camera { @@ -30,6 +31,8 @@ namespace Camera { const std::string function("Camera::Expose_RXRV::expose"); logwrite(function, "hi"); + this->interface->allocate_framebuf(100); + // read first frame pair // process (deinterlace) first frame pair @@ -37,6 +40,19 @@ namespace Camera { // loop: // subsequent frame pairs, read, deinterlace, write + // create an appropriate deinterlacer object + // + try { this->deinterlacer = make_deinterlacer("rxrv"); + } + catch(const std::exception &e) { + logwrite(function, "ERROR: "+std::string(e.what())); + return ERROR; + } + + // call a deinterlacer function + // + this->deinterlacer->test(); + return NO_ERROR; } /***** Camera::Expose_RXRV *************************************************/ diff --git a/camerad/archon_exposure_modes.h b/camerad/archon_exposure_modes.h index 21b1d17..1f58f71 100644 --- a/camerad/archon_exposure_modes.h +++ b/camerad/archon_exposure_modes.h @@ -1,6 +1,6 @@ /** * @file archon_exposure_modes.h - * @brief defines Archon-specific exposure mode classes + * @brief delcares Archon-specific exposure mode classes * @details Declares classes that implement exposure modes supported by * Archon. These classes override virtual functions in the * ExposureMode base class to provide mode-specific behavior. @@ -13,20 +13,22 @@ namespace Camera { - class Expose_Raw : public ExposureMode { - using ExposureMode::ExposureMode; + class ArchonInterface; // forward declaration + + class Expose_Raw : public ExposureMode { + using ExposureMode::ExposureMode; long expose() override; }; - class Expose_CCD : public ExposureMode { - using ExposureMode::ExposureMode; + class Expose_CCD : public ExposureMode { + using ExposureMode::ExposureMode; long expose() override; }; - class Expose_RXRV : public ExposureMode { - using ExposureMode::ExposureMode; + class Expose_RXRV : public ExposureMode { + using ExposureMode::ExposureMode; long expose() override; }; diff --git a/camerad/archon_interface.h b/camerad/archon_interface.h index cb83a01..11a249b 100644 --- a/camerad/archon_interface.h +++ b/camerad/archon_interface.h @@ -78,6 +78,7 @@ namespace Camera { // These functions are specific to the Archon Interface and are not // found in the base class. // + long allocate_framebuf(uint32_t reqsz) { return controller.allocate_framebuf(reqsz); } long load_timing(std::string cmd, std::string &reply); private: diff --git a/camerad/astrocam_exposure_modes.h b/camerad/astrocam_exposure_modes.h index 4806914..9466ac5 100644 --- a/camerad/astrocam_exposure_modes.h +++ b/camerad/astrocam_exposure_modes.h @@ -1,6 +1,6 @@ /** * @file astrocam_exposure_modes.h - * @brief defines AstroCam-specific exposure mode classes + * @brief declares AstroCam-specific exposure mode classes * @details Declares classes that implement exposure modes supported by * AstroCam. These classes override virtual functions in the * ExposureMode base class to provide mode-specific behavior. @@ -13,8 +13,10 @@ namespace Camera { - class Expose_CCD : public ExposureMode { - using ExposureMode::ExposureMode; + class AstroCamInterface; // forward declaration + + class Expose_CCD : public ExposureMode { + using ExposureMode::ExposureMode; long expose() override; }; diff --git a/camerad/camera_interface.h b/camerad/camera_interface.h index dbc685b..6ff4d0a 100644 --- a/camerad/camera_interface.h +++ b/camerad/camera_interface.h @@ -22,7 +22,7 @@ namespace Camera { Camera::Information camera_info; Common::FitsKeys systemkeys; - std::unique_ptr exposure_mode; + std::unique_ptr exposure_mode; public: virtual ~Interface() = default; diff --git a/camerad/deinterlace_modes.cpp b/camerad/deinterlace_modes.cpp new file mode 100644 index 0000000..be3b6d6 --- /dev/null +++ b/camerad/deinterlace_modes.cpp @@ -0,0 +1,62 @@ +/** + * @file deinterlace_modes.cpp + * @brief implementation of deinterlacing factory and specializations + * + */ + +#include "deinterlace_modes.h" + +namespace Camera { + + /***** Camera::make_deinterlacer ********************************************/ + /** + * @brief factory function creates appropriate deinterlacer object + * @param[in] mode + * @return unique_ptr to DeInterlaceBase derived object + * @throws std::invalid_argument + * + */ + std::unique_ptr make_deinterlacer(const std::string &mode) { + if (mode=="none") { + logwrite("Camera::make_deinterlacer", "factory made deinterlacer for \'none\'"); + return std::make_unique>(); + } + else + if (mode=="rxrv") { + logwrite("Camera::make_deinterlacer", "factory made deinterlacer for \'rxrv\'"); + return std::make_unique>(); + } + else { + logwrite("Camera::make_deinterlacer", "ERROR factory got unknown mode \'"+mode+"\'"); + throw std::invalid_argument("unknown mode "+mode); + } + } + /***** Camera::make_deinterlacer ********************************************/ + + + /***** Camera::DeInterlaceMode::test ****************************************/ + /** + * @brief specialization for ModeNone + * + */ + template <> + void DeInterlaceMode::test() { + const std::string function("Camera::DeInterlaceMode::ModeNone::test"); + logwrite(function, "here"); + } + /***** Camera::DeInterlaceMode::test ****************************************/ + + + /***** Camera::DeInterlaceMode::test ****************************************/ + /** + * @brief specialization for ModeRXRV + * + */ + template <> + void DeInterlaceMode::test() { + const std::string function("Camera::DeInterlaceMode::ModeRXRV::test"); + logwrite(function, "here"); + } + /***** Camera::DeInterlaceMode::test ****************************************/ + +} diff --git a/camerad/deinterlace_modes.h b/camerad/deinterlace_modes.h new file mode 100644 index 0000000..8df77ba --- /dev/null +++ b/camerad/deinterlace_modes.h @@ -0,0 +1,50 @@ +/** + * @file deinterlace_modes.h + * @brief template-based implementation for deinterlacing + * + */ + +#pragma once + +#include "common.h" + +namespace Camera { + + /** + * @brief tags for constructing appropriate deinterlacer object + * @details DeInterlaceMode tags are used to distinguish the type + * of deinterlacer the factory function will make. Empty + * structs take zero space. + */ + struct ModeNone {}; + struct ModeRXRV {}; + struct ModeFowler {}; + struct ModeCCD {}; + struct ModeUTR {}; + + /** + * @brief DeInterlace abstract base class + * @details Actual deinterlacing implementations are defined in + * template specifications. + */ + class DeInterlaceBase { + public: + virtual ~DeInterlaceBase() = default; + virtual void test() = 0; + }; + + /** + * @brief template for mode-specific deinterlacing + * @details Specialize this class for each ModeTag to implement the + * corresponding deinterlacer. + */ + template + class DeInterlaceMode : public DeInterlaceBase { + public: + void test() override; + }; + + // factory function creates appropriate deinterlacer object + std::unique_ptr make_deinterlacer(const std::string &mode); + +} diff --git a/camerad/exposure_modes.h b/camerad/exposure_modes.h index 74cd416..32fb5bb 100644 --- a/camerad/exposure_modes.h +++ b/camerad/exposure_modes.h @@ -1,34 +1,58 @@ /** * @file exposure_modes.h - * @brief defines supported camera exposure modes - * @details Contains derived classes for each exposure mode, selected by - * Camera::Interface::select_expose_mode(). These classes inherit - * from Camera::ExposureMode and override the expose function with - * mode-specific behavior. There can be an implementation for each - * controller. + * @brief defines camera exposure mode infrastructure + * @details Declares abstract base classes for camera exposure modes. + * Each derived exposure mode implements the specific exposure + * logic for a given Interface type. The appropriate mode is + * selected by Camera::Interface::select_expose_mode(). * */ #pragma once #include "common.h" #include "camera_information.h" +#include "deinterlace_modes.h" namespace Camera { class Interface; // forward declaration for ExposureMode class + /***** Camera::ExposureModeBase *********************************************/ + /** + * @brief non-templated base class for polymorphic exposure mode access + * @details Provides a common interface for exposure mode implementations, + * used to hold ExposureMode instances via polymorphic pointers. + * + */ + class ExposureModeBase { + public: + virtual ~ExposureModeBase() = default; + virtual long expose() = 0; + }; + /***** Camera::ExposureModeBase *********************************************/ + + /***** Camera::ExposureMode *************************************************/ /** * @class Camera::ExposureMode - * @brief abstract base class for camera exposure modes - * @details This base class is inherited by mode-specific classes. Each - * derived class must implement the expose() function which - * defines the exposure sequence for that exposure mode. + * @brief templated abstract base class for exposure mode implementations + * @details Defines Interface and common member functions for all exposure + * modes. Each mode inherits from this class and implements the + * expose() function with logic specific to that mode. The template + * parameter InterfaceType provides access to the appropriate + * Camera Interface. * */ - class ExposureMode { + template + class ExposureMode : public ExposureModeBase { protected: - Camera::Interface* interface; //!< pointer to the Camera::Interface class + InterfaceType* interface; //!< pointer to the specific Camera Interface instance + + // Pointer to the deinterlacer for this mode. This is a pointer + // to the base class -- each exposure mode will have to initialize + // this to an appropriate deinterlacer using a factory function. + // + std::unique_ptr deinterlacer; // Each exposure gets its own copy of the Camera::Information class. // There is one each for processed and unprocessed images. @@ -37,11 +61,16 @@ namespace Camera { Camera::Information unp_info; //!< un-processed images public: - ExposureMode(Camera::Interface* _interface) : interface(_interface) { } + /** + * @brief class constructor + * @param[in] _interface Pointer to Camera InterfaceType + */ + ExposureMode(InterfaceType* _interface) : interface(_interface) { } virtual ~ExposureMode() = default; virtual long expose() = 0; + }; /***** Camera::ExposureMode *************************************************/