560 lines
18 KiB
C
560 lines
18 KiB
C
/**************************************************************************************
|
|
Filename: ir_ac_control.c
|
|
Revised: Date: 2017-01-02
|
|
Revision: Revision: 1.0
|
|
|
|
Description: This file provides methods for AC IR control
|
|
|
|
Revision log:
|
|
* 2016-10-12: created by strawmanbobi
|
|
**************************************************************************************/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "include/ir_ac_control.h"
|
|
#include "include/ir_ac_binary_parse.h"
|
|
#include "include/ir_decode.h"
|
|
#include "include/ir_ac_parse_parameter.h"
|
|
#include "include/ir_ac_parse_forbidden_info.h"
|
|
#include "include/ir_ac_parse_frame_info.h"
|
|
#include "include/ir_utils.h"
|
|
|
|
|
|
#if defined USE_DYNAMIC_TAG
|
|
extern struct tag_head *tags;
|
|
#else
|
|
extern struct tag_head tags[];
|
|
#endif
|
|
|
|
extern UINT8 tag_count;
|
|
|
|
static INT8 ir_context_init();
|
|
|
|
|
|
static INT8 ir_context_init()
|
|
{
|
|
ir_memset(context, 0, sizeof(t_ac_protocol));
|
|
return IR_DECODE_SUCCEEDED;
|
|
}
|
|
|
|
|
|
INT8 ir_ac_lib_parse()
|
|
{
|
|
UINT i = 0;
|
|
// suggest not to call init function here for de-couple purpose
|
|
ir_context_init();
|
|
|
|
if (IR_DECODE_FAILED == binary_parse_offset())
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
|
|
if (IR_DECODE_FAILED == binary_parse_len())
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
|
|
if (IR_DECODE_FAILED == binary_parse_data())
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
|
|
binary_tags_info();
|
|
|
|
context->endian = 0;
|
|
context->last_bit = 0;
|
|
context->repeat_times = 1;
|
|
|
|
for (i = 0; i < N_MODE_MAX; i++)
|
|
{
|
|
context->n_mode[i].enable = TRUE;
|
|
context->n_mode[i].all_speed = FALSE;
|
|
context->n_mode[i].all_temp = FALSE;
|
|
ir_memset(context->n_mode[i].speed, 0x00, AC_WS_MAX);
|
|
context->n_mode[i].speed_cnt = 0;
|
|
ir_memset(context->n_mode[i].temp, 0x00, AC_TEMP_MAX);
|
|
context->n_mode[i].temp_cnt = 0;
|
|
}
|
|
|
|
// parse TAG 46 in first priority
|
|
for (i = 0; i < tag_count; i++)
|
|
{
|
|
if (tags[i].tag == TAG_AC_SWING_INFO)
|
|
{
|
|
if (tags[i].len != 0)
|
|
{
|
|
parse_swing_info(&tags[i], &(context->si));
|
|
}
|
|
else
|
|
{
|
|
context->si.type = SWING_TYPE_NORMAL;
|
|
context->si.mode_count = 2;
|
|
}
|
|
context->si.dir_index = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < tag_count; i++)
|
|
{
|
|
if (tags[i].len == 0)
|
|
{
|
|
continue;
|
|
}
|
|
// then parse TAG 26 or 33
|
|
if (context->si.type == SWING_TYPE_NORMAL)
|
|
{
|
|
UINT16 swing_space_size = 0;
|
|
if (tags[i].tag == TAG_AC_SWING_1)
|
|
{
|
|
context->swing1.count = context->si.mode_count;
|
|
context->swing1.len = (UINT8) tags[i].len >> (UINT8) 1;
|
|
swing_space_size = sizeof(t_tag_comp) * context->si.mode_count;
|
|
context->swing1.comp_data = (t_tag_comp *) ir_malloc(swing_space_size);
|
|
if (NULL == context->swing1.comp_data)
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
|
|
ir_memset(context->swing1.comp_data, 0x00, swing_space_size);
|
|
if (IR_DECODE_FAILED == parse_common_ac_parameter(&tags[i],
|
|
context->swing1.comp_data,
|
|
context->si.mode_count,
|
|
AC_PARAMETER_TYPE_1))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_SWING_2)
|
|
{
|
|
context->swing2.count = context->si.mode_count;
|
|
context->swing2.len = (UINT8) tags[i].len >> (UINT8) 1;
|
|
swing_space_size = sizeof(t_tag_comp) * context->si.mode_count;
|
|
context->swing2.comp_data = (t_tag_comp *) ir_malloc(swing_space_size);
|
|
if (NULL == context->swing2.comp_data)
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
ir_memset(context->swing2.comp_data, 0x00, swing_space_size);
|
|
if (IR_DECODE_FAILED == parse_common_ac_parameter(&tags[i],
|
|
context->swing2.comp_data,
|
|
context->si.mode_count,
|
|
AC_PARAMETER_TYPE_2))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (tags[i].tag == TAG_AC_DEFAULT_CODE) // default code TAG
|
|
{
|
|
context->default_code.data = (UINT8 *) ir_malloc(((size_t) tags[i].len - 2) >> (UINT8) 1);
|
|
if (NULL == context->default_code.data)
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
if (IR_DECODE_FAILED == parse_default_code(&tags[i], &(context->default_code)))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_POWER_1) // power tag
|
|
{
|
|
context->power1.len = (UINT8) tags[i].len >> (UINT8) 1;
|
|
if (IR_DECODE_FAILED == parse_common_ac_parameter(&tags[i],
|
|
context->power1.comp_data,
|
|
AC_POWER_MAX,
|
|
AC_PARAMETER_TYPE_1))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_TEMP_1) // temperature tag type 1
|
|
{
|
|
if (IR_DECODE_FAILED == parse_temp_1(&tags[i], &(context->temp1)))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_MODE_1) // mode tag
|
|
{
|
|
context->mode1.len = (UINT8) tags[i].len >> (UINT8) 1;
|
|
if (IR_DECODE_FAILED == parse_common_ac_parameter(&tags[i],
|
|
context->mode1.comp_data,
|
|
AC_MODE_MAX,
|
|
AC_PARAMETER_TYPE_1))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_SPEED_1) // wind speed tag
|
|
{
|
|
context->speed1.len = (UINT8) tags[i].len >> (UINT8) 1;
|
|
if (IR_DECODE_FAILED == parse_common_ac_parameter(&tags[i],
|
|
context->speed1.comp_data,
|
|
AC_WS_MAX,
|
|
AC_PARAMETER_TYPE_1))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_CHECKSUM_TYPE)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_checksum(&tags[i], &(context->checksum)))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_MODE_2)
|
|
{
|
|
context->mode2.len = (UINT8) tags[i].len >> (UINT8) 1;
|
|
if (IR_DECODE_FAILED ==
|
|
parse_common_ac_parameter(&tags[i],
|
|
context->mode2.comp_data, AC_MODE_MAX, AC_PARAMETER_TYPE_1))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_SPEED_2)
|
|
{
|
|
context->speed2.len = (UINT8) tags[i].len >> (UINT8) 1;
|
|
if (IR_DECODE_FAILED ==
|
|
parse_common_ac_parameter(&tags[i],
|
|
context->speed2.comp_data, AC_WS_MAX, AC_PARAMETER_TYPE_1))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_TEMP_2)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_temp_2(&tags[i], &(context->temp2)))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_SOLO_FUNCTION)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_solo_code(&tags[i], &(context->sc)))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
context->solo_function_mark = 1;
|
|
}
|
|
else if (tags[i].tag == TAG_AC_FUNCTION_1)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_function_1_tag29(&tags[i], &(context->function1)))
|
|
{
|
|
ir_printf("\nfunction code parse error\n");
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_FUNCTION_2)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_function_2_tag34(&tags[i], &(context->function2)))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_FRAME_LENGTH)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_frame_len(&tags[i], tags[i].len))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_ZERO)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_zero(&tags[i]))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_ONE)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_one(&tags[i]))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_BOOT_CODE)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_boot_code(&tags[i]))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_REPEAT_TIMES)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_repeat_times(&tags[i]))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_BIT_NUM)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_bit_num(&tags[i]))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_ENDIAN)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_endian(&tags[i]))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_BAN_FUNCTION_IN_COOL_MODE)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_nmode(&tags[i], N_COOL))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_BAN_FUNCTION_IN_HEAT_MODE)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_nmode(&tags[i], N_HEAT))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_BAN_FUNCTION_IN_AUTO_MODE)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_nmode(&tags[i], N_AUTO))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_BAN_FUNCTION_IN_FAN_MODE)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_nmode(&tags[i], N_FAN))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
else if (tags[i].tag == TAG_AC_BAN_FUNCTION_IN_DRY_MODE)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_nmode(&tags[i], N_DRY))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < tag_count; i++)
|
|
{
|
|
if (tags[i].len == 0)
|
|
{
|
|
continue;
|
|
}
|
|
if (tags[i].tag == TAG_AC_DELAY_CODE)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_delay_code(&tags[i]))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
if (tags[i].tag == TAG_AC_LAST_BIT)
|
|
{
|
|
if (IR_DECODE_FAILED == parse_lastbit(&tags[i]))
|
|
{
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if defined USE_DYNAMIC_TAG
|
|
if (NULL != tags)
|
|
{
|
|
ir_free(tags);
|
|
tags = NULL;
|
|
}
|
|
#endif
|
|
|
|
ir_hex_code = (UINT8 *) ir_malloc(context->default_code.len);
|
|
if (NULL == ir_hex_code)
|
|
{
|
|
// warning: this AC bin contains no default code
|
|
return IR_DECODE_FAILED;
|
|
}
|
|
|
|
ir_hex_len = context->default_code.len;
|
|
ir_memset(ir_hex_code, 0x00, ir_hex_len);
|
|
|
|
// pre-calculate solo function status after parse phase
|
|
if (1 == context->solo_function_mark)
|
|
{
|
|
context->solo_function_mark = 0x00;
|
|
// bit order from right to left : power, mode, temp+, temp-, wind_speed, swing, fix
|
|
for (i = AC_FUNCTION_POWER; i < AC_FUNCTION_MAX; i++)
|
|
{
|
|
if (is_in(context->sc.solo_function_codes, i, context->sc.solo_func_count))
|
|
{
|
|
context->solo_function_mark |= (UINT8) ((UINT8) 1 << (i - 1));
|
|
}
|
|
}
|
|
}
|
|
|
|
// it is strongly recommended that we free p_ir_buffer
|
|
// or make global buffer shared in extreme memory case
|
|
/* in case of running with test - begin */
|
|
#if (defined BOARD_PC || defined BOARD_PC_DLL)
|
|
ir_lib_free_inner_buffer();
|
|
ir_printf("AC parse done\n");
|
|
#endif
|
|
/* in case of running with test - end */
|
|
|
|
return IR_DECODE_SUCCEEDED;
|
|
}
|
|
|
|
|
|
INT8 free_ac_context()
|
|
{
|
|
UINT16 i = 0;
|
|
|
|
if (ir_hex_code != NULL)
|
|
{
|
|
ir_free(ir_hex_code);
|
|
ir_hex_code = NULL;
|
|
}
|
|
ir_hex_len = 0;
|
|
|
|
if (context->default_code.data != NULL)
|
|
{
|
|
ir_free(context->default_code.data);
|
|
context->default_code.data = NULL;
|
|
context->default_code.len = 0;
|
|
}
|
|
|
|
for (i = 0; i < (UINT16) AC_POWER_MAX; i++)
|
|
{
|
|
if (context->power1.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->power1.comp_data[i].segment);
|
|
context->power1.comp_data[i].segment = NULL;
|
|
context->power1.comp_data[i].seg_len = 0;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < (UINT16) AC_TEMP_MAX; i++)
|
|
{
|
|
if (context->temp1.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->temp1.comp_data[i].segment);
|
|
context->temp1.comp_data[i].segment = NULL;
|
|
context->temp1.comp_data[i].seg_len = 0;
|
|
}
|
|
if (context->temp2.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->temp2.comp_data[i].segment);
|
|
context->temp2.comp_data[i].segment = NULL;
|
|
context->temp2.comp_data[i].seg_len = 0;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < (UINT16) AC_MODE_MAX; i++)
|
|
{
|
|
if (context->mode1.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->mode1.comp_data[i].segment);
|
|
context->mode1.comp_data[i].segment = NULL;
|
|
context->mode1.comp_data[i].seg_len = 0;
|
|
}
|
|
if (context->mode2.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->mode2.comp_data[i].segment);
|
|
context->mode2.comp_data[i].segment = NULL;
|
|
context->mode2.comp_data[i].seg_len = 0;
|
|
}
|
|
}
|
|
for (i = 0; i < (UINT16) AC_WS_MAX; i++)
|
|
{
|
|
if (context->speed1.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->speed1.comp_data[i].segment);
|
|
context->speed1.comp_data[i].segment = NULL;
|
|
context->speed1.comp_data[i].seg_len = 0;
|
|
}
|
|
if (context->speed2.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->speed2.comp_data[i].segment);
|
|
context->speed2.comp_data[i].segment = NULL;
|
|
context->speed2.comp_data[i].seg_len = 0;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < context->si.mode_count; i++)
|
|
{
|
|
if (context->swing1.comp_data != NULL &&
|
|
context->swing1.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->swing1.comp_data[i].segment);
|
|
context->swing1.comp_data[i].segment = NULL;
|
|
context->swing1.comp_data[i].seg_len = 0;
|
|
}
|
|
if (context->swing2.comp_data != NULL &&
|
|
context->swing2.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->swing2.comp_data[i].segment);
|
|
context->swing2.comp_data[i].segment = NULL;
|
|
context->swing2.comp_data[i].seg_len = 0;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < (UINT16) AC_FUNCTION_MAX - 1; i++)
|
|
{
|
|
if (context->function1.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->function1.comp_data[i].segment);
|
|
context->function1.comp_data[i].segment = NULL;
|
|
context->function1.comp_data[i].seg_len = 0;
|
|
}
|
|
if (context->function2.comp_data[i].segment != NULL)
|
|
{
|
|
ir_free(context->function2.comp_data[i].segment);
|
|
context->function2.comp_data[i].segment = NULL;
|
|
context->function2.comp_data[i].seg_len = 0;
|
|
}
|
|
}
|
|
|
|
// free composite data for swing1 and swing 2
|
|
if (context->swing1.comp_data != NULL)
|
|
{
|
|
ir_free(context->swing1.comp_data);
|
|
context->swing1.comp_data = NULL;
|
|
}
|
|
if (context->swing2.comp_data != NULL)
|
|
{
|
|
ir_free(context->swing2.comp_data);
|
|
context->swing2.comp_data = NULL;
|
|
}
|
|
|
|
for (i = 0; i < context->checksum.count; i++)
|
|
{
|
|
if (context->checksum.checksum_data != NULL &&
|
|
context->checksum.checksum_data[i].spec_pos != NULL)
|
|
{
|
|
ir_free(context->checksum.checksum_data[i].spec_pos);
|
|
context->checksum.checksum_data[i].len = 0;
|
|
context->checksum.checksum_data[i].spec_pos = NULL;
|
|
}
|
|
}
|
|
if (context->checksum.checksum_data != NULL)
|
|
{
|
|
ir_free(context->checksum.checksum_data);
|
|
context->checksum.checksum_data = NULL;
|
|
}
|
|
|
|
return IR_DECODE_SUCCEEDED;
|
|
}
|
|
|
|
#if defined (BOARD_PC)
|
|
#pragma ide diagnostic ignored "hicpp-signed-bitwise"
|
|
#endif
|
|
|
|
BOOL is_solo_function(UINT8 function_code)
|
|
{
|
|
return (((context->solo_function_mark >> (function_code - 1)) & 0x01) == 0x01) ? TRUE : FALSE;
|
|
} |