/************************************************************************************** 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 #include #include #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; } BOOL is_solo_function(UINT8 function_code) { return (((context->solo_function_mark >> (function_code - 1)) & 0x01) == 0x01) ? TRUE : FALSE; }