Files
SDK_GD32W51x/NSPE/Example/IFRP/RC5_code/rc5_encode.c
2023-05-18 18:53:00 +08:00

290 lines
11 KiB
C

/*!
\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);
}