Home | History | Annotate | Download | only in f54test
      1 /*
      2  * Copyright (C) 2014 Satoshi Noguchi
      3  * Copyright (C) 2014 Synaptics Inc
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at
      8  *
      9  *      http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  */
     17 
     18 #include <alloca.h>
     19 #include <time.h>
     20 #include <stdint.h>
     21 #include <stdio.h>
     22 #include <unistd.h>
     23 #include <string.h>
     24 #include <stdlib.h>
     25 #include <errno.h>
     26 #include <math.h>
     27 
     28 #include "testutil.h"
     29 #include "f54test.h"
     30 #include "rmidevice.h"
     31 #include "display.h"
     32 
     33 /* Most recent device status event */
     34 #define RMI_F01_STATUS_CODE(status)		((status) & 0x0f)
     35 /* Indicates that flash programming is enabled (bootloader mode). */
     36 #define RMI_F01_STATUS_BOOTLOADER(status)	(!!((status) & 0x40))
     37 
     38 /*
     39  * Sleep mode controls power management on the device and affects all
     40  * functions of the device.
     41  */
     42 #define RMI_F01_CTRL0_SLEEP_MODE_MASK	0x03
     43 
     44 #define RMI_SLEEP_MODE_NORMAL		0x00
     45 #define RMI_SLEEP_MODE_SENSOR_SLEEP	0x01
     46 #define RMI_SLEEP_MODE_RESERVED0	0x02
     47 #define RMI_SLEEP_MODE_RESERVED1	0x03
     48 
     49 /*
     50  * This bit disables whatever sleep mode may be selected by the sleep_mode
     51  * field and forces the device to run at full power without sleeping.
     52  */
     53 #define RMI_F01_CRTL0_NOSLEEP_BIT	(1 << 2)
     54 
     55 F54Test::~F54Test()
     56 {
     57 	if (m_txAssignment != NULL) delete [] m_txAssignment;
     58 	if (m_rxAssignment != NULL) delete [] m_rxAssignment;
     59 }
     60 
     61 int F54Test::Prepare(f54_report_types reportType)
     62 {
     63 	int retval;
     64 	unsigned char data;
     65 
     66 	retval = FindTestFunctions();
     67 	if (retval != TEST_SUCCESS)
     68 		return retval;
     69 
     70 	retval = m_device.QueryBasicProperties();
     71 	if (retval < 0)
     72 		return TEST_FAIL_QUERY_BASIC_PROPERTIES;
     73 
     74 	retval = ReadF54Queries();
     75 	if (retval != TEST_SUCCESS)
     76 		return retval;
     77 
     78 	retval = SetupF54Controls();
     79 	if (retval != TEST_SUCCESS)
     80 		return retval;
     81 
     82 	retval = ReadF55Queries();
     83 	if (retval != TEST_SUCCESS)
     84 		return retval;
     85 
     86 	retval = SetF54ReportType(reportType);
     87 	if (retval != TEST_SUCCESS)
     88 		return retval;
     89 
     90 	retval = SetF54Interrupt();
     91 	if (retval != TEST_SUCCESS)
     92 		return retval;
     93 
     94 	data = (unsigned char)m_reportType;
     95 	retval = m_device.Write(m_f54.GetDataBase(), &data, 1);
     96 	if (retval < 0)
     97 		return retval;
     98 
     99 	return TEST_SUCCESS;
    100 }
    101 
    102 int F54Test::Run()
    103 {
    104 	int retval;
    105 	unsigned char command;
    106 
    107 	command = (unsigned char)COMMAND_GET_REPORT;
    108 	retval = DoF54Command(command);
    109 	if (retval != TEST_SUCCESS)
    110 		return retval;
    111 
    112 	retval = ReadF54Report();
    113 	if (retval != TEST_SUCCESS)
    114 		return retval;
    115 
    116 	retval = ShowF54Report();
    117 	if (retval != TEST_SUCCESS)
    118 		return retval;
    119 
    120 	return TEST_SUCCESS;
    121 }
    122 
    123 int F54Test::SetF54ReportType(f54_report_types report_type)
    124 {
    125 	switch (report_type) {
    126 	case F54_8BIT_IMAGE:
    127 	case F54_16BIT_IMAGE:
    128 	case F54_RAW_16BIT_IMAGE:
    129 	case F54_HIGH_RESISTANCE:
    130 	case F54_TX_TO_TX_SHORTS:
    131 	case F54_RX_TO_RX_SHORTS_1:
    132 	case F54_TRUE_BASELINE:
    133 	case F54_FULL_RAW_CAP_MIN_MAX:
    134 	case F54_RX_OPENS_1:
    135 	case F54_TX_OPENS:
    136 	case F54_TX_TO_GND_SHORTS:
    137 	case F54_RX_TO_RX_SHORTS_2:
    138 	case F54_RX_OPENS_2:
    139 	case F54_FULL_RAW_CAP:
    140 	case F54_FULL_RAW_CAP_NO_RX_COUPLING:
    141 	case F54_SENSOR_SPEED:
    142 	case F54_ADC_RANGE:
    143 	case F54_TRX_OPENS:
    144 	case F54_TRX_TO_GND_SHORTS:
    145 	case F54_TRX_SHORTS:
    146 	case F54_ABS_RAW_CAP:
    147 	case F54_ABS_DELTA_CAP:
    148 		m_reportType = report_type;
    149 		return SetF54ReportSize(report_type);
    150 	default:
    151 		m_reportType = INVALID_REPORT_TYPE;
    152 		m_reportSize = 0;
    153 		return TEST_FAIL_INVALID_PARAMETER;
    154 	}
    155 }
    156 
    157 int F54Test::SetF54ReportSize(f54_report_types report_type)
    158 {
    159 	int retval;
    160 	unsigned char tx = m_txAssigned;
    161 	unsigned char rx = m_rxAssigned;
    162 
    163 	switch (report_type) {
    164 	case F54_8BIT_IMAGE:
    165 		m_reportSize = tx * rx;
    166 		break;
    167 	case F54_16BIT_IMAGE:
    168 	case F54_RAW_16BIT_IMAGE:
    169 	case F54_TRUE_BASELINE:
    170 	case F54_FULL_RAW_CAP:
    171 	case F54_FULL_RAW_CAP_NO_RX_COUPLING:
    172 	case F54_SENSOR_SPEED:
    173 		m_reportSize = 2 * tx * rx;
    174 		break;
    175 	case F54_HIGH_RESISTANCE:
    176 		m_reportSize = HIGH_RESISTANCE_DATA_SIZE;
    177 		break;
    178 	case F54_TX_TO_TX_SHORTS:
    179 	case F54_TX_OPENS:
    180 	case F54_TX_TO_GND_SHORTS:
    181 		m_reportSize = (tx + 7) / 8;
    182 		break;
    183 	case F54_RX_TO_RX_SHORTS_1:
    184 	case F54_RX_OPENS_1:
    185 		if (rx < tx)
    186 			m_reportSize = 2 * rx * rx;
    187 		else
    188 			m_reportSize = 2 * tx * rx;
    189 		break;
    190 	case F54_FULL_RAW_CAP_MIN_MAX:
    191 		m_reportSize = FULL_RAW_CAP_MIN_MAX_DATA_SIZE;
    192 		break;
    193 	case F54_RX_TO_RX_SHORTS_2:
    194 	case F54_RX_OPENS_2:
    195 		if (rx <= tx)
    196 			m_reportSize = 0;
    197 		else
    198 			m_reportSize = 2 * rx * (rx - tx);
    199 		break;
    200 	case F54_ADC_RANGE:
    201 		if (m_f54Query.has_signal_clarity) {
    202 
    203 			retval = m_device.Read(m_f54Control.reg_41.address,
    204 					m_f54Control.reg_41.data,
    205 					sizeof(m_f54Control.reg_41.data));
    206 			if (retval < 0) {
    207 				m_reportSize = 0;
    208 				break;
    209 			}
    210 			if (m_f54Control.reg_41.no_signal_clarity) {
    211 				if (tx % 4)
    212 					tx += 4 - (tx % 4);
    213 			}
    214 		}
    215 		m_reportSize = 2 * tx * rx;
    216 		break;
    217 	case F54_TRX_OPENS:
    218 	case F54_TRX_TO_GND_SHORTS:
    219 	case F54_TRX_SHORTS:
    220 		m_reportSize = TRX_OPEN_SHORT_DATA_SIZE;
    221 		break;
    222 	case F54_ABS_RAW_CAP:
    223 	case F54_ABS_DELTA_CAP:
    224 		m_reportSize = 4 * (tx + rx);
    225 		break;
    226 	default:
    227 		m_reportSize = 0;
    228 		return TEST_FAIL_INVALID_PARAMETER;
    229 	}
    230 
    231 	return TEST_SUCCESS;
    232 }
    233 
    234 int F54Test::FindTestFunctions()
    235 {
    236 	if (0 > m_device.ScanPDT(0x00, 10))
    237 		return TEST_FAIL_SCAN_PDT;
    238 
    239 	if (!m_device.GetFunction(m_f01, 0x01))
    240 		return TEST_FAIL_NO_FUNCTION_01;
    241 
    242 	if (!m_device.GetFunction(m_f54, 0x54))
    243 		return TEST_FAIL_NO_FUNCTION_54;
    244 
    245 	if (!m_device.GetFunction(m_f55, 0x55))
    246 		return TEST_FAIL_NO_FUNCTION_55;
    247 
    248 	return TEST_SUCCESS;
    249 }
    250 
    251 int F54Test::ReadF54Queries()
    252 {
    253 	int retval;
    254 	unsigned short query_addr = m_f54.GetQueryBase();
    255 	unsigned char offset;
    256 
    257 	retval = m_device.Read(query_addr,
    258 			       m_f54Query.data,
    259 			       sizeof(m_f54Query.data));
    260 	if (retval < 0)
    261 		return retval;
    262 
    263 	offset = sizeof(m_f54Query.data);
    264 
    265 	/* query 12 */
    266 	if (m_f54Query.has_sense_frequency_control == 0)
    267 		offset -= 1;
    268 
    269 	/* query 13 */
    270 	if (m_f54Query.has_query13) {
    271 		retval = m_device.Read(query_addr + offset,
    272 				m_f54Query_13.data,
    273 				sizeof(m_f54Query_13.data));
    274 		if (retval < 0)
    275 			return retval;
    276 		offset += 1;
    277 	}
    278 
    279 	/* query 14 */
    280 	if ((m_f54Query.has_query13) && (m_f54Query_13.has_ctrl87))
    281 		offset += 1;
    282 
    283 	/* query 15 */
    284 	if (m_f54Query.has_query15) {
    285 		retval = m_device.Read(query_addr + offset,
    286 				m_f54Query_15.data,
    287 				sizeof(m_f54Query_15.data));
    288 		if (retval < 0)
    289 			return retval;
    290 		offset += 1;
    291 	}
    292 
    293 	/* query 16 */
    294 	if ((m_f54Query.has_query15) && (m_f54Query_15.has_query16)) {
    295 		retval = m_device.Read(query_addr + offset,
    296 				m_f54Query_16.data,
    297 				sizeof(m_f54Query_16.data));
    298 		if (retval < 0)
    299 			return retval;
    300 		offset += 1;
    301 	}
    302 
    303 	/* query 17 */
    304 	if ((m_f54Query.has_query15) &&
    305 			(m_f54Query_15.has_query16) &&
    306 			(m_f54Query_16.has_query17))
    307 		offset += 1;
    308 
    309 	/* query 18 */
    310 	if ((m_f54Query.has_query15) &&
    311 			(m_f54Query_15.has_query16) &&
    312 			(m_f54Query_16.has_ctrl94_query18))
    313 		offset += 1;
    314 
    315 	/* query 19 */
    316 	if ((m_f54Query.has_query15) &&
    317 			(m_f54Query_15.has_query16) &&
    318 			(m_f54Query_16.has_ctrl95_query19))
    319 		offset += 1;
    320 
    321 	/* query 20 */
    322 	if ((m_f54Query.has_query15) && (m_f54Query_15.has_query20))
    323 		offset += 1;
    324 
    325 	/* query 21 */
    326 	if ((m_f54Query.has_query15) && (m_f54Query_15.has_query21)) {
    327 		retval = m_device.Read(query_addr + offset,
    328 				m_f54Query_21.data,
    329 				sizeof(m_f54Query_21.data));
    330 		if (retval < 0)
    331 			return retval;
    332 		offset += 1;
    333 	}
    334 
    335 	/* query 22 */
    336 	if ((m_f54Query.has_query15) && (m_f54Query_15.has_query22)) {
    337 		retval = m_device.Read(query_addr + offset,
    338 				m_f54Query_22.data,
    339 				sizeof(m_f54Query_22.data));
    340 		if (retval < 0)
    341 			return retval;
    342 		offset += 1;
    343 	}
    344 
    345 	/* query 23 */
    346 	if ((m_f54Query.has_query15) &&
    347 			(m_f54Query_15.has_query22) &&
    348 			(m_f54Query_22.has_query23)) {
    349 		retval = m_device.Read(query_addr + offset,
    350 				m_f54Query_23.data,
    351 				sizeof(m_f54Query_23.data));
    352 		if (retval < 0)
    353 			return retval;
    354 		offset += 1;
    355 	}
    356 
    357 	/* query 24 */
    358 	if ((m_f54Query.has_query15) &&
    359 			(m_f54Query_15.has_query21) &&
    360 			(m_f54Query_21.has_query24_data18))
    361 		offset += 1;
    362 
    363 	/* query 25 */
    364 	if ((m_f54Query.has_query15) && (m_f54Query_15.has_query25)) {
    365 		retval = m_device.Read(query_addr + offset,
    366 				m_f54Query_25.data,
    367 				sizeof(m_f54Query_25.data));
    368 		if (retval < 0)
    369 			return retval;
    370 		offset += 1;
    371 	}
    372 
    373 	/* query 26 */
    374 	if ((m_f54Query.has_query15) &&
    375 			(m_f54Query_15.has_query22) &&
    376 			(m_f54Query_22.has_ctrl103_query26))
    377 		offset += 1;
    378 
    379 	/* query 27 */
    380 	if ((m_f54Query.has_query15) &&
    381 			(m_f54Query_15.has_query25) &&
    382 			(m_f54Query_25.has_query27)) {
    383 		retval = m_device.Read(query_addr + offset,
    384 				m_f54Query_27.data,
    385 				sizeof(m_f54Query_27.data));
    386 		if (retval < 0)
    387 			return retval;
    388 		offset += 1;
    389 	}
    390 
    391 	/* query 28 */
    392 	if ((m_f54Query.has_query15) &&
    393 			(m_f54Query_15.has_query22) &&
    394 			(m_f54Query_22.has_query28))
    395 		offset += 1;
    396 
    397 	/* query 29 */
    398 	if ((m_f54Query.has_query15) &&
    399 			(m_f54Query_15.has_query25) &&
    400 			(m_f54Query_25.has_query27) &&
    401 			(m_f54Query_27.has_query29)) {
    402 		retval = m_device.Read(query_addr + offset,
    403 				m_f54Query_29.data,
    404 				sizeof(m_f54Query_29.data));
    405 		if (retval < 0)
    406 			return retval;
    407 		offset += 1;
    408 	}
    409 
    410 	/* query 30 */
    411 	if ((m_f54Query.has_query15) &&
    412 			(m_f54Query_15.has_query25) &&
    413 			(m_f54Query_25.has_query27) &&
    414 			(m_f54Query_27.has_query29) &&
    415 			(m_f54Query_29.has_query30)) {
    416 		retval = m_device.Read(query_addr + offset,
    417 				m_f54Query_30.data,
    418 				sizeof(m_f54Query_30.data));
    419 		if (retval < 0)
    420 			return retval;
    421 		offset += 1;
    422 	}
    423 
    424 	/* query 31 */
    425 	if ((m_f54Query.has_query15) &&
    426 			(m_f54Query_15.has_query25) &&
    427 			(m_f54Query_25.has_query27) &&
    428 			(m_f54Query_27.has_query29) &&
    429 			(m_f54Query_29.has_query30) &&
    430 			(m_f54Query_30.has_ctrl122_query31))
    431 		offset += 1;
    432 
    433 	/* query 32 */
    434 	if ((m_f54Query.has_query15) &&
    435 			(m_f54Query_15.has_query25) &&
    436 			(m_f54Query_25.has_query27) &&
    437 			(m_f54Query_27.has_query29) &&
    438 			(m_f54Query_29.has_query30) &&
    439 			(m_f54Query_30.has_query32)) {
    440 		retval = m_device.Read(query_addr + offset,
    441 				m_f54Query_32.data,
    442 				sizeof(m_f54Query_32.data));
    443 		if (retval < 0)
    444 			return retval;
    445 		offset += 1;
    446 	}
    447 
    448 	/* query 33 */
    449 	if ((m_f54Query.has_query15) &&
    450 			(m_f54Query_15.has_query25) &&
    451 			(m_f54Query_25.has_query27) &&
    452 			(m_f54Query_27.has_query29) &&
    453 			(m_f54Query_29.has_query30) &&
    454 			(m_f54Query_30.has_query32) &&
    455 			(m_f54Query_32.has_query33)) {
    456 		retval = m_device.Read(query_addr + offset,
    457 				m_f54Query_33.data,
    458 				sizeof(m_f54Query_33.data));
    459 		if (retval < 0)
    460 			return retval;
    461 		offset += 1;
    462 	}
    463 
    464 	/* query 34 */
    465 	if ((m_f54Query.has_query15) &&
    466 			(m_f54Query_15.has_query25) &&
    467 			(m_f54Query_25.has_query27) &&
    468 			(m_f54Query_27.has_query29) &&
    469 			(m_f54Query_29.has_query30) &&
    470 			(m_f54Query_30.has_query32) &&
    471 			(m_f54Query_32.has_query34))
    472 		offset += 1;
    473 
    474 	/* query 35 */
    475 	if ((m_f54Query.has_query15) &&
    476 			(m_f54Query_15.has_query25) &&
    477 			(m_f54Query_25.has_query27) &&
    478 			(m_f54Query_27.has_query29) &&
    479 			(m_f54Query_29.has_query30) &&
    480 			(m_f54Query_30.has_query32) &&
    481 			(m_f54Query_32.has_query35)) {
    482 		retval = m_device.Read(query_addr + offset,
    483 				m_f54Query_35.data,
    484 				sizeof(m_f54Query_35.data));
    485 		if (retval < 0)
    486 			return retval;
    487 		offset += 1;
    488 	}
    489 
    490 	/* query 36 */
    491 	if ((m_f54Query.has_query15) &&
    492 			(m_f54Query_15.has_query25) &&
    493 			(m_f54Query_25.has_query27) &&
    494 			(m_f54Query_27.has_query29) &&
    495 			(m_f54Query_29.has_query30) &&
    496 			(m_f54Query_30.has_query32) &&
    497 			(m_f54Query_32.has_query33) &&
    498 			(m_f54Query_33.has_query36)) {
    499 		retval = m_device.Read(query_addr + offset,
    500 				m_f54Query_36.data,
    501 				sizeof(m_f54Query_36.data));
    502 		if (retval < 0)
    503 			return retval;
    504 		offset += 1;
    505 	}
    506 
    507 	/* query 37 */
    508 	if ((m_f54Query.has_query15) &&
    509 			(m_f54Query_15.has_query25) &&
    510 			(m_f54Query_25.has_query27) &&
    511 			(m_f54Query_27.has_query29) &&
    512 			(m_f54Query_29.has_query30) &&
    513 			(m_f54Query_30.has_query32) &&
    514 			(m_f54Query_32.has_query33) &&
    515 			(m_f54Query_33.has_query36) &&
    516 			(m_f54Query_36.has_query37))
    517 		offset += 1;
    518 
    519 	/* query 38 */
    520 	if ((m_f54Query.has_query15) &&
    521 			(m_f54Query_15.has_query25) &&
    522 			(m_f54Query_25.has_query27) &&
    523 			(m_f54Query_27.has_query29) &&
    524 			(m_f54Query_29.has_query30) &&
    525 			(m_f54Query_30.has_query32) &&
    526 			(m_f54Query_32.has_query33) &&
    527 			(m_f54Query_33.has_query36) &&
    528 			(m_f54Query_36.has_query38)) {
    529 		retval = m_device.Read(query_addr + offset,
    530 				m_f54Query_38.data,
    531 				sizeof(m_f54Query_38.data));
    532 		if (retval < 0)
    533 			return retval;
    534 		offset += 1;
    535 	}
    536 
    537 	return TEST_SUCCESS;;
    538 }
    539 
    540 int F54Test::SetupF54Controls()
    541 {
    542 	unsigned char length;
    543 	unsigned char num_of_sensing_freqs;
    544 	unsigned short reg_addr = m_f54.GetControlBase();
    545 
    546 	num_of_sensing_freqs = m_f54Query.number_of_sensing_frequencies;
    547 
    548 	/* control 0 */
    549 	reg_addr += CONTROL_0_SIZE;
    550 
    551 	/* control 1 */
    552 	if ((m_f54Query.touch_controller_family == 0) ||
    553 			(m_f54Query.touch_controller_family == 1))
    554 		reg_addr += CONTROL_1_SIZE;
    555 
    556 	/* control 2 */
    557 	reg_addr += CONTROL_2_SIZE;
    558 
    559 	/* control 3 */
    560 	if (m_f54Query.has_pixel_touch_threshold_adjustment == 1)
    561 		reg_addr += CONTROL_3_SIZE;
    562 
    563 	/* controls 4 5 6 */
    564 	if ((m_f54Query.touch_controller_family == 0) ||
    565 			(m_f54Query.touch_controller_family == 1))
    566 		reg_addr += CONTROL_4_6_SIZE;
    567 
    568 	/* control 7 */
    569 	if (m_f54Query.touch_controller_family == 1) {
    570 		m_f54Control.reg_7.address = reg_addr;
    571 		reg_addr += CONTROL_7_SIZE;
    572 	}
    573 
    574 	/* controls 8 9 */
    575 	if ((m_f54Query.touch_controller_family == 0) ||
    576 			(m_f54Query.touch_controller_family == 1))
    577 		reg_addr += CONTROL_8_9_SIZE;
    578 
    579 	/* control 10 */
    580 	if (m_f54Query.has_interference_metric == 1)
    581 		reg_addr += CONTROL_10_SIZE;
    582 
    583 	/* control 11 */
    584 	if (m_f54Query.has_ctrl11 == 1)
    585 		reg_addr += CONTROL_11_SIZE;
    586 
    587 	/* controls 12 13 */
    588 	if (m_f54Query.has_relaxation_control == 1)
    589 		reg_addr += CONTROL_12_13_SIZE;
    590 
    591 	/* controls 14 15 16 */
    592 	if (m_f54Query.has_sensor_assignment == 1) {
    593 		reg_addr += CONTROL_14_SIZE;
    594 		reg_addr += CONTROL_15_SIZE * m_f54Query.num_of_rx_electrodes;
    595 		reg_addr += CONTROL_16_SIZE * m_f54Query.num_of_tx_electrodes;
    596 	}
    597 
    598 	/* controls 17 18 19 */
    599 	if (m_f54Query.has_sense_frequency_control == 1) {
    600 		reg_addr += CONTROL_17_SIZE * num_of_sensing_freqs;
    601 		reg_addr += CONTROL_18_SIZE * num_of_sensing_freqs;
    602 		reg_addr += CONTROL_19_SIZE * num_of_sensing_freqs;
    603 	}
    604 
    605 	/* control 20 */
    606 	reg_addr += CONTROL_20_SIZE;
    607 
    608 	/* control 21 */
    609 	if (m_f54Query.has_sense_frequency_control == 1)
    610 		reg_addr += CONTROL_21_SIZE;
    611 
    612 	/* controls 22 23 24 25 26 */
    613 	if (m_f54Query.has_firmware_noise_mitigation == 1)
    614 		reg_addr += CONTROL_22_26_SIZE;
    615 
    616 	/* control 27 */
    617 	if (m_f54Query.has_iir_filter == 1)
    618 		reg_addr += CONTROL_27_SIZE;
    619 
    620 	/* control 28 */
    621 	if (m_f54Query.has_firmware_noise_mitigation == 1)
    622 		reg_addr += CONTROL_28_SIZE;
    623 
    624 	/* control 29 */
    625 	if (m_f54Query.has_cmn_removal == 1)
    626 		reg_addr += CONTROL_29_SIZE;
    627 
    628 	/* control 30 */
    629 	if (m_f54Query.has_cmn_maximum == 1)
    630 		reg_addr += CONTROL_30_SIZE;
    631 
    632 	/* control 31 */
    633 	if (m_f54Query.has_touch_hysteresis == 1)
    634 		reg_addr += CONTROL_31_SIZE;
    635 
    636 	/* controls 32 33 34 35 */
    637 	if (m_f54Query.has_edge_compensation == 1)
    638 		reg_addr += CONTROL_32_35_SIZE;
    639 
    640 	/* control 36 */
    641 	if ((m_f54Query.curve_compensation_mode == 1) ||
    642 			(m_f54Query.curve_compensation_mode == 2)) {
    643 		if (m_f54Query.curve_compensation_mode == 1) {
    644 			length = std::max(m_f54Query.num_of_rx_electrodes,
    645 					m_f54Query.num_of_tx_electrodes);
    646 		} else if (m_f54Query.curve_compensation_mode == 2) {
    647 			length = m_f54Query.num_of_rx_electrodes;
    648 		}
    649 		reg_addr += CONTROL_36_SIZE * length;
    650 	}
    651 
    652 	/* control 37 */
    653 	if (m_f54Query.curve_compensation_mode == 2)
    654 		reg_addr += CONTROL_37_SIZE * m_f54Query.num_of_tx_electrodes;
    655 
    656 	/* controls 38 39 40 */
    657 	if (m_f54Query.has_per_frequency_noise_control == 1) {
    658 		reg_addr += CONTROL_38_SIZE * num_of_sensing_freqs;
    659 		reg_addr += CONTROL_39_SIZE * num_of_sensing_freqs;
    660 		reg_addr += CONTROL_40_SIZE * num_of_sensing_freqs;
    661 	}
    662 
    663 	/* control 41 */
    664 	if (m_f54Query.has_signal_clarity == 1) {
    665 		m_f54Control.reg_41.address = reg_addr;
    666 		reg_addr += CONTROL_41_SIZE;
    667 	}
    668 
    669 	/* control 42 */
    670 	if (m_f54Query.has_variance_metric == 1)
    671 		reg_addr += CONTROL_42_SIZE;
    672 
    673 	/* controls 43 44 45 46 47 48 49 50 51 52 53 54 */
    674 	if (m_f54Query.has_multi_metric_state_machine == 1)
    675 		reg_addr += CONTROL_43_54_SIZE;
    676 
    677 	/* controls 55 56 */
    678 	if (m_f54Query.has_0d_relaxation_control == 1)
    679 		reg_addr += CONTROL_55_56_SIZE;
    680 
    681 	/* control 57 */
    682 	if (m_f54Query.has_0d_acquisition_control == 1) {
    683 		m_f54Control.reg_57.address = reg_addr;
    684 		reg_addr += CONTROL_57_SIZE;
    685 	}
    686 
    687 	/* control 58 */
    688 	if (m_f54Query.has_0d_acquisition_control == 1)
    689 		reg_addr += CONTROL_58_SIZE;
    690 
    691 	/* control 59 */
    692 	if (m_f54Query.has_h_blank == 1)
    693 		reg_addr += CONTROL_59_SIZE;
    694 
    695 	/* controls 60 61 62 */
    696 	if ((m_f54Query.has_h_blank == 1) ||
    697 			(m_f54Query.has_v_blank == 1) ||
    698 			(m_f54Query.has_long_h_blank == 1))
    699 		reg_addr += CONTROL_60_62_SIZE;
    700 
    701 	/* control 63 */
    702 	if ((m_f54Query.has_h_blank == 1) ||
    703 			(m_f54Query.has_v_blank == 1) ||
    704 			(m_f54Query.has_long_h_blank == 1) ||
    705 			(m_f54Query.has_slew_metric == 1) ||
    706 			(m_f54Query.has_slew_option == 1) ||
    707 			(m_f54Query.has_noise_mitigation2 == 1))
    708 		reg_addr += CONTROL_63_SIZE;
    709 
    710 	/* controls 64 65 66 67 */
    711 	if (m_f54Query.has_h_blank == 1)
    712 		reg_addr += CONTROL_64_67_SIZE * 7;
    713 	else if ((m_f54Query.has_v_blank == 1) ||
    714 			(m_f54Query.has_long_h_blank == 1))
    715 		reg_addr += CONTROL_64_67_SIZE;
    716 
    717 	/* controls 68 69 70 71 72 73 */
    718 	if ((m_f54Query.has_h_blank == 1) ||
    719 			(m_f54Query.has_v_blank == 1) ||
    720 			(m_f54Query.has_long_h_blank == 1))
    721 		reg_addr += CONTROL_68_73_SIZE;
    722 
    723 	/* control 74 */
    724 	if (m_f54Query.has_slew_metric == 1)
    725 		reg_addr += CONTROL_74_SIZE;
    726 
    727 	/* control 75 */
    728 	if (m_f54Query.has_enhanced_stretch == 1)
    729 		reg_addr += CONTROL_75_SIZE * num_of_sensing_freqs;
    730 
    731 	/* control 76 */
    732 	if (m_f54Query.has_startup_fast_relaxation == 1)
    733 		reg_addr += CONTROL_76_SIZE;
    734 
    735 	/* controls 77 78 */
    736 	if (m_f54Query.has_esd_control == 1)
    737 		reg_addr += CONTROL_77_78_SIZE;
    738 
    739 	/* controls 79 80 81 82 83 */
    740 	if (m_f54Query.has_noise_mitigation2 == 1)
    741 		reg_addr += CONTROL_79_83_SIZE;
    742 
    743 	/* controls 84 85 */
    744 	if (m_f54Query.has_energy_ratio_relaxation == 1)
    745 		reg_addr += CONTROL_84_85_SIZE;
    746 
    747 	/* control 86 */
    748 	if ((m_f54Query.has_query13 == 1) && (m_f54Query_13.has_ctrl86 == 1))
    749 		reg_addr += CONTROL_86_SIZE;
    750 
    751 	/* control 87 */
    752 	if ((m_f54Query.has_query13 == 1) && (m_f54Query_13.has_ctrl87 == 1))
    753 		reg_addr += CONTROL_87_SIZE;
    754 
    755 	/* control 88 */
    756 	if (m_f54Query.has_ctrl88 == 1) {
    757 		m_f54Control.reg_88.address = reg_addr;
    758 		reg_addr += CONTROL_88_SIZE;
    759 	}
    760 
    761 	/* control 89 */
    762 	if ((m_f54Query.has_query13 == 1) &&
    763 			(m_f54Query_13.has_cidim == 1 ||
    764 			m_f54Query_13.has_noise_mitigation_enhancement ||
    765 			m_f54Query_13.has_rail_im))
    766 		reg_addr += CONTROL_89_SIZE;
    767 
    768 	/* control 90 */
    769 	if ((m_f54Query.has_query15) && (m_f54Query_15.has_ctrl90))
    770 		reg_addr += CONTROL_90_SIZE;
    771 
    772 	/* control 91 */
    773 	if ((m_f54Query.has_query15) &&
    774 			(m_f54Query_15.has_query21) &&
    775 			(m_f54Query_21.has_ctrl91))
    776 		reg_addr += CONTROL_91_SIZE;
    777 
    778 	/* control 92 */
    779 	if ((m_f54Query.has_query15) &&
    780 			(m_f54Query_15.has_query16) &&
    781 			(m_f54Query_16.has_ctrl92))
    782 		reg_addr += CONTROL_92_SIZE;
    783 
    784 	/* control 93 */
    785 	if ((m_f54Query.has_query15) &&
    786 			(m_f54Query_15.has_query16) &&
    787 			(m_f54Query_16.has_ctrl93))
    788 		reg_addr += CONTROL_93_SIZE;
    789 
    790 	/* control 94 */
    791 	if ((m_f54Query.has_query15) &&
    792 			(m_f54Query_15.has_query16) &&
    793 			(m_f54Query_16.has_ctrl94_query18))
    794 		reg_addr += CONTROL_94_SIZE;
    795 
    796 	/* control 95 */
    797 	if ((m_f54Query.has_query15) &&
    798 			(m_f54Query_15.has_query16) &&
    799 			(m_f54Query_16.has_ctrl95_query19))
    800 		reg_addr += CONTROL_95_SIZE;
    801 
    802 	/* control 96 */
    803 	if ((m_f54Query.has_query15) &&
    804 			(m_f54Query_15.has_query21) &&
    805 			(m_f54Query_21.has_ctrl96))
    806 		reg_addr += CONTROL_96_SIZE;
    807 
    808 	/* control 97 */
    809 	if ((m_f54Query.has_query15) &&
    810 			(m_f54Query_15.has_query21) &&
    811 			(m_f54Query_21.has_ctrl97))
    812 		reg_addr += CONTROL_97_SIZE;
    813 
    814 	/* control 98 */
    815 	if ((m_f54Query.has_query15) &&
    816 			(m_f54Query_15.has_query21) &&
    817 			(m_f54Query_21.has_ctrl98))
    818 		reg_addr += CONTROL_98_SIZE;
    819 
    820 	/* control 99 */
    821 	if (m_f54Query.touch_controller_family == 2)
    822 		reg_addr += CONTROL_99_SIZE;
    823 
    824 	/* control 100 */
    825 	if ((m_f54Query.has_query15) &&
    826 			(m_f54Query_15.has_query16) &&
    827 			(m_f54Query_16.has_ctrl100))
    828 		reg_addr += CONTROL_100_SIZE;
    829 
    830 	/* control 101 */
    831 	if ((m_f54Query.has_query15) &&
    832 			(m_f54Query_15.has_query22) &&
    833 			(m_f54Query_22.has_ctrl101))
    834 		reg_addr += CONTROL_101_SIZE;
    835 
    836 
    837 	/* control 102 */
    838 	if ((m_f54Query.has_query15) &&
    839 			(m_f54Query_15.has_query22) &&
    840 			(m_f54Query_22.has_query23) &&
    841 			(m_f54Query_23.has_ctrl102))
    842 		reg_addr += CONTROL_102_SIZE;
    843 
    844 	/* control 103 */
    845 	if ((m_f54Query.has_query15) &&
    846 			(m_f54Query_15.has_query22) &&
    847 			(m_f54Query_22.has_ctrl103_query26))
    848 		reg_addr += CONTROL_103_SIZE;
    849 
    850 	/* control 104 */
    851 	if ((m_f54Query.has_query15) &&
    852 			(m_f54Query_15.has_query22) &&
    853 			(m_f54Query_22.has_ctrl104))
    854 		reg_addr += CONTROL_104_SIZE;
    855 
    856 	/* control 105 */
    857 	if ((m_f54Query.has_query15) &&
    858 			(m_f54Query_15.has_query22) &&
    859 			(m_f54Query_22.has_ctrl105))
    860 		reg_addr += CONTROL_105_SIZE;
    861 
    862 	/* control 106 */
    863 	if ((m_f54Query.has_query15) &&
    864 			(m_f54Query_15.has_query25) &&
    865 			(m_f54Query_25.has_ctrl106))
    866 		reg_addr += CONTROL_106_SIZE;
    867 
    868 	/* control 107 */
    869 	if ((m_f54Query.has_query15) &&
    870 			(m_f54Query_15.has_query25) &&
    871 			(m_f54Query_25.has_ctrl107))
    872 		reg_addr += CONTROL_107_SIZE;
    873 
    874 	/* control 108 */
    875 	if ((m_f54Query.has_query15) &&
    876 			(m_f54Query_15.has_query25) &&
    877 			(m_f54Query_25.has_ctrl108))
    878 		reg_addr += CONTROL_108_SIZE;
    879 
    880 	/* control 109 */
    881 	if ((m_f54Query.has_query15) &&
    882 			(m_f54Query_15.has_query25) &&
    883 			(m_f54Query_25.has_ctrl109))
    884 		reg_addr += CONTROL_109_SIZE;
    885 
    886 	/* control 110 */
    887 	if ((m_f54Query.has_query15) &&
    888 			(m_f54Query_15.has_query25) &&
    889 			(m_f54Query_25.has_query27) &&
    890 			(m_f54Query_27.has_ctrl110)) {
    891 		m_f54Control.reg_110.address = reg_addr;
    892 		reg_addr += CONTROL_110_SIZE;
    893 	}
    894 
    895 	/* control 111 */
    896 	if ((m_f54Query.has_query15) &&
    897 			(m_f54Query_15.has_query25) &&
    898 			(m_f54Query_25.has_query27) &&
    899 			(m_f54Query_27.has_ctrl111))
    900 		reg_addr += CONTROL_111_SIZE;
    901 
    902 	/* control 112 */
    903 	if ((m_f54Query.has_query15) &&
    904 			(m_f54Query_15.has_query25) &&
    905 			(m_f54Query_25.has_query27) &&
    906 			(m_f54Query_27.has_ctrl112))
    907 		reg_addr += CONTROL_112_SIZE;
    908 
    909 	/* control 113 */
    910 	if ((m_f54Query.has_query15) &&
    911 			(m_f54Query_15.has_query25) &&
    912 			(m_f54Query_25.has_query27) &&
    913 			(m_f54Query_27.has_ctrl113))
    914 		reg_addr += CONTROL_113_SIZE;
    915 
    916 	/* control 114 */
    917 	if ((m_f54Query.has_query15) &&
    918 			(m_f54Query_15.has_query25) &&
    919 			(m_f54Query_25.has_query27) &&
    920 			(m_f54Query_27.has_ctrl114))
    921 		reg_addr += CONTROL_114_SIZE;
    922 
    923 	/* control 115 */
    924 	if ((m_f54Query.has_query15) &&
    925 			(m_f54Query_15.has_query25) &&
    926 			(m_f54Query_25.has_query27) &&
    927 			(m_f54Query_27.has_query29) &&
    928 			(m_f54Query_29.has_ctrl115))
    929 		reg_addr += CONTROL_115_SIZE;
    930 
    931 	/* control 116 */
    932 	if ((m_f54Query.has_query15) &&
    933 			(m_f54Query_15.has_query25) &&
    934 			(m_f54Query_25.has_query27) &&
    935 			(m_f54Query_27.has_query29) &&
    936 			(m_f54Query_29.has_ctrl116))
    937 		reg_addr += CONTROL_116_SIZE;
    938 
    939 	/* control 117 */
    940 	if ((m_f54Query.has_query15) &&
    941 			(m_f54Query_15.has_query25) &&
    942 			(m_f54Query_25.has_query27) &&
    943 			(m_f54Query_27.has_query29) &&
    944 			(m_f54Query_29.has_ctrl117))
    945 		reg_addr += CONTROL_117_SIZE;
    946 
    947 	/* control 118 */
    948 	if ((m_f54Query.has_query15) &&
    949 			(m_f54Query_15.has_query25) &&
    950 			(m_f54Query_25.has_query27) &&
    951 			(m_f54Query_27.has_query29) &&
    952 			(m_f54Query_29.has_query30) &&
    953 			(m_f54Query_30.has_ctrl118))
    954 		reg_addr += CONTROL_118_SIZE;
    955 
    956 	/* control 119 */
    957 	if ((m_f54Query.has_query15) &&
    958 			(m_f54Query_15.has_query25) &&
    959 			(m_f54Query_25.has_query27) &&
    960 			(m_f54Query_27.has_query29) &&
    961 			(m_f54Query_29.has_query30) &&
    962 			(m_f54Query_30.has_ctrl119))
    963 		reg_addr += CONTROL_119_SIZE;
    964 
    965 	/* control 120 */
    966 	if ((m_f54Query.has_query15) &&
    967 			(m_f54Query_15.has_query25) &&
    968 			(m_f54Query_25.has_query27) &&
    969 			(m_f54Query_27.has_query29) &&
    970 			(m_f54Query_29.has_query30) &&
    971 			(m_f54Query_30.has_ctrl120))
    972 		reg_addr += CONTROL_120_SIZE;
    973 
    974 	/* control 121 */
    975 	if ((m_f54Query.has_query15) &&
    976 			(m_f54Query_15.has_query25) &&
    977 			(m_f54Query_25.has_query27) &&
    978 			(m_f54Query_27.has_query29) &&
    979 			(m_f54Query_29.has_query30) &&
    980 			(m_f54Query_30.has_ctrl121))
    981 		reg_addr += CONTROL_121_SIZE;
    982 
    983 	/* control 122 */
    984 	if ((m_f54Query.has_query15) &&
    985 			(m_f54Query_15.has_query25) &&
    986 			(m_f54Query_25.has_query27) &&
    987 			(m_f54Query_27.has_query29) &&
    988 			(m_f54Query_29.has_query30) &&
    989 			(m_f54Query_30.has_ctrl122_query31))
    990 		reg_addr += CONTROL_122_SIZE;
    991 
    992 	/* control 123 */
    993 	if ((m_f54Query.has_query15) &&
    994 			(m_f54Query_15.has_query25) &&
    995 			(m_f54Query_25.has_query27) &&
    996 			(m_f54Query_27.has_query29) &&
    997 			(m_f54Query_29.has_query30) &&
    998 			(m_f54Query_30.has_ctrl123))
    999 		reg_addr += CONTROL_123_SIZE;
   1000 
   1001 	/* control 124 reserved */
   1002 
   1003 	/* control 125 */
   1004 	if ((m_f54Query.has_query15) &&
   1005 			(m_f54Query_15.has_query25) &&
   1006 			(m_f54Query_25.has_query27) &&
   1007 			(m_f54Query_27.has_query29) &&
   1008 			(m_f54Query_29.has_query30) &&
   1009 			(m_f54Query_30.has_query32) &&
   1010 			(m_f54Query_32.has_ctrl125))
   1011 		reg_addr += CONTROL_125_SIZE;
   1012 
   1013 	/* control 126 */
   1014 	if ((m_f54Query.has_query15) &&
   1015 			(m_f54Query_15.has_query25) &&
   1016 			(m_f54Query_25.has_query27) &&
   1017 			(m_f54Query_27.has_query29) &&
   1018 			(m_f54Query_29.has_query30) &&
   1019 			(m_f54Query_30.has_query32) &&
   1020 			(m_f54Query_32.has_ctrl126))
   1021 		reg_addr += CONTROL_126_SIZE;
   1022 
   1023 	/* control 127 */
   1024 	if ((m_f54Query.has_query15) &&
   1025 			(m_f54Query_15.has_query25) &&
   1026 			(m_f54Query_25.has_query27) &&
   1027 			(m_f54Query_27.has_query29) &&
   1028 			(m_f54Query_29.has_query30) &&
   1029 			(m_f54Query_30.has_query32) &&
   1030 			(m_f54Query_32.has_ctrl127))
   1031 		reg_addr += CONTROL_127_SIZE;
   1032 
   1033 	/* controls 128 129 130 131 reserved */
   1034 
   1035 	/* control 132 */
   1036 	if ((m_f54Query.has_query15) &&
   1037 			(m_f54Query_15.has_query25) &&
   1038 			(m_f54Query_25.has_query27) &&
   1039 			(m_f54Query_27.has_query29) &&
   1040 			(m_f54Query_29.has_query30) &&
   1041 			(m_f54Query_30.has_query32) &&
   1042 			(m_f54Query_32.has_query33) &&
   1043 			(m_f54Query_33.has_ctrl132))
   1044 		reg_addr += CONTROL_132_SIZE;
   1045 
   1046 	/* control 133 */
   1047 	if ((m_f54Query.has_query15) &&
   1048 			(m_f54Query_15.has_query25) &&
   1049 			(m_f54Query_25.has_query27) &&
   1050 			(m_f54Query_27.has_query29) &&
   1051 			(m_f54Query_29.has_query30) &&
   1052 			(m_f54Query_30.has_query32) &&
   1053 			(m_f54Query_32.has_query33) &&
   1054 			(m_f54Query_33.has_ctrl133))
   1055 		reg_addr += CONTROL_133_SIZE;
   1056 
   1057 	/* control 134 */
   1058 	if ((m_f54Query.has_query15) &&
   1059 			(m_f54Query_15.has_query25) &&
   1060 			(m_f54Query_25.has_query27) &&
   1061 			(m_f54Query_27.has_query29) &&
   1062 			(m_f54Query_29.has_query30) &&
   1063 			(m_f54Query_30.has_query32) &&
   1064 			(m_f54Query_32.has_query33) &&
   1065 			(m_f54Query_33.has_ctrl134))
   1066 		reg_addr += CONTROL_134_SIZE;
   1067 
   1068 	/* controls 135 136 reserved */
   1069 
   1070 	/* control 137 */
   1071 	if ((m_f54Query.has_query15) &&
   1072 			(m_f54Query_15.has_query25) &&
   1073 			(m_f54Query_25.has_query27) &&
   1074 			(m_f54Query_27.has_query29) &&
   1075 			(m_f54Query_29.has_query30) &&
   1076 			(m_f54Query_30.has_query32) &&
   1077 			(m_f54Query_32.has_query35) &&
   1078 			(m_f54Query_35.has_ctrl137))
   1079 		reg_addr += CONTROL_137_SIZE;
   1080 
   1081 	/* control 138 */
   1082 	if ((m_f54Query.has_query15) &&
   1083 			(m_f54Query_15.has_query25) &&
   1084 			(m_f54Query_25.has_query27) &&
   1085 			(m_f54Query_27.has_query29) &&
   1086 			(m_f54Query_29.has_query30) &&
   1087 			(m_f54Query_30.has_query32) &&
   1088 			(m_f54Query_32.has_query35) &&
   1089 			(m_f54Query_35.has_ctrl138))
   1090 		reg_addr += CONTROL_138_SIZE;
   1091 
   1092 	/* control 139 */
   1093 	if ((m_f54Query.has_query15) &&
   1094 			(m_f54Query_15.has_query25) &&
   1095 			(m_f54Query_25.has_query27) &&
   1096 			(m_f54Query_27.has_query29) &&
   1097 			(m_f54Query_29.has_query30) &&
   1098 			(m_f54Query_30.has_query32) &&
   1099 			(m_f54Query_32.has_query35) &&
   1100 			(m_f54Query_35.has_ctrl139))
   1101 		reg_addr += CONTROL_139_SIZE;
   1102 
   1103 	/* control 140 */
   1104 	if ((m_f54Query.has_query15) &&
   1105 			(m_f54Query_15.has_query25) &&
   1106 			(m_f54Query_25.has_query27) &&
   1107 			(m_f54Query_27.has_query29) &&
   1108 			(m_f54Query_29.has_query30) &&
   1109 			(m_f54Query_30.has_query32) &&
   1110 			(m_f54Query_32.has_query35) &&
   1111 			(m_f54Query_35.has_ctrl140))
   1112 		reg_addr += CONTROL_140_SIZE;
   1113 
   1114 	/* control 141 reserved */
   1115 
   1116 	/* control 142 */
   1117 	if ((m_f54Query.has_query15) &&
   1118 			(m_f54Query_15.has_query25) &&
   1119 			(m_f54Query_25.has_query27) &&
   1120 			(m_f54Query_27.has_query29) &&
   1121 			(m_f54Query_29.has_query30) &&
   1122 			(m_f54Query_30.has_query32) &&
   1123 			(m_f54Query_32.has_query33) &&
   1124 			(m_f54Query_33.has_query36) &&
   1125 			(m_f54Query_36.has_ctrl142))
   1126 		reg_addr += CONTROL_142_SIZE;
   1127 
   1128 	/* control 143 */
   1129 	if ((m_f54Query.has_query15) &&
   1130 			(m_f54Query_15.has_query25) &&
   1131 			(m_f54Query_25.has_query27) &&
   1132 			(m_f54Query_27.has_query29) &&
   1133 			(m_f54Query_29.has_query30) &&
   1134 			(m_f54Query_30.has_query32) &&
   1135 			(m_f54Query_32.has_query33) &&
   1136 			(m_f54Query_33.has_query36) &&
   1137 			(m_f54Query_36.has_ctrl143))
   1138 		reg_addr += CONTROL_143_SIZE;
   1139 
   1140 	/* control 144 */
   1141 	if ((m_f54Query.has_query15) &&
   1142 			(m_f54Query_15.has_query25) &&
   1143 			(m_f54Query_25.has_query27) &&
   1144 			(m_f54Query_27.has_query29) &&
   1145 			(m_f54Query_29.has_query30) &&
   1146 			(m_f54Query_30.has_query32) &&
   1147 			(m_f54Query_32.has_query33) &&
   1148 			(m_f54Query_33.has_query36) &&
   1149 			(m_f54Query_36.has_ctrl144))
   1150 		reg_addr += CONTROL_144_SIZE;
   1151 
   1152 	/* control 145 */
   1153 	if ((m_f54Query.has_query15) &&
   1154 			(m_f54Query_15.has_query25) &&
   1155 			(m_f54Query_25.has_query27) &&
   1156 			(m_f54Query_27.has_query29) &&
   1157 			(m_f54Query_29.has_query30) &&
   1158 			(m_f54Query_30.has_query32) &&
   1159 			(m_f54Query_32.has_query33) &&
   1160 			(m_f54Query_33.has_query36) &&
   1161 			(m_f54Query_36.has_ctrl145))
   1162 		reg_addr += CONTROL_145_SIZE;
   1163 
   1164 	/* control 146 */
   1165 	if ((m_f54Query.has_query15) &&
   1166 			(m_f54Query_15.has_query25) &&
   1167 			(m_f54Query_25.has_query27) &&
   1168 			(m_f54Query_27.has_query29) &&
   1169 			(m_f54Query_29.has_query30) &&
   1170 			(m_f54Query_30.has_query32) &&
   1171 			(m_f54Query_32.has_query33) &&
   1172 			(m_f54Query_33.has_query36) &&
   1173 			(m_f54Query_36.has_ctrl146))
   1174 		reg_addr += CONTROL_146_SIZE;
   1175 
   1176 	/* control 147 */
   1177 	if ((m_f54Query.has_query15) &&
   1178 			(m_f54Query_15.has_query25) &&
   1179 			(m_f54Query_25.has_query27) &&
   1180 			(m_f54Query_27.has_query29) &&
   1181 			(m_f54Query_29.has_query30) &&
   1182 			(m_f54Query_30.has_query32) &&
   1183 			(m_f54Query_32.has_query33) &&
   1184 			(m_f54Query_33.has_query36) &&
   1185 			(m_f54Query_36.has_query38) &&
   1186 			(m_f54Query_38.has_ctrl147))
   1187 		reg_addr += CONTROL_147_SIZE;
   1188 
   1189 	/* control 148 */
   1190 	if ((m_f54Query.has_query15) &&
   1191 			(m_f54Query_15.has_query25) &&
   1192 			(m_f54Query_25.has_query27) &&
   1193 			(m_f54Query_27.has_query29) &&
   1194 			(m_f54Query_29.has_query30) &&
   1195 			(m_f54Query_30.has_query32) &&
   1196 			(m_f54Query_32.has_query33) &&
   1197 			(m_f54Query_33.has_query36) &&
   1198 			(m_f54Query_36.has_query38) &&
   1199 			(m_f54Query_38.has_ctrl148))
   1200 		reg_addr += CONTROL_148_SIZE;
   1201 
   1202 	/* control 149 */
   1203 	if ((m_f54Query.has_query15) &&
   1204 			(m_f54Query_15.has_query25) &&
   1205 			(m_f54Query_25.has_query27) &&
   1206 			(m_f54Query_27.has_query29) &&
   1207 			(m_f54Query_29.has_query30) &&
   1208 			(m_f54Query_30.has_query32) &&
   1209 			(m_f54Query_32.has_query33) &&
   1210 			(m_f54Query_33.has_query36) &&
   1211 			(m_f54Query_36.has_query38) &&
   1212 			(m_f54Query_38.has_ctrl149)) {
   1213 		m_f54Control.reg_149.address = reg_addr;
   1214 		reg_addr += CONTROL_149_SIZE;
   1215 	}
   1216 
   1217 	return TEST_SUCCESS;
   1218 }
   1219 
   1220 int F54Test::ReadF55Queries()
   1221 {
   1222 	int retval;
   1223 	unsigned char ii;
   1224 	unsigned char rx_electrodes = m_f54Query.num_of_rx_electrodes;
   1225 	unsigned char tx_electrodes = m_f54Query.num_of_tx_electrodes;
   1226 
   1227 	retval = m_device.Read(m_f55.GetQueryBase(),
   1228 			m_f55Query.data,
   1229 			sizeof(m_f55Query.data));
   1230 	if (retval < 0) {
   1231 		return retval;
   1232 	}
   1233 
   1234 	if (!m_f55Query.has_sensor_assignment)
   1235 	{
   1236 		m_txAssigned = tx_electrodes;
   1237 		m_rxAssigned = rx_electrodes;
   1238 		m_txAssignment = NULL;
   1239 		m_rxAssignment = NULL;
   1240 		return TEST_SUCCESS;
   1241 	}
   1242 
   1243 	if (m_txAssignment != NULL) delete [] m_txAssignment;
   1244 	if (m_rxAssignment != NULL) delete [] m_rxAssignment;
   1245 	m_txAssignment = new unsigned char[tx_electrodes];
   1246 	m_rxAssignment = new unsigned char[rx_electrodes];
   1247 
   1248 	retval = m_device.Read(m_f55.GetControlBase() + SENSOR_TX_MAPPING_OFFSET,
   1249 			m_txAssignment,
   1250 			tx_electrodes);
   1251 	if (retval < 0) {
   1252 		goto exit;
   1253 	}
   1254 
   1255 	retval = m_device.Read(m_f55.GetControlBase() + SENSOR_RX_MAPPING_OFFSET,
   1256 			m_rxAssignment,
   1257 			rx_electrodes);
   1258 	if (retval < 0) {
   1259 		goto exit;
   1260 	}
   1261 
   1262 	m_txAssigned = 0;
   1263 	for (ii = 0; ii < tx_electrodes; ii++) {
   1264 		if (m_txAssignment[ii] != 0xff)
   1265 			m_txAssigned++;
   1266 	}
   1267 
   1268 	m_rxAssigned = 0;
   1269 	for (ii = 0; ii < rx_electrodes; ii++) {
   1270 		if (m_rxAssignment[ii] != 0xff)
   1271 			m_rxAssigned++;
   1272 	}
   1273 
   1274 	return TEST_SUCCESS;
   1275 
   1276 exit:
   1277 	if (m_txAssignment != NULL)
   1278 	{
   1279 		delete [] m_txAssignment;
   1280 		m_txAssignment = NULL;
   1281 	}
   1282 	if (m_rxAssignment != NULL)
   1283 	{
   1284 		delete [] m_rxAssignment;
   1285 		m_rxAssignment = NULL;
   1286 	}
   1287 
   1288 	return retval;
   1289 }
   1290 
   1291 int F54Test::SetF54Interrupt()
   1292 {
   1293 	int retval;
   1294 	unsigned char mask = m_f54.GetInterruptMask();
   1295 	unsigned char zero = 0;
   1296 	unsigned int i;
   1297 
   1298 	for (i = 0; i < m_device.GetNumInterruptRegs(); i++)
   1299 	{
   1300 		if (i == m_f54.GetInterruptRegNum())
   1301 		{
   1302 			retval = m_device.Write(m_f54.GetControlBase() + 1 + i, &mask, 1);
   1303 		}
   1304 		else
   1305 		{
   1306 			retval = m_device.Write(m_f54.GetControlBase() + 1 + i, &zero, 1);
   1307 		}
   1308 
   1309 		if (retval < 0)
   1310 			return retval;
   1311 	}
   1312 	return TEST_SUCCESS;
   1313 }
   1314 
   1315 int F54Test::DoF54Command(unsigned char command)
   1316 {
   1317 	int retval;
   1318 
   1319 	retval = m_device.Write(m_f54.GetCommandBase(), &command, 1);
   1320 	if (retval < 0)
   1321 		return retval;
   1322 
   1323 	retval = WaitForF54CommandCompletion();
   1324 	if (retval != TEST_SUCCESS)
   1325 		return retval;
   1326 
   1327 	return TEST_SUCCESS;
   1328 }
   1329 
   1330 int F54Test::WaitForF54CommandCompletion()
   1331 {
   1332 	int retval;
   1333 	unsigned char value;
   1334 	unsigned char timeout_count;
   1335 
   1336 	timeout_count = 0;
   1337 	do {
   1338 		retval = m_device.Read(m_f54.GetCommandBase(),
   1339 				&value,
   1340 				sizeof(value));
   1341 		if (retval < 0)
   1342 			return retval;
   1343 
   1344 		if (value == 0x00)
   1345 			break;
   1346 
   1347 		Sleep(100);
   1348 		timeout_count++;
   1349 	} while (timeout_count < COMMAND_TIMEOUT_100MS);
   1350 
   1351 	if (timeout_count == COMMAND_TIMEOUT_100MS) {
   1352 		return -ETIMEDOUT;
   1353 	}
   1354 
   1355 	return TEST_SUCCESS;
   1356 }
   1357 
   1358 int F54Test::ReadF54Report()
   1359 {
   1360 	int retval;
   1361 	unsigned char report_index[2];
   1362 
   1363 	if (m_reportBufferSize < m_reportSize) {
   1364 		if (m_reportData != NULL)
   1365 			delete [] m_reportData;
   1366 		m_reportData = new unsigned char[m_reportSize];
   1367 		if (!m_reportData) {
   1368 			m_reportBufferSize = 0;
   1369 			retval = TEST_FAIL_MEMORY_ALLOCATION;
   1370 			goto exit;
   1371 		}
   1372 		m_reportBufferSize = m_reportSize;
   1373 	}
   1374 
   1375 	report_index[0] = 0;
   1376 	report_index[1] = 0;
   1377 
   1378 	retval = m_device.Write(m_f54.GetDataBase() + REPORT_INDEX_OFFSET,
   1379 				report_index,
   1380 				sizeof(report_index));
   1381 
   1382 	if (retval < 0)
   1383 		goto exit;
   1384 
   1385 	retval = m_device.Read(m_f54.GetDataBase() + REPORT_DATA_OFFSET,
   1386 				m_reportData,
   1387 				m_reportSize);
   1388 	if (retval < 0)
   1389 		goto exit;
   1390 
   1391 	return TEST_SUCCESS;
   1392 
   1393 exit:
   1394 	if (m_reportData != NULL)
   1395 	{
   1396 		delete [] m_reportData;
   1397 		m_reportData = NULL;
   1398 	}
   1399 
   1400 	return retval;
   1401 }
   1402 
   1403 int F54Test::ShowF54Report()
   1404 {
   1405 	unsigned int ii;
   1406 	unsigned int jj;
   1407 	unsigned int tx_num = m_txAssigned;
   1408 	unsigned int rx_num = m_rxAssigned;
   1409 	char *report_data_8;
   1410 	short *report_data_16;
   1411 	int *report_data_32;
   1412 	unsigned int *report_data_u32;
   1413 	char buf[256];
   1414 
   1415 	switch (m_reportType) {
   1416 	case F54_8BIT_IMAGE:
   1417 		report_data_8 = (char *)m_reportData;
   1418 		for (ii = 0; ii < m_reportSize; ii++) {
   1419 			sprintf(buf, "%03d: %d\n",
   1420 					ii, *report_data_8);
   1421 			m_display.Output(buf);
   1422 			report_data_8++;
   1423 		}
   1424 		break;
   1425 	case F54_16BIT_IMAGE:
   1426 	case F54_RAW_16BIT_IMAGE:
   1427 	case F54_TRUE_BASELINE:
   1428 	case F54_FULL_RAW_CAP:
   1429 	case F54_FULL_RAW_CAP_NO_RX_COUPLING:
   1430 	case F54_SENSOR_SPEED:
   1431 		report_data_16 = (short *)m_reportData;
   1432 		sprintf(buf, "tx = %d\nrx = %d\n",
   1433 				tx_num, rx_num);
   1434 		m_display.Output(buf);
   1435 
   1436 		for (ii = 0; ii < tx_num; ii++) {
   1437 			for (jj = 0; jj < (rx_num - 1); jj++) {
   1438 				sprintf(buf, "%-4d ",
   1439 						*report_data_16);
   1440 				report_data_16++;
   1441 				m_display.Output(buf);
   1442 			}
   1443 			sprintf(buf, "%-4d\n",
   1444 					*report_data_16);
   1445 			m_display.Output(buf);
   1446 			report_data_16++;
   1447 		}
   1448 		break;
   1449 	case F54_HIGH_RESISTANCE:
   1450 	case F54_FULL_RAW_CAP_MIN_MAX:
   1451 		report_data_16 = (short *)m_reportData;
   1452 		for (ii = 0; ii < m_reportSize; ii += 2) {
   1453 			sprintf(buf, "%03d: %d\n",
   1454 					ii / 2, *report_data_16);
   1455 			m_display.Output(buf);
   1456 			report_data_16++;
   1457 		}
   1458 		break;
   1459 	case F54_ABS_RAW_CAP:
   1460 		report_data_u32 = (unsigned int *)m_reportData;
   1461 		sprintf(buf, "rx ");
   1462 		m_display.Output(buf);
   1463 
   1464 		for (ii = 0; ii < rx_num; ii++) {
   1465 			sprintf(buf, "     %2d", ii);
   1466 			m_display.Output(buf);
   1467 		}
   1468 		sprintf(buf, "\n");
   1469 		m_display.Output(buf);
   1470 
   1471 		sprintf(buf, "   ");
   1472 		m_display.Output(buf);
   1473 
   1474 		for (ii = 0; ii < rx_num; ii++) {
   1475 			sprintf(buf, "  %5u",
   1476 					*report_data_u32);
   1477 			report_data_u32++;
   1478 			m_display.Output(buf);
   1479 		}
   1480 		sprintf(buf, "\n");
   1481 		m_display.Output(buf);
   1482 
   1483 		sprintf(buf, "tx ");
   1484 		m_display.Output(buf);
   1485 
   1486 		for (ii = 0; ii < tx_num; ii++) {
   1487 			sprintf(buf, "     %2d", ii);
   1488 			m_display.Output(buf);
   1489 		}
   1490 		sprintf(buf, "\n");
   1491 		m_display.Output(buf);
   1492 
   1493 		sprintf(buf, "   ");
   1494 		m_display.Output(buf);
   1495 
   1496 		for (ii = 0; ii < tx_num; ii++) {
   1497 			sprintf(buf, "  %5u",
   1498 					*report_data_u32);
   1499 			report_data_u32++;
   1500 			m_display.Output(buf);
   1501 		}
   1502 		sprintf(buf, "\n");
   1503 		m_display.Output(buf);
   1504 
   1505 		break;
   1506 	case F54_ABS_DELTA_CAP:
   1507 		report_data_32 = (int *)m_reportData;
   1508 		sprintf(buf, "rx ");
   1509 		m_display.Output(buf);
   1510 
   1511 		for (ii = 0; ii < rx_num; ii++) {
   1512 			sprintf(buf, "     %2d", ii);
   1513 			m_display.Output(buf);
   1514 		}
   1515 		sprintf(buf, "\n");
   1516 		m_display.Output(buf);
   1517 
   1518 		sprintf(buf, "   ");
   1519 		m_display.Output(buf);
   1520 
   1521 		for (ii = 0; ii < rx_num; ii++) {
   1522 			sprintf(buf, "  %5d",
   1523 					*report_data_32);
   1524 			report_data_32++;
   1525 			m_display.Output(buf);
   1526 		}
   1527 		sprintf(buf, "\n");
   1528 		m_display.Output(buf);
   1529 
   1530 		sprintf(buf, "tx ");
   1531 		m_display.Output(buf);
   1532 
   1533 		for (ii = 0; ii < tx_num; ii++) {
   1534 			sprintf(buf, "     %2d", ii);
   1535 			m_display.Output(buf);
   1536 		}
   1537 		sprintf(buf, "\n");
   1538 		m_display.Output(buf);
   1539 
   1540 		sprintf(buf, "   ");
   1541 		m_display.Output(buf);
   1542 
   1543 		for (ii = 0; ii < tx_num; ii++) {
   1544 			sprintf(buf, "  %5d",
   1545 					*report_data_32);
   1546 			report_data_32++;
   1547 			m_display.Output(buf);
   1548 		}
   1549 		sprintf(buf, "\n");
   1550 		m_display.Output(buf);
   1551 
   1552 		break;
   1553 	default:
   1554 		for (ii = 0; ii < m_reportSize; ii++) {
   1555 			sprintf(buf, "%03d: 0x%02x\n",
   1556 					ii, m_reportData[ii]);
   1557 			m_display.Output(buf);
   1558 		}
   1559 		break;
   1560 	}
   1561 
   1562 	sprintf(buf, "\n");
   1563 	m_display.Output(buf);
   1564 
   1565 	m_display.Reflesh();
   1566 
   1567 	return TEST_SUCCESS;
   1568 }
   1569