[Add] First commit
This commit is contained in:
375
NSPE/Example/IFRP/RC5_code/rc5_decode.c
Normal file
375
NSPE/Example/IFRP/RC5_code/rc5_decode.c
Normal file
@ -0,0 +1,375 @@
|
||||
/*!
|
||||
\file rc5_decode.c
|
||||
\brief the rc5 infrared decoding file
|
||||
|
||||
\version 2021-10-30, V1.0.0, firmware for GD32W51x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2021, GigaDevice Semiconductor Inc.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "rc5_decode.h"
|
||||
#include "ir_decode.h"
|
||||
|
||||
/* logic table for rising edge: every line has values corresponding to previous bit.
|
||||
in columns are actual bit values for given bit time. */
|
||||
const trc5_last_bit_type rc5_logic_table_rising_edge[2][2] =
|
||||
{
|
||||
/* last_bit = ZERO */
|
||||
{RC5_ZER ,RC5_INV},
|
||||
/* last_bit = ONE */
|
||||
{RC5_NAN ,RC5_ZER},
|
||||
};
|
||||
|
||||
/* logic table for falling edge: every line has values corresponding to previous bit.
|
||||
in columns are actual bit values for given bit time. */
|
||||
const trc5_last_bit_type rc5_logic_table_falling_edge[2][2] =
|
||||
{
|
||||
/* last_bit = ZERO */
|
||||
{RC5_NAN ,RC5_ONE},
|
||||
/* last_bit = ONE */
|
||||
{RC5_ONE ,RC5_INV},
|
||||
};
|
||||
|
||||
/* rc5 frame state */
|
||||
__IO status_yes_or_no rc5_frame_received = NO;
|
||||
|
||||
/* first empty packet */
|
||||
__IO trc5_packet_struct rc5_tmp_packet;
|
||||
|
||||
/* rc5 bits time definitions */
|
||||
uint16_t rc5_mint = 0;
|
||||
uint16_t rc5_maxt = 0;
|
||||
uint16_t rc5_min2t = 0;
|
||||
uint16_t rc5_max2t = 0;
|
||||
uint32_t rc5_data = 0;
|
||||
|
||||
/* timer clock */
|
||||
static uint32_t timer_clk_value_khz = 0;
|
||||
|
||||
static uint8_t rc5_get_pulse_length (uint16_t pulse_length);
|
||||
static void rc5_modify_last_bit(trc5_last_bit_type bit);
|
||||
static void rc5_write_bit(uint8_t bit_val);
|
||||
static uint32_t timer_get_counter_clk_value(void);
|
||||
|
||||
/*!
|
||||
\brief de-initializes the peripherals
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rc5_decode_deinit(void)
|
||||
{
|
||||
timer_deinit(IR_TIMER);
|
||||
gpio_deinit(IR_GPIO_PORT);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief initialize the rc5 decoder module
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rc5_decode_init(void)
|
||||
{
|
||||
__IO uint16_t rc5_time_out = 0;
|
||||
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
|
||||
/* clock configuration for TIMER */
|
||||
rcu_periph_clock_enable(IR_TIMER_CLK);
|
||||
/* enable GPIO clock */
|
||||
rcu_periph_clock_enable(IR_GPIO_PORT_CLK);
|
||||
|
||||
/* IR_decode */
|
||||
/* GD32W515P-EVAL:TIMER3_CH1 PB7 */
|
||||
{
|
||||
/*configure PB7 (TIMER3 CH1) as alternate function*/
|
||||
gpio_mode_set(IR_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, IR_GPIO_PIN);
|
||||
gpio_output_options_set(IR_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ , IR_GPIO_PIN);
|
||||
gpio_af_set(IR_GPIO_PORT, GPIO_AF_2, IR_GPIO_PIN);
|
||||
}
|
||||
|
||||
/* enable the TIMER global interrupt */
|
||||
nvic_irq_enable(IR_TIMER_IRQn, 0, 1);
|
||||
|
||||
{
|
||||
timer_ic_parameter_struct timer_icinitpara;
|
||||
timer_parameter_struct timer_initpara;
|
||||
|
||||
/* deinit IR_TIMER */
|
||||
|
||||
/* TIMER3 configuration */
|
||||
timer_deinit(IR_TIMER);
|
||||
|
||||
/* timer base configuration for timer IR_TIMER */
|
||||
timer_initpara.prescaler = 0x00;
|
||||
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
|
||||
timer_initpara.counterdirection = TIMER_COUNTER_UP;
|
||||
timer_initpara.period = 0x00;
|
||||
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
|
||||
timer_initpara.repetitioncounter = 0;
|
||||
timer_init(IR_TIMER,&timer_initpara);
|
||||
|
||||
/* prescaler configuration */
|
||||
timer_prescaler_config(IR_TIMER, 179, TIMER_PSC_RELOAD_NOW);
|
||||
|
||||
/* TIMER2 CH0 input capture configuration */
|
||||
timer_icinitpara.icpolarity = TIMER_IC_POLARITY_FALLING;
|
||||
timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
|
||||
timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
|
||||
timer_icinitpara.icfilter = 0x0;
|
||||
timer_input_pwm_capture_config(IR_TIMER,IR_TIMER_Channel,&timer_icinitpara);
|
||||
}
|
||||
|
||||
/* timer clock */
|
||||
timer_clk_value_khz = timer_get_counter_clk_value()/1000;
|
||||
|
||||
/* select the TIMER input trigger */
|
||||
#if defined TIMER_CHANNEL1
|
||||
timer_input_trigger_source_select(IR_TIMER, TIMER_SMCFG_TRGSEL_CI1FE1);
|
||||
#else
|
||||
timer_input_trigger_source_select(IR_TIMER, TIMER_SMCFG_TRGSEL_CI0FE0);
|
||||
#endif
|
||||
|
||||
/* select the slave mode: reset mode */
|
||||
timer_slave_mode_select(IR_TIMER, TIMER_SLAVE_MODE_RESTART);
|
||||
|
||||
/* configures the TIMER update request interrupt source: counter overflow */
|
||||
timer_update_source_config( IR_TIMER, TIMER_UPDATE_SRC_REGULAR );
|
||||
|
||||
rc5_time_out = timer_clk_value_khz * RC5_TIME_OUT_US/1000;
|
||||
|
||||
/* set the TIMER auto-reload register for each IR protocol */
|
||||
TIMER_CAR(IR_TIMER) = rc5_time_out;
|
||||
|
||||
/* clear flag */
|
||||
timer_interrupt_flag_clear(IR_TIMER, TIMER_INT_UP | TIMER_INT_CH0 | TIMER_INT_CH1);
|
||||
|
||||
/* enable the CH1 interrupt request */
|
||||
timer_interrupt_enable(IR_TIMER, TIMER_INT_CH1);
|
||||
|
||||
/* enable the CH0 interrupt request */
|
||||
timer_interrupt_enable(IR_TIMER, TIMER_INT_CH0);
|
||||
|
||||
/* enable the timer */
|
||||
timer_enable(IR_TIMER);
|
||||
|
||||
/* bit time range */
|
||||
rc5_mint = ( RC5_T_US - RC5_T_TOLERANCE_US ) * timer_clk_value_khz / 1000 ;
|
||||
rc5_maxt = ( RC5_T_US + RC5_T_TOLERANCE_US ) * timer_clk_value_khz / 1000 ;
|
||||
rc5_min2t = ( 2 * RC5_T_US - RC5_T_TOLERANCE_US ) * timer_clk_value_khz / 1000 ;
|
||||
rc5_max2t = ( 2 * RC5_T_US + RC5_T_TOLERANCE_US ) * timer_clk_value_khz / 1000 ;
|
||||
|
||||
/* default state */
|
||||
rc5_reset_packet();
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief decode the IR frame when all the frame is received, the rc5_frame_received will equal to YES
|
||||
\param[in] rc5_frame: pointer to rc5_frame_struct structure that contains the IR protocol fields
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rc5_decode(rc5_frame_struct *rc5_frame)
|
||||
{
|
||||
/* if frame received */
|
||||
if(rc5_frame_received != NO){
|
||||
rc5_data = rc5_tmp_packet.data ;
|
||||
|
||||
/* rc5 frame field decoding */
|
||||
rc5_frame->address = (rc5_tmp_packet.data >> 6) & 0x1F;
|
||||
rc5_frame->command = (rc5_tmp_packet.data) & 0x3F;
|
||||
rc5_frame->field_bit = (rc5_tmp_packet.data >> 12) & 0x1;
|
||||
rc5_frame->toggle_bit = (rc5_tmp_packet.data >> 11) & 0x1;
|
||||
|
||||
/* check if command ranges between 64 to 127:upper field */
|
||||
if(rc5_frame->field_bit == 0x00){
|
||||
rc5_frame->command = (1<<6)| rc5_frame->command;
|
||||
}
|
||||
|
||||
/* default state */
|
||||
rc5_frame_received = NO;
|
||||
rc5_reset_packet();
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief set the incoming packet structure to default state
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rc5_reset_packet(void)
|
||||
{
|
||||
rc5_tmp_packet.data = 0;
|
||||
rc5_tmp_packet.bit_count = RC5_PACKET_BIT_COUNT - 1;
|
||||
rc5_tmp_packet.last_bit = RC5_ONE;
|
||||
rc5_tmp_packet.status = RC5_PACKET_STATUS_EMPTY;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief identify the rc5 data bits
|
||||
\param[in] raw_pulse_length: low/high pulse duration
|
||||
\param[in] edge: '1' for rising or '0' for falling edge
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rc5_data_sampling(uint16_t raw_pulse_length, uint8_t edge)
|
||||
{
|
||||
uint8_t pulse;
|
||||
trc5_last_bit_type tmp_last_bit;
|
||||
|
||||
/* decode the pulse length in protocol units */
|
||||
pulse = rc5_get_pulse_length(raw_pulse_length);
|
||||
|
||||
/* on rising edge */
|
||||
if(1 == edge){
|
||||
if(pulse <= RC5_2T_TIME){
|
||||
/* bit determination by the rising edge */
|
||||
tmp_last_bit = rc5_logic_table_rising_edge[rc5_tmp_packet.last_bit][pulse];
|
||||
rc5_modify_last_bit(tmp_last_bit);
|
||||
}else{
|
||||
rc5_reset_packet();
|
||||
}
|
||||
}
|
||||
/* on falling edge */
|
||||
else {
|
||||
/* if this is the first falling edge - don't compute anything */
|
||||
if(rc5_tmp_packet.status & RC5_PACKET_STATUS_EMPTY){
|
||||
rc5_tmp_packet.status &= (uint8_t)~RC5_PACKET_STATUS_EMPTY;
|
||||
}else{
|
||||
if(pulse <= RC5_2T_TIME){
|
||||
/* bit determination by the falling edge */
|
||||
tmp_last_bit = rc5_logic_table_falling_edge[rc5_tmp_packet.last_bit][pulse];
|
||||
rc5_modify_last_bit(tmp_last_bit);
|
||||
}else{
|
||||
rc5_reset_packet();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief convert raw pulse length expressed in timer ticks to protocol bit times
|
||||
\param[in] pulse_length: pulse duration
|
||||
\param[out] none
|
||||
\retval bit time value
|
||||
*/
|
||||
static uint8_t rc5_get_pulse_length (uint16_t pulse_length)
|
||||
{
|
||||
/* valid bit time */
|
||||
if((pulse_length > rc5_mint) && (pulse_length < rc5_maxt)){
|
||||
/* found the length,return the correct value */
|
||||
return (RC5_1T_TIME);
|
||||
}else if((pulse_length > rc5_min2t) && (pulse_length < rc5_max2t)){
|
||||
/* found the length,return the correct value */
|
||||
return (RC5_2T_TIME);
|
||||
}
|
||||
/* error */
|
||||
return RC5_WRONG_TIME;
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief perform checks if the last bit was not incorrect
|
||||
\param[in] bit: where bit can be RC5_NAN or RC5_INV or RC5_ZER or RC5_ONE
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void rc5_modify_last_bit(trc5_last_bit_type bit)
|
||||
{
|
||||
if(RC5_NAN != bit){
|
||||
if(RC5_INV != rc5_tmp_packet.last_bit){
|
||||
/* restore the last bit */
|
||||
rc5_tmp_packet.last_bit = bit;
|
||||
/* insert one bit into the rc5 packet */
|
||||
rc5_write_bit(rc5_tmp_packet.last_bit);
|
||||
}else{
|
||||
rc5_reset_packet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief insert one bit into the final data word
|
||||
\param[in] bit_val: bit value 'RC5_ONE' or 'RC5_ZER'
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
static void rc5_write_bit(uint8_t bit_val)
|
||||
{
|
||||
/* first convert rc5 symbols to ones and zeros */
|
||||
if(bit_val == RC5_ONE){
|
||||
bit_val = 1;
|
||||
}else if(bit_val == RC5_ZER){
|
||||
bit_val = 0;
|
||||
}else{
|
||||
rc5_reset_packet();
|
||||
return;
|
||||
}
|
||||
|
||||
/* write this particular bit to data field */
|
||||
rc5_tmp_packet.data |= bit_val;
|
||||
|
||||
/* test the bit number determined */
|
||||
/* if this is not the last bit */
|
||||
if(0 != rc5_tmp_packet.bit_count){
|
||||
/* shift the data field */
|
||||
rc5_tmp_packet.data = rc5_tmp_packet.data << 1;
|
||||
/* decrement the bit_count */
|
||||
rc5_tmp_packet.bit_count--;
|
||||
}else{
|
||||
rc5_frame_received = YES;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief identify TIMER clock
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval timer clock
|
||||
*/
|
||||
static uint32_t timer_get_counter_clk_value(void)
|
||||
{
|
||||
uint32_t apb_prescaler = 0, apb_frequency = 0;
|
||||
uint32_t timer_prescaler = 0;
|
||||
|
||||
rcu_clock_freq_get(CK_APB1);
|
||||
|
||||
/* get the clock prescaler of APB1 */
|
||||
apb_prescaler = ((RCU_CFG0>> 8) & 0x7);
|
||||
apb_frequency=rcu_clock_freq_get(CK_APB1);
|
||||
|
||||
timer_prescaler = TIMER_PRESCALER;
|
||||
|
||||
/* if APBx clock div >= 4 */
|
||||
if(apb_prescaler >= 4){
|
||||
return((apb_frequency * 2)/(timer_prescaler + 1));
|
||||
}else{
|
||||
return(apb_frequency/(timer_prescaler+ 1));
|
||||
}
|
||||
}
|
||||
96
NSPE/Example/IFRP/RC5_code/rc5_decode.h
Normal file
96
NSPE/Example/IFRP/RC5_code/rc5_decode.h
Normal file
@ -0,0 +1,96 @@
|
||||
/*!
|
||||
\file rc5_decode.h
|
||||
\brief the header file of rc5 infrared decoding
|
||||
|
||||
\version 2021-10-30, V1.0.0, firmware for GD32W51x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2021, GigaDevice Semiconductor Inc.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RC5_DECODE_H
|
||||
#define RC5_DECODE_H
|
||||
|
||||
#include "gd32w51x.h"
|
||||
|
||||
/* rc5 frame structure */
|
||||
typedef struct
|
||||
{
|
||||
__IO uint8_t field_bit; /*!< field bit */
|
||||
__IO uint8_t toggle_bit; /*!< toggle bit field */
|
||||
__IO uint8_t address; /*!< address field */
|
||||
__IO uint8_t command; /*!< command field */
|
||||
} rc5_frame_struct;
|
||||
|
||||
/* rc5 packet structure */
|
||||
typedef struct
|
||||
{
|
||||
__IO uint16_t data; /*!< rc5 data */
|
||||
__IO uint8_t status; /*!< rc5 status */
|
||||
__IO uint8_t last_bit; /*!< rc5 last bit */
|
||||
__IO uint8_t bit_count; /*!< rc5 bit count */
|
||||
} trc5_packet_struct;
|
||||
|
||||
/* rc5 last bit type enum */
|
||||
enum rc5_last_bit_type
|
||||
{
|
||||
RC5_ZER,
|
||||
RC5_ONE,
|
||||
RC5_NAN,
|
||||
RC5_INV
|
||||
};
|
||||
|
||||
typedef enum rc5_last_bit_type trc5_last_bit_type;
|
||||
|
||||
#define RC5_1T_TIME 0x00
|
||||
#define RC5_2T_TIME 0x01
|
||||
#define RC5_WRONG_TIME 0xFF
|
||||
#define RC5_TIME_OUT_US 3600
|
||||
|
||||
/* half bit period */
|
||||
#define RC5_T_US 900
|
||||
|
||||
/* tolerance time */
|
||||
#define RC5_T_TOLERANCE_US 270
|
||||
#define RC5_NUMBER_OF_VALID_PULSE_LENGTH 2
|
||||
|
||||
/* total bits */
|
||||
#define RC5_PACKET_BIT_COUNT 13
|
||||
|
||||
/* packet struct for reception */
|
||||
#define RC5_PACKET_STATUS_EMPTY (uint16_t)(1<<0)
|
||||
|
||||
void menu_rc5decode_func(void);
|
||||
void rc5_decode_deinit(void);
|
||||
void rc5_decode_init(void);
|
||||
void rc5_decode(rc5_frame_struct *rc5_frame);
|
||||
void rc5_reset_packet(void);
|
||||
void rc5_data_sampling(uint16_t raw_pulse_length, uint8_t edge);
|
||||
|
||||
#endif /* RC5_DECODE_H */
|
||||
289
NSPE/Example/IFRP/RC5_code/rc5_encode.c
Normal file
289
NSPE/Example/IFRP/RC5_code/rc5_encode.c
Normal file
@ -0,0 +1,289 @@
|
||||
/*!
|
||||
\file rc5_encode.c
|
||||
\brief the rc5 infrared encoder file
|
||||
|
||||
\version 2021-10-30, V1.0.0, firmware for GD32W51x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2021, GigaDevice Semiconductor Inc.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "rc5_encode.h"
|
||||
#include "ir_decode.h"
|
||||
|
||||
/* rc5 high level definition*/
|
||||
#define RC5_HIGH_STATE ((uint8_t)0x02)
|
||||
/* rc5 low level definition*/
|
||||
#define RC5_LOW_STATE ((uint8_t)0x01)
|
||||
|
||||
rc5_ctrl_enum rc5_ctrl1 = RC5_CTRL_RESET;
|
||||
|
||||
uint8_t rc5_real_frame_length = 14;
|
||||
uint8_t rc5_global_frame_length = 64;
|
||||
uint16_t rc5_frame_binary_format = 0;
|
||||
uint32_t rc5_frame_manchester_format = 0;
|
||||
uint8_t send_operation_ready = 0;
|
||||
__IO uint8_t send_operation_completed = 1;
|
||||
uint8_t bits_sent_counter = 0;
|
||||
|
||||
uint8_t address_index = 0;
|
||||
uint8_t instruction_index = 0;
|
||||
|
||||
static uint16_t rc5_bin_frame_generation(uint8_t rc5_address, uint8_t rc5_instruction, rc5_ctrl_enum rc5_ctrl);
|
||||
static uint32_t rc5_manchester_convert(uint16_t rc5_binary_frame_format);
|
||||
|
||||
/*!
|
||||
\brief init hardware (ips used) for rc5 generation
|
||||
\param[in] none
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rc5_encode_init( void )
|
||||
{
|
||||
timer_oc_parameter_struct timer_ocintpara;
|
||||
timer_parameter_struct timer_initpara;
|
||||
|
||||
rcu_timer_clock_prescaler_config(RCU_TIMER_PSC_MUL4);
|
||||
|
||||
/* TIMER15 clock enable */
|
||||
rcu_periph_clock_enable(RCU_TIMER15);
|
||||
/* TIMER16 clock enable */
|
||||
rcu_periph_clock_enable(RCU_TIMER16);
|
||||
|
||||
{
|
||||
/* IR_encode */
|
||||
/* PB5 IR_OUT pin configuration: output */
|
||||
gpio_af_set(GPIOB, GPIO_AF_0, GPIO_PIN_5);
|
||||
gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5);
|
||||
gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO_PIN_5);
|
||||
}
|
||||
|
||||
{
|
||||
{
|
||||
/* deinit TIMER16 */
|
||||
timer_deinit(TIMER16);
|
||||
|
||||
/* time base = 36Khz */
|
||||
/* time base configuration for TIMER16 */
|
||||
timer_initpara.prescaler = 0x01;
|
||||
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
|
||||
timer_initpara.counterdirection = TIMER_COUNTER_UP;
|
||||
timer_initpara.period = 2499;
|
||||
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
|
||||
timer_initpara.repetitioncounter = 0;
|
||||
timer_init(TIMER16,&timer_initpara);
|
||||
|
||||
/* prescaler configuration */
|
||||
timer_prescaler_config(TIMER16,0x01,TIMER_PSC_RELOAD_NOW);
|
||||
|
||||
/* output compare timing mode configuration: channel 0N */
|
||||
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
|
||||
timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
|
||||
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
|
||||
timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_LOW;
|
||||
timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
|
||||
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
|
||||
timer_channel_output_config(TIMER16,TIMER_CH_0,&timer_ocintpara);
|
||||
|
||||
timer_channel_output_pulse_value_config(TIMER16,TIMER_CH_0,(2500/4-1));
|
||||
timer_channel_output_mode_config(TIMER16,TIMER_CH_0,TIMER_OC_MODE_PWM1);
|
||||
timer_channel_output_shadow_config(TIMER16,TIMER_CH_0,TIMER_OC_SHADOW_ENABLE);
|
||||
|
||||
/* TIMER16 enable */
|
||||
timer_enable(TIMER16);
|
||||
/* enable the TIMER16 channel1 output to be connected internly to the IRTIMER */
|
||||
timer_primary_output_config(TIMER16,ENABLE);
|
||||
}
|
||||
|
||||
{
|
||||
/* deinit TIMER15 */
|
||||
timer_deinit(TIMER15);
|
||||
|
||||
/* elementary period 889 us */
|
||||
/* time base configuration for TIMER15 */
|
||||
timer_initpara.prescaler = 4;
|
||||
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
|
||||
timer_initpara.counterdirection = TIMER_COUNTER_UP;
|
||||
timer_initpara.period = 64008 /2 - 1;
|
||||
timer_initpara.clockdivision = 0;
|
||||
timer_initpara.repetitioncounter = 0;
|
||||
timer_init(TIMER15,&timer_initpara);
|
||||
|
||||
/* duty cycle = 25% */
|
||||
/* channel 1 configuration in timing mode */
|
||||
timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
|
||||
timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
|
||||
timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
|
||||
timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
|
||||
timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
|
||||
timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
|
||||
timer_channel_output_config(TIMER15,TIMER_CH_0,&timer_ocintpara);
|
||||
|
||||
timer_channel_output_pulse_value_config(TIMER15,TIMER_CH_0,(64008 /2 /4));
|
||||
timer_channel_output_mode_config(TIMER15,TIMER_CH_0,TIMER_OC_MODE_TIMING);
|
||||
|
||||
/* enable the TIMER15 interrupt */
|
||||
// nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
|
||||
nvic_irq_enable(TIMER15_IRQn, 0, 0);
|
||||
|
||||
/* TIMER15 main output enable */
|
||||
timer_primary_output_config(TIMER15,ENABLE);
|
||||
/* TIMER15 INT disable */
|
||||
timer_interrupt_disable(TIMER15,TIMER_INT_UP);
|
||||
/* TIMER15 disable */
|
||||
timer_disable(TIMER15);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief generate and send the rc5 frame
|
||||
\param[in] rc5_address: the rc5 device destination
|
||||
\param[in] rc5_instruction: the rc5 command instruction
|
||||
\param[in] rc5_ctrl: the rc5 control bit
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rc5_encode_send_frame(uint8_t rc5_address, uint8_t rc5_instruction, rc5_ctrl_enum rc5_ctrl)
|
||||
{
|
||||
uint16_t rc5_frame_binary_format = 0;
|
||||
|
||||
/* generate a binary format of the frame */
|
||||
rc5_frame_binary_format = rc5_bin_frame_generation(rc5_address, rc5_instruction, rc5_ctrl);
|
||||
|
||||
/* generate a manchester format of the frame */
|
||||
rc5_frame_manchester_format = rc5_manchester_convert(rc5_frame_binary_format);
|
||||
|
||||
/* set the send operation ready flag to indicate that the frame is ready to be sent */
|
||||
send_operation_ready = 1;
|
||||
|
||||
/* TIMER15 INT enable */
|
||||
timer_interrupt_enable(TIMER15,TIMER_INT_UP);
|
||||
|
||||
/* enable TIMER15 */
|
||||
timer_enable(TIMER15);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief send by hardware manchester format rc5 frame
|
||||
\param[in] rc5_manchester_frame_format: the rc5 frame in manchester format
|
||||
\param[out] none
|
||||
\retval none
|
||||
*/
|
||||
void rc5_encode_signal_generate( uint32_t rc5_manchester_frame_format )
|
||||
{
|
||||
uint8_t bit_msg = 0;
|
||||
|
||||
if((1 == send_operation_ready ) && ((rc5_global_frame_length * 2) >= bits_sent_counter)){
|
||||
send_operation_completed = 0x00;
|
||||
bit_msg = (uint8_t)((rc5_manchester_frame_format >> bits_sent_counter) & 1);
|
||||
|
||||
if(1 == bit_msg){
|
||||
timer_channel_output_mode_config(TIMER15, TIMER_CH_0, TIMER_OC_MODE_HIGH);
|
||||
}else{
|
||||
timer_channel_output_mode_config(TIMER15, TIMER_CH_0, TIMER_OC_MODE_LOW);
|
||||
}
|
||||
bits_sent_counter++;
|
||||
}else{
|
||||
send_operation_completed = 0x01;
|
||||
|
||||
/* TIMER15 INT disable */
|
||||
timer_interrupt_disable(TIMER15, TIMER_INT_UP);
|
||||
timer_disable(TIMER15);
|
||||
|
||||
send_operation_ready = 0;
|
||||
bits_sent_counter = 0;
|
||||
timer_channel_output_mode_config(TIMER15, TIMER_CH_0, TIMER_OC_MODE_LOW);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief generate the binary format of the rc5 frame
|
||||
\param[in] rc5_address: select the device adress
|
||||
\param[in] rc5_instruction: select the device instruction
|
||||
\param[in] rc5_ctrl: select the device control bit status
|
||||
\param[out] none
|
||||
\retval binary format of the rc5 frame
|
||||
*/
|
||||
static uint16_t rc5_bin_frame_generation(uint8_t rc5_address, uint8_t rc5_instruction, rc5_ctrl_enum rc5_ctrl)
|
||||
{
|
||||
uint16_t star1 = 0x2000;
|
||||
uint16_t star2 = 0x1000;
|
||||
uint16_t addr = 0;
|
||||
|
||||
while(0x00 == send_operation_completed);
|
||||
|
||||
/* check if instruction is 128-bit length */
|
||||
if(64 <= rc5_instruction){
|
||||
/* reset field bit: command is 7-bit length */
|
||||
star2 = 0;
|
||||
/* keep the lowest 6 bits of the command */
|
||||
rc5_instruction &= 0x003F;
|
||||
}
|
||||
/* instruction is 64-bit length */
|
||||
else{
|
||||
/* set field bit: command is 6-bit length */
|
||||
star2 = 0x1000;
|
||||
}
|
||||
|
||||
send_operation_ready = 0;
|
||||
rc5_frame_manchester_format = 0;
|
||||
rc5_frame_binary_format = 0;
|
||||
addr = ((uint16_t)(rc5_address))<<6;
|
||||
rc5_frame_binary_format = (star1) | (star2) | (rc5_ctrl) | (addr) | (rc5_instruction);
|
||||
return(rc5_frame_binary_format);
|
||||
}
|
||||
|
||||
/*!
|
||||
\brief convert the rc5 frame from binary to manchester format
|
||||
\param[in] rc5_binary_frame_format: the rc5 frame in binary format
|
||||
\param[out] none
|
||||
\retval the rc5 frame in manchester format
|
||||
*/
|
||||
static uint32_t rc5_manchester_convert(uint16_t rc5_binary_frame_format)
|
||||
{
|
||||
uint8_t i=0;
|
||||
uint16_t mask = 1;
|
||||
uint16_t bit_format = 0;
|
||||
uint32_t converted_msg =0;
|
||||
|
||||
for(i = 0; i < rc5_real_frame_length; i++){
|
||||
bit_format = ((((uint16_t)(rc5_binary_frame_format))>>i)& mask)<<i;
|
||||
converted_msg = converted_msg << 2;
|
||||
|
||||
if(0 != bit_format){
|
||||
/* manchester 1 -|_ */
|
||||
converted_msg |= RC5_HIGH_STATE;
|
||||
}else{
|
||||
/* manchester 0 _|- */
|
||||
converted_msg |= RC5_LOW_STATE;
|
||||
}
|
||||
}
|
||||
return(converted_msg);
|
||||
}
|
||||
55
NSPE/Example/IFRP/RC5_code/rc5_encode.h
Normal file
55
NSPE/Example/IFRP/RC5_code/rc5_encode.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*!
|
||||
\file rc5_encode.h
|
||||
\brief the header file of rc5 infrared encoder
|
||||
|
||||
\version 2021-10-30, V1.0.0, firmware for GD32W51x
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2021, GigaDevice Semiconductor Inc.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef RC5_ENCODE_H
|
||||
#define RC5_ENCODE_H
|
||||
|
||||
#include "gd32w51x.h"
|
||||
|
||||
/* definition of the rc5 control bit value */
|
||||
typedef enum
|
||||
{
|
||||
RC5_CTRL_RESET = ((uint16_t)0),
|
||||
RC5_CTRL_SET = ((uint16_t)0x0800)
|
||||
}rc5_ctrl_enum;
|
||||
|
||||
void menu_rc5_encode_func(void);
|
||||
void rc5_encode_init(void);
|
||||
void rc5_encode_send_frame(uint8_t rc5_address, uint8_t rc5_instruction, rc5_ctrl_enum rc5_ctrl);
|
||||
void rc5_encode_signal_generate(uint32_t rc5_manchester_frame_format);
|
||||
|
||||
#endif /*RC5_ENCODE_H */
|
||||
Reference in New Issue
Block a user