blob: 3626666b1ba0d89595c9f63be1f3ca9ecbca13da [file] [log] [blame]
/******************************************************************************
* @file app_ir.c
*
* @brief for TLSR chips
*
* @author public@telink-semi.com;
* @date Sep. 30, 2010
*
* @attention
*
* Copyright (C) 2019-2020 Telink Semiconductor (Shanghai) Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************/
#include "tl_common.h"
#include "drivers.h"
#include "../common/blt_soft_timer.h"
#include "app_ir.h"
#include "rc_ir.h"
#include "app_ir.h"
#include "app_flash_write.h"
#include "app_ui.h"
#include "app_custom.h"
#include "../../stack/ble/host/attr/att.h"
#if APP_IR_OVER_BLE
extern void google_reset_rsp_delay(void);
extern u8 is_mic_enable(void);
//programming timeout 30s
#define PROGRAMMING_TIMEOUT 30000000
//Regularly query whether the current time can be erased
#define FLASH_ERASE_TIMEOUT 100000
#define INVALID_KEY_ID 0xFF00
#define MAX_CODE_LENGTH 300 /* The maximum number of ir codes for each key. */
#define MAX_KEY_COUNT 5 /* The maximum number of key for ir programming.*/
#define KEY_IDX_NULL 0xff
typedef struct{
u16 key_id; //Key ID, comes from ATV (host keyid)
u16 code_size;
u8 button_idx; //button index, based on enum in firmware
u8 code[MAX_CODE_LENGTH];
}key_code_t;
typedef struct{
u32 release_timer;
u32 repeat_delay;
}ir_repeat_delay_t;
typedef struct {
u8 programming_start;
u8 programmed_key_count;
u8 key_notification_flag;
u16 current_programming_key_id;
}ir_programming_key_t;
typedef struct {
u16 ir_code_pos;
u16 ir_keycode_total_len;
u8 ir_current_button;
}ir_keycode_merge_t;
typedef struct {
u8 ir_save_en;
u8 ir_save_button;
u16 ir_save_pos;
}ir_save_t;
typedef struct {
u8 duty_cycle;
u16 carrier_frequency;
u8 current_programming_key_send;
u8 odd_or_even_press;
u8 is_key_programming;
u8 programming_timer;
u8 ir_suppress[MAX_KEY_COUNT];
ir_repeat_delay_t ir_repeat_delay;
ir_programming_key_t ir_programming;
ir_keycode_merge_t ir_merge;
ir_save_t ir_save;
}ir_app_parm_t;
typedef struct {
u16 key_id;
u8 button_idx;
u8 button;
}key_button_pair_t;
typedef enum
{
APP_NEC_IR_TABLE_PREPARE=1,
APP_NEC_IR_TABLE_PREPARE_END,
APP_NEC_IR_TABLE_START,
APP_NEC_IR_TABLE_WRITEFAIL,
APP_NEC_IR_TABLE_END
}app_nec_ir_table_sts;
_attribute_data_retention_ app_nec_ir_table_sts nec_ir_table_start = APP_NEC_IR_TABLE_END;
//keyid: receive from the host. button_idx: Corresponding to the key index in the memory ir_table[].button:The actual keyid corresponding to the board
const key_button_pair_t key_button_map_g10[MAX_KEY_COUNT] = {
{0x0018, KEY_IDX_VOLUP, 0x10},
{0x0019, KEY_IDX_VOLDN, 0x02},
{0x00A4, KEY_IDX_MUTE, 0x16},
{0x001A, KEY_IDX_POWER, 0 },
{0x00B2, KEY_IDX_INPUT, 0x03}
};
/* 230529 by ken. change input(android key code) to Magic */
const key_button_pair_t key_button_map_g10_magic[MAX_KEY_COUNT] = {
{0x0018, KEY_IDX_VOLUP, 0x10},
{0x0019, KEY_IDX_VOLDN, 0x02},
{0x00A4, KEY_IDX_MUTE, 0x16},
{0x001A, KEY_IDX_POWER, 0 },
{0x0139, KEY_IDX_MAGIC, 0x03}
};
//keyid: receive from the host. button_idx: Corresponding to the key index in the memory ir_table[].button:The actual keyid corresponding to the board
const key_button_pair_t key_button_map_g20[MAX_KEY_COUNT] = {
{0x0018, KEY_IDX_VOLUP, 0x1f},
{0x0019, KEY_IDX_VOLDN, 0x02},
{0x00A4, KEY_IDX_MUTE, 0x2B},
{0x001A, KEY_IDX_POWER, 0 },
{0x00B2, KEY_IDX_INPUT, 0x06}
};
/* 230529 by ken. change input(android key code) to Magic */
const key_button_pair_t key_button_map_g20_magic[MAX_KEY_COUNT] = {
{0x0018, KEY_IDX_VOLUP, 0x1f},
{0x0019, KEY_IDX_VOLDN, 0x02},
{0x00A4, KEY_IDX_MUTE, 0x2B},
{0x001A, KEY_IDX_POWER, 0 },
{0x0139, KEY_IDX_MAGIC, 0x06}
};
//The following address corresponds to the flash memory address written each time. Upto 5 keys can be written at a time, and each key occupies a maximum of 256 bytes.
const u32 if_flash_sect_addr[IR_DATA_SECT_MAX_NUM] ={IR_DATA_SECT_0_ADDR+256,IR_DATA_SECT_0_ADDR+1536,IR_DATA_SECT_0_ADDR+2816,IR_DATA_SECT_1_ADDR+256,IR_DATA_SECT_1_ADDR+1536,IR_DATA_SECT_1_ADDR+2816, \
IR_DATA_SECT_2_ADDR+256,IR_DATA_SECT_2_ADDR+1536,IR_DATA_SECT_2_ADDR+2816,IR_DATA_SECT_3_ADDR+256,IR_DATA_SECT_3_ADDR+1536,IR_DATA_SECT_3_ADDR+2816};
static _attribute_data_retention_ ir_app_parm_t ir_app_parm={0};
static _attribute_data_retention_ key_code_t ir_table[MAX_KEY_COUNT]={{0},{0},{0},{0},{0}};
extern u32 ir_flash_erase_tick;
/*
"ir_flash_index" is used to record the current ir code programming times.(The maxinum value of
"ir_flash_index" is 12,when the value of "ir_flash_index" is 6,the erase operation must be performed.)
*/
_attribute_data_retention_ u8 ir_flash_index=0;
/*
ir_flash_need_erase_sector:0 -> erase the IR_DATA_SECT_0_ADDR,IR_DATA_SECT_1_ADDR sector
ir_flash_need_erase_sector:2 -> erase the IR_DATA_SECT_2_ADDR,IR_DATA_SECT_3_ADDR sector
*/
_attribute_data_retention_ u8 ir_flash_need_erase_sector=0;
_attribute_data_retention_ u8 ir_flash_erase_sector_step=0;
_attribute_data_retention_ u8 ir_flash_erase_flag=0;
_attribute_data_retention_ u8 ir_save_error_flag=0;
extern _attribute_data_retention_ u8 device_in_connection_state;
extern int blt_soft_timer_delete(blt_timer_callback_t func);
extern int bls_ll_requestConnBrxEventDisable(void);
extern void bls_ll_disableConnBrxEvent(void);
extern void bls_ll_restoreConnBrxEvent(void);
#if(BLT_TEST_SOFT_TIMER_ENABLE == 0)
int blt_soft_timer_add(blt_timer_callback_t func, u32 interval_us)
{
}
int blt_soft_timer_delete(blt_timer_callback_t func)
{
}
#endif
_attribute_data_retention_ app_ir_programming_end_Cb_t app_ir_programming_end_Cb = NULL;
/**
* @brief This function servers to register the callback at the end of ir programming
* @param[in] Callback function that needs to be registered
* @return none
*/
void app_ir_programming_end_register(app_ir_programming_end_Cb_t cb)
{
app_ir_programming_end_Cb = cb;
}
/**
* @brief This function set the programming flag
* @param[in] flag the progtamming key. 0x55:current key is a programming key 0:current key not is a propramming key
* @return none
*/
void programming_key_set(u8 data)
{
ir_app_parm.is_key_programming = data;
}
/**
* @brief This function is used to determine whether the current key is a programming key
* @param[in] none
* @return 1: programming key
* 0: not a programming key
*/
u8 is_programming_key_send(void)
{
if(ir_app_parm.is_key_programming == 0x55)
return 1;
else
return 0;
}
/**
* @brief This function is used to get the corresponding button index by board keyid
* @param[in] button: keyid on the board
* @return index 0-4
*/
u8 ir_get_button_idx_from_button(u8 button)
{
u8 i;
for(i = 0; i < MAX_KEY_COUNT; i++)
{
if(app_custom_get_device_type() == REMOTE_G10)
{
/* 230529 by ken. Select key_button_map_g10 or key_button_map_g10_magic according to the key value of the input (magic) key */
if(CR_INPUT == key_map_ble[3]){
if (key_button_map_g10[i].button == button)
{
return key_button_map_g10[i].button_idx;
}
}else{
if (key_button_map_g10_magic[i].button == button)
{
return key_button_map_g10_magic[i].button_idx;
}
}
}
else
{
/* 230529 by ken. Select key_button_map_g20 or key_button_map_g20_magic according to the key value of the input (magic) key */
if(CR_INPUT == key_map_ble[6]){
if (key_button_map_g20[i].button == button)
{
return key_button_map_g20[i].button_idx;
}
}else{
if (key_button_map_g20_magic[i].button == button)
{
return key_button_map_g20_magic[i].button_idx;
}
}
}
}
return KEY_IDX_NULL;
}
/**
* @brief This function is used to get the corresponding button index by host keyid
* @param[in] button: keyid issued by host
* @return index 0-4
*/
u8 ir_get_button_idx_from_key_id(u16 key_id)
{
u8 i;
for(i = 0; i < MAX_KEY_COUNT; i++)
{
if(app_custom_get_device_type() == REMOTE_G10)
{
/* 230529 by ken. Select key_button_map_g10 or key_button_map_g10_magic according to the key value of the input (magic) key */
if(CR_INPUT == key_map_ble[3]){
if (key_button_map_g10[i].key_id == key_id)
{
return key_button_map_g10[i].button_idx;
}
}else{
if (key_button_map_g10_magic[i].key_id == key_id)
{
return key_button_map_g10_magic[i].button_idx;
}
}
}
else
{
/* 230529 by ken. Select key_button_map_g20 or key_button_map_g20_magic according to the key value of the input (magic) key */
if(CR_INPUT == key_map_ble[6]){
if (key_button_map_g20[i].key_id == key_id)
{
return key_button_map_g20[i].button_idx;
}
}else{
if (key_button_map_g20_magic[i].key_id == key_id)
{
return key_button_map_g20_magic[i].button_idx;
}
}
}
}
return KEY_IDX_NULL;
}
/**
* @brief This function is used to get the corresponding ir data by board keyid
* @param[in] key_idx: keyid on the board
* @return ir data
*/
key_code_t* ir_get_key_code_from_keyid_idx(u8 key_idx)
{
u8 i;
if(key_idx == 0) //powerkey
{
if(ir_table[KEY_IDX_POWER].button_idx == KEY_IDX_POWER)
{
ir_app_parm.current_programming_key_send = KEY_IDX_POWER;
return &ir_table[KEY_IDX_POWER];
}
}
else
{
for(i = 0; i < MAX_KEY_COUNT; i++)
{
if(ir_table[i].key_id == key_idx)
{
if(ir_table[i].button_idx == i)
{
ir_app_parm.current_programming_key_send = i;
return &ir_table[i];
}
}
}
}
return NULL;
}
/**
* @brief This function is used to get the corresponding button index by board keyid
* @param[in] key_idx: keyid on the board
* @return button index
*/
u8 ir_get_suppress_index_from_keyid_idx(u8 key_idx)
{
u8 i;
//printf("ir_app_parm.ir_programming.programmed_key_count=%x\r\n",ir_app_parm.ir_programming.programmed_key_count);
if(key_idx == 0) //powerkey
{
if(ir_table[KEY_IDX_POWER].button_idx == KEY_IDX_POWER)
{
//printf("ir power key\r\n");
return KEY_IDX_POWER;
}
}
else
{
for(i = 0; i < MAX_KEY_COUNT; i++)
{
if(ir_table[i].key_id == key_idx)
{
if(ir_table[i].button_idx == i)
{
//printf("button index i=%x\r\n",i);
return i;
}
}
}
}
return KEY_IDX_NULL;
}
/**
* @brief This function is init the ir buffer
* @param[in] none
* @return none
*/
void ir_table_init(void)
{
u8 i;
memset(ir_table, 0, sizeof(key_code_t) * MAX_KEY_COUNT);
for (i = 0; i < MAX_KEY_COUNT; i++)
{
ir_table[i].key_id = INVALID_KEY_ID;
}
ir_app_parm.ir_save.ir_save_en = 0;
ir_app_parm.ir_save.ir_save_pos = 0;
ir_app_parm.ir_save.ir_save_button = 0xff;
ir_app_parm.programming_timer = NULL;
ir_app_parm.ir_programming.programmed_key_count = 0;
ir_app_parm.ir_programming.current_programming_key_id = INVALID_KEY_ID;
ir_app_parm.ir_merge.ir_current_button = MAX_KEY_COUNT;
}
/*
1)A total of 6 flash sectors are used to store ir code. Each sector can store ir code
programming three times. Each ir code programming occupies 5*256 bytes. 5 means that
each programming supports up to 5 keys, 256 Indicates the maximum number of ir codes
for each key.
2)The first 6 bytes of each sector are used to check whether the ir code programming
data is valid for 3 times. If the value is 0xa5,0xxx, the ir code programming data for
this time is valid. If the value is 0x00,0xxx this time The data is invalid
(0xxx is a reserved byte, to be expanded).
3)The api "ir_flash_set_flag" is used for set the ir code data to invalid. The variable
"ir_flash_index" is used to record the current ir code programming times.(The maxinum value of
"ir_flash_index" is 12,when the value of "ir_flash_index" is 6,the erase operation must be performed.)
4)Use 16 bytes as a unit for flash write operation.
*/
#define APP_IR_DATA_HEAD 0xa5
#define APP_IR_DATA_HEAD_INVALID 0x0
/**
* @brief Write a flag to indicate that the ir data is invalid
* @param[in] 0:indicate the ir data is invalid 1:indicate the ir data is valid
* @return none
*/
void ir_flash_set_flag(u8 flag)
{
u8 sect= ir_flash_index/3;
u8 sect_index = ir_flash_index%3;
u8 data;
//printf("ir_flash_set_flag =%x,ir_flash_index =%x\r\n",flag,ir_flash_index);
u32 addr = IR_DATA_SECT_0_ADDR+sect*0x1000+sect_index*2;
if(flag == 0)
{
data = APP_IR_DATA_HEAD_INVALID;
flash_write_page(addr,1,&data);
}
else
{
data = APP_IR_DATA_HEAD;
flash_write_page(addr,1,&data);
//printf("ir_flash_set_flag addr =%x\r\n",addr);
}
}
/**
* @brief Read the ir data from the flash
* @param[in] flash addr
* @return none
*/
void ir_flash_check(u32 addr)
{
u8 button_index=0,i;
u16 code_size=0;
u8 buf[300];
u16 key_id=0;
for(i=0;i<MAX_KEY_COUNT;i++)
{
flash_read_page(addr+i*256, 256, buf);
button_index = ir_get_button_idx_from_button(buf[0]);
if (button_index == KEY_IDX_NULL)
{
continue;
}
code_size = *(u16*)&buf[2];
key_id = buf[0]|(buf[1]<<8);
ir_table[button_index].key_id = key_id;
ir_table[button_index].code_size = code_size;
ir_table[button_index].button_idx = button_index;
if(code_size>256)
{
printf("addr=%x\r\n",addr-0x7000+i*256);
flash_read_page(addr-0x7000+i*256, code_size-251, &buf[256]);
}
memcpy(ir_table[button_index].code, &buf[5], code_size);
printf("button =%x \r\n",button_index);
/*
for(u16 k=0;k<code_size;k++ )
{
printf(" %x",ir_table[button_index].code[k]);
}
printf("\r\n");
*/
}
}
/**
* @brief Read the flag from the flash,and find the address which backup the valid ir data
* @param[in] none
* @return none
*/
void ir_param_init(void)
{
u32 addr;
u8 data[6],i,j;
u8 nodata_flag=0;
u8 find_flag=0;
ir_flash_index = IR_DATA_SECT_MAX_NUM;
printf("ir flash head=\r\n");
for(i=0;i<IR_DATA_SECT_NUM;i++)
{
flash_read_page(IR_DATA_SECT_0_ADDR+i*0x1000, 6, data);
for(u8 k=0;k<6;k++)
printf(" %x",data[k]);
for(j=0;j<3;j++)
{
if(data[j*2] == APP_IR_DATA_HEAD)
{
ir_flash_index= i*3+j;
nodata_flag = 0;
find_flag = 1;
break;
}
if(data[j*2] == APP_IR_DATA_HEAD_INVALID)
{
ir_flash_index = i*3+j;
nodata_flag = 1;
}
}
if(find_flag == 1) break;
}
if(ir_flash_index == IR_DATA_SECT_MAX_NUM)
{
ir_flash_index = 0;
printf("\r\nno ir data\r\n");
return;
}
if(ir_flash_index >= IR_DATA_NEED_ERASE_NUM)
{
flash_read_page(IR_DATA_SECT_0_ADDR,1,&data[0]);
flash_read_page(IR_DATA_SECT_0_EXT_ADDR,1,&data[1]);
flash_read_page(IR_DATA_SECT_1_EXT_ADDR,1,&data[2]);
if(data[0] != 0xff)
{
printf("erase 1 part flash\r\n");
flash_erase_sector(IR_DATA_SECT_0_ADDR);
flash_erase_sector(IR_DATA_SECT_1_ADDR);
}
if(data[1]!= 0xff)
{
flash_erase_sector(IR_DATA_SECT_0_EXT_ADDR);
}
if(data[2]!= 0xff)
{
flash_erase_sector(IR_DATA_SECT_1_EXT_ADDR);
}
}
if(ir_flash_index < IR_DATA_NEED_ERASE_NUM)
{
flash_read_page(IR_DATA_SECT_2_ADDR,1,&data[0]);
flash_read_page(IR_DATA_SECT_2_EXT_ADDR,1,&data[1]);
flash_read_page(IR_DATA_SECT_3_EXT_ADDR,1,&data[2]);
if((data[0] != 0xff))
{
printf("erase 2 part flash\r\n");
flash_erase_sector(IR_DATA_SECT_2_ADDR);
flash_erase_sector(IR_DATA_SECT_3_ADDR);
}
if(data[1]!= 0xff)
{
flash_erase_sector(IR_DATA_SECT_2_EXT_ADDR);
}
if(data[2]!= 0xff)
{
flash_erase_sector(IR_DATA_SECT_3_EXT_ADDR);
}
}
if(nodata_flag == 1)
{
printf("\r\nno ir data, but ir_flash_index =%x\r\n",ir_flash_index);
}
else
{
addr = if_flash_sect_addr[ir_flash_index];
printf("current sector= %x app_ir_param_init addr=%x\r\n",ir_flash_index,addr);
ir_flash_check(addr);
}
}
void ir_flash_save_en(u8 button_index)
{
ir_app_parm.ir_save.ir_save_en |= 1<<button_index;
printf("ir_flash_save_en ir_save_en=%x\r\n",ir_app_parm.ir_save.ir_save_en);
}
void ir_flash_save_flag_for_ext_sector(void)
{
u8 index;
u32 addr;
u8 data;
index = ir_flash_index/3;
addr = IR_DATA_SECT_0_EXT_ADDR + index*0x1000;
flash_read_page(addr,1,&data);
if(data != APP_IR_DATA_HEAD)
{
data = APP_IR_DATA_HEAD;
flash_write_page(addr,1,&data);
printf("ir_flash_save_flag_for_ext_sector =%x",index);
}
}
void ir_flash_save(u8 button)
{
u32 flash_addr;
u8 write_len_per;
flash_addr = if_flash_sect_addr[ir_flash_index] + button*256;
if(((ir_table[button].code_size+5) - ir_app_parm.ir_save.ir_save_pos) >= 16)
{
write_len_per = 16;
}
else
{
write_len_per = ir_table[button].code_size + 5 - ir_app_parm.ir_save.ir_save_pos;
}
if(ir_app_parm.ir_save.ir_save_pos<256)
{
if(bls_ll_requestConnBrxEventDisable() > 2)
{
bls_ll_disableConnBrxEvent();
//device_led_on(1);
flash_write_page(flash_addr+ir_app_parm.ir_save.ir_save_pos,write_len_per,(((u8*)(&ir_table[button]))+ir_app_parm.ir_save.ir_save_pos));
//device_led_off(1);
bls_ll_restoreConnBrxEvent();
}
else
return;
}
else
{
if(bls_ll_requestConnBrxEventDisable() > 2)
{
bls_ll_disableConnBrxEvent();
//device_led_on(1);
flash_write_page(flash_addr-0x7000+ir_app_parm.ir_save.ir_save_pos-256,write_len_per,(((u8*)(&ir_table[button]))+ir_app_parm.ir_save.ir_save_pos));
//device_led_off(1);
bls_ll_restoreConnBrxEvent();
ir_flash_save_flag_for_ext_sector();
}
else
return;
}
ir_app_parm.ir_save.ir_save_pos += write_len_per;
ir_app_parm.ir_save.ir_save_button = button;
//printf("pos=%x,button=%x\r\n",ir_app_parm.ir_save.ir_save_pos,ir_app_parm.ir_save.ir_save_button);
if(ir_app_parm.ir_save.ir_save_pos == (ir_table[button].code_size+5))
{
printf("\r\n w butt=%x\r\n",button);
ir_app_parm.ir_save.ir_save_en &= ~(1<<button);
ir_app_parm.ir_save.ir_save_button = 0xff;
}
}
/**
* @brief Backup the ir data in flash
* @param[in] none
* @return none
*/
int ir_flash_save_timeoutcb(void)
{
u32 flash_addr;
u8 i,buf;
u8 ir_save_flag;
if((ir_app_parm.ir_save.ir_save_button == 0xff) && (ir_app_parm.ir_save.ir_save_pos == 0))
{
if(ir_save_error_flag == 0xaa)
{
if((ir_flash_erase_tick == 0) && (ir_flash_erase_sector_step == 0))
{
ir_flash_index = 0;
ir_save_error_flag = 0;
}
return 0;
}
else
{
flash_addr = if_flash_sect_addr[ir_flash_index];
flash_read_page(flash_addr, 1, &buf);
if(buf != 0xff)
{
printf("ir_flash_save error\r\n");
printf("ir_flash_save error\r\n");
ir_save_error_flag = 0xaa;
if(ir_flash_index >= IR_DATA_NEED_ERASE_NUM)
{
flash_addr = if_flash_sect_addr[0];
flash_read_page(flash_addr, 1, &buf);
if(buf == 0xff)
{
ir_flash_need_erase_sector = 2;
ir_flash_erase_tick = clock_time() | 1;
ir_flash_index = 0;
}
else
{
//erase all
ir_flash_need_erase_sector = 4;
}
}
else
{
flash_addr = if_flash_sect_addr[IR_DATA_NEED_ERASE_NUM];
flash_read_page(flash_addr, 1, &buf);
if(buf == 0xff)
{
ir_flash_need_erase_sector = 0;
ir_flash_erase_tick = clock_time() | 1;
ir_flash_index = IR_DATA_NEED_ERASE_NUM;
}
else
{
//erase all
ir_flash_need_erase_sector = 4;
}
}
return 0;
}
}
}
ir_save_flag = ir_app_parm.ir_save.ir_save_en;
if((ir_app_parm.ir_save.ir_save_button != 0xff) && (ir_app_parm.ir_save.ir_save_button <= 4))
{
ir_flash_save(ir_app_parm.ir_save.ir_save_button);
return 0;
}
else
{
for(i=0;i<MAX_KEY_COUNT;i++)
{
if(ir_save_flag & 0x01)
{
if(ir_app_parm.ir_save.ir_save_button == 0xff)
ir_app_parm.ir_save.ir_save_pos = 0;
ir_app_parm.ir_save.ir_save_button = i;
ir_flash_save(ir_app_parm.ir_save.ir_save_button);
return 0;
}
else
{
ir_save_flag = ir_save_flag>>1;
}
}
return -1;
}
}
void ir_init_key_event_notify(u8 value)
{
ir_app_parm.ir_programming.key_notification_flag = value;
}
/**
* @brief Erase the flash sector
* @return 0: not erase success
-1: erase success
*/
int ir_flash_erase_timeoutcb(void)
{
//printf("ir_flash_erase_timeoutcb\r\n");
//u32 time;
u8 data;
u32 pos_addr_ext=0, pos_addr=0;
if(is_mic_enable() == 1)
return 0;
//u32 erase_time=clock_time();
//printf("flash erase sector=%x \r\n",ir_flash_need_erase_sector);
// time = bls_ll_requestConnBrxEventDisable();
if(ir_flash_need_erase_sector == 0)
{
pos_addr = 0;
pos_addr_ext = 0;
}
else if(ir_flash_need_erase_sector == 2)
{
pos_addr = 0x2000;
pos_addr_ext = 0x7000;
}
else
{
//erase all
if(bls_ll_requestConnBrxEventDisable() > 150)
{
bls_ll_disableConnBrxEvent();
if(ir_flash_erase_sector_step == 0)
{
flash_erase_sector(IR_DATA_SECT_0_ADDR);
flash_erase_sector(IR_DATA_SECT_1_ADDR);
ir_flash_erase_sector_step = 1;
}
else if(ir_flash_erase_sector_step == 1)
{
flash_erase_sector(IR_DATA_SECT_0_EXT_ADDR);
flash_erase_sector(IR_DATA_SECT_1_EXT_ADDR);
ir_flash_erase_sector_step = 2;
}
else if(ir_flash_erase_sector_step == 2)
{
flash_erase_sector(IR_DATA_SECT_2_ADDR);
flash_erase_sector(IR_DATA_SECT_3_ADDR);
ir_flash_erase_sector_step = 3;
}
else
{
flash_erase_sector(IR_DATA_SECT_2_EXT_ADDR);
flash_erase_sector(IR_DATA_SECT_3_EXT_ADDR);
ir_flash_erase_sector_step = 0;
}
bls_ll_restoreConnBrxEvent();
if(ir_flash_erase_sector_step)
return 0;
else
return -1;
}
}
if(bls_ll_requestConnBrxEventDisable() > 70)
{
//device_led_on(1);
bls_ll_disableConnBrxEvent();
//printf("flash erase sector=%x \r\n",ir_flash_need_erase_sector);
if(ir_flash_erase_sector_step == 0)
{
flash_erase_sector(IR_DATA_SECT_0_ADDR + pos_addr);
ir_flash_erase_sector_step = 1;
}
else if(ir_flash_erase_sector_step == 1)
{
flash_erase_sector(IR_DATA_SECT_1_ADDR + pos_addr);
ir_flash_erase_sector_step = 2;
}
else
{
if(ir_flash_erase_sector_step == 2)
{
flash_read_page(IR_DATA_SECT_0_EXT_ADDR + pos_addr,1,&data);
if(data == APP_IR_DATA_HEAD)
{
printf("step_2\r\n");
flash_erase_sector(IR_DATA_SECT_0_EXT_ADDR + pos_addr);
ir_flash_erase_sector_step = 3;
}
else
{
printf("step_2_2\r\n");
flash_read_page(IR_DATA_SECT_1_EXT_ADDR + pos_addr,1,&data);
if(data == APP_IR_DATA_HEAD)
{
flash_erase_sector(IR_DATA_SECT_1_EXT_ADDR + pos_addr);
ir_flash_erase_sector_step = 0;
printf("erase_succ\r\n");
}
else
{
printf("step_2_2_2\r\n");
ir_flash_erase_sector_step = 0;
}
}
}
else
{
printf("step_3\r\n");
flash_read_page(IR_DATA_SECT_1_EXT_ADDR - pos_addr_ext, 1, &data);
if(data == APP_IR_DATA_HEAD)
{
printf("step_3_3\r\n");
flash_erase_sector(IR_DATA_SECT_1_EXT_ADDR - pos_addr_ext);
ir_flash_erase_sector_step = 0;
printf("erase_succ\r\n");
}
else
{
printf("step_3_3_3\r\n");
ir_flash_erase_sector_step = 0;
}
}
}
bls_ll_restoreConnBrxEvent();
if(ir_flash_erase_sector_step)
return 0;
else
return -1;
}
return 0;
}
#if 0
/**
* @brief Add a timer for erase flash
* @return none
*/
void ir_flash_erase(void)
{
printf("ir_flash_erase\r\n");
//blt_soft_timer_add(ir_flash_erase_timeoutcb, FLASH_ERASE_TIMEOUT);
ir_flash_erase_timeoutcb();
}
#endif
/**
* @brief Ir flash factory
* @return none
*/
void ir_flash_factory(void)
{
printf("ir_flash_factory\r\n");
ir_flash_set_flag(0);
}
/**
* @brief Erase the flash sector
* @return 0: not erase success
-1: erase success
*/
int ir_key_event_notify_erase_timeoutcb(void)
{
printf("ir_key_event_notify_erase_timeoutcb\r\n");
if(bls_ll_requestConnBrxEventDisable() > 120)
{
bls_ll_disableConnBrxEvent();
flash_erase_sector(IR_KEY_EVENT_NOTIFY_SECT_ADDR);
printf("erase_succ\r\n");
bls_ll_restoreConnBrxEvent();
write_ir_key_event_notify(ir_app_parm.ir_programming.key_notification_flag);
return -1;
}
return 0;
}
/**
* @brief ir_programming_timeoutcb
* @return -1: exit the timer
0: exit the timer this time
*/
int ir_programming_timeoutcb(void)
{
printf("ir_programming_timeoutcb\r\n");
ir_app_parm.ir_programming.programming_start = 0;
if (ir_app_parm.programming_timer)
{
ir_app_parm.programming_timer = NULL;
}
return -1;
}
/**
* @brief Recognize the programming key is IR mode or BLE HID modes
* @param[in] button_index: which button
* @return 1: BLE HID mode
0: IR mode
*/
u8 ir_key_is_suppress(u8 key_idx)
{
u8 index;
index = ir_get_suppress_index_from_keyid_idx(key_idx);
if (index == KEY_IDX_NULL) return KEY_IDX_NULL;
if(ir_app_parm.ir_suppress[index])
return true;
else
return false;
}
void ir_suppress_reinit(void)
{
u8 i;
for (i = 0; i < MAX_KEY_COUNT; i++)
{
ir_app_parm.ir_suppress[i] = 0;
}
}
/**
* @brief ir_type_read
* @param[in] none
* @return 1 or 0
*/
int ir_type_read(void)
{
u8 type;
u8* code = ir_table[ir_app_parm.current_programming_key_send].code;
type = code[0];
if(type == 1) //one time ir seqnence
{
return 0;
}
else if(type == 3) //one time + repeated ir sequence
{
u16 sequence_length = ((u16)code[4] << 8 | code[5])<<2;
sequence_length += 8;
u8* p_sequence = &code[sequence_length];
sequence_length = ((u16)code[6] << 8 | code[7]);
T_dmaData_buf.data_num = 0;
for(u8 i = 0; i < sequence_length; i++)
{
T_dmaData_buf.data[T_dmaData_buf.data_num ++] = \
pwm_config_dma_fifo_waveform(1, PWM0_PULSE_NORMAL,(u16)(p_sequence[0]<<8) | p_sequence[1]);
T_dmaData_buf.data[T_dmaData_buf.data_num ++] = \
pwm_config_dma_fifo_waveform(0, PWM0_PULSE_NORMAL,(u16)(p_sequence[2]<<8) | p_sequence[3]);
p_sequence += 4;
}
T_dmaData_buf.dma_len = T_dmaData_buf.data_num * 2;
}
else if(type == 4) // two repeated ir sequence
{
}
return 1;
}
/**
* @brief Obtain the duty,frequency,repear delay
* @param[in] none
* @return none
*/
void ir_fallback_get_protocol_configure(unsigned char* p_duty_cycle, unsigned short* p_carrier_frequency,
unsigned short* p_repeat_delay)
{
*p_duty_cycle = ir_app_parm.duty_cycle;
*p_carrier_frequency = ir_app_parm.carrier_frequency;
*p_repeat_delay = ir_app_parm.ir_repeat_delay.repeat_delay;
}
/**
* @brief Load ir data to ir send buffer
* @param[in] ir data
* @return none
*/
void ir_send_key_code(key_code_t* p_key_code)
{
u8* code = p_key_code->code;
u16 sequence_length,sequence_length2,length; //4 bytes per sequence
u8* p_sequence;
T_dmaData_buf.data_num = 0;
u8 type = code[0];
if(type)
{
ir_app_parm.duty_cycle = code[1]; //as percentage
ir_app_parm.carrier_frequency = ((u16)code[2] << 8 | code[3]) * 100; //in unit of 100Hz
sequence_length = (u16)code[4] << 8 | code[5];
}
//disable button
if (type == 0)
{
return;
}
//one time ir sequence
else if (type == 1)
{
p_sequence = &code[6];
for(u8 i = 0; i < sequence_length; i++)
{
T_dmaData_buf.data[T_dmaData_buf.data_num ++] = \
pwm_config_dma_fifo_waveform(1, PWM0_PULSE_NORMAL,(u16)(p_sequence[0]<<8) | p_sequence[1]);
T_dmaData_buf.data[T_dmaData_buf.data_num ++] = \
pwm_config_dma_fifo_waveform(0, PWM0_PULSE_NORMAL,(u16)(p_sequence[2]<<8) | p_sequence[3]);
p_sequence += 4;
}
}
//repeat ir sequence
else if (type == 2)
{
ir_app_parm.ir_repeat_delay.repeat_delay = (u16)code[6] << 8 | code[7];
//printf("ir_app_parm.ir_repeat_delay_cycle=%x\r\n",ir_app_parm.ir_repeat_delay.repeat_delay);
ir_app_parm.ir_repeat_delay.repeat_delay = \
ir_app_parm.ir_repeat_delay.repeat_delay*(1000000/ir_app_parm.carrier_frequency);
//printf("ir_repeat_delay_us=%x\r\n",ir_app_parm.ir_repeat_delay.repeat_delay);
p_sequence = &code[8];
for(u8 i = 0; i < sequence_length; i++)
{
T_dmaData_buf.data[T_dmaData_buf.data_num ++] = \
pwm_config_dma_fifo_waveform(1, PWM0_PULSE_NORMAL,(u16)(p_sequence[0]<<8) | p_sequence[1]);
T_dmaData_buf.data[T_dmaData_buf.data_num ++] = \
pwm_config_dma_fifo_waveform(0, PWM0_PULSE_NORMAL,(u16)(p_sequence[2]<<8) | p_sequence[3]);
p_sequence += 4;
}
//printf("duty_cycle=%x\r\n",ir_app_parm.duty_cycle);
//printf("carrier_frequency=%x\r\n",ir_app_parm.carrier_frequency);
//printf("sequence_length=%x\r\n",sequence_length);
}
//one time + repeat ir sequence
else if (type == 3)
{
sequence_length2 = (u16)code[6] << 8 | code[7];
//printf("sequence_length=%x\r\n",sequence_length);
p_sequence = &code[8];
for(u8 i = 0; i < sequence_length; i++)
{
T_dmaData_buf.data[T_dmaData_buf.data_num ++] = \
pwm_config_dma_fifo_waveform(1, PWM0_PULSE_NORMAL,(u16)(p_sequence[0]<<8) | p_sequence[1]);
T_dmaData_buf.data[T_dmaData_buf.data_num ++] = \
pwm_config_dma_fifo_waveform(0, PWM0_PULSE_NORMAL,(u16)(p_sequence[2]<<8) | p_sequence[3]);
p_sequence += 4;
}
}
else
{
sequence_length2 = (u16)code[6] << 8 | code[7];
if(ir_app_parm.odd_or_even_press % 2 == 1)
{
p_sequence = &code[8];
length = sequence_length;
}
else
{
length = sequence_length*4 + 8;
p_sequence = &code[length];
length = sequence_length2;
}
for(u8 i = 0; i < length; i++)
{
T_dmaData_buf.data[T_dmaData_buf.data_num ++] = \
pwm_config_dma_fifo_waveform(1, PWM0_PULSE_NORMAL,(u16)(p_sequence[0]<<8) | p_sequence[1]);
T_dmaData_buf.data[T_dmaData_buf.data_num ++] = \
pwm_config_dma_fifo_waveform(0, PWM0_PULSE_NORMAL,(u16)(p_sequence[2]<<8) | p_sequence[3]);
p_sequence += 4;
}
ir_app_parm.odd_or_even_press++;
}
ir_send_specil(ir_app_parm.carrier_frequency,ir_app_parm.duty_cycle);
}
extern void app_ota_status(u8 status);
_attribute_data_retention_ u8 ir_cache_key[3]={0};
/**
* @brief Ir_repeat_delay_release_time
* @param[in] none
* @return 0
*/
int ir_cache_key_timer(void)
{
printf("ir_cache_key_timer\r\n");
if(device_in_connection_state)
{
printf("send cachekey_notify\r\n");
ir_cache_key[0] = 0; //down
bls_att_pushNotifyData(ATV_IR_KEY_EVENT_IDX, ir_cache_key, sizeof(ir_cache_key));
sleep_us(100);
ir_cache_key[0] = 1; //up
bls_att_pushNotifyData(ATV_IR_KEY_EVENT_IDX, ir_cache_key, sizeof(ir_cache_key));
return -1;
}
printf("send cachekey_notify timeout\r\n");
return -1;
}
/**
* @brief send ir data and send nofity
* @param[in] 1: down 0:up
* @return 0
*/
int ir_fallback_send(u8 key_down)
{
key_code_t* p_key_code = &ir_table[ir_app_parm.current_programming_key_send];
u16 key_id;
//printf("ir_fallback_send\r\n");
if(key_down)
app_ota_status(0);
else
app_ota_status(1);
if(key_down)
{
printf("key down\r\n");
ir_send_key_code(p_key_code);
}
if (ir_app_parm.ir_programming.key_notification_flag)
{
//Besides sending IR code, also notify ATV that the key event
printf("send notify\r\n");
if(app_custom_get_device_type() == REMOTE_G10){
/* 230529 by ken. Select key_button_map_g10 or key_button_map_g10_magic according to the key value of the input (magic) key */
if(CR_INPUT == key_map_ble[3]){
key_id = key_button_map_g10[ir_app_parm.current_programming_key_send].key_id;
}else{
key_id = key_button_map_g10_magic[ir_app_parm.current_programming_key_send].key_id;
}
}
else{
/* 230529 by ken. Select key_button_map_g20 or key_button_map_g20_magic according to the key value of the input (magic) key */
if(CR_INPUT == key_map_ble[6]){
key_id = key_button_map_g20[ir_app_parm.current_programming_key_send].key_id;
}else{
key_id = key_button_map_g20_magic[ir_app_parm.current_programming_key_send].key_id;
}
}
//printf("key_id=%x\r\n",key_id);
ir_cache_key[0] = key_down ? 0:1;
ir_cache_key[1] = (key_id >> 8);
ir_cache_key[2] = key_id;
if(device_in_connection_state)
bls_att_pushNotifyData(ATV_IR_KEY_EVENT_IDX, ir_cache_key, sizeof(ir_cache_key));
else
{
if(key_down == 1)
{
printf("add cache key\r\n");
blt_soft_timer_delete(ir_cache_key_timer);
blt_soft_timer_add(ir_cache_key_timer, 5000000);
}
}
}
return 0;
}
/**
* @brief Ir_repeat_delay_release_time
* @param[in] none
* @return 0
*/
int ir_repeat_delay_release_time(void)
{
ir_app_parm.ir_repeat_delay.release_timer = clock_time();
//printf("ir_app_parm.ir_repeat_delay_release_time=%x\r\n",ir_app_parm.ir_repeat_delay.release_timer);
return 0;
}
/**
* @brief ir_repeat_delay_timer
* @param[in] none
* @return -1
*/
int ir_repeat_delay_timer(void)
{
printf("ir_repeat_delay_timer\r\n");
if(app_is_key_released())
{
programming_key_set(0x55);
ir_fallback_send(1);
}
return -1;
}
/**
* @brief ir_fallback_send_key_code
* @param[in] button_idx
* @param[in] key_down 1:down 0:up
* @return false or true
*/
u8 ir_fallback_send_key_code(u8 button_idx, u8 key_down)
{
u8 last_key_send = ir_app_parm.current_programming_key_send;
u32 current_time;
u32 time;
key_code_t* p_key_code = ir_get_key_code_from_keyid_idx(button_idx);
//printf("current_programming_key=%x\r\n",ir_app_parm.current_programming_key_send);
u8* code = ir_table[ir_app_parm.current_programming_key_send].code;
u8 type = code[0];
if (p_key_code == NULL)
{
return false;
}
if(type == 2)
{
if((last_key_send == ir_app_parm.current_programming_key_send))
{
current_time = clock_time();
/*
printf("current_time=%x\r\n",current_time);
printf("current_time - ir_app_parm.ir_repeat_delay.release_timer=%x\r\n",\
current_time - ir_app_parm.ir_repeat_delay.release_timer);
*/
time = (current_time - ir_app_parm.ir_repeat_delay.release_timer)>>4;
if(time < ir_app_parm.ir_repeat_delay.repeat_delay)
{
time = ir_app_parm.ir_repeat_delay.repeat_delay - time;
//printf("need delay=%x\r\n",time);
blt_soft_timer_add(ir_repeat_delay_timer, time);
}
else
{
//printf("exceed delay time\r\n");
programming_key_set(0x55);
ir_fallback_send(key_down);
}
}
else
{
programming_key_set(0x55);
ir_fallback_send(key_down);
}
}
else
{
programming_key_set(0x55);
ir_fallback_send(key_down);
}
return true;
}
/**
* @brief ir_code_merge
* @param[in] key_id
* @param[in] button_index
* @param[in] code size: ir data length
* @param[in] code: ir data
* @return none
*/
void ir_code_merge(u16 key_id,u8 button_index,u16 code_size,u8* code)
{
//u32 flash_addr_pos=0;
u32 len;
//printf("ir_code_merge,ir_app_parm.ir_merge.ir_current_button=%x,button_index=%x\r\n",ir_app_parm.ir_merge.ir_current_button,button_index);
if(ir_app_parm.ir_merge.ir_current_button != button_index)
{
ir_app_parm.ir_merge.ir_code_pos = 0;
ir_app_parm.ir_merge.ir_keycode_total_len = 0;
if(code[0] == 1)
{
ir_app_parm.ir_merge.ir_keycode_total_len = ((u16)code[4] << 8 | code[5])*4 + 6;
}
else if(code[0] == 2)
{
ir_app_parm.ir_merge.ir_keycode_total_len = ((u16)code[4] << 8 | code[5])*4 + 8;
}
else if((code[0] == 3) || (code[0] == 4))
{
ir_app_parm.ir_merge.ir_keycode_total_len = ((u16)code[4] << 8 | code[5])*4 + ((u16)code[6] << 8 | code[7])*4 + 8;
}
//printf(" ir_app_parm.ir_merge.ir_keycode_total_len=%x,codesize=%x\r\n", ir_app_parm.ir_merge.ir_keycode_total_len,code_size);
memcpy(ir_table[button_index].code + ir_app_parm.ir_merge.ir_code_pos, code, code_size);
ir_app_parm.ir_merge.ir_code_pos += code_size;
}
else
{
memcpy(ir_table[button_index].code + ir_app_parm.ir_merge.ir_code_pos, code, code_size);
ir_app_parm.ir_merge.ir_code_pos += code_size;
}
// printf("ir_code_merge: ir_app_parm.ir_merge.ir_code_pos=%x,ir_app_parm.ir_merge.ir_keycode_total_len=%x,code_size=%x",ir_app_parm.ir_merge.ir_code_pos,ir_app_parm.ir_merge.ir_keycode_total_len,code_size);
if(ir_app_parm.ir_merge.ir_code_pos == ir_app_parm.ir_merge.ir_keycode_total_len)
{
len = ir_app_parm.ir_merge.ir_keycode_total_len;
ir_table[button_index].key_id = key_id;
ir_table[button_index].code_size = len;
ir_table[button_index].button_idx = button_index;
//flash_addr_pos += button_index*256;
//ir_flash_save(button_index,flash_addr_pos,len+5);
ir_flash_save_en(button_index);
/*
for(u8 i=0;i<len;i++ )
{
printf(" %x\r\n",*(ir_table[button_index].code+i));
}
*/
ir_app_parm.ir_programming.programmed_key_count++;
//printf("add key\r\n");
}
}
/**
* @brief ir_table_add_key
* @param[in] key_id,code_size,code
* @return 0,11
*/
u8 ir_table_add_key(u16 key_id, u16 code_size, u8* code)
{
u8 button_index=0;
u16 button;
button_index = ir_get_button_idx_from_key_id(key_id);
if (button_index == KEY_IDX_NULL)
{
return false;
}
if ((ir_app_parm.ir_programming.programmed_key_count < MAX_KEY_COUNT)
&& (code_size <= MAX_CODE_LENGTH))
{
if(app_custom_get_device_type() == REMOTE_G10)
{
/* 230529 by ken. Select key_button_map_g10 or key_button_map_g10_magic according to the key value of the input (magic) key */
if(CR_INPUT == key_map_ble[3]){
button = key_button_map_g10[button_index].button;
}else{
button = key_button_map_g10_magic[button_index].button;
}
//printf("ir_table[button_index].key_id=%x \r\n",button);
}
else
{
/* 230529 by ken. Select key_button_map_g20 or key_button_map_g20_magic according to the key value of the input (magic) key */
if(CR_INPUT == key_map_ble[6]){
button = key_button_map_g20[button_index].button;
}else{
button = key_button_map_g20_magic[button_index].button;
}
// printf("ir_table[button_index].key_id=%x \r\n",button);
}
//printf("ir_table[button_index].button_idx=%x \r\n",button_index);
ir_code_merge(button,button_index,code_size,code);
}
return true;
}
/**
* @brief ir_key_event_notify_erase
* @param[in] none
* @return none
*/
void ir_key_event_notify_erase(void)
{
blt_soft_timer_add(ir_key_event_notify_erase_timeoutcb, 100000);
}
/**
* @brief Receive ATV commands and processed
* @param[in] handle :ATV command
* @param[in] buf:command
* @param[in] len: command data length
* @return false or true
*/
void ir_fallback_process(u16 handle, u8* buf, u16 len)
{
u8 index,data;
// u8 testdata[6],i;
// u32 addr;
u8 k;
switch (handle)
{
case ATV_IR_PROG_CONTROL_IDX:
{
if (len == 1)
{
ir_app_parm.ir_programming.programming_start = *buf;
if (ir_app_parm.ir_programming.programming_start == 1)
{
printf("ir table programming start\r\n");
#if BLE_AUDIO_ENABLE
google_reset_rsp_delay();
#endif
ir_table_init();
ir_flash_set_flag(0);
if(ir_flash_index == 0)
{
flash_read_page(IR_DATA_SECT_0_ADDR,1,&data);
if(data == APP_IR_DATA_HEAD_INVALID)
ir_flash_index++;
}
else
ir_flash_index++;
if(ir_flash_index >= IR_DATA_SECT_MAX_NUM)
ir_flash_index = 0;
printf("ir_flash_index=%x\r\n",ir_flash_index);
if (ir_app_parm.programming_timer)
{
blt_soft_timer_delete(ir_programming_timeoutcb);
ir_app_parm.programming_timer = NULL;
}
ir_app_parm.programming_timer = 1;
blt_soft_timer_add(ir_programming_timeoutcb, PROGRAMMING_TIMEOUT);
}
else
{
printf("ir table programming end\r\n");
extern u32 ir_flash_erase_tick;
if(ir_app_parm.ir_programming.programmed_key_count == 0)
{
ir_flash_set_flag(0);
printf(" empty ir programming\r\n");
}
if(ir_app_parm.ir_programming.programmed_key_count >= 1)
{
ir_flash_set_flag(1);
}
if(ir_flash_index == IR_DATA_NEED_ERASE_NUM)
{
ir_flash_need_erase_sector = 0;
ir_flash_erase_tick = clock_time() | 1;
}
if(ir_flash_index == 0)
{
ir_flash_need_erase_sector = 2;
ir_flash_erase_tick = clock_time() | 1;
}
if (ir_app_parm.programming_timer)
{
blt_soft_timer_delete(ir_programming_timeoutcb);
ir_app_parm.programming_timer = NULL;
}
printf("ir_flash_erase_tick=%x\r\n",ir_flash_erase_tick);
/*
for(i=0;i<IR_DATA_SECT_NUM;i++)
{
addr = IR_DATA_SECT_0_ADDR+i*0x1000;
flash_read_page(addr, 6, testdata);
printf("sect i=%x addr =%x\r\n",i,addr);
for(k=0;k<6;k++)
//printf(" %x",testdata[k]);
}
*/
if(app_ir_programming_end_Cb != NULL)
{
app_ir_programming_end_Cb();
}
}
}
break;
}
case ATV_IR_KEY_ID_IDX:
{
if ((ir_app_parm.ir_programming.programming_start == 1)
//&& (ir_app_parm.ir_programming.current_programming_key_id == INVALID_KEY_ID)
&& (len == 2))
{
ir_app_parm.ir_programming.current_programming_key_id = buf[0];
ir_app_parm.ir_programming.current_programming_key_id <<= 8;
ir_app_parm.ir_programming.current_programming_key_id |= buf[1];
if (ir_app_parm.programming_timer)
{
blt_soft_timer_delete(ir_programming_timeoutcb);
ir_app_parm.programming_timer = NULL;
}
blt_soft_timer_add(ir_programming_timeoutcb, PROGRAMMING_TIMEOUT);
ir_app_parm.programming_timer = 1;
}
break;
}
case ATV_IR_CODE_IDX:
{
if ((ir_app_parm.ir_programming.programming_start == 1) && (len > 0))
{
if (ir_app_parm.ir_programming.current_programming_key_id != INVALID_KEY_ID)
{
u8 return_value;
return_value = ir_table_add_key(ir_app_parm.ir_programming.current_programming_key_id, len, buf);
ir_app_parm.ir_programming.current_programming_key_id = INVALID_KEY_ID;
}
else
{
//response error
}
if (ir_app_parm.programming_timer)
{
blt_soft_timer_delete(ir_programming_timeoutcb);
ir_app_parm.programming_timer = NULL;
}
blt_soft_timer_add(ir_programming_timeoutcb, PROGRAMMING_TIMEOUT);
ir_app_parm.programming_timer = 1;
}
break;
}
case ATV_IR_SUPPRESS_IDX:
{
if(len)
{
printf("switch to ble\r\n");
if(len%2 == 0)
{
for(k=0;k<len/2;k++)
{
u16 id = (buf[2*k]<<8) | buf[2*k+1];
index = ir_get_button_idx_from_key_id(id);
printf("index=%x\r\n",index);
if(ir_app_parm.ir_suppress[index] == 0)
{
ir_app_parm.ir_suppress[index] = 1;
}
}
}
}
else
{
printf("switch to ir\r\n");
for(k=0;k<MAX_KEY_COUNT;k++)
{
if(ir_app_parm.ir_suppress[k])
{
ir_app_parm.ir_suppress[k] = 0;
}
}
}
break;
}
case ATV_IR_KEY_EVENT_CCCD_IDX:
{
if (len == 2)
{
printf("ccc buf[0]=%x\r\n",buf[0]);
if(buf[0] != ir_app_parm.ir_programming.key_notification_flag)
{
ir_app_parm.ir_programming.key_notification_flag = buf[0];
if(is_ir_key_event_notify_flash_info_full() == 1)
{
ir_key_event_notify_erase();
}
else
write_ir_key_event_notify(buf[0]);
}
}
break;
}
default:
{
//printf("!!unhandled IDX\r\n");
}
break;
}
}
void ir_flash_save_loop(void)
{
if(ir_app_parm.ir_save.ir_save_en)
{
ir_flash_save_timeoutcb();
}
}
void ir_flash_erase_loop(void)
{
if((ir_flash_erase_tick) && (ir_send_ctrl.is_sending== 0))
{
if(ir_flash_erase_timeoutcb() == -1)
{
ir_flash_erase_tick = 0;
}
}
}
u8 ir_flash_busy(void)
{
if(ir_app_parm.ir_save.ir_save_en || ir_flash_erase_tick || ir_app_parm.ir_programming.programming_start)
return 1;
else
return 0;
}
#define APP_IR_CMD_OTA_NEC_IR_TABLE_PREPARE 0xEF00
#define APP_IR_CMD_OTA_NEC_IR_TABLE_START 0xEF01
#define APP_IR_CMD_OTA_NEC_IR_TABLE_END 0xEF02
void ir_nec_ir_table_process(u8 *data,u16 len)
{
u8 datasend[3];
u16 crc=0;
u32 flash_addr=0,pos=0;
u8 readdata[16];
u8 result=0;
u16 cmd = data[0] | (data[1]<<8);
if(cmd == APP_IR_CMD_OTA_NEC_IR_TABLE_PREPARE)
{
nec_ir_table_start = APP_NEC_IR_TABLE_PREPARE;
}
else if(cmd == APP_IR_CMD_OTA_NEC_IR_TABLE_START)
{
nec_ir_table_start = APP_NEC_IR_TABLE_START;
}
else if(((data[0] == 2) && (data[1] == 0xEF))) //IR end
{
datasend[0] = 0xEE;
datasend[1] = 2;
datasend[2] = 0;
bls_att_pushNotifyData(OTA_CMD_OUT_DP_H, datasend, sizeof(datasend));
if(nec_ir_table_start == APP_NEC_IR_TABLE_START)
{
app_custom_set_new_ir_table();
}
nec_ir_table_start = APP_NEC_IR_TABLE_END;
}
if(nec_ir_table_start == APP_NEC_IR_TABLE_START)
{
if(len == 20)
{
crc = (data[19]<<8) | data[18];
pos = (data[0]) | (data[1]<<8);
extern unsigned short crc16 (unsigned char *pD, int len);
if(crc == crc16(data,18))
{
flash_addr = APP_NEC_IR_CODE_TABLE + pos*16;
flash_write_page(flash_addr,16,&data[2]);
flash_read_page(flash_addr,16, readdata);
if(memcmp(&data[2],readdata,16))
{
result = 1;
}
}
else
{
result = 1;
}
if(result == 1)
{
datasend[0] = 0xEE;
datasend[1] = 2;
datasend[2] = 1;
bls_att_pushNotifyData(OTA_CMD_OUT_DP_H, datasend, sizeof(datasend));
nec_ir_table_start = APP_NEC_IR_TABLE_WRITEFAIL; //data invalid, must erase
}
}
}
}
int ir_nec_ir_table_erase_timeoutcb(void)
{
if(is_mic_enable() == 1)
return 0;
if(bls_ll_requestConnBrxEventDisable() > 120)
{
printf("ir_nec_ir_table_erase_timeoutcb\r\n");
bls_ll_disableConnBrxEvent();
flash_erase_sector(APP_NEC_IR_CODE_TABLE);
bls_ll_restoreConnBrxEvent();
return -1;
}
return 0;
}
void ir_nec_ir_table_erase_loop(void)
{
u8 datasend[3];
if((nec_ir_table_start == APP_NEC_IR_TABLE_PREPARE) || (nec_ir_table_start == APP_NEC_IR_TABLE_WRITEFAIL))
{
if(ir_send_ctrl.is_sending == 0)
{
if(ir_nec_ir_table_erase_timeoutcb() == -1)
{
if(device_in_connection_state && (nec_ir_table_start == APP_NEC_IR_TABLE_PREPARE))
{
//printf("ir_nec_ir_table_erase_end\r\n");
datasend[0] = 0XEE;
datasend[1] = 0;
datasend[2] = 0;
bls_att_pushNotifyData(OTA_CMD_OUT_DP_H, datasend, sizeof(datasend));
}
nec_ir_table_start = APP_NEC_IR_TABLE_PREPARE_END;
}
}
}
}
#endif