/**
 * \brief Start an exposure on the M26C camera
 *
 * \param exposure	exposure structure for the exposure to perform
 */
void	SxCcdM26C::startExposure0(const Exposure& exposure) {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "exposure %s requested",
		exposure.toString().c_str());
	// remember the exposre, we need it for the second field for the
	// case where we do two fields one after the other
	this->exposure = symmetrize(exposure);
	m26c = m26cExposure();

	// compute a better request for the M26C camera
	exposeField(0);
	timer.start();

	// we are now in exposing state
	state = Exposure::exposing;
}
/**
 * \brief Start an exposure on the M26C camera
 *
 * \param exposure	exposure structure for the exposure to perform
 */
void	SxCcdM26C::startExposure0(const Exposure& exposure) {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "exposure %s requested",
		exposure.toString().c_str());
	// remember the exposure, we need it for the second field for the
	// case where we do two fields one after the other
	this->exposure = symmetrize(exposure);

	// compute a better request for the M26C camera
	m26c = m26cExposure();

	// start the exposure
	if (!camera.reserve("exposure M26C", 1000)) {
		std::string	msg("cannot reserve camera");
		debug(LOG_ERR, DEBUG_LOG, 0, "%s", msg.c_str());
		throw std::runtime_error(msg);
	}
	exposeField(0);
	timer.start();

	// we are now in exposing state
	state(CcdState::exposing);
}
/**
 * \brief Retrieve an image from the caemra
 *
 * This method completes the exposure on the main ccd and reads the field.
 * Depending on the exposure time, it then either starts a new exposure
 * (for short exposures, because the second field would otherwise be too
 * different), or reads out the already exposed second field (for long
 * exposures). In the latter case, the first field is rescaled to account
 * for the different exposure time.
 */
void	SxCcdM26C::getImage0() {
	debug(LOG_DEBUG, DEBUG_LOG, 0, "get an image from the camera");

	// read the right number of pixels from the IN endpoint
	Field	*field0 = readField();
	debug(LOG_DEBUG, DEBUG_LOG, 0, "field 0 transferred");
	if (debuglevel == LOG_DEBUG) {
		debug(LOG_DEBUG, DEBUG_LOG, 0, "writing field 0");
		std::ofstream	out("field0.raw", std::ofstream::binary);
		out << *field0;
		out.close();
	}

	// for long exposures, we just read the second field.
	Field	*field1 = NULL;
	if (exposure.exposuretime() > EXPOSURE_FIELD_CUTOVER) {
		debug(LOG_DEBUG, DEBUG_LOG, 0, "request second field 1");
		timer.end();
		requestField(1);
	} else {
		debug(LOG_DEBUG, DEBUG_LOG, 0, "expose second field 1");
		exposeField(1);
	}

	// read the second field
	debug(LOG_DEBUG, DEBUG_LOG, 0, "read field 1");
	field1 = readField();
	if (debuglevel == LOG_DEBUG) {
		debug(LOG_DEBUG, DEBUG_LOG, 0, "writing field 1");
		std::ofstream	out("field1.raw", std::ofstream::binary);
		out << *field1;
		out.close();
	}

	// rescale the first field, if we did only one exposure
	if (exposure.exposuretime() > EXPOSURE_FIELD_CUTOVER) {
		//double	deadtime = 3.37; // exposuretime = 11
		//double	deadtime = 3.99; // exposuretime = 20
		double	deadtime = 1.2;
		double	scalefactor
			= (timer.elapsed() - deadtime) / exposure.exposuretime();
		debug(LOG_DEBUG, DEBUG_LOG, 0, "scalefactor = %f", scalefactor);
		// rescale the field. We have to multiply the first field
		// with the scaling factor, because of overflows
		if (scalefactor > 0) {
			field0->rescale(scalefactor);
		} else {
			debug(LOG_DEBUG, DEBUG_LOG, 0, "no rescaling");
		}
		//field0->rescale(1.1283);
	}

	// prepare a new image, this now needs binned pixels
	Image<unsigned short>	*_image = new Image<unsigned short>(
		exposure.frame().size() / exposure.mode());
	_image->setOrigin(exposure.frame().origin());
	_image->setMosaicType(MosaicType::BAYER_RGGB);

	// now we have to demultiplex the two fields
	debug(LOG_DEBUG, DEBUG_LOG, 0, "demultiplex the fields");
	if (1 == exposure.mode().x()) {
		DemuxerUnbinned	demuxer;
		demuxer(*_image, *field0, *field1);
	} else {
		DemuxerBinned	demuxer;
		demuxer(*_image, *field0, *field1);
	}

	// remove the data
	delete field0;
	delete field1;

	// return the demultiplexed image
	image = ImagePtr(_image);
	state = Exposure::exposed;
}