Example #1
0
/*
 * Calculate and set the AFE offset.
 *
 * low:  known-good AFE offset-register value. See note.
 * high: known-good AFE offset-register value. See note. 
 *
 * Note:
 * 'low' and 'high' depend on the scanner model.
 * Choose them so that
 * 1. both produce black pixel samples > 0, and never zero.
 * 2. 'low' produces a a darker black level than 'high',
 * 3. 'low' and 'high' values are as far apart as possible,
 *    for better precision.
 * Example: For CanoScan 4400F, select low = 75, high = 0.
 * Notice that the 'low' register value is not necessarily
 * less than the 'high' register value. It is what comes
 * out of the scanner that counts.
 */
static int calc_afe_blacklevel(struct gl843_device *dev,
			       struct calibration_info *cal,
			       uint8_t low, uint8_t high)
{
	int ret, i;
	struct gl843_image *img;
	struct img_stat lo_stat, hi_stat;

	DBG(DBG_msg, "Calibrating A/D-converter black level.\n");

	CHK_MEM(img = create_image(cal->width, cal->height, PXFMT_RGB16));

	/* Scan with the lamp off to produce black pixels. */
	CHK(set_lamp(dev, LAMP_OFF, 0));

	/* Sample 'low' black level */

	for (i = 0; i < 3; i++) {
		CHK(write_afe_gain(dev, i, 1.0));
		CHK(write_afe(dev, 32 + i, low));  /* Set 'low' black level */
	}
	CHK(scan_img(dev, img, 10000));
	get_image_stats(img, &lo_stat);

	/* Sample 'high' black level */

	for (i = 0; i < 3; i++) {
		CHK(write_afe(dev, 32 + i, high)); /* Set 'high' black level */
	}
	CHK(scan_img(dev, img, 10000));
	get_image_stats(img, &hi_stat);

	/* Use the line equation to find and set the best offset value */

	for (i = 0; i < 3; i++) {
		double m, c; /* y = mx + c */
		int o;	/* offset */
		m = (hi_stat.avg[i] - lo_stat.avg[i]) / (high - low);
		c = lo_stat.avg[i] - m * low;
		o = (int) satf(-c / m + 0.5, 0, 255);
		cal->offset[i] = o;
		CHK(write_afe(dev, 32 + i, o));
		DBG(DBG_info, "AFE %s offset = %d\n", idx_name(i), o);
	}

	ret = 0;
chk_failed:
	free(img);
	return ret;	
chk_mem_failed:
	ret = LIBUSB_ERROR_NO_MEM;
	goto chk_failed;
}
Example #2
0
int test_scan(struct gl843_device *dev)
{
	int ret;
	struct scan_setup ss = {};
	struct gl843_image *img = NULL;

	CHK(write_reg(dev, GL843_SCANRESET, 1));
	CHK(wait_until_home(dev));

	CHK(setup_static(dev));
	ss.source = LAMP_PLATEN;
	ss.fmt = PXFMT_RGB16;
	ss.dpi = 1200;
	ss.start_x = 128;
	ss.width = 10208;
	//ss.start_y = 236;
	ss.start_y = 5;
	ss.height = 1200;
	ss.use_backtracking = 1;

	CHK_MEM(img = create_image(ss.width, ss.height, ss.fmt));

	CHK(setup_common(dev, &ss));
	CHK(setup_horizontal(dev, &ss));
	CHK(setup_vertical(dev, &ss, 0));
	CHK(set_lamp(dev, ss.source, 10));
	CHK(write_reg(dev, GL843_MTRPWR, 1));
	CHK(scan_img(dev, img, 10000));

	write_pnm_image("test.pnm", img);

	CHK(wait_until_home(dev));
	CHK(write_reg(dev, GL843_MTRPWR, 0));

chk_mem_failed:
chk_failed:
	free(img);
	return ret;
}
Example #3
0
int do_warmup_scan(struct gl843_device *dev, float cal_y_pos)
{
	int ret;
	struct scan_setup ss = {};
	struct calibration_info *cal;
	int lamp_to = 4; // FIXME: Get user setting

	CHK(write_reg(dev, GL843_SCANRESET, 1));
	CHK(wait_until_home(dev));

	CHK(setup_static(dev));

	CHK(move_scanner_head(dev, cal_y_pos));
	CHK(wait_motor(dev));

	// FIXME: Get user setting
	ss.source = LAMP_PLATEN;
	ss.fmt = PXFMT_RGB16;
	ss.dpi = 1200;
	ss.start_x = 128;
	ss.width = 10208;
	ss.height = 16;

	CHK(setup_common(dev, &ss));
	CHK(setup_horizontal(dev, &ss));

	CHK_MEM(cal = create_calinfo(ss.source, cal_y_pos,
		ss.start_x, ss.width, ss.height, ss.dpi));

#if 0 
Old stuff
	enum gl843_lamp lamp = LAMP_PLATEN;
	int lamp_to = 4;
	int start_x = 128;
	int width = 10208;
	int height = 16;
	int dpi = 4800;
	CHK(setup_ccd_and_afe(dev,
			/* fmt */ PXFMT_RGB16,
			/* start_x */ start_x,
			/* width */ width * 4800 / dpi,
			/* dpi */ dpi,
			/* afe_dpi */ 1200,
			/* linesel */ 0,
		  	/* tgtime */ 0,
			/* lperiod */ 11640,
			/* expr,g,b */ 40000, 40000, 40000));
#endif

	CHK(select_shading(dev, SHADING_CORR_OFF));

	set_reg(dev, GL843_MTRREV, 0);
	set_reg(dev, GL843_NOTHOME, 0);
	set_reg(dev, GL843_CLRLNCNT, 1);
	set_reg(dev, GL843_MTRPWR, 0);
	set_reg(dev, GL843_AGOHOME, 0);
	CHK(flush_regs(dev));

	CHK(write_afe(dev, 4, 0));
	CHK(write_afe(dev, 1, 0x23));
	CHK(write_afe(dev, 2, 0x24));
	CHK(write_afe(dev, 3, 0x2f)); /* Can be 0x1f or 0x2f */

	CHK(set_lamp(dev, LAMP_OFF, 0));
	CHK(calc_afe_blacklevel(dev, cal, 75, 0));
	CHK(set_lamp(dev, ss.source, lamp_to));
	CHK(warm_up_lamp(dev, cal));
	CHK(calc_afe_gain(dev, cal));
	CHK(calc_shading(dev, cal));
	CHK(set_lamp(dev, ss.source, lamp_to));
	CHK(send_shading(dev, cal->sc, cal->sc_len, 0));
	CHK(select_shading(dev, SHADING_CORR_AREA));
	CHK(move_scanner_head(dev, -cal_y_pos));
	CHK(wait_until_home(dev));
	CHK(write_reg(dev, GL843_MTRPWR, 0));

	free(cal);

	ret = 0;
chk_failed:
	return ret;
chk_mem_failed:
	ret = LIBUSB_ERROR_NO_MEM;
	goto chk_failed;	
}
Example #4
0
/* Warm up the scanner lamp and calibrate the AFE gain and offsets.
 *
 * cal_y_pos: calibration y position, distance from home [mm].
 *
 * Note: it is assumed the scanner head is in the home position
 * when this function is called.
 */
int warm_up_scanner(struct gl843_device *dev,
		    enum gl843_lamp source,
		    int lamp_timeout,
		    float cal_y_pos)
{
	int ret;
	struct scan_setup ss = {};
	struct calibration_info *cal;

	DBG(DBG_msg, "Starting warmup.\n");

	/* Move head into position */

	CHK(move_scanner_head(dev, cal_y_pos));
	CHK(wait_motor(dev));

	/* Setup scan */

	ss.source = source;
	if (source == LAMP_PLATEN) {
		ss.fmt = PXFMT_RGB16;
		ss.dpi = 1200;
		ss.start_x = 128;
		ss.width = 10208;
		ss.start_y = 5; /* Dummy value */
		ss.height = 16;
		ss.overscan = 0;
	} else {
		DBG(DBG_error, "Only platen scanning is implemented right now.\n");
		return -1;
	}

	CHK_MEM(cal = create_calinfo(ss.source, cal_y_pos,
		ss.start_x, ss.width, ss.height, ss.dpi));

	CHK(setup_static(dev));
	CHK(setup_common(dev, &ss));
	CHK(setup_horizontal(dev, &ss));
	CHK(setup_vertical(dev, &ss, 1));
	CHK(select_shading(dev, SHADING_CORR_OFF));

	/* Scan with motor and lamp off and calculate AFE black level */

	CHK(write_reg(dev, GL843_AGOHOME, 0));
	CHK(write_reg(dev, GL843_MTRPWR, 0));
	CHK(set_lamp(dev, LAMP_OFF, 0));
	CHK(calc_afe_blacklevel(dev, cal, 75, 0)); /* 75 and 0 are CS4400F-specific */

	/* Turn on the lamp, do warm up scan, and calculate AFE gain */

	CHK(set_lamp(dev, source, lamp_timeout));
	CHK(warm_up_lamp(dev, cal));
	CHK(calc_afe_gain(dev, cal));

	/* Move home when finished */

	CHK(move_scanner_head(dev, -cal_y_pos));
	CHK(wait_motor(dev));
	CHK(write_reg(dev, GL843_MTRPWR, 0));

	free(cal);

	DBG(DBG_msg, "Done.\n");
		
	ret = 0;
chk_failed:
	return ret;
chk_mem_failed:
	ret = LIBUSB_ERROR_NO_MEM;
	goto chk_failed;	
}
Example #5
0
static int calc_shading(struct gl843_device *dev,
			struct calibration_info *cal)
{
	int ret, i;
	struct gl843_image *light_img = NULL, *dark_img = NULL;
	uint16_t *Ln, *Dn, *p, *p_end;
	const int target = 0xffff;
	int div_by_zero = 0;
	int gain_overflow = 0;

	DBG(DBG_msg, "Calculating shading correction.\n");

	CHK_MEM(light_img = create_image(cal->width, cal->height, PXFMT_RGB16));
	CHK_MEM(dark_img = create_image(cal->width, cal->height, PXFMT_RGB16));

	/* Scan light (white) pixels */

	/* Assume lamp is on */
	CHK(scan_img(dev, light_img, 10000));
	get_vertical_average(light_img);

	/* Scan dark (black) pixels */

	CHK(set_lamp(dev, LAMP_OFF, 0));
	CHK(scan_img(dev, dark_img, 10000));
	get_vertical_average(dark_img);

	/* Calculate shading
	 * Ref: shading & correction in GL843 datasheet. */

	p = cal->sc;
	p_end = p + cal->sc_len;
	Ln = (uint16_t *) light_img->data;
	Dn = (uint16_t *) dark_img->data;

	for (i = 0; i < cal->width * 3; i++) {
		int diff, gain;

		diff = *Ln++ - *Dn;
		if (diff == 0) {
			div_by_zero = 1;
			diff = target;
		}
		gain = (cal->A * target) / diff;
		if (gain > 0xffff) {
			gain_overflow = 1;
			gain = 0xffff;
		}

		*p++ = *Dn++;
		*p++ = gain;

		if (p > p_end) {
			DBG(DBG_error, "internal error: buffer overrun.");
			break;
		}
	}

	if (host_is_big_endian())
		swap_buffer_endianness(cal->sc, cal->sc, cal->sc_len / 2);

	if (div_by_zero)
		DBG(DBG_warn, "division by zero detected.\n");
	if (gain_overflow)
		DBG(DBG_warn, "gain overflow detected.\n");

	ret = 0;
chk_failed:
	free(light_img);
	free(dark_img);
	return ret;
chk_mem_failed:
	ret = LIBUSB_ERROR_NO_MEM;
	goto chk_failed;
}
void display()	{
	n++;							// animation angle ++
	if(n == 360) n=0; // avoid infinity 
	changeView();

	GLfloat ebene[4][3]={ // Grundflaeche
		{-30.0f, 0.0f,-15.0f}, { 30.0f,0.0f,-15.0f},
		{ -30.0f, 0.0f,15.0f},{ 30.0f,0.0f, 15.0f}};
	GLfloat light_position1[]={ -20.0f, 20.0f, -20.0f, 0.0};

	glClearColor(1.0, 1.0, 1.0, 1.0);
	glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
	float angle;

	glLightfv(GL_LIGHT0, GL_POSITION, light_position1);
	glDisable(GL_LIGHTING);

	// Skybox, Kugel ueber die aktuelle Szene, hellblau
	glPushMatrix();
		// bewegt sich mit der kamera
		glTranslatef(swipe_left_right, swipe_up_down, swipe_through_back);
		glColor4ub(15,170,255,100);
		glutSolidSphere(25,30,30);
	glPopMatrix();

	glPushMatrix();	
			// Bodenflaeche
			glTranslatef(0.0f, -3.0f, 0.0f); // nach unten verschoben
			glColor4ub(143, 163, 112, 255);
			glBegin(GL_QUAD_STRIP);
					glVertex3fv(ebene[0]);
					glVertex3fv(ebene[1]);
					glVertex3fv(ebene[2]);
					glVertex3fv(ebene[3]);
			glEnd();

			// Licht
			glEnable(GL_LIGHTING);
			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

			// Teapot
			glPushMatrix();
					set_mat3();
					glTranslated(-2.5, 0.5, 3);
					glRotated(n,0,1,0);
					glutSolidTeapot(0.5);
			glPopMatrix();

			// Bank ausgeben
			// Bank2 ausgeben, Drehwinkel: ITMZ: 190 -> 910 % 360 = 190  ...
			glPushMatrix();
					glRotated(190, 0.0f, 1.0f, 0.0f);
					set_bank();
			glPopMatrix();

			glPushMatrix();
					glTranslated(3.0, 0.0, 0.0);	// (laengs, hoch, tief) = (x, y, z)
					glRotated(190, 0.0f, 1.0f, 0.0f);	// (winkel, x, y, z)
					set_bank();
			glPopMatrix();

				// Bank2 ausgeben
			glPushMatrix();
					glTranslated(-3.0, 0.0, 0.0);	// (laengs, hoch, tief)
					glRotated(190, 0.0f, 1.0f, 0.0f);
					set_bank();
			glPopMatrix();
			
			// Lampe
			glPushMatrix();
					glTranslated(-5,0,2);
					glRotated(45, 0,1,0);
					set_lamp();
			glPopMatrix();

			// *********** bewegliche Teile ******************
			glDisable(GL_LIGHTING);

			glPushMatrix(); 
					glRotated(90, 1.0, 0.0, 0.0);
					angle = glutGet(GLUT_ELAPSED_TIME)/1000.0f *15;
					glRotated(angle, 0.0, 0.0, 1.0);

					/*  Hier Drohe zusammensetzen und Parameter auswerten*/
					glTranslatef(0, -4, - drone_y_positon);
					set_drone();
			glPopMatrix(); // Time

	glPopMatrix(); // Gesamtszene

	glutSwapBuffers();
	glutPostRedisplay();
}