update 2017-12-24

1. removed arduino example
2. added CC254X example
This commit is contained in:
2017-12-24 17:01:51 +08:00
parent e86bede45f
commit 40f7237cf1
33 changed files with 7344 additions and 1967 deletions

View File

@@ -0,0 +1,43 @@
/**************************************************************************************
Filename: ir_ac_apply.h
Revised: Date: 2016-10-12
Revision: Revision: 1.0
Description: This file provides methods for AC IR applying functionalities
Revision log:
* 2016-10-12: created by strawmanbobi
**************************************************************************************/
#ifndef _IRDA_APPLY_H_
#define _IRDA_APPLY_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "ir_decode.h"
#define MIN_TAG_LENGTH_TYPE_1 4
#define MIN_TAG_LENGTH_TYPE_2 6
INT8 apply_power(t_remote_ac_status ac_status, UINT8 function_code);
INT8 apply_mode(t_remote_ac_status ac_status, UINT8 function_code);
INT8 apply_wind_speed(t_remote_ac_status ac_status, UINT8 function_code);
INT8 apply_swing(t_remote_ac_status ac_status, UINT8 function_code);
INT8 apply_temperature(t_remote_ac_status ac_status, UINT8 function_code);
INT8 apply_function(struct ac_protocol *protocol, UINT8 function);
INT8 apply_checksum(struct ac_protocol *protocol);
#ifdef __cplusplus
}
#endif
#endif //_IRDA_APPLY_H_

View File

@@ -0,0 +1,35 @@
/**************************************************************************************
Filename: ir_ac_binary_parse.h
Revised: Date: 2017-01-03
Revision: Revision: 1.0
Description: This file provides methods for AC binary parse
Revision log:
* 2017-01-03: created by strawmanbobi
**************************************************************************************/
#ifndef IRDA_DECODER_IR_AC_BINARY_PARSE_H
#define IRDA_DECODER_IR_AC_BINARY_PARSE_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ir_defs.h"
extern INT8 binary_parse_offset();
extern INT8 binary_parse_len();
extern void binary_tags_info();
extern INT8 binary_parse_data();
#ifdef __cplusplus
}
#endif
#endif //IRDA_DECODER_IR_AC_BINARY_PARSE_H

View File

@@ -0,0 +1,28 @@
/**************************************************************************************
Filename: ir_utils.c
Revised: Date: 2016-10-26
Revision: Revision: 1.0
Description: This file provides generic utils for IR frame build
Revision log:
* 2016-10-01: created by strawmanbobi
**************************************************************************************/
#ifndef _IRDA_IRFRAME_H_
#define _IRDA_IRFRAME_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "ir_defs.h"
extern UINT16 create_ir_frame();
#ifdef __cplusplus
}
#endif
#endif // _IRDA_IRFRAME_H_

View File

@@ -0,0 +1,439 @@
/**************************************************************************************
Filename: ir_ac_control.h
Revised: Date: 2016-12-31
Revision: Revision: 1.0
Description: This file provides methods for AC IR control
Revision log:
* 2016-10-12: created by strawmanbobi
**************************************************************************************/
#ifndef IRDA_DECODER_IR_AC_CONTROL_H
#define IRDA_DECODER_IR_AC_CONTROL_H
#ifdef __cplusplus
extern "C"
{
#endif
#include "ir_defs.h"
#define TAG_COUNT_FOR_PROTOCOL 29
#define TAG_INVALID 0xffff
#define MAX_DELAYCODE_NUM 16
#define MAX_BITNUM 16
#define AC_PARAMETER_TYPE_1 0
#define AC_PARAMETER_TYPE_2 1
typedef enum
{
AC_POWER_ON = 0,
AC_POWER_OFF,
AC_POWER_MAX
} t_ac_power;
typedef enum
{
AC_TEMP_16 = 0,
AC_TEMP_17,
AC_TEMP_18,
AC_TEMP_19,
AC_TEMP_20,
AC_TEMP_21,
AC_TEMP_22,
AC_TEMP_23,
AC_TEMP_24,
AC_TEMP_25,
AC_TEMP_26,
AC_TEMP_27,
AC_TEMP_28,
AC_TEMP_29,
AC_TEMP_30,
AC_TEMP_MAX
} t_ac_temperature;
typedef enum
{
AC_MODE_COOL = 0,
AC_MODE_HEAT,
AC_MODE_AUTO,
AC_MODE_FAN,
AC_MODE_DRY,
AC_MODE_MAX
} t_ac_mode;
typedef enum
{
AC_FUNCTION_POWER = 1,
AC_FUNCTION_MODE,
AC_FUNCTION_TEMPERATURE_UP,
AC_FUNCTION_TEMPERATURE_DOWN,
AC_FUNCTION_WIND_SPEED,
AC_FUNCTION_WIND_SWING,
AC_FUNCTION_WIND_FIX,
AC_FUNCTION_MAX,
} t_ac_function;
typedef enum
{
AC_WS_AUTO = 0,
AC_WS_LOW,
AC_WS_MEDIUM,
AC_WS_HIGH,
AC_WS_MAX
} t_ac_wind_speed;
typedef enum
{
AC_SWING_ON = 0,
AC_SWING_OFF,
AC_SWING_MAX
} t_ac_swing;
typedef enum
{
SWING_TYPE_SWING_ONLY = 0,
SWING_TYPE_NORMAL,
SWING_TYPE_NOT_SPECIFIED,
SWING_TYPE_MAX
} swing_type;
typedef enum
{
TEMP_TYPE_DYNAMIC = 0,
TEMP_TYPE_STATIC,
TEMP_TYPE_MAX,
} t_temp_type;
// enumeration for application polymorphism
typedef enum
{
AC_APPLY_POWER = 0,
AC_APPLY_MODE,
AC_APPLY_TEMPERATURE_UP,
AC_APPLY_TEMPERATURE_DOWN,
AC_APPLY_WIND_SPEED,
AC_APPLY_WIND_SWING,
AC_APPLY_WIND_FIX,
AC_APPLY_MAX
} t_ac_apply;
typedef struct _ac_hex
{
UINT8 len;
UINT8 *data;
} t_ac_hex;
typedef struct _ac_level
{
UINT16 low;
UINT16 high;
} t_ac_level;
typedef struct _ac_bootcode
{
UINT16 len;
UINT16 data[16];
} t_ac_bootcode;
typedef struct _ac_delaycode
{
INT16 pos;
UINT16 time[8];
UINT16 time_cnt;
} t_ac_delaycode;
/*
* the array of tag_100X application data
* seg_len : length for each segment
* byte_pos : the position of update byte
* byte_value : the value to be updated to position
*/
typedef struct _tag_comp_type_1
{
UINT8 seg_len;
UINT8 *segment;
} t_tag_comp;
typedef struct _tag_swing_info
{
swing_type type;
UINT8 mode_count;
UINT8 dir_index;
} t_swing_info;
typedef struct _tag_power_1
{
UINT8 len;
t_tag_comp comp_data[AC_POWER_MAX];
} t_power_1;
typedef struct _tag_temp_1
{
UINT8 len;
UINT8 type;
t_tag_comp comp_data[AC_TEMP_MAX];
} t_temp_1;
typedef struct tag_mode_1
{
UINT8 len;
t_tag_comp comp_data[AC_MODE_MAX];
} t_mode_1;
typedef struct tag_speed_1
{
UINT8 len;
t_tag_comp comp_data[AC_WS_MAX];
} t_speed_1;
typedef struct tag_swing_1
{
UINT8 len;
UINT16 count;
t_tag_comp *comp_data;
} t_swing_1;
typedef struct tag_temp_2
{
UINT8 len;
UINT8 type;
t_tag_comp comp_data[AC_TEMP_MAX];
} t_temp_2;
typedef struct tag_mode_2
{
UINT8 len;
t_tag_comp comp_data[AC_MODE_MAX];
} t_mode_2;
typedef struct tag_speed_2
{
UINT8 len;
t_tag_comp comp_data[AC_WS_MAX];
} t_speed_2;
typedef struct tag_swing_2
{
UINT8 len;
UINT16 count;
t_tag_comp *comp_data;
} t_swing_2;
#if defined SUPPORT_HORIZONTAL_SWING
typedef struct tag_horiswing_1
{
UINT16 len;
t_tag_comp comp_data[AC_HORI_SWING_MAX];
} hori_swing_1;
#endif
typedef struct _tag_checksum_data
{
UINT8 len;
UINT8 type;
UINT8 start_byte_pos;
UINT8 end_byte_pos;
UINT8 checksum_byte_pos;
UINT8 checksum_plus;
UINT8 *spec_pos;
} t_tag_checksum_data;
typedef struct tag_checksum
{
UINT8 len;
UINT16 count;
t_tag_checksum_data *checksum_data;
} t_checksum;
typedef struct tag_function_1
{
UINT8 len;
t_tag_comp comp_data[AC_FUNCTION_MAX - 1];
} t_function_1;
typedef struct tag_function_2
{
UINT8 len;
t_tag_comp comp_data[AC_FUNCTION_MAX - 1];
} t_function_2;
typedef struct tag_solo_code
{
UINT8 len;
UINT8 solo_func_count;
UINT8 solo_function_codes[AC_FUNCTION_MAX - 1];
} t_solo_code;
typedef struct _ac_bitnum
{
INT16 pos;
UINT16 bits;
} t_ac_bit_num;
typedef enum
{
N_COOL = 0,
N_HEAT,
N_AUTO,
N_FAN,
N_DRY,
N_MODE_MAX,
} t_ac_n_mode;
typedef enum
{
CHECKSUM_TYPE_BYTE = 1,
CHECKSUM_TYPE_BYTE_INVERSE,
CHECKSUM_TYPE_HALF_BYTE,
CHECKSUM_TYPE_HALF_BYTE_INVERSE,
CHECKSUM_TYPE_SPEC_HALF_BYTE,
CHECKSUM_TYPE_SPEC_HALF_BYTE_INVERSE,
CHECKSUM_TYPE_SPEC_HALF_BYTE_ONE_BYTE,
CHECKSUM_TYPE_SPEC_HALF_BYTE_INVERSE_ONE_BYTE,
CHECKSUM_TYPE_MAX,
} t_checksum_type;
typedef struct _ac_n_mode_info
{
UINT8 enable;
UINT8 all_speed;
UINT8 all_temp;
UINT8 temp[AC_TEMP_MAX];
UINT8 temp_cnt;
UINT8 speed[AC_WS_MAX];
UINT8 speed_cnt;
} t_ac_n_mode_info;
typedef struct ac_protocol
{
UINT8 endian;
// t_ac_hex default_code;
t_ac_hex default_code;
t_ac_level zero;
t_ac_level one;
t_ac_bootcode boot_code;
t_ac_delaycode dc[MAX_DELAYCODE_NUM];
t_power_1 power1;
t_temp_1 temp1;
t_mode_1 mode1;
t_speed_1 speed1;
t_swing_1 swing1;
t_checksum checksum;
t_function_1 function1;
t_function_2 function2;
t_temp_2 temp2;
t_mode_2 mode2;
t_speed_2 speed2;
t_swing_2 swing2;
t_swing_info si;
t_solo_code sc;
UINT8 swing_status;
BOOL change_wind_direction;
UINT16 dc_cnt;
t_ac_bit_num bit_num[MAX_BITNUM];
UINT16 bit_num_cnt;
UINT16 repeat_times;
t_ac_n_mode_info n_mode[N_MODE_MAX];
UINT16 code_cnt;
UINT8 last_bit;
UINT16 *time;
UINT8 solo_function_mark;
UINT16 frame_length;
} t_ac_protocol;
typedef struct tag_head
{
UINT16 tag;
UINT16 len;
unsigned short offset;
UINT8 *p_data;
} t_tag_head;
struct ir_bin_buffer
{
UINT8 *data;
UINT16 len;
UINT16 offset;
};
typedef struct REMOTE_AC_STATUS
{
t_ac_power ac_power;
t_ac_temperature ac_temp;
t_ac_mode ac_mode;
t_ac_swing ac_wind_dir;
t_ac_wind_speed ac_wind_speed;
UINT8 ac_display;
UINT8 ac_sleep;
UINT8 ac_timer;
} t_remote_ac_status;
// function polymorphism
typedef INT8 (*lp_apply_ac_parameter)(t_remote_ac_status ac_status, UINT8 function_code);
#define TAG_AC_BOOT_CODE 1
#define TAG_AC_ZERO 2
#define TAG_AC_ONE 3
#define TAG_AC_DELAY_CODE 4
#define TAG_AC_FRAME_LENGTH 5
#define TAG_AC_ENDIAN 6
#define TAG_AC_LAST_BIT 7
#define TAG_AC_POWER_1 21
#define TAG_AC_DEFAULT_CODE 22
#define TAG_AC_TEMP_1 23
#define TAG_AC_MODE_1 24
#define TAG_AC_SPEED_1 25
#define TAG_AC_SWING_1 26
#define TAG_AC_CHECKSUM_TYPE 27
#define TAG_AC_SOLO_FUNCTION 28
#define TAG_AC_FUNCTION_1 29
#define TAG_AC_TEMP_2 30
#define TAG_AC_MODE_2 31
#define TAG_AC_SPEED_2 32
#define TAG_AC_SWING_2 33
#define TAG_AC_FUNCTION_2 34
#define TAG_AC_BAN_FUNCTION_IN_COOL_MODE 41
#define TAG_AC_BAN_FUNCTION_IN_HEAT_MODE 42
#define TAG_AC_BAN_FUNCTION_IN_AUTO_MODE 43
#define TAG_AC_BAN_FUNCTION_IN_FAN_MODE 44
#define TAG_AC_BAN_FUNCTION_IN_DRY_MODE 45
#define TAG_AC_SWING_INFO 46
#define TAG_AC_REPEAT_TIMES 47
#define TAG_AC_BIT_NUM 48
// definition about size
#define PROTOCOL_SIZE (sizeof(t_ac_protocol))
/* exported variables */
extern UINT8 *ir_hex_code;
extern UINT8 ir_hex_len;
extern t_ac_protocol *context;
extern INT8 ir_ac_lib_parse();
extern INT8 free_ac_context();
extern BOOL is_solo_function(UINT8 function_code);
#ifdef __cplusplus
}
#endif
#endif //IRDA_DECODER_IR_AC_CONTROL_H

View File

@@ -0,0 +1,29 @@
/**************************************************************************************
Filename: ir_parse_forbidden_info.h
Revised: Date: 2016-10-05
Revision: Revision: 1.0
Description: This file provides algorithms for forbidden area of AC code
Revision log:
* 2016-10-05: created by strawmanbobi
**************************************************************************************/
#ifndef _IRDA_PARSE_PARSE_H_
#define _IRDA_PARSE_PARSE_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "ir_decode.h"
extern INT8 parse_nmode(struct tag_head *tag, t_ac_n_mode index);
#ifdef __cplusplus
}
#endif
#endif // _IRDA_PARSE_PARSE_H_

View File

@@ -0,0 +1,44 @@
/**************************************************************************************
Filename: ir_parse_frame_parameter.h
Revised: Date: 2016-10-11
Revision: Revision: 1.0
Description: This file provides algorithms for IR decode for AC frame parameters
Revision log:
* 2016-10-11: created by strawmanbobi
**************************************************************************************/
#ifndef _IRDA_PARSE_FRAME_PARAMETER_H_
#define _IRDA_PARSE_FRAME_PARAMETER_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "ir_decode.h"
extern INT8 parse_boot_code(struct tag_head *tag);
extern INT8 parse_zero(struct tag_head *tag);
extern INT8 parse_one(struct tag_head *tag);
extern INT8 parse_delay_code(struct tag_head *tag);
extern INT8 parse_frame_len(struct tag_head *tag, UINT16 len);
extern INT8 parse_endian(struct tag_head *tag);
extern INT8 parse_lastbit(struct tag_head *tag);
extern INT8 parse_repeat_times(struct tag_head *tag);
extern INT8 parse_bit_num(struct tag_head *tag);
#ifdef __cplusplus
}
#endif
#endif // _IRDA_PARSE_FRAME_PARAMETER_H_

View File

@@ -0,0 +1,58 @@
/**************************************************************************************
Filename: ir_parse_ac_parameter.h
Revised: Date: 2016-10-12
Revision: Revision: 1.0
Description: This file provides algorithms for IR decode for AC functionality parameters
Revision log:
* 2016-10-12: created by strawmanbobi
**************************************************************************************/
#ifndef _IRDA_PARSE_AC_PARAMETER_H_
#define _IRDA_PARSE_AC_PARAMETER_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "ir_decode.h"
extern INT8 parse_common_ac_parameter(t_tag_head *tag, t_tag_comp *comp_data, UINT8 with_end, UINT8 type);
extern INT8 parse_default_code(struct tag_head *tag, t_ac_hex *default_code);
extern INT8 parse_power_1(struct tag_head *tag, t_power_1 *power1);
extern INT8 parse_temp_1(struct tag_head *tag, t_temp_1 *temp1);
extern INT8 parse_mode_1(struct tag_head *tag, t_mode_1 *mode1);
extern INT8 parse_speed_1(struct tag_head *tag, t_speed_1 *speed1);
extern INT8 parse_swing_1(struct tag_head *tag, t_swing_1 *swing1, UINT16 swing_count);
extern INT8 parse_checksum(struct tag_head *tag, t_checksum *checksum);
extern INT8 parse_function_1_tag29(struct tag_head *tag, t_function_1 *function1);
extern INT8 parse_temp_2(struct tag_head *tag, t_temp_2 *temp2);
extern INT8 parse_mode_2(struct tag_head *tag, t_mode_2 *mode2);
extern INT8 parse_speed_2(struct tag_head *tag, t_speed_2 *speed2);
extern INT8 parse_swing_2(struct tag_head *tag, t_swing_2 *swing2, UINT16 swing_count);
extern INT8 parse_function_2_tag34(struct tag_head *tag, t_function_2 *function2);
extern INT8 parse_swing_info(struct tag_head *tag, t_swing_info *si);
extern INT8 parse_solo_code(struct tag_head *tag, t_solo_code *sc);
#ifdef __cplusplus
}
#endif
#endif // _IRDA_PARSE_AC_PARAMETER_H_

View File

@@ -0,0 +1,160 @@
/**************************************************************************************
Filename: ir_decode.h
Revised: Date: 2016-10-01
Revision: Revision: 1.0
Description: This file provides algorithms for IR decode
Revision log:
* 2016-10-01: created by strawmanbobi
**************************************************************************************/
#ifndef _IRDA_DECODE_H_
#define _IRDA_DECODE_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdio.h>
#include "ir_defs.h"
#include "ir_ac_control.h"
#include "ir_tv_control.h"
#define IR_DECODE_FAILED (-1)
#define IR_DECODE_SUCCEEDED (0)
#define IR_CATEGORY_AC 1
#define IR_CATEGORY_TV 2
#define IR_TYPE_STATUS 0
#define IR_TYPE_COMMANDS 1
#define SUB_CATEGORY_QUATERNARY 0
#define SUB_CATEGORY_HEXADECIMAL 1
// exported functions
/**
* function ir_file_open
*
* description: open IR binary code from file
*
* parameters: category (in) - category ID get from indexing API
* sub_category (in) - subcategory ID get from indexing API
* file_name (in) - file name of IR binary
*
* returns: IR_DECODE_SUCCEEDED / IR_DECODE_FAILED
*
*/
extern INT8 ir_file_open(const UINT8 category, const UINT8 sub_category, const char* file_name);
/**
* function ir_binary_open
*
* description: open IR binary code from buffer
*
* parameters: category (in) - category ID get from indexing API
* sub_category (in) - subcategory ID get from indexing API
* binary (in) - pointer to binary buffer
* binary_length (in) - binary buffer size
*
* returns: IR_DECODE_SUCCEEDED / IR_DECODE_FAILED
*/
extern INT8 ir_binary_open(const UINT8 category, const UINT8 sub_category, UINT8* binary, UINT16 binary_length);
/**
* function ir_decode
*
* description: decode IR binary into INT16 array which indicates the IR levels
*
* parameters: key_code (in) - the code of pressed key
* user_data (out) - output decoded data in INT16 array format
* ac_status(in) - pointer to AC status (optional)
* change_wind_direction (in) - if control changes wind direction for AC (for AC only)
*
* returns: length of decoded data (0 indicates decode failure)
*/
extern UINT16 ir_decode(UINT8 key_code, UINT16* user_data, t_remote_ac_status* ac_status, BOOL change_wind_direction);
/**
* function ir_close
*
* description: close IR binary code
*
* parameters: N/A
*
* returns: IR_DECODE_SUCCEEDED / IR_DECODE_FAILED
*/
extern INT8 ir_close();
/**
* function get_temperature_range
*
* description: get the supported temperature range [min, max] for the opened AC IR binary
*
* parameters: ac_mode (in) specify in which AC mode the application need to get temperature info
* temp_min (out) the min temperature supported in a specified AC mode
* temp_max (out) the max temperature supported in a specified AC mode
*
* returns: IR_DECODE_SUCCEEDED / IR_DECODE_FAILED
*/
extern INT8 get_temperature_range(UINT8 ac_mode, INT8 *temp_min, INT8 *temp_max);
/**
* function get_supported_mode
*
* description: get supported mode for the opened AC IR binary
*
* parameters: supported_mode (out) mode supported by the remote in lower 5 bits
*
* returns: IR_DECODE_SUCCEEDED / IR_DECODE_FAILED
*/
extern INT8 get_supported_mode(UINT8 *supported_mode);
/**
* function get_supported_wind_speed
*
* description: get supported wind speed levels for the opened AC IR binary in certain mode
*
* parameters: ac_mode (in) specify in which AC mode the application need to get wind speed info
* supported_wind_speed (out) wind speed supported by the remote in lower 4 bits
*
* returns: IR_DECODE_SUCCEEDED / IR_DECODE_FAILED
*/
extern INT8 get_supported_wind_speed(UINT8 ac_mode, UINT8 *supported_wind_speed);
/**
* function get_supported_swing
*
* description: get supported swing functions for the opened AC IR binary in certain mode
*
* parameters: ac_mode (in) specify in which AC mode the application need to get swing info
* supported_swing (out) swing supported by the remote in lower 2 bits
*
* returns: IR_DECODE_SUCCEEDED / IR_DECODE_FAILED
*/
extern INT8 get_supported_swing(UINT8 ac_mode, UINT8 *supported_swing);
/**
* function get_supported_wind_direction
*
* description: get supported wind directions for the opened AC IR binary in certain mode
*
* parameters: supported_wind_direction (out) swing supported by the remote in lower 2 bits
*
* returns: IR_DECODE_SUCCEEDED / IR_DECODE_FAILED
*/
extern INT8 get_supported_wind_direction(UINT8 *supported_wind_direction);
// private extern function
#if (defined BOARD_PC || defined BOARD_PC_DLL)
extern void ir_lib_free_inner_buffer();
#endif
#ifdef __cplusplus
}
#endif
#endif // _IRDA_DECODE_H_

View File

@@ -0,0 +1,63 @@
/**************************************************************************************
Filename: ir_defs.h
Revised: Date: 2016-10-26
Revision: Revision: 1.0
Description: This file provides algorithms for IR decode
Revision log:
* 2016-10-01: created by strawmanbobi
**************************************************************************************/
#ifndef PARSE_IR_DEFS_H
#define PARSE_IR_DEFS_H
#ifdef __cplusplus
extern "C"
{
#endif
#if defined BOARD_ANDROID
#include <android/log.h>
#define LOG_TAG "ir_decode"
#endif
#if defined BOARD_CC26XX
#include "OSAL.h"
#endif
#define TRUE 1
#define FALSE 0
typedef unsigned char UINT8;
typedef signed char INT8;
typedef unsigned short UINT16;
typedef signed short INT16;
typedef signed int INT;
typedef unsigned int UINT;
typedef int BOOL;
void noprint(const char *fmt, ...);
#if !defined BOARD_CC26XX
#define ir_malloc(A) malloc(A)
#define ir_free(A) free(A)
#else
#define ir_malloc(A) ICall_malloc(A)
#define ir_free(A) ICall_free(A)
#endif
#define ir_memcpy(A, B, C) memcpy(A, B, C)
#define ir_memset(A, B, C) memset(A, B, C)
#define ir_strlen(A) strlen(A)
#if (defined BOARD_PC) && (!defined BOARD_PC_JNI)
#define ir_printf printf
#else
#define ir_printf noprint
#endif
#define USER_DATA_SIZE 1636
#ifdef __cplusplus
}
#endif
#endif //PARSE_IR_DEFS_H

View File

@@ -0,0 +1,215 @@
/**************************************************************************************
Filename: ir_lib.h
Revised: Date: 2016-02-23
Revision: Revision: 1.0
Description: This file provides algorithms for IR decode (compressed command type)
Revision log:
* 2016-10-21: created by strawmanbobi
**************************************************************************************/
#ifndef _IRDA_LIB_H_
#define _IRDA_LIB_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "ir_defs.h"
#define STB_CHANNEL_OFFSET 14
#define IRDA_FLAG_NORMAL 0
#define IRDA_FLAG_INVERSE 1
#define IRDA_LEVEL_LOW 0
#define IRDA_LEVEL_HIGH 1
#define IRDA_LSB 0
#define IRDA_MSB 1
enum
{
IRDA_DECODE_1_BIT = 0,
IRDA_DECODE_2_BITS,
IRDA_DECODE_4_BITS,
};
/*
* global type definitions
*/
typedef enum ir_flags
{
IRDA_BOOT = 0,
IRDA_STOP,
IRDA_SEP,
IRDA_ONE,
IRDA_ZERO,
IRDA_FLIP,
IRDA_TWO,
IRDA_THREE = 7,
IRDA_FOUR,
IRDA_FIVE,
IRDA_SIX,
IRDA_SEVEN,
IRDA_EIGHT,
IRDA_NINE,
IRDA_A,
IRDA_B,
IRDA_C,
IRDA_D,
IRDA_E,
IRDA_F,
IRDA_MAX = 20,
} t_ir_flags;
typedef struct ir_data
{
UINT8 bits;
UINT8 lsb;
UINT8 mode;
UINT8 index;
} t_ir_data;
#if !defined BOARD_51
#pragma pack(1)
#endif
typedef struct ir_cycles
{
UINT8 flag;
UINT16 mask;
UINT16 space;
} t_ir_cycles;
#if !defined BOARD_51
#pragma pack()
#endif
typedef enum tv_key_value
{
TV_POWER = 0,
TV_MUTE,
TV_UP,
TV_DOWN,
TV_LEFT,
TV_RIGHT,
TV_OK,
TV_VOL_UP,
TV_VOL_DOWN,
TV_BACK,
TV_INPUT,
TV_MENU,
TV_HOME,
TV_SET,
TV_0,
TV_1,
TV_2,
TV_3,
TV_4,
TV_5,
TV_6,
TV_7,
TV_8,
TV_9,
TV_KEY_MAX,
} t_tv_key_value;
typedef enum stb_key_value
{
STB_POWER = 0,
STB_MUTE,
STB_UP,
STB_DOWN,
STB_LEFT,
STB_RIGHT,
STB_OK,
STB_VOL_UP,
STB_VOL_DOWN,
STB_BACK,
STB_INPUT,
STB_MENU,
STB_PAGE_UP,
STB_PAGE_DOWN,
STB_0,
STB_1,
STB_2,
STB_3,
STB_4,
STB_5,
STB_6,
STB_7,
STB_8,
STB_9,
STB_KEY_MAX,
} t_stb_key_value;
typedef enum nw_key_value
{
NW_POWER = 0,
NW_UP,
NW_DOWN,
NW_LEFT,
NW_RIGHT,
NW_OK,
NW_VOL_UP,
NW_VOL_DOWN,
NW_BACK,
NW_MENU,
NW_HOME,
NW_0,
NW_1,
NW_2,
NW_3,
NW_4,
NW_5,
NW_6,
NW_7,
NW_8,
NW_9,
NW_KEY_MAX,
} t_nw_key_value;
typedef enum cm_key_value
{
CM_POWER = 0,
CM_UP,
CM_DOWN,
CM_LEFT,
CM_RIGHT,
CM_OK,
CM_VOL_UP,
CM_VOL_DOWN,
CM_FUNC_1,
CM_FUNC_2,
CM_FUNC_3,
CM_BACK,
CM_HOME,
CM_MENU,
CM_MODE,
CM_KEY_MAX,
} t_cm_key_value;
typedef struct ir_data_tv
{
char magic[4];
UINT8 per_keycode_bytes;
} t_ir_data_tv;
extern INT8 tv_lib_open(UINT8 *binary, UINT16 binary_length);
extern BOOL tv_lib_parse(UINT8 encode_type);
extern UINT16 tv_lib_control(UINT8 key, UINT16 *user_data);
extern UINT8 tv_lib_close();
#ifdef __cplusplus
}
#endif
#endif /* _IRDA_LIB_H_ */

View File

@@ -0,0 +1,36 @@
/**************************************************************************************
Filename: ir_utils.c
Revised: Date: 2016-10-26
Revision: Revision: 1.0
Description: This file provides generic utils for IRDA algorithms
Revision log:
* 2016-10-01: created by strawmanbobi
**************************************************************************************/
#ifndef _IRDA_UTILS_H_
#define _IRDA_UTILS_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include "ir_defs.h"
#include "ir_decode.h"
#include <stdio.h>
extern void string_to_hex(UINT8 *p, t_ac_hex *pac_hex);
extern void string_to_hex_common(UINT8 *p, UINT8 *hex_data, UINT16 len);
extern BOOL is_in(const UINT8 *array, UINT8 value, UINT8 len);
extern void hex_byte_to_double_char(char *dest, UINT8 length, UINT8 src);
#ifdef __cplusplus
}
#endif
#endif // _IRDA_UTILS_H_

View File

@@ -0,0 +1,772 @@
/**************************************************************************************
Filename: ir_ac_apply.c
Revised: Date: 2016-10-12
Revision: Revision: 1.0
Description: This file provides methods for AC IR applying functionalities
Revision log:
* 2016-10-12: created by strawmanbobi
**************************************************************************************/
#include "../include/ir_utils.h"
#include "../include/ir_ac_apply.h"
static INT8 apply_ac_power(struct ac_protocol *protocol, UINT8 power_status);
static INT8 apply_ac_mode(struct ac_protocol *protocol, UINT8 mode_status);
static INT8 apply_ac_temperature(struct ac_protocol *protocol, UINT8 temp_diff);
static INT8 apply_ac_wind_speed(struct ac_protocol *protocol, UINT8 wind_speed);
static INT8 apply_ac_swing(struct ac_protocol *protocol, UINT8 swing_mode);
static UINT8 has_function(struct ac_protocol *protocol, UINT8 function);
INT8 apply_ac_parameter_type_1(UINT8 *dc_data, t_tag_comp *comp_data, UINT8 current_seg, UINT8 is_temp)
{
if (0 != (comp_data->seg_len & 0x01))
{
return IR_DECODE_FAILED;
}
if (1 == is_temp)
{
dc_data[comp_data->segment[current_seg]] += comp_data->segment[current_seg + 1];
}
else
{
dc_data[comp_data->segment[current_seg]] = comp_data->segment[current_seg + 1];
}
return IR_DECODE_SUCCEEDED;
}
INT8 apply_ac_parameter_type_2(UINT8 *dc_data, t_tag_comp *comp_data, UINT8 current_seg, UINT8 is_temp)
{
UINT8 start_bit = 0;
UINT8 end_bit = 0;
UINT8 cover_byte_pos_hi = 0;
UINT8 cover_byte_pos_lo = 0;
UINT8 value;
UINT8 move_bit = 0;
if (0 != (comp_data->seg_len % 3))
{
return IR_DECODE_FAILED;
}
start_bit = comp_data->segment[current_seg];
end_bit = comp_data->segment[current_seg + 1];
cover_byte_pos_hi = start_bit >> 3;
cover_byte_pos_lo = (UINT8) (end_bit - 1) >> 3;
if (cover_byte_pos_hi == cover_byte_pos_lo)
{
// cover_byte_pos_hi or cover_bytes_pos_lo is target byte to be applied with AC parameter
// try get raw value of byte to be applied
UINT8 raw_value = comp_data->segment[current_seg + 2];
UINT8 int_start_bit = start_bit - (cover_byte_pos_hi << 3);
UINT8 int_end_bit = end_bit - (cover_byte_pos_lo << 3);
UINT8 bit_range = end_bit - start_bit;
UINT8 mask = (UINT8) ((0xFF << (8 - int_start_bit)) | (0xFF >> int_end_bit));
UINT8 origin = dc_data[cover_byte_pos_lo];
if (TRUE == is_temp)
{
move_bit = (UINT8) (8 - int_end_bit);
value = (origin & mask) | (((((origin & ~mask) >> move_bit) + raw_value) << move_bit) & ~mask);
}
else
{
value = (origin & mask) | ((raw_value << (8 - int_start_bit - bit_range)) & ~mask);
}
dc_data[cover_byte_pos_lo] = value;
}
else
{
UINT8 origin_hi = 0;
UINT8 origin_lo = 0;
UINT8 mask_hi = 0;
UINT8 mask_lo = 0;
UINT8 raw_value = 0;
UINT8 int_start_bit = 0;
UINT8 int_end_bit = 0;
if (cover_byte_pos_hi > cover_byte_pos_lo)
{
return IR_DECODE_FAILED;
}
// calculate the bit scope
UINT8 bit_range = end_bit - start_bit;
raw_value = comp_data->segment[current_seg + 2];
origin_hi = dc_data[cover_byte_pos_hi];
origin_lo = dc_data[cover_byte_pos_lo];
int_start_bit = start_bit - (cover_byte_pos_hi << 3);
int_end_bit = end_bit - (cover_byte_pos_lo << 3);
mask_hi = (UINT8) 0xFF << (8 - int_start_bit);
mask_lo = (UINT8) 0xFF >> int_end_bit;
value = ((origin_hi & ~mask_hi) << int_end_bit) | ((origin_lo & ~mask_lo) >> (8 - int_end_bit));
if (TRUE == is_temp)
{
raw_value += value;
}
dc_data[cover_byte_pos_hi] = (UINT8) ((origin_hi & mask_hi) |
(((0xFF >> (8 - bit_range)) & raw_value) >> int_end_bit));
dc_data[cover_byte_pos_lo] = (UINT8) ((origin_lo & mask_lo) |
(((0xFF >> (8 - bit_range)) & raw_value) << (8 - int_end_bit)));
}
return IR_DECODE_SUCCEEDED;
}
static INT8 apply_ac_power(struct ac_protocol *protocol, UINT8 power_status)
{
UINT16 i = 0;
if (0 == protocol->power1.len)
{
return IR_DECODE_SUCCEEDED;
}
if (0 == protocol->power1.comp_data[power_status].seg_len)
{
// force to apply power in any cases
return IR_DECODE_SUCCEEDED;
}
for (i = 0; i < protocol->power1.comp_data[power_status].seg_len; i += 2)
{
apply_ac_parameter_type_1(ir_hex_code, &(protocol->power1.comp_data[power_status]), (UINT8) i, FALSE);
}
return IR_DECODE_SUCCEEDED;
}
static INT8 apply_ac_mode(struct ac_protocol *protocol, UINT8 mode_status)
{
UINT16 i = 0;
if (0 == protocol->mode1.len)
{
goto try_applying_mode2;
}
if (0 == protocol->mode1.comp_data[mode_status].seg_len)
{
return IR_DECODE_FAILED;
}
for (i = 0; i < protocol->mode1.comp_data[mode_status].seg_len; i += 2)
{
apply_ac_parameter_type_1(ir_hex_code, &(protocol->mode1.comp_data[mode_status]), (UINT8) i, FALSE);
}
// get return here since wind mode 1 is already applied
return IR_DECODE_SUCCEEDED;
try_applying_mode2:
if (0 == protocol->mode2.len)
{
return IR_DECODE_SUCCEEDED;
}
if (0 == protocol->mode2.comp_data[mode_status].seg_len)
{
return IR_DECODE_FAILED;
}
for (i = 0; i < protocol->mode2.comp_data[mode_status].seg_len; i += 3)
{
apply_ac_parameter_type_2(ir_hex_code,
&(protocol->mode2.comp_data[mode_status]),
(UINT8) i, FALSE);
}
return IR_DECODE_SUCCEEDED;
}
static INT8 apply_ac_wind_speed(struct ac_protocol *protocol, UINT8 wind_speed)
{
UINT16 i = 0;
if (0 == protocol->speed1.len)
{
goto try_applying_wind_speed2;
}
if (0 == protocol->speed1.comp_data[wind_speed].seg_len)
{
return IR_DECODE_FAILED;
}
for (i = 0; i < protocol->speed1.comp_data[wind_speed].seg_len; i += 2)
{
apply_ac_parameter_type_1(ir_hex_code, &(protocol->speed1.comp_data[wind_speed]), (UINT8) i, FALSE);
}
// get return here since wind speed 1 is already applied
return IR_DECODE_SUCCEEDED;
try_applying_wind_speed2:
if (0 == protocol->speed2.len)
{
return IR_DECODE_SUCCEEDED;
}
if (0 == protocol->speed2.comp_data[wind_speed].seg_len)
{
return IR_DECODE_FAILED;
}
for (i = 0; i < protocol->speed2.comp_data[wind_speed].seg_len; i += 3)
{
apply_ac_parameter_type_2(ir_hex_code,
&(protocol->speed2.comp_data[wind_speed]),
(UINT8) i, FALSE);
}
return IR_DECODE_SUCCEEDED;
}
static INT8 apply_ac_temperature(struct ac_protocol *protocol, UINT8 temp_diff)
{
UINT16 i = 0;
if (0 == protocol->temp1.len)
{
goto try_applying_temp2;
}
if (0 == protocol->temp1.comp_data[temp_diff].seg_len)
{
return IR_DECODE_FAILED;
}
for (i = 0; i < protocol->temp1.comp_data[temp_diff].seg_len; i += 2)
{
if (TEMP_TYPE_DYNAMIC == protocol->temp1.type)
{
apply_ac_parameter_type_1(ir_hex_code, &(protocol->temp1.comp_data[temp_diff]), (UINT8) i, TRUE);
}
else if (TEMP_TYPE_STATIC == protocol->temp1.type)
{
apply_ac_parameter_type_1(ir_hex_code, &(protocol->temp1.comp_data[temp_diff]), (UINT8) i, FALSE);
}
}
// get return here since temperature 1 is already applied
return IR_DECODE_SUCCEEDED;
try_applying_temp2:
if (0 == protocol->temp2.len)
{
return IR_DECODE_SUCCEEDED;
}
if (0 == protocol->temp2.comp_data[temp_diff].seg_len)
{
return IR_DECODE_FAILED;
}
for (i = 0; i < protocol->temp2.comp_data[temp_diff].seg_len; i += 3)
{
if (0 != protocol->temp2.comp_data[temp_diff].seg_len)
{
if (TEMP_TYPE_DYNAMIC == protocol->temp2.type)
{
apply_ac_parameter_type_2(ir_hex_code, &(protocol->temp2.comp_data[temp_diff]), (UINT8) i, TRUE);
}
else if (TEMP_TYPE_STATIC == protocol->temp2.type)
{
apply_ac_parameter_type_2(ir_hex_code, &(protocol->temp2.comp_data[temp_diff]), (UINT8) i, FALSE);
}
}
}
return IR_DECODE_SUCCEEDED;
}
static INT8 apply_ac_swing(struct ac_protocol *protocol, UINT8 swing_mode)
{
UINT16 i = 0;
if (0 == protocol->swing1.len)
{
goto try_applying_swing2;
}
if (swing_mode >= protocol->swing1.count)
{
return IR_DECODE_FAILED;
}
if (0 == protocol->swing1.comp_data[swing_mode].seg_len)
{
// swing does not have any empty data segment
return IR_DECODE_FAILED;
}
for (i = 0; i < protocol->swing1.comp_data[swing_mode].seg_len; i += 2)
{
apply_ac_parameter_type_1(ir_hex_code, &(protocol->swing1.comp_data[swing_mode]), (UINT8) i, FALSE);
}
// get return here since temperature 1 is already applied
return IR_DECODE_SUCCEEDED;
try_applying_swing2:
if (0 == protocol->swing2.len)
{
return IR_DECODE_SUCCEEDED;
}
if (swing_mode >= protocol->swing2.count)
{
return IR_DECODE_FAILED;
}
if (0 == protocol->swing2.comp_data[swing_mode].seg_len)
{
// swing does not have any empty data segment
return IR_DECODE_FAILED;
}
for (i = 0; i < protocol->swing2.comp_data[swing_mode].seg_len; i += 3)
{
apply_ac_parameter_type_2(ir_hex_code,
&(protocol->swing2.comp_data[swing_mode]),
(UINT8) i, FALSE);
}
return IR_DECODE_SUCCEEDED;
}
static INT8 apply_checksum_byte(UINT8 *ac_code, t_tag_checksum_data cs, BOOL inverse)
{
UINT16 i = 0;
UINT8 checksum = 0x00;
if (cs.len < 3)
{
return IR_DECODE_SUCCEEDED;
}
for (i = cs.start_byte_pos; i < cs.end_byte_pos; i++)
{
checksum += ac_code[i];
}
checksum += cs.checksum_plus;
if (TRUE == inverse)
{
checksum = ~checksum;
}
// apply checksum
ac_code[cs.checksum_byte_pos] = checksum;
return IR_DECODE_SUCCEEDED;
}
static INT8 apply_checksum_halfbyte(UINT8 *ac_code, t_tag_checksum_data cs, BOOL inverse)
{
UINT16 i = 0;
UINT8 checksum = 0x00;
if (cs.len < 3)
{
return IR_DECODE_SUCCEEDED;
}
for (i = cs.start_byte_pos; i < cs.end_byte_pos; i++)
{
checksum += (ac_code[i] >> 4) + (ac_code[i] & 0x0F);
}
checksum += cs.checksum_plus;
if (TRUE == inverse)
{
checksum = ~checksum;
}
// apply checksum
ac_code[cs.checksum_byte_pos] = checksum;
return IR_DECODE_SUCCEEDED;
}
static INT8 apply_checksum_spec_byte(UINT8 *ac_code, t_tag_checksum_data cs, BOOL inverse)
{
UINT16 i = 0;
UINT8 apply_byte_pos = 0;
UINT8 checksum = 0x00;
#if 1
if (cs.len < 4)
{
return IR_DECODE_SUCCEEDED;
}
#endif
for (i = 0; i < cs.len - 3; i++)
{
UINT8 pos = cs.spec_pos[i];
UINT8 byte_pos = pos >> 1;
if (0 == (pos & 0x01))
{
checksum += ac_code[byte_pos] >> 4;
}
else
{
checksum += ac_code[byte_pos] & 0x0F;
}
}
checksum += cs.checksum_plus;
if (TRUE == inverse)
{
checksum = ~checksum;
}
// apply checksum, for specific-half-byte checksum, the byte pos actually indicates the half-byte pos
apply_byte_pos = cs.checksum_byte_pos >> 1;
if (0 == (cs.checksum_byte_pos & 0x01))
{
// save low bits and add checksum as high bits
ac_code[apply_byte_pos] = (UINT8) ((ac_code[apply_byte_pos] & 0x0F) | (checksum << 4));
}
else
{
// save high bits and add checksum as low bits
ac_code[apply_byte_pos] = (UINT8) ((ac_code[apply_byte_pos] & 0xF0) | (checksum & 0x0F));
}
return IR_DECODE_SUCCEEDED;
}
static INT8 apply_checksum_spec_byte_onebyte(UINT8 *ac_code, t_tag_checksum_data cs, BOOL inverse)
{
UINT16 i = 0;
UINT8 apply_byte_pos = 0;
UINT8 checksum = 0x00;
#if 1
if (cs.len < 4)
{
return IR_DECODE_SUCCEEDED;
}
#endif
for (i = 0; i < cs.len - 3; i++)
{
UINT8 pos = cs.spec_pos[i];
UINT8 byte_pos = pos >> 1;
if (0 == (pos & 0x01))
{
checksum += ac_code[byte_pos] >> 4;
}
else
{
checksum += ac_code[byte_pos] & 0x0F;
}
}
checksum += cs.checksum_plus;
if (TRUE == inverse)
{
checksum = ~checksum;
}
// apply checksum, for specific-half-byte checksum, the byte pos actually indicates the half-byte pos
apply_byte_pos = cs.checksum_byte_pos >> 1;
ac_code[apply_byte_pos] = checksum;
return IR_DECODE_SUCCEEDED;
}
static UINT8 has_function(struct ac_protocol *protocol, UINT8 function)
{
if (0 != protocol->function1.len)
{
if (0 != protocol->function1.comp_data[function - 1].seg_len)
{
return TRUE;
}
}
if (0 != protocol->function2.len)
{
if (0 != protocol->function2.comp_data[function - 1].seg_len)
{
return TRUE;
}
}
return FALSE;
}
INT8 apply_function(struct ac_protocol *protocol, UINT8 function)
{
UINT16 i = 0;
// function index starts from 1 (AC_FUNCTION_POWER), do -1 operation at first
if (0 == protocol->function1.len)
{
goto try_applying_function2;
}
if (0 == protocol->function1.comp_data[function - 1].seg_len)
{
// force to apply function in any case
return IR_DECODE_SUCCEEDED;
}
for (i = 0; i < protocol->function1.comp_data[function - 1].seg_len; i += 2)
{
apply_ac_parameter_type_1(ir_hex_code, &(protocol->function1.comp_data[function - 1]), (UINT8) i, FALSE);
}
// get return here since function 1 is already applied
return IR_DECODE_SUCCEEDED;
try_applying_function2:
if (0 == protocol->function2.len)
{
return IR_DECODE_SUCCEEDED;
}
if (0 == protocol->function2.comp_data[function - 1].seg_len)
{
return IR_DECODE_SUCCEEDED;
}
for (i = 0; i < protocol->function2.comp_data[function - 1].seg_len; i += 3)
{
apply_ac_parameter_type_2(ir_hex_code,
&(protocol->function2.comp_data[function - 1]),
(UINT8) i, FALSE);
}
return IR_DECODE_SUCCEEDED;
}
INT8 apply_checksum(struct ac_protocol *protocol)
{
UINT8 i = 0;
if (0 == protocol->checksum.len)
{
return IR_DECODE_SUCCEEDED;
}
for (i = 0; i < protocol->checksum.count; i++)
{
switch (protocol->checksum.checksum_data[i].type)
{
case CHECKSUM_TYPE_BYTE:
apply_checksum_byte(ir_hex_code, protocol->checksum.checksum_data[i], FALSE);
break;
case CHECKSUM_TYPE_BYTE_INVERSE:
apply_checksum_byte(ir_hex_code, protocol->checksum.checksum_data[i], TRUE);
break;
case CHECKSUM_TYPE_HALF_BYTE:
apply_checksum_halfbyte(ir_hex_code, protocol->checksum.checksum_data[i], FALSE);
break;
case CHECKSUM_TYPE_HALF_BYTE_INVERSE:
apply_checksum_halfbyte(ir_hex_code, protocol->checksum.checksum_data[i], TRUE);
break;
case CHECKSUM_TYPE_SPEC_HALF_BYTE:
apply_checksum_spec_byte(ir_hex_code, protocol->checksum.checksum_data[i], FALSE);
break;
case CHECKSUM_TYPE_SPEC_HALF_BYTE_INVERSE:
apply_checksum_spec_byte(ir_hex_code, protocol->checksum.checksum_data[i], TRUE);
break;
case CHECKSUM_TYPE_SPEC_HALF_BYTE_ONE_BYTE:
apply_checksum_spec_byte_onebyte(ir_hex_code, protocol->checksum.checksum_data[i], FALSE);
break;
case CHECKSUM_TYPE_SPEC_HALF_BYTE_INVERSE_ONE_BYTE:
apply_checksum_spec_byte_onebyte(ir_hex_code, protocol->checksum.checksum_data[i], TRUE);
break;
default:
break;
}
}
return IR_DECODE_SUCCEEDED;
}
INT8 apply_power(t_remote_ac_status ac_status, UINT8 function_code)
{
apply_ac_power(context, ac_status.ac_power);
return IR_DECODE_SUCCEEDED;
}
INT8 apply_mode(t_remote_ac_status ac_status, UINT8 function_code)
{
if (IR_DECODE_FAILED == apply_ac_mode(context, ac_status.ac_mode))
{
// do not implement this mechanism since mode, temperature, wind
// speed would have unspecified function
//if(FALSE == has_function(context, AC_FUNCTION_MODE))
{
return IR_DECODE_FAILED;
}
}
return IR_DECODE_SUCCEEDED;
}
INT8 apply_wind_speed(t_remote_ac_status ac_status, UINT8 function_code)
{
if (FALSE == context->n_mode[ac_status.ac_mode].all_speed)
{
// if this level is not in black list
if (!is_in(context->n_mode[ac_status.ac_mode].speed,
ac_status.ac_wind_speed,
context->n_mode[ac_status.ac_mode].speed_cnt))
{
if (IR_DECODE_FAILED == apply_ac_wind_speed(context, ac_status.ac_wind_speed) &&
function_code == AC_FUNCTION_WIND_SPEED)
{
// do not implement this mechanism since mode, temperature, wind
// speed would have unspecified function
//if(FALSE == has_function(context, AC_FUNCTION_WIND_SPEED))
{
return IR_DECODE_FAILED;
}
}
}
else
{
// if this level is in black list, do not send IR wave if user want to apply this function
if (function_code == AC_FUNCTION_WIND_SPEED)
{
// do not implement this mechanism since mode, temperature, wind
// speed would have unspecified function
//if(FALSE == has_function(context, AC_FUNCTION_WIND_SPEED))
{
return IR_DECODE_FAILED;
}
}
}
}
else
{
// if this level is in black list, do not send IR wave if user want to apply this function
if (function_code == AC_FUNCTION_WIND_SPEED)
{
// do not implement this mechanism since mode, temperature, wind
// speed would have unspecified function
//if(FALSE == has_function(context, AC_FUNCTION_WIND_SPEED))
{
return IR_DECODE_FAILED;
}
}
}
return IR_DECODE_SUCCEEDED;
}
INT8 apply_swing(t_remote_ac_status ac_status, UINT8 function_code)
{
if (function_code == AC_FUNCTION_WIND_FIX)
{
// adjust fixed wind direction according to current status
if (context->si.type == SWING_TYPE_NORMAL && context->si.mode_count > 1)
{
if (TRUE == context->change_wind_direction)
{
context->si.dir_index++;
}
if (context->si.dir_index == context->si.mode_count)
{
// reset dir index
context->si.dir_index = 1;
}
context->swing_status = context->si.dir_index;
}
}
else if (function_code == AC_FUNCTION_WIND_SWING)
{
context->swing_status = 0;
}
else
{
// do nothing
}
if (IR_DECODE_FAILED == apply_ac_swing(context, context->swing_status))
{
if (function_code == AC_FUNCTION_WIND_SWING && FALSE == has_function(context, AC_FUNCTION_WIND_SWING))
{
return IR_DECODE_FAILED;
}
else if (function_code == AC_FUNCTION_WIND_FIX && FALSE == has_function(context, AC_FUNCTION_WIND_FIX))
{
return IR_DECODE_FAILED;
}
}
return IR_DECODE_SUCCEEDED;
}
INT8 apply_temperature(t_remote_ac_status ac_status, UINT8 function_code)
{
if (FALSE == context->n_mode[ac_status.ac_mode].all_temp)
{
if (!is_in(context->n_mode[ac_status.ac_mode].temp,
ac_status.ac_temp,
context->n_mode[ac_status.ac_mode].temp_cnt))
{
if (IR_DECODE_FAILED == apply_ac_temperature(context, ac_status.ac_temp))
{
if (function_code == AC_FUNCTION_TEMPERATURE_UP
/*&& FALSE == has_function(context, AC_FUNCTION_TEMPERATURE_UP)*/)
{
return IR_DECODE_FAILED;
}
else if (function_code == AC_FUNCTION_TEMPERATURE_DOWN
/*&& FALSE == has_function(context, AC_FUNCTION_TEMPERATURE_DOWN)*/)
{
return IR_DECODE_FAILED;
}
}
}
else
{
// if this level is in black list, do not send IR wave if user want to apply this function
if (function_code == AC_FUNCTION_TEMPERATURE_UP
/*&& FALSE == has_function(context, AC_FUNCTION_TEMPERATURE_UP)*/)
{
return IR_DECODE_FAILED;
}
else if (function_code == AC_FUNCTION_TEMPERATURE_DOWN
/*&& FALSE == has_function(context, AC_FUNCTION_TEMPERATURE_DOWN)*/)
{
return IR_DECODE_FAILED;
}
}
}
else
{
// if this level is in black list, do not send IR wave if user want to apply this function
if (function_code == AC_FUNCTION_TEMPERATURE_UP
/*&& FALSE == has_function(context, AC_FUNCTION_TEMPERATURE_UP)*/)
{
return IR_DECODE_FAILED;
}
else if (function_code == AC_FUNCTION_TEMPERATURE_DOWN
/*&& FALSE == has_function(context, AC_FUNCTION_TEMPERATURE_DOWN)*/)
{
return IR_DECODE_FAILED;
}
}
return IR_DECODE_SUCCEEDED;
}

View File

@@ -0,0 +1,121 @@
/**************************************************************************************
Filename: ir_ac_binary_parse.c
Revised: Date: 2017-01-03
Revision: Revision: 1.0
Description: This file provides methods for AC binary parse
Revision log:
* 2017-01-03: created by strawmanbobi
**************************************************************************************/
#include <stdlib.h>
#include "../include/ir_ac_binary_parse.h"
#include "../include/ir_decode.h"
UINT16 tag_head_offset = 0;
extern struct ir_bin_buffer *p_ir_buffer;
extern struct tag_head *tags;
UINT8 tag_count = 0;
const UINT16 tag_index[TAG_COUNT_FOR_PROTOCOL] =
{
1, 2, 3, 4, 5, 6, 7,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
41, 42, 43, 44, 45, 46, 47, 48
};
INT8 binary_parse_offset()
{
int i = 0;
UINT16 *phead = (UINT16 *) &p_ir_buffer->data[1];
tag_count = p_ir_buffer->data[0];
if (TAG_COUNT_FOR_PROTOCOL != tag_count)
{
return IR_DECODE_FAILED;
}
tag_head_offset = (UINT16) ((tag_count << 1) + 1);
tags = (t_tag_head *) ir_malloc(tag_count * sizeof(t_tag_head));
if (NULL == tags)
{
return IR_DECODE_FAILED;
}
for (i = 0; i < tag_count; i++)
{
tags[i].tag = tag_index[i];
tags[i].offset = *(phead + i);
if (tags[i].offset == TAG_INVALID)
{
tags[i].len = 0;
}
}
return IR_DECODE_SUCCEEDED;
}
INT8 binary_parse_len()
{
UINT16 i = 0, j = 0;
for (i = 0; i < (tag_count - 1); i++)
{
if (tags[i].offset == TAG_INVALID)
{
continue;
}
for (j = (UINT16) (i + 1); j < tag_count; j++)
{
if (tags[j].offset != TAG_INVALID)
{
break;
}
}
if (j < tag_count)
{
tags[i].len = tags[j].offset - tags[i].offset;
}
else
{
tags[i].len = p_ir_buffer->len - tags[i].offset - tag_head_offset;
return IR_DECODE_SUCCEEDED;
}
}
if (tags[tag_count - 1].offset != TAG_INVALID)
{
tags[tag_count - 1].len = p_ir_buffer->len - tag_head_offset - tags[tag_count - 1].offset;
}
return IR_DECODE_SUCCEEDED;
}
void binary_tags_info()
{
#if defined BOARD_PC
UINT16 i = 0;
for (i = 0; i < tag_count; i++)
{
if (tags[i].len == 0)
{
continue;
}
ir_printf("tag(%d).len = %d\n", tags[i].tag, tags[i].len);
}
#endif
}
INT8 binary_parse_data()
{
UINT16 i = 0;
for (i = 0; i < tag_count; i++)
{
tags[i].p_data = p_ir_buffer->data + tags[i].offset + tag_head_offset;
}
return IR_DECODE_SUCCEEDED;
}

View File

@@ -0,0 +1,145 @@
/**************************************************************************************
Filename: ir_irframe.c
Revised: Date: 2016-10-01
Revision: Revision: 1.0
Description: This file provides algorithms for IR frame build
Revision log:
* 2016-10-01: created by strawmanbobi
**************************************************************************************/
#include "../include/ir_ac_build_frame.h"
#include "../include/ir_decode.h"
extern t_ac_protocol *context;
//return bit number per byte,default value is 8
UINT8 bits_per_byte(UINT8 index)
{
UINT8 i = 0;
UINT8 size = 0;
if (context->bit_num_cnt == 0)
return 8; //defaut value
if (context->bit_num_cnt >= MAX_BITNUM)
size = MAX_BITNUM;
else
size = (UINT8) context->bit_num_cnt;
for (i = 0; i < size; i++)
{
if (context->bit_num[i].pos == index)
return (UINT8) context->bit_num[i].bits;
if (context->bit_num[i].pos > index)
return 8;
}
return 8;
}
UINT16 add_delaycode(UINT8 index)
{
UINT8 i = 0, j = 0;
UINT8 size = 0;
UINT8 tail_delaycode = 0;
UINT16 tail_pos = 0;
if (context->dc_cnt != 0)
{
size = (UINT8) context->dc_cnt;
for (i = 0; i < size; i++)
{
if (context->dc[i].pos == index)
{
for (j = 0; j < context->dc[i].time_cnt; j++)
{
context->time[context->code_cnt++] = context->dc[i].time[j];
}
}
else if (context->dc[i].pos == -1)
{
tail_delaycode = 1;
tail_pos = i;
}
}
}
if ((context->last_bit == 0) && (index == (ir_hex_len - 1)))
{
context->time[context->code_cnt++] = context->one.low; //high
}
if (context->dc_cnt != 0)
{
if ((index == (ir_hex_len - 1)) && (tail_delaycode == 1))
{
for (i = 0; i < context->dc[tail_pos].time_cnt; i++)
{
context->time[context->code_cnt++] = context->dc[tail_pos].time[i];
}
}
}
return context->dc[i].time_cnt;
}
UINT16 create_ir_frame()
{
UINT16 i = 0, j = 0;
UINT8 bitnum = 0;
UINT8 *irdata = ir_hex_code;
UINT8 mask = 1;
UINT16 framelen = 0;
context->code_cnt = 0;
// boot code
for (i = 0; i < context->boot_code.len; i++)
{
context->time[context->code_cnt++] = context->boot_code.data[i];
}
//code_cnt += context->boot_code.len;
for (i = 0; i < ir_hex_len; i++)
{
bitnum = bits_per_byte((UINT8) i);
for (j = 0; j < bitnum; j++)
{
if (context->endian == 0)
mask = (UINT8) ((1 << (bitnum - 1)) >> j);
else
mask = (UINT8) (1 << j);
if (irdata[i] & mask)
{
//ir_printf("%d,%d,", context->one.low, context->one.high);
context->time[context->code_cnt++] = context->one.low;
context->time[context->code_cnt++] = context->one.high;
}
else
{
//ir_printf("%d,%d,", context->zero.low, context->zero.high);
context->time[context->code_cnt++] = context->zero.low;
context->time[context->code_cnt++] = context->zero.high;
}
}
add_delaycode((UINT8) i);
}
framelen = context->code_cnt;
for (i = 0; i < (context->repeat_times - 1); i++)
{
for (j = 0; j < framelen; j++)
{
context->time[context->code_cnt++] = context->time[j];
}
}
return context->code_cnt;
}

View File

@@ -0,0 +1,548 @@
/**************************************************************************************
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"
extern struct tag_head *tags;
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()
{
UINT8 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;
}
}
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 >> 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 >> 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) >> 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 >> 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 >> 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 >> 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 >> 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 >> 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 (NULL != tags)
{
ir_free(tags);
tags = NULL;
}
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 |= (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 < 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 < 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 < 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 < 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 < 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;
}

View File

@@ -0,0 +1,143 @@
/**************************************************************************************
Filename: ir_parse_forbidden_info.c
Revised: Date: 2016-10-05
Revision: Revision: 1.0
Description: This file provides algorithms for forbidden area of AC code
Revision log:
* 2016-10-05: created by strawmanbobi
**************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../include/ir_decode.h"
#include "../include/ir_ac_parse_forbidden_info.h"
extern t_ac_protocol *context;
INT8 parse_nmode_data_speed(char *pdata, t_ac_n_mode seq)
{
char buf[16] = {0};
char *p = pdata;
UINT16 pos = 0;
UINT16 cnt = 0, index = 0;
while (index <= ir_strlen(pdata))
{
while ((index != ir_strlen(pdata)) && (*(p++) != ','))
{
index++;
}
ir_memcpy(buf, pdata + pos, index - pos);
pos = (UINT16) (index + 1);
index = pos;
context->n_mode[seq].speed[cnt++] = (UINT8) atoi(buf);
context->n_mode[seq].speed_cnt = (UINT8) cnt;
ir_memset(buf, 0, 16);
}
return IR_DECODE_SUCCEEDED;
}
INT8 parse_nmode_data_temp(char *pdata, t_ac_n_mode seq)
{
char buf[16] = {0};
char *p = pdata;
UINT16 pos = 0;
UINT16 cnt = 0, index = 0;
while (index <= ir_strlen(pdata))
{
while ((index != ir_strlen(pdata)) && (*(p++) != ','))
{
index++;
}
ir_memcpy(buf, pdata + pos, index - pos);
pos = (UINT16) (index + 1);
index = pos;
context->n_mode[seq].temp[cnt++] = (UINT8) (atoi(buf) - 16);
context->n_mode[seq].temp_cnt = (UINT8) cnt;
ir_memset(buf, 0, 16);
}
return IR_DECODE_SUCCEEDED;
}
INT8 parse_nmode_pos(char *buf, t_ac_n_mode index)
{
UINT16 i = 0;
char data[64] = {0};
// char start[8] = {0};
if (ir_strlen(buf) == 1)
{
if (buf[0] == 'S' || buf[0] == 's')
{
context->n_mode[index].all_speed = 1;
}
else if (buf[0] == 'T' || buf[0] == 't')
{
context->n_mode[index].all_temp = 1;
}
return IR_DECODE_SUCCEEDED;
}
for (i = 0; i < ir_strlen(buf); i++)
{
if (buf[i] == '&')
{
ir_memcpy(data, buf + i + 1, ir_strlen(buf) - i - 1);
break;
}
}
if (buf[0] == 'S')
{
parse_nmode_data_speed(data, index);
}
else
{
parse_nmode_data_temp(data, index);
}
return IR_DECODE_SUCCEEDED;
}
INT8 parse_nmode(struct tag_head *tag, t_ac_n_mode index)
{
UINT16 i = 0;
UINT16 preindex = 0;
char buf[64] = {0};
if (tag->p_data[0] == 'N' && tag->p_data[1] == 'A')
{
// ban this function directly
context->n_mode[index].enable = 0;
return IR_DECODE_SUCCEEDED;
}
else
{
context->n_mode[index].enable = 1;
}
preindex = 0;
for (i = 0; i < tag->len; i++)
{
if (tag->p_data[i] == '|')
{
ir_memcpy(buf, tag->p_data + preindex, i - preindex);
preindex = (UINT16) (i + 1);
parse_nmode_pos(buf, index);
ir_memset(buf, 0, 64);
}
}
ir_memcpy(buf, tag->p_data + preindex, i - preindex);
parse_nmode_pos(buf, index);
ir_memset(buf, 0, 64);
return IR_DECODE_SUCCEEDED;
}

View File

@@ -0,0 +1,329 @@
/**************************************************************************************
Filename: ir_parse_frame_parameter.c
Revised: Date: 2016-10-11
Revision: Revision: 1.0
Description: This file provides algorithms for IR decode for AC frame parameters
Revision log:
* 2016-10-11: created by strawmanbobi
**************************************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../include/ir_utils.h"
#include "../include/ir_ac_parse_frame_info.h"
INT8 parse_boot_code(struct tag_head *tag)
{
UINT8 buf[16] = {0};
UINT8 *p = NULL;
UINT16 pos = 0;
UINT16 cnt = 0, index = 0;
if (NULL == tag)
{
return IR_DECODE_FAILED;
}
p = tag->p_data;
if (NULL == p)
{
return IR_DECODE_FAILED;
}
while (index <= tag->len)
{
while ((index != (tag->len)) && (*(p++) != ','))
{
index++;
}
ir_memcpy(buf, tag->p_data + pos, index - pos);
pos = (UINT16) (index + 1);
index = pos;
context->boot_code.data[cnt++] = (UINT16) (atoi((char *) buf));
ir_memset(buf, 0, 16);
}
context->boot_code.len = cnt;
return IR_DECODE_SUCCEEDED;
}
INT8 parse_zero(struct tag_head *tag)
{
UINT8 low[16] = {0};
UINT8 high[16] = {0};
UINT16 index = 0;
UINT8 *p = NULL;
if (NULL == tag)
{
return IR_DECODE_FAILED;
}
p = tag->p_data;
if (NULL == p)
{
return IR_DECODE_FAILED;
}
while (*(p++) != ',')
{
index++;
}
ir_memcpy(low, tag->p_data, index);
ir_memcpy(high, tag->p_data + index + 1, (size_t) (tag->len - index - 1));
context->zero.low = (UINT16) (atoi((char *) low));
context->zero.high = (UINT16) (atoi((char *) high));
return IR_DECODE_SUCCEEDED;
}
INT8 parse_one(struct tag_head *tag)
{
UINT8 low[16] = {0};
UINT8 high[16] = {0};
UINT16 index = 0;
UINT8 *p = NULL;
if (NULL == tag)
{
return IR_DECODE_FAILED;
}
p = tag->p_data;
if (NULL == p)
{
return IR_DECODE_FAILED;
}
while (*(p++) != ',')
{
index++;
}
ir_memcpy(low, tag->p_data, index);
ir_memcpy(high, tag->p_data + index + 1, (size_t) (tag->len - index - 1));
context->one.low = (UINT16) (atoi((char *) low));
context->one.high = (UINT16) (atoi((char *) high));
return IR_DECODE_SUCCEEDED;
}
INT8 parse_delay_code_data(UINT8 *pdata)
{
UINT8 buf[16] = {0};
UINT8 *p = NULL;
UINT16 pos = 0;
UINT16 cnt = 0, index = 0;
if (NULL == pdata)
{
return IR_DECODE_FAILED;
}
p = pdata;
while (index <= ir_strlen((char *) pdata))
{
while ((index != ir_strlen((char *) pdata)) && (*(p++) != ','))
{
index++;
}
ir_memcpy(buf, pdata + pos, index - pos);
pos = (UINT16) (index + 1);
index = pos;
context->dc[context->dc_cnt].time[cnt++] = (UINT16) (atoi((char *) buf));
context->dc[context->dc_cnt].time_cnt = cnt;
ir_memset(buf, 0, 16);
}
return IR_DECODE_SUCCEEDED;
}
INT8 parse_delay_code_pos(UINT8 *buf)
{
UINT16 i = 0;
UINT8 data[64] = {0}, start[8] = {0};
if (NULL == buf)
{
return IR_DECODE_FAILED;
}
for (i = 0; i < ir_strlen((char *) buf); i++)
{
if (buf[i] == '&')
{
ir_memcpy(start, buf, i);
ir_memcpy(data, buf + i + 1, ir_strlen((char *) buf) - i - 1);
break;
}
}
parse_delay_code_data(data);
context->dc[context->dc_cnt].pos = (UINT16) (atoi((char *) start));
context->dc_cnt++;
return IR_DECODE_SUCCEEDED;
}
INT8 parse_delay_code(struct tag_head *tag)
{
UINT8 buf[64] = {0};
UINT16 i = 0;
UINT16 preindex = 0;
preindex = 0;
if (NULL == tag)
{
return IR_DECODE_FAILED;
}
for (i = 0; i < tag->len; i++)
{
if (tag->p_data[i] == '|')
{
ir_memcpy(buf, tag->p_data + preindex, i - preindex);
preindex = (UINT16) (i + 1);
parse_delay_code_pos(buf);
ir_memset(buf, 0, 64);
}
}
ir_memcpy(buf, tag->p_data + preindex, i - preindex);
parse_delay_code_pos(buf);
ir_memset(buf, 0, 64);
return IR_DECODE_SUCCEEDED;
}
INT8 parse_frame_len(struct tag_head *tag, UINT16 len)
{
UINT8 *temp = NULL;
if (NULL == tag)
{
return IR_DECODE_FAILED;
}
temp = (UINT8 *) ir_malloc(len + 1);
if (NULL == temp)
{
return IR_DECODE_FAILED;
}
ir_memset(temp, 0x00, len + 1);
ir_memcpy(temp, tag->p_data, len);
temp[len] = '\0';
context->frame_length = (UINT16) (atoi((char *) temp));
ir_free(temp);
return IR_DECODE_SUCCEEDED;
}
INT8 parse_endian(struct tag_head *tag)
{
UINT8 buf[8] = {0};
if (NULL == tag)
{
return IR_DECODE_FAILED;
}
ir_memcpy(buf, tag->p_data, tag->len);
context->endian = (UINT8) (atoi((char *) buf));
return IR_DECODE_SUCCEEDED;
}
INT8 parse_lastbit(struct tag_head *tag)
{
UINT8 buf[8] = {0};
if (NULL == tag)
{
return IR_DECODE_FAILED;
}
ir_memcpy(buf, tag->p_data, tag->len);
context->last_bit = (UINT8) (atoi((char *) buf));
return IR_DECODE_SUCCEEDED;
}
INT8 parse_repeat_times(struct tag_head *tag)
{
char asc_code[8] = {0};
if (NULL == tag)
{
return IR_DECODE_FAILED;
}
ir_memcpy(asc_code, tag->p_data, tag->len);
context->repeat_times = (UINT16) (atoi((char *) asc_code));
return IR_DECODE_SUCCEEDED;
}
INT8 parse_delay_code_tag48_pos(UINT8 *buf)
{
UINT16 i = 0;
UINT8 data[64] = {0}, start[8] = {0};
if (NULL == buf)
{
return IR_DECODE_FAILED;
}
for (i = 0; i < ir_strlen((char *) buf); i++)
{
if (buf[i] == '&')
{
ir_memcpy(start, buf, i);
ir_memcpy(data, buf + i + 1, ir_strlen((char *) buf) - i - 1);
break;
}
}
context->bit_num[context->bit_num_cnt].pos = (UINT16) (atoi((char *) start));
context->bit_num[context->bit_num_cnt].bits = (UINT16) (atoi((char *) data));
context->bit_num_cnt++;
return IR_DECODE_SUCCEEDED;
}
INT8 parse_bit_num(struct tag_head *tag)
{
UINT16 i = 0;
UINT16 preindex = 0;
UINT8 buf[64] = {0};
if (NULL == tag)
{
return IR_DECODE_FAILED;
}
preindex = 0;
for (i = 0; i < tag->len; i++)
{
if (tag->p_data[i] == '|')
{
ir_memcpy(buf, tag->p_data + preindex, i - preindex);
preindex = (UINT16) (i + 1);
parse_delay_code_tag48_pos(buf);
ir_memset(buf, 0, 64);
}
}
ir_memcpy(buf, tag->p_data + preindex, i - preindex);
parse_delay_code_tag48_pos(buf);
ir_memset(buf, 0, 64);
for (i = 0; i < context->bit_num_cnt; i++)
{
if (context->bit_num[i].pos == -1)
context->bit_num[i].pos = (UINT16) (context->default_code.len - 1); //convert -1 to last data pos
}
return IR_DECODE_SUCCEEDED;
}

View File

@@ -0,0 +1,640 @@
/**************************************************************************************
Filename: ir_decode.c
Revised: Date: 2016-10-01
Revision: Revision: 1.0
Description: This file provides algorithms for IR decode (status type)
Revision log:
* 2016-10-01: created by strawmanbobi
**************************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../include/ir_decode.h"
#include "../include/ir_utils.h"
#include "../include/ir_ac_build_frame.h"
#include "../include/ir_ac_apply.h"
struct ir_bin_buffer binary_file;
struct ir_bin_buffer *p_ir_buffer = &binary_file;
struct tag_head *tags;
UINT8 *ir_hex_code = NULL;
UINT8 ir_hex_len = 0;
UINT8 byteArray[PROTOCOL_SIZE] = {0};
size_t binary_length = 0;
UINT8 *binary_content = NULL;
UINT8 ir_binary_type = IR_TYPE_STATUS;
UINT8 ir_hexadecimal = SUB_CATEGORY_QUATERNARY;
t_ac_protocol *context = (t_ac_protocol *) byteArray;
lp_apply_ac_parameter apply_table[AC_APPLY_MAX] =
{
apply_power,
apply_mode,
apply_temperature,
apply_temperature,
apply_wind_speed,
apply_swing,
apply_swing
};
// static functions declarations
static INT8 ir_ac_file_open(const char *file_name);
static INT8 ir_ac_lib_open(UINT8 *binary, UINT16 binary_length);
static UINT16 ir_ac_lib_control(t_remote_ac_status ac_status, UINT16 *user_data, UINT8 function_code,
BOOL change_wind_direction);
static INT8 ir_ac_lib_close();
static INT8 ir_tv_file_open(const char *file_name);
static INT8 ir_tv_lib_open(UINT8 *binary, UINT16 binary_length);
static INT8 ir_tv_lib_parse(UINT8 ir_hex_encode);
static UINT16 ir_tv_lib_control(UINT8 key, UINT16 *l_user_data);
static INT8 ir_tv_lib_close();
void noprint(const char *fmt, ...)
{
return;
}
// pubic function definitions
INT8 ir_file_open(const UINT8 category, const UINT8 sub_category, const char* file_name)
{
INT8 ret = IR_DECODE_SUCCEEDED;
if (category == IR_CATEGORY_AC)
{
ir_binary_type = IR_TYPE_STATUS;
ret = ir_ac_file_open(file_name);
if (IR_DECODE_SUCCEEDED == ret)
{
return ir_ac_lib_parse();
}
else
{
return ret;
}
}
else
{
ir_binary_type = IR_TYPE_COMMANDS;
if (1 == sub_category)
{
ir_hexadecimal = SUB_CATEGORY_QUATERNARY;
}
else if (2 == sub_category)
{
ir_hexadecimal = SUB_CATEGORY_HEXADECIMAL;
}
else
{
return IR_DECODE_FAILED;
}
ret = ir_tv_file_open(file_name);
if (IR_DECODE_SUCCEEDED == ret)
{
return ir_tv_lib_parse(ir_hexadecimal);
}
else
{
return ret;
}
}
}
INT8 ir_binary_open(const UINT8 category, const UINT8 sub_category, UINT8* binary, UINT16 binary_length)
{
INT8 ret = IR_DECODE_SUCCEEDED;
if (category == IR_CATEGORY_AC)
{
ir_binary_type = IR_TYPE_STATUS;
ret = ir_ac_lib_open(binary, binary_length);
if (IR_DECODE_SUCCEEDED == ret)
{
return ir_ac_lib_parse();
}
else
{
return ret;
}
}
else
{
ir_binary_type = IR_TYPE_COMMANDS;
if (1 == sub_category)
{
ir_hexadecimal = SUB_CATEGORY_QUATERNARY;
}
else if (2 == sub_category)
{
ir_hexadecimal = SUB_CATEGORY_HEXADECIMAL;
}
else
{
return IR_DECODE_FAILED;
}
ret = ir_tv_lib_open(binary, binary_length);
if (IR_DECODE_SUCCEEDED == ret)
{
return ir_tv_lib_parse(ir_hexadecimal);
}
else
{
return ret;
}
}
}
UINT16 ir_decode(UINT8 key_code, UINT16* user_data, t_remote_ac_status* ac_status, BOOL change_wind_direction)
{
if (IR_TYPE_COMMANDS == ir_binary_type)
{
return ir_tv_lib_control(key_code, user_data);
}
else
{
if (NULL == ac_status)
{
return 0;
}
return ir_ac_lib_control(*ac_status, user_data, key_code, change_wind_direction);
}
}
INT8 ir_close()
{
if (IR_TYPE_COMMANDS == ir_binary_type)
{
return ir_tv_lib_close();
}
else
{
return ir_ac_lib_close();
}
}
#if (defined BOARD_PC || defined BOARD_PC_DLL)
void ir_lib_free_inner_buffer();
#endif
// static function definitions
//////// AC Begin ////////
static INT8 ir_ac_file_open(const char *file_name)
{
#if !defined NO_FS
size_t ret = 0;
#if !defined WIN32
FILE *stream = fopen(file_name, "rb");
#else
FILE *stream;
fopen_s(&stream, file_name, "rb");
#endif
if (NULL == stream)
{
ir_printf("\nfile open failed\n");
return IR_DECODE_FAILED;
}
fseek(stream, 0, SEEK_END);
binary_length = (size_t) ftell(stream);
binary_content = (UINT8 *) ir_malloc(binary_length);
if (NULL == binary_content)
{
ir_printf("\nfailed to alloc memory for binary\n");
fclose(stream);
return IR_DECODE_FAILED;
}
fseek(stream, 0, SEEK_SET);
ret = fread(binary_content, binary_length, 1, stream);
if (ret <= 0)
{
fclose(stream);
ir_free(binary_content);
binary_length = 0;
return IR_DECODE_FAILED;
}
fclose(stream);
if (IR_DECODE_FAILED == ir_ac_lib_open(binary_content, (UINT16) binary_length))
{
ir_free(binary_content);
binary_length = 0;
return IR_DECODE_FAILED;
}
#endif
return IR_DECODE_SUCCEEDED;
}
static INT8 ir_ac_lib_open(UINT8 *binary, UINT16 binary_length)
{
// it is recommended that the parameter binary pointing to
// a global memory block in embedded platform environment
p_ir_buffer->data = binary;
p_ir_buffer->len = binary_length;
p_ir_buffer->offset = 0;
return IR_DECODE_SUCCEEDED;
}
static UINT16 ir_ac_lib_control(t_remote_ac_status ac_status, UINT16 *user_data, UINT8 function_code,
BOOL change_wind_direction)
{
UINT16 time_length = 0;
#if defined BOARD_PC
UINT8 i = 0;
#endif
if (0 == context->default_code.len)
{
ir_printf("\ndefault code is empty\n");
return 0;
}
// pre-set change wind direction flag here
context->change_wind_direction = change_wind_direction;
context->time = user_data;
// generate temp buffer for frame calculation
ir_memcpy(ir_hex_code, context->default_code.data, context->default_code.len);
#if defined USE_APPLY_TABLE
if(ac_status.ac_power != AC_POWER_OFF)
{
for (i = AC_APPLY_POWER; i < AC_APPLY_MAX; i++)
{
apply_table[i](context, parameter_array[i]);
}
}
#else
if (ac_status.ac_power == AC_POWER_OFF)
{
// otherwise, power should always be applied
apply_power(ac_status, function_code);
}
else
{
// check the mode as the first priority, despite any other status
if (TRUE == context->n_mode[ac_status.ac_mode].enable)
{
if (is_solo_function(function_code))
{
// this key press function needs to send solo code
apply_table[function_code - 1](ac_status, function_code);
}
else
{
if (!is_solo_function(AC_FUNCTION_POWER))
{
apply_power(ac_status, function_code);
}
if (!is_solo_function(AC_FUNCTION_MODE))
{
if (IR_DECODE_FAILED == apply_mode(ac_status, function_code))
{
return 0;
}
}
if (!is_solo_function(AC_FUNCTION_WIND_SPEED))
{
if (IR_DECODE_FAILED == apply_wind_speed(ac_status, function_code))
{
return 0;
}
}
if (!is_solo_function(AC_FUNCTION_WIND_SWING) &&
!is_solo_function(AC_FUNCTION_WIND_FIX))
{
if (IR_DECODE_FAILED == apply_swing(ac_status, function_code))
{
return 0;
}
}
if (!is_solo_function(AC_FUNCTION_TEMPERATURE_UP) &&
!is_solo_function(AC_FUNCTION_TEMPERATURE_DOWN))
{
if (IR_DECODE_FAILED == apply_temperature(ac_status, function_code))
{
return 0;
}
}
}
}
else
{
return 0;
}
}
#endif
apply_function(context, function_code);
// checksum should always be applied
apply_checksum(context);
time_length = create_ir_frame();
#if (defined BOARD_PC)
#if (defined BOARD_PC_JNI)
ir_printf("code count = %d\n", context->code_cnt);
#else
for (i = 0; i < context->code_cnt; i++)
{
ir_printf("%d,", context->time[i]);
}
#endif
ir_printf("\n");
#endif
return time_length;
}
static INT8 ir_ac_lib_close()
{
// free context
if (NULL != tags)
{
ir_free(tags);
tags = NULL;
}
free_ac_context();
return IR_DECODE_SUCCEEDED;
}
// utils
INT8 get_temperature_range(UINT8 ac_mode, INT8 *temp_min, INT8 *temp_max)
{
UINT8 i = 0;
if (ac_mode >= AC_MODE_MAX)
{
return IR_DECODE_FAILED;
}
if (NULL == temp_min || NULL == temp_max)
{
return IR_DECODE_FAILED;
}
if (1 == context->n_mode[ac_mode].all_temp)
{
*temp_min = *temp_max = -1;
return IR_DECODE_SUCCEEDED;
}
*temp_min = -1;
*temp_max = -1;
for (i = 0; i < AC_TEMP_MAX; i++)
{
if (is_in(context->n_mode[ac_mode].temp, i, context->n_mode[ac_mode].temp_cnt) ||
(context->temp1.len != 0 && 0 == context->temp1.comp_data[i].seg_len) ||
(context->temp2.len != 0 && 0 == context->temp2.comp_data[i].seg_len))
{
continue;
}
if (-1 == *temp_min)
{
*temp_min = i;
}
if (-1 == *temp_max || i > *temp_max)
{
*temp_max = i;
}
}
return IR_DECODE_SUCCEEDED;
}
INT8 get_supported_mode(UINT8 *supported_mode)
{
UINT8 i = 0;
if (NULL == supported_mode)
{
return IR_DECODE_FAILED;
}
*supported_mode = 0x1F;
for (i = 0; i < AC_MODE_MAX; i++)
{
if (0 == context->n_mode[i].enable ||
(context->mode1.len != 0 && 0 == context->mode1.comp_data[i].seg_len) ||
(context->mode2.len != 0 && 0 == context->mode2.comp_data[i].seg_len))
{
*supported_mode &= ~(1 << i);
}
}
return IR_DECODE_SUCCEEDED;
}
INT8 get_supported_wind_speed(UINT8 ac_mode, UINT8 *supported_wind_speed)
{
UINT8 i = 0;
if (ac_mode >= AC_MODE_MAX)
{
return IR_DECODE_FAILED;
}
if (NULL == supported_wind_speed)
{
return IR_DECODE_FAILED;
}
if (1 == context->n_mode[ac_mode].all_speed)
{
*supported_wind_speed = 0;
return IR_DECODE_SUCCEEDED;
}
*supported_wind_speed = 0x0F;
for (i = 0; i < AC_WS_MAX; i++)
{
if (is_in(context->n_mode[ac_mode].speed, i, context->n_mode[ac_mode].speed_cnt) ||
(context->speed1.len != 0 && 0 == context->speed1.comp_data[i].seg_len) ||
(context->speed2.len != 0 && 0 == context->speed2.comp_data[i].seg_len))
{
*supported_wind_speed &= ~(1 << i);
}
}
return IR_DECODE_SUCCEEDED;
}
INT8 get_supported_swing(UINT8 ac_mode, UINT8 *supported_swing)
{
if (ac_mode >= AC_MODE_MAX)
{
return IR_DECODE_FAILED;
}
if (NULL == supported_swing)
{
return IR_DECODE_FAILED;
}
if (context->si.type == SWING_TYPE_NORMAL)
{
*supported_swing = 0x03;
}
else if (context->si.type == SWING_TYPE_SWING_ONLY)
{
*supported_swing = 0x02;
}
else if (context->si.type == SWING_TYPE_NOT_SPECIFIED)
{
*supported_swing = 0x00;
}
else
{
*supported_swing = 0x01;
}
return IR_DECODE_SUCCEEDED;
}
INT8 get_supported_wind_direction(UINT8 *supported_wind_direction)
{
if (NULL != context)
{
*supported_wind_direction = (UINT8) (context->si.mode_count - 1);
return IR_DECODE_SUCCEEDED;
}
else
{
return IR_DECODE_FAILED;
}
}
//////// AC End ////////
//////// TV Begin ////////
static INT8 ir_tv_file_open(const char *file_name)
{
#if !defined NO_FS
size_t ret = 0;
#if !defined WIN32
FILE *stream = fopen(file_name, "rb");
#else
FILE *stream;
fopen_s(&stream, file_name, "rb");
#endif
if (stream == NULL)
{
ir_printf("\nfile open failed\n");
return IR_DECODE_FAILED;
}
fseek(stream, 0, SEEK_END);
binary_length = (size_t) ftell(stream);
binary_content = (UINT8 *) ir_malloc(binary_length);
if (NULL == binary_content)
{
ir_printf("\nfailed to alloc memory for binary\n");
fclose(stream);
return IR_DECODE_FAILED;
}
fseek(stream, 0, SEEK_SET);
ret = fread(binary_content, binary_length, 1, stream);
if (ret <= 0)
{
fclose(stream);
ir_free(binary_content);
binary_length = 0;
return IR_DECODE_FAILED;
}
fclose(stream);
if (IR_DECODE_FAILED == ir_tv_lib_open(binary_content, (UINT16) binary_length))
{
ir_free(binary_content);
binary_length = 0;
return IR_DECODE_FAILED;
}
#endif
return IR_DECODE_SUCCEEDED;
}
static INT8 ir_tv_lib_open(UINT8 *binary, UINT16 binary_length)
{
return tv_lib_open(binary, binary_length);
}
static INT8 ir_tv_lib_parse(UINT8 ir_hex_encode)
{
if (FALSE == tv_lib_parse(ir_hex_encode))
{
ir_printf("parse irda binary failed\n");
return IR_DECODE_FAILED;
}
return IR_DECODE_SUCCEEDED;
}
static UINT16 ir_tv_lib_control(UINT8 key, UINT16 *l_user_data)
{
#if defined BOARD_PC
UINT16 print_index = 0;
#endif
UINT16 ir_code_length = 0;
memset(l_user_data, 0x00, USER_DATA_SIZE);
ir_code_length = tv_lib_control(key, l_user_data);
#if defined BOARD_PC
// have some debug
ir_printf("length of IR code = %d\n", ir_code_length);
for (print_index = 0; print_index < ir_code_length; print_index++)
{
ir_printf("%d ", l_user_data[print_index]);
}
#endif
return ir_code_length;
}
static INT8 ir_tv_lib_close()
{
#if (defined BOARD_PC || defined BOARD_PC_DLL)
ir_lib_free_inner_buffer();
#endif
return IR_DECODE_SUCCEEDED;
}
//////// TV End ////////
#if (defined BOARD_PC || defined BOARD_PC_DLL)
void ir_lib_free_inner_buffer()
{
if (NULL != binary_content)
{
ir_free(binary_content);
binary_content = NULL;
}
}
#endif

View File

@@ -0,0 +1,448 @@
/**************************************************************************************
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
**************************************************************************************/
#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_lib_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_lib_parse(UINT8 encode_type)
{
if (FALSE == get_ir_protocol(encode_type))
{
return FALSE;
}
return get_ir_keymap();
}
UINT16 tv_lib_control(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 quanternary 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;
}
}

View File

@@ -0,0 +1,98 @@
/**************************************************************************************
Filename: ir_utils.c
Revised: Date: 2016-10-26
Revision: Revision: 1.0
Description: This file provides generic utils for IRDA algorithms
Revision log:
* 2016-10-01: created by strawmanbobi
**************************************************************************************/
#include "../include/ir_utils.h"
UINT8 char_to_hex(char chr)
{
UINT8 value = 0;
if (chr >= '0' && chr <= '9')
value = (UINT8) (chr - '0');
if (chr >= 'a' && chr <= 'f')
value = (UINT8) (chr - 'a' + 10);
if (chr >= 'A' && chr <= 'F')
value = (UINT8) (chr - 'A' + 10);
return value;
}
UINT8 chars_to_hex(const UINT8 *p)
{
return (char_to_hex(*p) << 4) + char_to_hex(*(p + 1));
}
void string_to_hex_common(UINT8 *p, UINT8 *hex_data, UINT16 len)
{
// in condition of hex_code is already assigned
UINT16 i = 0;
for (i = 0; i < len; i++)
{
hex_data[i] = chars_to_hex(p);
p = p + 2;
}
}
void string_to_hex(UINT8 *p, t_ac_hex *pac_hex)
{
UINT8 i = 0;
pac_hex->len = chars_to_hex(p);
p = p + 2;
for (i = 0; i < pac_hex->len; i++)
{
pac_hex->data[i] = chars_to_hex(p);
p = p + 2;
}
}
char hex_half_byte_to_single_char(UINT8 length, UINT8 half_byte)
{
if (1 != length || half_byte >= 16)
{
return '0';
}
if (half_byte >= 10 && half_byte < 16)
{
return (char) (half_byte - 10 + 0x41);
}
else
{
return (char) (half_byte + 0x30);
}
}
void hex_byte_to_double_char(char *dest, UINT8 length, UINT8 src)
{
UINT8 hi_num = 0;
UINT8 lo_num = 0;
if (NULL == dest || 2 != length)
{
return;
}
hi_num = (UINT8) ((src >> 4) & 0x0F);
lo_num = (UINT8) (src & 0x0F);
dest[0] = hex_half_byte_to_single_char(1, hi_num);
dest[1] = hex_half_byte_to_single_char(1, lo_num);
}
BOOL is_in(const UINT8 *array, UINT8 value, UINT8 len)
{
UINT16 i = 0;
for (i = 0; i < len; i++)
{
if (array[i] == value)
{
return TRUE;
}
}
return FALSE;
}