Exemplo n.º 1
0
/**
 * handle a group of points of a particular type, with potentially
 * multiple sets delimited by triplicate points.
 */
void 
process_multi_group(point_line_t **plta, int count, double tolerance) {
    int i;
    point_line_t *plt = NULL;

    int points = 0;
    point_line_t *pltg = NULL;

    int marker = 0;
    point_line_t *prev_plt = NULL;

    if (!plta) {
	printf("WARNING: Unexpected call to process_multi_group with a NULL point array\n");
	return;
    }

#if PRINT_ARRAY
    static int print_counter = 0;
    if (print_counter == 0) {
	bu_log("--- BEFORE ---\n");
	print_array(plta, count);
    }
#endif

    /* remove points marked as bogus, 5-identical points in succession */
    count = delete_points(plta, count, tolerance);

#if PRINT_ARRAY
    if (print_counter == 0) {
	print_counter++;
	bu_log("--- AFTER ---\n");
	print_array(plta, count);
    }
#endif

    /* isolate groups and pass them on to the group processing routine */
    for (i = 0; i < count; i++) {
	plt = &(*plta)[i];
	if (!plt || !plt->type) {
	    printf("WARNING: Unexpected NULL encountered while processing a point array (%d of %d)\n", i, count);
	    continue;
	}

	/* if this is the first point of a group, allocate and initialize */
	if (!prev_plt) {
	    prev_plt = &(*plta)[i];
	    pltg = (point_line_t *) bu_malloc(sizeof(point_line_t), "begin point_line_t subgroup");
	    COPY_POINT_LINE_T(*pltg, *prev_plt);
	    marker = 0;
	    continue;
	}

	if (marker) {
	    /* gobble up repeats points used as a marker, average new point */
	    if (DIST_PT_PT(prev_plt->val, plt->val) < tolerance) {
		prev_plt->val[X] = (prev_plt->val[X] + plt->val[X]) / 2.0;
		prev_plt->val[Y] = (prev_plt->val[Y] + plt->val[Y]) / 2.0;
		prev_plt->val[Z] = (prev_plt->val[Z] + plt->val[Z]) / 2.0;
		INITIALIZE_POINT_LINE_T(*plt); /* poof */
		continue;
	    }

	    if (process_group(&pltg, points+1)) {
		bu_free((genptr_t)pltg, "end subgroup: point_line_t");
		pltg = NULL;
		prev_plt = NULL;
		points = 0;
		marker = 0;
		--i;
		continue;
	    } else {
		/* process_group is allowed to return non-zero if
		   there are not enough points -- they get returned to
		   the stack for processing again */
		printf("warning, process_group returned 0\n");
	    }

	    marker = 0;
	    continue;
	}

	/* FIXME: shouldn't just average to the average, later points
	   get weighted too much.. */
	if (DIST_PT_PT(prev_plt->val, plt->val) < tolerance) {
	    /*	    printf("%d: CLOSE DISTANCE of %f\n", plt->index, DIST_PT_PT(prev_plt->val, plt->val));*/
	    marker = points;
	    (pltg[marker]).val[X] = (prev_plt->val[X] + plt->val[X]) / 2.0;
	    (pltg[marker]).val[Y] = (prev_plt->val[Y] + plt->val[Y]) / 2.0;
	    (pltg[marker]).val[Z] = (prev_plt->val[Z] + plt->val[Z]) / 2.0;
	    continue;
	}

	if (!pltg) {
	    printf("Blah! Error. Group array is null. Shouldn't be here!\n");
	    return;
	}

	pltg = (point_line_t *) bu_realloc(pltg, sizeof(point_line_t) * (points + 2), "add subgroup: point_line_t");

	points++;
	COPY_POINT_LINE_T(pltg[points], *plt);
	prev_plt = plt;
    }
    printf("i: %d, count: %d", i, count);

    /* make sure we're not at the end of a list (i.e. no end marker,
       but we're at the end of this group */
    if (points > 0) {
	if (process_group(&pltg, points+1)) {
	    bu_free((genptr_t)pltg, "end point_line_t subgroup");
	    pltg = NULL;
	    prev_plt = NULL;
	    points = 0;
	    marker = 0;
	} else {
	    /* this one shouldn't return zero, we're at the end of a multiblock */
	    printf("ERROR, process_group returned 0\n");
	}
    }

}
Exemplo n.º 2
0
/*******************************************************	
功能:
	触摸屏工作函数
	由中断触发,接受1组坐标数据,校验后再分析输出
参数:
	ts:	client私有数据结构体
return:
	执行结果码,0表示正常执行
********************************************************/
static void goodix_ts_work_func(struct work_struct *work)
{	
	static uint8_t finger_bit=0;	//last time fingers' state
	struct point_data * p = NULL;
	uint8_t read_position = 0;
	uint8_t point_data[READ_BYTES_NUM]={ 0 };
	uint8_t finger=0;				//record which finger is changed
	uint8_t check_sum = 0;
	int ret = -1; 
	int count = 0;

	struct goodix_ts_data *ts = container_of(work, struct goodix_ts_data, work);

	if (ts->use_shutdown && gpio_get_value(ts->gpio_shutdown))
		goto NO_ACTION;					//The data is invalid.

	//if i2c-transfer is failed, let it restart less than 10 times. FOR DEBUG.
	/*
	if( ts->retry > 9) {
		if(!ts->use_irq && (ts->timer.state != HRTIMER_STATE_INACTIVE))		
			hrtimer_cancel(&ts->timer);
		dev_info(&(ts->client->dev), "Because of transfer error, %s stop working.\n",s3c_ts_name);
		ts->bad_data = 1;
		return ;
	}
	*/
	ret=i2c_read_bytes(ts->client, point_data, sizeof(point_data));
	if(ret <= 0)	
	{
		dev_dbg(&(ts->client->dev),"I2C transfer error. ERROR Number:%d\n ", ret);
		ts->retry++;
		if(ts->power)
		{
			ts->power(ts, 0);
			ts->power(ts, 1);
		}
		else
		{
			goodix_init_panel(ts);
			msleep(260);
		}
		goto XFER_ERROR;
	}	
	
	//如果能够保证在INT中断后及时的读取坐标数据,可以不进行校验
	if(!ts->use_irq)	
	{
		switch(point_data[1]& 0x1f)
		{
		case 0:
			break;
		case 1:
			for(count=1; count<8; count++)
				check_sum += (int)point_data[count];
			read_position = 8;
			break;
		case 2:
		case 3:
			for(count=1; count<13;count++)
				check_sum += (int)point_data[count];
			read_position = 13;
			break;	
		default:		//(point_data[1]& 0x1f) > 3
			for(count=1; count<34;count++)
				check_sum += (int)point_data[count];
			read_position = 34;
		}
		if(check_sum != point_data[read_position])
			goto XFER_ERROR;
	}
	//The bits indicate which fingers pressed down
	point_data[1]&=0x1f;
	finger = finger_bit^point_data[1];
	if(finger == 0 && point_data[1] == 0)			
		goto NO_ACTION;						//no fingers and no action
	else if(finger == 0)						//the same as last time
		goto BIT_NO_CHANGE;
	
	//check which point(s) DOWN or UP
	analyse_points(&finger_list, finger_bit, finger);

	if(finger_list.head == NULL)
		goto NO_ACTION;
	else
		dev_dbg(&ts->client->dev, "fingers count:%d\n", finger_list.length);

BIT_NO_CHANGE:
	for(p = finger_list.head; p != NULL; p = p->next)
	{	
		if(p->state == FLAG_UP)
		{
			p->x = p->y = 0;
			p->pressure = 0;
			continue;
		}
		
		if(p->id < 3)
			read_position = p->id*5+3;
		else
			read_position = 29;

		
		if(p->id != 3)
		{
			p->x = (unsigned int) (point_data[read_position]<<8) + (unsigned int)( point_data[read_position+1]);
			p->y = (unsigned int)(point_data[read_position+2]<<8) + (unsigned int) (point_data[read_position+3]);
			p->pressure = point_data[read_position+4];
		}
		
		#if MAX_FINGER_NUM > 3
		else 
		{
			p->x = (unsigned int) (point_data[18]<<8) + (unsigned int)( point_data[25]);
			p->y = (unsigned int)(point_data[26]<<8) + (unsigned int) (point_data[27]);
			p->pressure = point_data[28];
		}
		#endif

		// 将触摸屏的坐标映射到LCD坐标上. 触摸屏短边为X轴,LCD坐标一般长边为X轴,可能需要调整原点位置
		p->x = (TOUCH_MAX_WIDTH - p->x)*SCREEN_MAX_WIDTH/TOUCH_MAX_WIDTH;//y
		if (board_version == 0){
			p->y =  p->y*SCREEN_MAX_HEIGHT/TOUCH_MAX_HEIGHT;//x

		} else if (board_version == 1) {
			p->y = (TOUCH_MAX_HEIGHT - p->y)*SCREEN_MAX_HEIGHT/TOUCH_MAX_HEIGHT;//x
		}
		swap(p->x, p->y); 
	}

#ifndef GOODIX_MULTI_TOUCH	
		if(finger_list.head->state == FLAG_DOWN)
		{
			input_report_abs(ts->input_dev, ABS_X, finger_list.head->x);
			input_report_abs(ts->input_dev, ABS_Y, finger_list.head.y);	
		} 
		input_report_abs(ts->input_dev, ABS_PRESSURE, finger_list.head->pressure);
		input_report_key(ts->input_dev, BTN_TOUCH, finger_list.head->state);   
#else

	/* ABS_MT_TOUCH_MAJOR is used as ABS_MT_PRESSURE in android. */
	for(p = finger_list.head; p != NULL; p = p->next)
	{
		if(p->state == FLAG_DOWN)
		{
			input_report_abs(ts->input_dev, ABS_MT_POSITION_X, p->x);
			input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, p->y);
		} 
		//input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, p->id);
		input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, p->pressure);
		input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, p->pressure);
		//printk("ID:%d.\n", p->id);
		input_mt_sync(ts->input_dev);	
	}

#endif
	input_sync(ts->input_dev);

	delete_points(&finger_list);
	finger_bit = point_data[1]&0x1f;	//restore last presse state.

XFER_ERROR:	
NO_ACTION:
	if(ts->use_irq)
		enable_irq(ts->client->irq);

}