123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548 |
- /*
- * Copyright (c) 2017 Actions Semiconductor Co., Ltd
- *
- * SPDX-License-Identifier: Apache-2.0
- */
- /**
- * @file
- * @brief TP Keyboard driver for Actions SoC
- */
- #define ir_protocol_param_init
- #define capture_param_init
- #include <shell/shell.h>
- #include <drivers/input/input_dev.h>
- #include <ir_data_hal.h>
- #include <ir_protocol_hal.h>
- #include <logging/log.h>
- #include "IR_context.h"
- struct capture_handle cp_handle;
- static int capture_acts_rate_check(u32_t code_rate, u32_t carrier_rate)
- {
- if((code_rate - carrier_rate) * (code_rate - carrier_rate) > 4)
- return -1;
- return 0;
- }
- static int capture_acts_lc_length(u32_t code)
- {
- u32_t lc_num = 0;
- u32_t temp_val = 0;
- while(code) {
- temp_val = code & 1;
- code = code >> 1;
- if((code & 1) != temp_val)
- lc_num++;
- }
- return lc_num;
- }
- static int capture_acts_halfcode_compare(uint32_t code, uint32_t cp, u32_t threshold)
- {
- int temp_val = 0;
- u32_t threshold_val = 0;
- temp_val = (code & 0x7fff) - (cp & 0x7fff);
- threshold_val = (cp&0x7fff)*threshold/100;
- if(temp_val * temp_val > threshold_val * threshold_val)
- return -EIO;
- return 0;
- }
- static int capture_acts_lead_check(u32_t *data, u32_t bit_length, u32_t code, u32_t threshold)
- {
- u32_t lc_num, temp_val, lc_length;
- u32_t irpro_buf[32];
- memset(irpro_buf, 0, 32);
- lc_num = 0;
- while(code) {
- irpro_buf[lc_num] = irpro_buf[lc_num] + 1;
- temp_val = code & 1;
- code = code >> 1;
- if((code & 1) != temp_val)
- lc_num++;
- }
- for(int j = 0; j < lc_num; j++) {
- lc_length = irpro_buf[lc_num - 1 - j] * bit_length;
- temp_val = data[j] & 0x7fff;
- if(j == (lc_num - 1)) {
- if(temp_val > (lc_length + threshold*bit_length/100))
- return temp_val -lc_length - threshold*bit_length/200;
- }
- if((temp_val - lc_length) * (temp_val - lc_length) > (threshold*bit_length/100)*(threshold*bit_length/100))
- return -2;
- }
- return 0;
- }
- static int capture_acts_code_compare(uint32_t code_pre, uint32_t code_post, uint32_t cp_pre, uint32_t cp_post, u32_t threshold)
- {
- int temp_val = 0;
- u32_t threshold_val = 0;
- if((code_pre & 0x8000) != (cp_pre & 0x8000))
- return -EIO;
- if((code_post & 0x8000) != (cp_post & 0x8000))
- return -EIO;
- temp_val = (code_pre & 0x7fff) - (cp_pre & 0x7fff);
- threshold_val = (cp_pre&0x7fff)*threshold/100;
- if(temp_val * temp_val > threshold_val * threshold_val)
- return -EIO;
- threshold_val = (cp_post&0x7fff)*threshold/100;
- if(code_post < (cp_post + threshold_val))//belong to a complete message
- return 0;
- temp_val = (code_post & 0x7fff) - (cp_post & 0x7fff) - (cp_post & 0x7fff)*threshold/200;//post including a next message
- return temp_val;
- }
- static int capture_acts_cv(u32_t *data, u32_t offset, ir_receive_param_t *param, u32_t threshold, u32_t leader_hc, u32_t *decode)
- {
- int data_pre, data_post;
- uint32_t code_off;
- int temp_val, temp_data;
- uint32_t code0_pre, code0_post, code1_pre, code1_post;
- uint32_t tr0_pre, tr0_post, tr1_pre, tr1_post;
- int cp_result[4];
- bool code1_discriminate = false;
- code0_pre = (param->ir_0_code & 0x8000) | ((param->ir_0_code & 0x7f00) >> 8) * param->code_bit_length;
- code0_post = (param->ir_0_code & 0x80) << 8 | (param->ir_0_code & 0x7f) * param->code_bit_length;
- code1_pre = (param->ir_1_code & 0x8000) | ((param->ir_1_code & 0x7f00) >> 8) * param->code_bit_length;
- code1_post = (param->ir_1_code & 0x80) << 8 | (param->ir_1_code & 0x7f) * param->code_bit_length;
- if(param->ir_trc_loc) {
- tr0_pre = (param->ir_tr0_code & 0x8000) | ((param->ir_tr0_code & 0x7f00) >> 8) * param->code_bit_length;
- tr0_post = (param->ir_tr0_code & 0x80) << 8 | (param->ir_tr0_code & 0x7f) * param->code_bit_length;
- tr1_pre = (param->ir_tr1_code & 0x8000) | ((param->ir_tr1_code & 0x7f00) >> 8) * param->code_bit_length;
- tr1_post = (param->ir_tr1_code & 0x80) << 8 | (param->ir_tr1_code & 0x7f) * param->code_bit_length;
- }
- code_off = decode[0] = decode[1] = 0;
- if(leader_hc) {
- offset = offset - 1;
- data_pre = (data[offset] & 0x8000) | leader_hc;
- } else
- data_pre = data[offset];// a complete message including data_pre | data_ post
- data_post = data[offset + 1];
- for(int j = offset; j < 99; j++) {
- code_off++;
- if(data[j] == 0)
- break;
- if(((data[j] & 0x8000) == 0) && ((data[j] & 0x7fff) > param->ir_max_code))
- break;
- if(code_off > param->ir_dc_length + 1)
- return -3;
- if(code_off > param->ir_dc_length)
- continue;
- if(j > offset)
- data_post = data[j + 1];
- temp_val = capture_acts_code_compare(data_pre, data_post, code0_pre, code0_post, threshold);
- if(temp_val > 0) {
- cp_result[0] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_val, code0_pre, threshold);
- cp_result[1] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_val, code1_pre, threshold);
- cp_result[2] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_val, tr0_pre, threshold);
- cp_result[3] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_val, tr1_pre, threshold);
- if(cp_result[3]&&cp_result[2]&&cp_result[1]&&cp_result[0])
- temp_val = -5;
- }
- if(temp_val != 0) {
- temp_data = capture_acts_code_compare(data_pre, data_post, code1_pre, code1_post, threshold);
- if(temp_data > 0) {
- cp_result[0] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_data, code0_pre, threshold);
- cp_result[1] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_data, code1_pre, threshold);
- cp_result[2] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_data, tr0_pre, threshold);
- cp_result[3] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_data, tr1_pre, threshold);
-
- if(cp_result[3]&&cp_result[2]&&cp_result[1]&&cp_result[0])
- temp_data = -5;
- }
- if(temp_data >= 0) {
- temp_val = temp_data;
- code1_discriminate = true;
- }
- }
- if(temp_val >= 0) {
- if(code1_discriminate) {
- if(param->ir_dc_length - code_off > 32)
- decode[1] |= 1 << (param->ir_dc_length - code_off - 32);
- else
- decode[0] |= 1 << (param->ir_dc_length - code_off);
- }
- code1_discriminate = false;
- }
- if(temp_val > 0) {//compare status and including next message
- data_pre = (data_post & 0x8000) | temp_val;
- continue;
- } else if(temp_val == 0) {//campare status
- j++;
- data_pre = data[j + 1];
- continue;
- }
- if(param->ir_trc_loc) {
- temp_val = capture_acts_code_compare(data_pre, data_post, tr0_pre, tr0_post, threshold);
- if(temp_val > 0) {
- cp_result[0] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_val, code0_pre, threshold);
- cp_result[1] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_val, code1_pre, threshold);
- cp_result[2] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_val, tr0_pre, threshold);
- cp_result[3] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_val, tr1_pre, threshold);
- if(cp_result[3]&&cp_result[2]&&cp_result[1]&&cp_result[0])
- temp_val = -5;
- }
- if(temp_val != 0) {
- temp_data = capture_acts_code_compare(data_pre, data_post, tr1_pre, tr1_post, threshold);
- if(temp_data > 0) {
- cp_result[0] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_data, code0_pre, threshold);
- cp_result[1] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_data, code1_pre, threshold);
- cp_result[2] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_data, tr0_pre, threshold);
- cp_result[3] = capture_acts_halfcode_compare((data_post & 0x8000) | temp_data, tr1_pre, threshold);
-
- if(cp_result[3]&&cp_result[2]&&cp_result[1]&&cp_result[0])
- temp_data = -5;
- }
- if(temp_data >= 0) {
- temp_val = temp_data;
- code1_discriminate = true;
- }
- }
- if(temp_val >= 0) {
- if(code1_discriminate) {
- if(param->ir_dc_length - code_off > 32)
- decode[1] |= 1 << (param->ir_dc_length - code_off - 32);
- else
- decode[0] |= 1 << (param->ir_dc_length - code_off);
- }
- code1_discriminate = false;
- }
- if(temp_val > 0) {//compare status and including next message
- data_pre = (data_post & 0x8000) | temp_val;
- continue;
- } else if(temp_val == 0) {//campare status
- j++;
- data_pre = data[j + 1];
- continue;
- }
- }
- return -3;
- }
- if(decode[1])
- printk("decode:0x%x%x\n", decode[1], decode[0]);
- else
- printk("decode:0x%x\n", decode[0]);
- return 0;
- }
- static int capture_acts_Tf(u32_t *data, u32_t Tf, u32_t lc_bit_length, u32_t threshold)
- {
- int data_val, temp_val;
- int j = 0;
- temp_val = 0;
- for(j = 0; j < 100; j++) {
- data_val = data[j] & 0x7fff;
- temp_val += data_val/10;
- if(data_val == 0)
- break;
- if(((data[j] & 0x8000) == 0) && ((data[j] & 0x7fff) > lc_bit_length))
- break;
- }
- for(; j < 100; j++) {
- data_val = data[j] & 0x8000;
- if(data_val != 0) {
- break;
- }
- data_val = data[j] & 0x7fff;
- if(data_val == 0)
- temp_val += 3277/3;
- else
- temp_val += data_val/10;
- }
- if(temp_val < Tf - Tf*threshold/100)
- return -4;
- return 0;
- }
- static u32_t capture_acts_ic(u32_t *decode, ir_receive_param_t *param)
- {
- u32_t data[2];
- data[0] = ((decode[0] >> param->ir_ic_co) | (decode[1] << (32 - param->ir_ic_co)))¶m->ir_ic_mask;
- data[1] = (decode[0] >> param->ir_ic_ico)¶m->ir_ic_mask;
- if(data[0] & data[1])
- return -5;
- return 0;
- }
- static int capture_acts_discriminate(struct capture_data *data, u32_t *decode)
- {
- u32_t irpro_param1, irpro_param2, irpro_param3;
- int i, result;
- u32_t leader_hc;
-
- result = 0;
- for(i = 0; i < Protocols_MAX; i++) {
- irpro_param3 = ir_protocol_param[i].ir_threshold_val;
- /* rate check */
- if(ir_protocol_param[i].ir_cr_check_en) {
- if(capture_acts_rate_check(ir_protocol_param[i].ir_cr_rate ,
- data->carrier_rate)) {
- result = -1;
- continue;
- }
- }
- /* lead check */
- if(ir_protocol_param[i].ir_lc_check_en) {
- irpro_param1 = ir_protocol_param[i].ir_lc_bit_length;
- irpro_param2 = ir_protocol_param[i].ir_lc_code;
- leader_hc = capture_acts_lead_check(data->capture_data, irpro_param1,
- irpro_param2, irpro_param3);
- if(leader_hc < 0) {
- result = -2;
- continue;
- }
- }
- /* code check */
- if(ir_protocol_param[i].ir_cv_check_en) {
- irpro_param1 = capture_acts_lc_length(ir_protocol_param[i].ir_lc_code);
- result = capture_acts_cv(data->capture_data, irpro_param1,
- &ir_protocol_param[i], irpro_param3, leader_hc, decode);
- if(result == -3) {
- continue;
- }
- }
- /* Tf check */
- if(ir_protocol_param[i].ir_Tf_check_en) {
- irpro_param1 = ir_protocol_param[i].ir_Tf_length;
- if(capture_acts_Tf(data->capture_data, irpro_param1,
- ir_protocol_param[i].ir_max_code, irpro_param3)) {
- result = -4;
- continue;
- }
- }
- /* ir inverse code check */
- if(ir_protocol_param[i].ir_ic_check_en) {
- irpro_param1 = capture_acts_lc_length(ir_protocol_param[i].ir_lc_code);
- if(capture_acts_ic(decode, &ir_protocol_param[i])) {
- result = -5;
- continue;
- }
- }
- break;
- }
- if(i < Protocols_MAX)
- return i;
- else
- return result;
- }
- static int capture_acts_protocol(int ret)
- {
- u32_t protocol;
- switch(ret) {
- case PWM_IR_6122:
- protocol = IR_uPD6121;
- printk("IR protocol is nec\n");
- break;
- case PWM_IR_9012:
- protocol = IR_9012;
- printk("IR protocol is 9012\n");
- break;
- case PWM_IR_RC6:
- protocol = IR_RC6_dat1;
- printk("IR protocol is RC6\n");
- break;
- case PWM_IR_50462:
- protocol = IR_50462;
- printk("IR protocol is 50462\n");
- break;
- case PWM_IR_M50560:
- protocol = IR_M50560_dat1;
- printk("IR protocol is 50560\n");
- break;
- case PWM_IR_RC5X:
- protocol = IR_RC5;
- printk("IR protocol is rc5x\n");
- break;
- case PWM_IR_7461:
- protocol = IR_7461;
- printk("IR protocol is 7461\n");
- break;
- case PWM_IR_3004:
- protocol = IR_3004;
- printk("IR protocol is 3004\n");
- break;
- case PWM_IR_RCA:
- protocol = IR_RCA;
- printk("IR protocol is RCA\n");
- break;
- default:
- printk("can not find right protocol: %d\n", ret);
- return -ENOTSUP;
- }
- return protocol;
- }
- static void capture_data_dump(struct capture_data *data)
- {
- printk("rate:%dkhz\n", data->carrier_rate);
- for(int i = 0;i < 100;i++) {
- data->capture_data[i] = (data->capture_data[i] & 0x8000) | ((data->capture_data[i] & 0x7fff)/3);//cycle to us
- if(i%10 == 9) {
- printk("%d0%d\n", ((data->capture_data[i] & 0x8000) >> 15), (data->capture_data[i] & 0x7fff));
- continue;
- }
- printk("%d0%d ", ((data->capture_data[i] & 0x8000) >> 15), (data->capture_data[i] & 0x7fff));
- }
- }
- void capture_notify_callback(struct device *dev, struct input_value *val)
- {
- struct capture_handle * handle = &cp_handle;
- struct input_value report_val;
- uint32_t decode_data[2] = {0x11,0x22};
- struct capture_data data;
- int result;
- data.capture_data = val->ir.protocol.data;
- data.carrier_rate = val->ir.protocol.carry_rate;
- capture_data_dump(&data);
- result = capture_acts_discriminate(&data, decode_data);
- result = capture_acts_protocol(result);
- report_val.ir.protocol.mode = result;
- report_val.ir.protocol.data = decode_data;
- handle->capture_notify(NULL, &report_val);
- }
- struct capture_handle * capture_device_open(capture_notify_cb cb, char * dev_name)
- {
- struct capture_handle * handle = &cp_handle;
- if(handle == NULL)
- {
- printk("capture device in mem_malloc failed need %d bytes ",(int)sizeof(struct capture_handle));
- return NULL;
- }
- handle->input_dev = (struct device *)device_get_binding(dev_name);
- if (!handle->input_dev) {
- printk("cannot found capture dev %s\n",dev_name);
- return NULL;
- }
- input_dev_enable(handle->input_dev);
- input_dev_register_notify(handle->input_dev, capture_notify_callback);
- handle->capture_notify = cb;
- return handle;
- }
- void capture_device_close(void * handle)
- {
- struct capture_handle * capture = &cp_handle;
- input_dev_unregister_notify(capture->input_dev, capture->capture_notify);
- input_dev_disable(capture->input_dev);
- }
- void capture_device_abort_cb(void * handle)
- {
- struct capture_handle * capture = &cp_handle;
- input_dev_unregister_notify(capture->input_dev, capture->capture_notify);
- }
- void capture_device_enable_cb(void * handle)
- {
- struct capture_handle * capture = &cp_handle;
- input_dev_register_notify(capture->input_dev, capture->capture_notify);
- }
|