453 lines
12 KiB
C
453 lines
12 KiB
C
/**************************************************************************************
|
|
Filename: ir_tv_control.c
|
|
Revised: Date: 2016-10-21
|
|
Revision: Revision: 1.0
|
|
|
|
Description: This file provides algorithms for IR decode (compressed command type)
|
|
|
|
Revision log:
|
|
* 2016-10-21: created by strawmanbobi
|
|
**************************************************************************************/
|
|
|
|
#if defined (BOARD_PC)
|
|
#pragma ide diagnostic ignored "hicpp-signed-bitwise"
|
|
#endif
|
|
|
|
#include <string.h>
|
|
|
|
#include "include/ir_defs.h"
|
|
#include "include/ir_decode.h"
|
|
#include "include/ir_tv_control.h"
|
|
|
|
|
|
struct buffer
|
|
{
|
|
UINT8 *data;
|
|
UINT16 len;
|
|
UINT16 offset;
|
|
} ir_file;
|
|
|
|
|
|
static struct buffer *pbuffer = &ir_file;
|
|
|
|
static UINT8 *prot_cycles_num = NULL;
|
|
static t_ir_cycles *prot_cycles_data[IRDA_MAX];
|
|
static UINT8 prot_items_cnt = 0;
|
|
static t_ir_data *prot_items_data = NULL;
|
|
static t_ir_data_tv *remote_p;
|
|
static UINT8 *remote_pdata = NULL;
|
|
|
|
static UINT16 time_index = 0;
|
|
static UINT8 ir_level = IRDA_LEVEL_LOW;
|
|
static UINT8 ir_toggle_bit = FALSE;
|
|
static UINT8 ir_decode_flag = IRDA_DECODE_1_BIT;
|
|
static UINT8 cycles_num_size = 0;
|
|
|
|
|
|
static BOOL get_ir_protocol(UINT8 encode_type);
|
|
|
|
static BOOL get_ir_keymap(void);
|
|
|
|
static void print_ir_time(t_ir_data *data, UINT8 key_index, UINT16 *ir_time);
|
|
|
|
static void process_decode_number(UINT8 keycode, t_ir_data *data, UINT8 valid_bits, UINT16 *ir_time);
|
|
|
|
static void convert_to_ir_time(UINT8 value, UINT16 *ir_time);
|
|
|
|
static void replace_with(t_ir_cycles *pcycles_num, UINT16 *ir_time);
|
|
|
|
|
|
INT8 tv_binary_open(UINT8 *binary, UINT16 binary_length)
|
|
{
|
|
// load binary to buffer
|
|
pbuffer->data = binary;
|
|
pbuffer->len = binary_length;
|
|
pbuffer->offset = 0;
|
|
return IR_DECODE_SUCCEEDED;
|
|
}
|
|
|
|
BOOL tv_binary_parse(UINT8 encode_type)
|
|
{
|
|
if (FALSE == get_ir_protocol(encode_type))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return get_ir_keymap();
|
|
}
|
|
|
|
UINT16 tv_binary_decode(UINT8 key, UINT16 *user_data)
|
|
{
|
|
UINT16 i = 0;
|
|
|
|
time_index = 0;
|
|
ir_level = IRDA_LEVEL_LOW;
|
|
|
|
for (i = 0; i < prot_items_cnt; i++)
|
|
{
|
|
print_ir_time(&prot_items_data[i], key, user_data);
|
|
}
|
|
|
|
// next flip
|
|
if (2 == prot_cycles_num[IRDA_FLIP])
|
|
{
|
|
ir_toggle_bit = (ir_toggle_bit == FALSE) ? TRUE : FALSE;
|
|
}
|
|
|
|
return time_index;
|
|
}
|
|
|
|
|
|
static BOOL get_ir_protocol(UINT8 encode_type)
|
|
{
|
|
UINT8 i = 0;
|
|
UINT8 name_size = 20;
|
|
UINT8 *prot_cycles = NULL;
|
|
UINT8 cycles_sum = 0;
|
|
|
|
if (pbuffer->data == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pbuffer->offset = 0;
|
|
|
|
/* t_ac_protocol name */
|
|
pbuffer->offset += name_size;
|
|
|
|
/* cycles number */
|
|
prot_cycles_num = pbuffer->data + pbuffer->offset;
|
|
|
|
if (encode_type == 0)
|
|
{
|
|
cycles_num_size = 8;
|
|
/* "BOOT", "STOP", "SEP", "ONE", "ZERO", "FLIP", "TWO", "THREE" */
|
|
if (prot_cycles_num[IRDA_TWO] == 0 && prot_cycles_num[IRDA_THREE] == 0)
|
|
{
|
|
ir_decode_flag = IRDA_DECODE_1_BIT;
|
|
}
|
|
else
|
|
{
|
|
ir_decode_flag = IRDA_DECODE_2_BITS;
|
|
}
|
|
}
|
|
else if (encode_type == 1)
|
|
{
|
|
cycles_num_size = IRDA_MAX;
|
|
ir_decode_flag = IRDA_DECODE_4_BITS;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
pbuffer->offset += cycles_num_size;
|
|
|
|
/* cycles data */
|
|
prot_cycles = pbuffer->data + pbuffer->offset;
|
|
for (i = 0; i < cycles_num_size; i++)
|
|
{
|
|
if (0 != prot_cycles_num[i])
|
|
{
|
|
prot_cycles_data[i] = (t_ir_cycles *) (&prot_cycles[sizeof(t_ir_cycles) * cycles_sum]);
|
|
}
|
|
else
|
|
{
|
|
prot_cycles_data[i] = NULL;
|
|
}
|
|
cycles_sum += prot_cycles_num[i];
|
|
}
|
|
pbuffer->offset += sizeof(t_ir_cycles) * cycles_sum;
|
|
|
|
/* items count */
|
|
prot_items_cnt = pbuffer->data[pbuffer->offset];
|
|
pbuffer->offset += sizeof(UINT8);
|
|
|
|
/* items data */
|
|
prot_items_data = (t_ir_data *) (pbuffer->data + pbuffer->offset);
|
|
pbuffer->offset += prot_items_cnt * sizeof(t_ir_data);
|
|
|
|
ir_toggle_bit = FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL get_ir_keymap(void)
|
|
{
|
|
remote_p = (t_ir_data_tv *) (pbuffer->data + pbuffer->offset);
|
|
pbuffer->offset += sizeof(t_ir_data_tv);
|
|
|
|
if (strncmp(remote_p->magic, "irda", 4) == 0)
|
|
{
|
|
remote_pdata = pbuffer->data + pbuffer->offset;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void print_ir_time(t_ir_data *data, UINT8 key_index, UINT16 *ir_time)
|
|
{
|
|
UINT8 i = 0;
|
|
UINT8 cycles_num = 0;
|
|
t_ir_cycles *pcycles = NULL;
|
|
UINT8 key_code = 0;
|
|
|
|
if (NULL == data || NULL == ir_time)
|
|
{
|
|
ir_printf("data or ir_time is null\n");
|
|
return;
|
|
}
|
|
|
|
pcycles = prot_cycles_data[data->index];
|
|
key_code = remote_pdata[remote_p->per_keycode_bytes * key_index + data->index - 1];
|
|
|
|
if (prot_cycles_num[IRDA_ONE] != 1 || prot_cycles_num[IRDA_ZERO] != 1)
|
|
{
|
|
ir_printf("logical 1 or 0 is invalid\n");
|
|
return;
|
|
}
|
|
|
|
if (time_index >= USER_DATA_SIZE)
|
|
{
|
|
ir_printf("time index exceeded\n");
|
|
return;
|
|
}
|
|
|
|
if (data->bits == 1)
|
|
{
|
|
if (pcycles == NULL)
|
|
{
|
|
ir_printf("pcycles is null\n");
|
|
return;
|
|
}
|
|
|
|
cycles_num = prot_cycles_num[data->index];
|
|
if (cycles_num > 5)
|
|
{
|
|
ir_printf("cycles number exceeded\n");
|
|
return;
|
|
}
|
|
|
|
for (i = cycles_num; i > 0; i--)
|
|
{
|
|
if (cycles_num == 2 && data->index == IRDA_FLIP)
|
|
{
|
|
if (ir_toggle_bit == TRUE)
|
|
{
|
|
pcycles += 1;
|
|
}
|
|
}
|
|
|
|
if (pcycles->mask && pcycles->space)
|
|
{
|
|
if (pcycles->flag == IRDA_FLAG_NORMAL)
|
|
{
|
|
if (ir_level == IRDA_LEVEL_HIGH && time_index != 0)
|
|
{
|
|
time_index--;
|
|
ir_time[time_index++] += pcycles->mask;
|
|
}
|
|
else if (ir_level == IRDA_LEVEL_LOW)
|
|
{
|
|
ir_time[time_index++] = pcycles->mask;
|
|
}
|
|
ir_time[time_index++] = pcycles->space;
|
|
ir_level = IRDA_LEVEL_LOW;
|
|
}
|
|
else if (pcycles->flag == IRDA_FLAG_INVERSE)
|
|
{
|
|
if (ir_level == IRDA_LEVEL_LOW && time_index != 0)
|
|
{
|
|
time_index--;
|
|
ir_time[time_index++] += pcycles->space;
|
|
}
|
|
else if (ir_level == IRDA_LEVEL_HIGH)
|
|
{
|
|
ir_time[time_index++] = pcycles->space;
|
|
}
|
|
ir_time[time_index++] = pcycles->mask;
|
|
ir_level = IRDA_LEVEL_HIGH;
|
|
}
|
|
}
|
|
else if (0 == pcycles->mask && 0 != pcycles->space)
|
|
{
|
|
if (ir_level == IRDA_LEVEL_LOW && time_index != 0)
|
|
{
|
|
time_index--;
|
|
ir_time[time_index++] += pcycles->space;
|
|
}
|
|
else if (ir_level == IRDA_LEVEL_HIGH)
|
|
{
|
|
ir_time[time_index++] = pcycles->space;
|
|
}
|
|
ir_level = IRDA_LEVEL_LOW;
|
|
}
|
|
else if (0 == pcycles->space && 0 != pcycles->mask)
|
|
{
|
|
if (ir_level == IRDA_LEVEL_HIGH && time_index != 0)
|
|
{
|
|
time_index--;
|
|
ir_time[time_index++] += pcycles->mask;
|
|
}
|
|
else if (ir_level == IRDA_LEVEL_LOW)
|
|
{
|
|
ir_time[time_index++] = pcycles->mask;
|
|
}
|
|
ir_level = IRDA_LEVEL_HIGH;
|
|
}
|
|
else
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
if (cycles_num == 2 && data->index == IRDA_FLIP)
|
|
{
|
|
break;
|
|
}
|
|
pcycles++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// mode: inverse
|
|
if (data->mode == 1)
|
|
key_code = ~key_code;
|
|
|
|
if (ir_decode_flag == IRDA_DECODE_1_BIT)
|
|
{
|
|
// for binary formatted code
|
|
process_decode_number(key_code, data, 1, ir_time);
|
|
}
|
|
else if (ir_decode_flag == IRDA_DECODE_2_BITS)
|
|
{
|
|
// for quaternary formatted code
|
|
process_decode_number(key_code, data, 2, ir_time);
|
|
}
|
|
else if (ir_decode_flag == IRDA_DECODE_4_BITS)
|
|
{
|
|
// for hexadecimal formatted code
|
|
process_decode_number(key_code, data, 4, ir_time);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void process_decode_number(UINT8 keycode, t_ir_data *data, UINT8 valid_bits, UINT16 *ir_time)
|
|
{
|
|
UINT8 i = 0;
|
|
UINT8 value = 0;
|
|
UINT8 bit_num = data->bits / valid_bits;
|
|
UINT8 valid_value = 0;
|
|
|
|
valid_value = (UINT8) ((valid_bits == 1) ? 1 : (valid_bits * valid_bits - 1));
|
|
|
|
if (data->lsb == IRDA_LSB)
|
|
{
|
|
for (i = 0; i < bit_num; i++)
|
|
{
|
|
value = (keycode >> (valid_bits * i)) & valid_value;
|
|
convert_to_ir_time(value, ir_time);
|
|
}
|
|
}
|
|
else if (data->lsb == IRDA_MSB)
|
|
{
|
|
for (i = 0; i < bit_num; i++)
|
|
{
|
|
value = (keycode >> (data->bits - valid_bits * (i + 1))) & valid_value;
|
|
convert_to_ir_time(value, ir_time);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void convert_to_ir_time(UINT8 value, UINT16 *ir_time)
|
|
{
|
|
switch (value)
|
|
{
|
|
case 0:
|
|
replace_with(prot_cycles_data[IRDA_ZERO], ir_time);
|
|
break;
|
|
case 1:
|
|
replace_with(prot_cycles_data[IRDA_ONE], ir_time);
|
|
break;
|
|
case 2:
|
|
replace_with(prot_cycles_data[IRDA_TWO], ir_time);
|
|
break;
|
|
case 3:
|
|
replace_with(prot_cycles_data[IRDA_THREE], ir_time);
|
|
break;
|
|
case 4:
|
|
replace_with(prot_cycles_data[IRDA_FOUR], ir_time);
|
|
break;
|
|
case 5:
|
|
replace_with(prot_cycles_data[IRDA_FIVE], ir_time);
|
|
break;
|
|
case 6:
|
|
replace_with(prot_cycles_data[IRDA_SIX], ir_time);
|
|
break;
|
|
case 7:
|
|
replace_with(prot_cycles_data[IRDA_SEVEN], ir_time);
|
|
break;
|
|
case 8:
|
|
replace_with(prot_cycles_data[IRDA_EIGHT], ir_time);
|
|
break;
|
|
case 9:
|
|
replace_with(prot_cycles_data[IRDA_NINE], ir_time);
|
|
break;
|
|
case 0x0A:
|
|
replace_with(prot_cycles_data[IRDA_A], ir_time);
|
|
break;
|
|
case 0x0B:
|
|
replace_with(prot_cycles_data[IRDA_B], ir_time);
|
|
break;
|
|
case 0x0C:
|
|
replace_with(prot_cycles_data[IRDA_C], ir_time);
|
|
break;
|
|
case 0x0D:
|
|
replace_with(prot_cycles_data[IRDA_D], ir_time);
|
|
break;
|
|
case 0x0E:
|
|
replace_with(prot_cycles_data[IRDA_E], ir_time);
|
|
break;
|
|
case 0x0F:
|
|
replace_with(prot_cycles_data[IRDA_F], ir_time);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void replace_with(t_ir_cycles *pcycles_num, UINT16 *ir_time)
|
|
{
|
|
if (NULL == pcycles_num || NULL == ir_time)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (pcycles_num->flag == IRDA_FLAG_NORMAL)
|
|
{
|
|
if (ir_level == IRDA_LEVEL_HIGH && time_index != 0)
|
|
{
|
|
time_index--;
|
|
ir_time[time_index++] += pcycles_num->mask;
|
|
}
|
|
else if (ir_level == IRDA_LEVEL_LOW)
|
|
{
|
|
ir_time[time_index++] = pcycles_num->mask;
|
|
}
|
|
ir_time[time_index++] = pcycles_num->space;
|
|
ir_level = IRDA_LEVEL_LOW;
|
|
}
|
|
else if (pcycles_num->flag == IRDA_FLAG_INVERSE)
|
|
{
|
|
if (ir_level == IRDA_LEVEL_LOW && time_index != 0)
|
|
{
|
|
time_index--;
|
|
ir_time[time_index++] += pcycles_num->space;
|
|
}
|
|
else if (ir_level == IRDA_LEVEL_HIGH)
|
|
{
|
|
ir_time[time_index++] = pcycles_num->space;
|
|
}
|
|
ir_time[time_index++] = pcycles_num->mask;
|
|
ir_level = IRDA_LEVEL_HIGH;
|
|
}
|
|
} |