Files
iris-kit/lib/IRext/ir_tv_control.c
2024-02-11 12:42:50 +08:00

450 lines
12 KiB
C

/**************************************************************************************
Filename: ir_lib.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
**************************************************************************************/
// #pragma ide diagnostic ignored "hicpp-signed-bitwise"
#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;
}
}