Exemple #1
0
/**
 * osp_device_take_spectrum_internal:
 **/
static CdSpectrum *
osp_device_take_spectrum_internal (GUsbDevice *device,
				   guint64 sample_duration,
				   GError **error)
{
	CdSpectrum *sp;
	gdouble val;
	gsize data_len;
	guint i;
	g_autofree guint8 *data = NULL;
	g_autoptr(GTimer) t = NULL;

	/* set integral time in us */
	if (!osp_device_send_command (device, OSP_CMD_SET_INTEGRATION_TIME,
				      (guint8 *) &sample_duration, 4, error))
		return NULL;

	/* get spectrum */
	t = g_timer_new ();
	if (!osp_device_query (device, OSP_CMD_GET_AND_SEND_RAW_SPECTRUM,
			       NULL, 0, &data, &data_len, error))
		return NULL;
	g_debug ("For integration of %.0fms, sensor took %.0fms",
		 sample_duration / 1000.f, g_timer_elapsed (t, NULL) * 1000.f);

	/* check values */
	if (data_len != 2048) {
		g_set_error (error,
			     OSP_DEVICE_ERROR,
			     OSP_DEVICE_ERROR_INTERNAL,
			     "Expected %i bytes, got %" G_GSIZE_FORMAT,
			     2048, data_len);
		return NULL;
	}

	/* export */
	sp = cd_spectrum_sized_new (1024);
	for (i = 0; i < 1024; i++) {
		val = data[i*2+1] * 256 + data[i*2+0];
		cd_spectrum_add_value (sp, val / (gdouble) 0xffff);
	}

	/* the maximum value the hardware can return is 0x3fff */
	val = cd_spectrum_get_value_max (sp);
	if (val > 0.25) {
		g_set_error (error,
			     OSP_DEVICE_ERROR,
			     OSP_DEVICE_ERROR_INTERNAL,
			     "spectral max should be <= 0.25f, was %f",
			     val);
		cd_spectrum_free (sp);
		return NULL;
	}

	return sp;
}
Exemple #2
0
/**
 * cd_spectrum_to_string:
 * @spectrum: a #CdSpectrum instance
 * @max_width: the terminal width
 * @max_height: the terminal height
 *
 * Returns a graphical representation of the spectrum.
 *
 * Return value: a printable ASCII string
 *
 * Since: 1.3.1
 **/
gchar *
cd_spectrum_to_string (CdSpectrum *spectrum, guint max_width, guint max_height)
{
	GString *str = g_string_new ("");
	guint i, j;
	gdouble val_max;
	gdouble nm_scale;

	/* make space for the axes */
	max_width -= 9;
	max_height -= 2;

	/* find value maximum */
	val_max = cd_spectrum_get_value_max (spectrum);
	if (val_max < 0.001)
		val_max = 0.001;
	nm_scale = (cd_spectrum_get_end (spectrum) -
		    cd_spectrum_get_start (spectrum)) / (gdouble) (max_width - 1);

	/* draw grid */
	for (i = 0; i < max_height; i++) {
		gdouble val;
		val = val_max / (gdouble) max_height * (max_height - i);
		g_string_append_printf (str, "%7.3f |", val);
		for (j = 0; j < max_width; j++) {
			gdouble nm;
			nm = ((gdouble) j * nm_scale) + cd_spectrum_get_start (spectrum);
			if (cd_spectrum_get_value_for_nm (spectrum, nm) >= val)
				g_string_append (str, "#");
			else
				g_string_append (str, "_");
		}
		g_string_append (str, "\n");
	}

	/* draw x axis */
	g_string_append_printf (str, "%7.3f  ", 0.f);
	for (j = 0; j < max_width; j++)
		g_string_append (str, "-");
	g_string_append (str, "\n");

	/* draw X labels */
	g_string_append_printf (str, "         %.0fnm",
				cd_spectrum_get_start (spectrum));
	for (j = 0; j < max_width - 10; j++)
		g_string_append (str, " ");
	g_string_append_printf (str, "%.0fnm",
				cd_spectrum_get_end (spectrum));
	g_string_append (str, "\n");

	/* success */
	return g_string_free (str, FALSE);
}
Exemple #3
0
/**
 * osp_device_take_spectrum:
 * @device: a #GUsbDevice instance.
 * @error: A #GError or %NULL
 *
 * Returns a spectrum. The optimal sample duration is calculated automatically.
 *
 * Return value: A #CdSpectrum, or %NULL for error
 *
 * Since: 1.2.11
 **/
CdSpectrum *
osp_device_take_spectrum (GUsbDevice *device, GError **error)
{
	const guint sample_duration_max_secs = 3;
	gboolean relax_requirements = FALSE;
	gdouble max;
	gdouble scale = 0.f;
	guint64 sample_duration = 10000; /* us */
	CdSpectrum *sp = NULL;
	guint i;

	g_return_val_if_fail (G_USB_IS_DEVICE (device), NULL);
	g_return_val_if_fail (error == NULL || *error == NULL, NULL);

	/* loop until we're in 1/4 to 3/4 FSD */
	for (i = 0; i < 5; i++) {
		g_autoptr(CdSpectrum) sp_probe = NULL;

		/* for the last try, relax what we deem acceptable so we can
		 * measure very black things with a long integration time */
		if (i == 4)
			relax_requirements = TRUE;

		/* take a measurement */
		sp_probe = osp_device_take_spectrum_full (device,
							  sample_duration,
							  error);
		if (sp_probe == NULL)
			return NULL;

		/* sensor picked up nothing, take action */
		max = cd_spectrum_get_value_max (sp_probe);
		if (max < 0.001f) {
			sample_duration *= 100.f;
			g_debug ("sensor read no data, setting duration "
				 "to %" G_GUINT64_FORMAT ,
				 sample_duration);
			continue;
		}

		/* sensor is saturated, take action */
		if (max > 0.99f) {
			sample_duration /= 100.f;
			g_debug ("sensor saturated, setting duration "
				 "to %" G_GUINT64_FORMAT,
				 sample_duration);
			continue;
		}

		/* break out if we got valid readings */
		if (max > 0.25f && max < 0.75f) {
			sp = cd_spectrum_dup (sp_probe);
			break;
		}

		/* be more accepting */
		if (relax_requirements && max > 0.01f) {
			sp = cd_spectrum_dup (sp_probe);
			break;
		}

		/* aim for FSD / 2 */
		scale = (gdouble) 0.5 / max;
		sample_duration *= scale;
		g_debug ("for max of %f, using scale=%f for duration %" G_GUINT64_FORMAT,
			 max, scale, sample_duration);

		/* limit this to something sane */
		if (sample_duration / G_USEC_PER_SEC > sample_duration_max_secs) {
			g_debug ("limiting duration from %us to %us",
				 (guint) (sample_duration / G_USEC_PER_SEC),
				 (guint) (sample_duration_max_secs));
			sample_duration = sample_duration_max_secs * G_USEC_PER_SEC;
			relax_requirements = TRUE;
		}
	}

	/* no suitable readings */
	if (sp == NULL) {
		g_set_error_literal (error,
				     OSP_DEVICE_ERROR,
				     OSP_DEVICE_ERROR_NO_DATA,
				     "Got no valid data");
		return NULL;
	}

	/* scale with the new integral time */
	cd_spectrum_set_norm (sp, cd_spectrum_get_norm (sp) / scale);
	g_debug ("normalised spectral max is %f", cd_spectrum_get_value_max (sp));
	return sp;
}