rc5_encode.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. /*!
  2. \file rc5_encode.c
  3. \brief the rc5 infrared encoder file
  4. */
  5. /*
  6. Copyright (C) 2017 GigaDevice
  7. 2017-06-06, V1.0.0, firmware for GD32F3x0
  8. */
  9. #include "rc5_encode.h"
  10. #include "ir_decode.h"
  11. /* rc5 high level definition*/
  12. #define RC5_HIGH_STATE ((uint8_t)0x02)
  13. /* rc5 low level definition*/
  14. #define RC5_LOW_STATE ((uint8_t)0x01)
  15. rc5_ctrl_enum rc5_ctrl1 = RC5_CTRL_RESET;
  16. uint8_t rc5_real_frame_length = 14;
  17. uint8_t rc5_global_frame_length = 64;
  18. uint16_t rc5_frame_binary_format = 0;
  19. uint32_t rc5_frame_manchester_format = 0;
  20. uint8_t send_operation_ready = 0;
  21. __IO uint8_t send_operation_completed = 1;
  22. uint8_t bits_sent_counter = 0;
  23. uint8_t address_index = 0;
  24. uint8_t instruction_index = 0;
  25. static uint16_t rc5_bin_frame_generation(uint8_t rc5_address, uint8_t rc5_instruction, rc5_ctrl_enum rc5_ctrl);
  26. static uint32_t rc5_manchester_convert(uint16_t rc5_binary_frame_format);
  27. /*!
  28. \brief init hardware (ips used) for rc5 generation
  29. \param[in] none
  30. \param[out] none
  31. \retval none
  32. */
  33. void rc5_encode_init( void )
  34. {
  35. timer_oc_parameter_struct timer_ocintpara;
  36. timer_parameter_struct timer_initpara;
  37. /* TIMER15 clock enable */
  38. rcu_periph_clock_enable(RCU_TIMER15);
  39. /* TIMER16 clock enable */
  40. rcu_periph_clock_enable(RCU_TIMER16);
  41. {
  42. /* IR_encode */
  43. /* PB9 IR_OUT pin configuration: output */
  44. gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
  45. gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);
  46. gpio_af_set(GPIOB, GPIO_AF_0, GPIO_PIN_9);
  47. }
  48. {
  49. {
  50. /* deinit TIMER16 */
  51. timer_deinit(TIMER16);
  52. /* time base = 36Khz */
  53. /* time base configuration for TIMER16 */
  54. timer_initpara.prescaler = 0x00;
  55. timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
  56. timer_initpara.counterdirection = TIMER_COUNTER_UP;
  57. timer_initpara.period = 2999;
  58. timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
  59. timer_initpara.repetitioncounter = 0;
  60. timer_init(TIMER16,&timer_initpara);
  61. /* prescaler configuration */
  62. timer_prescaler_config(TIMER16,0,TIMER_PSC_RELOAD_NOW);
  63. /* output compare timing mode configuration: channel 0N */
  64. timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
  65. timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
  66. timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
  67. timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_LOW;
  68. timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
  69. timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
  70. timer_channel_output_config(TIMER16,TIMER_CH_0,&timer_ocintpara);
  71. timer_channel_output_pulse_value_config(TIMER16,TIMER_CH_0,(3000/4-1));
  72. timer_channel_output_mode_config(TIMER16,TIMER_CH_0,TIMER_OC_MODE_PWM1);
  73. timer_channel_output_shadow_config(TIMER16,TIMER_CH_0,TIMER_OC_SHADOW_ENABLE);
  74. /* TIMER16 enable */
  75. timer_enable(TIMER16);
  76. /* enable the TIMER16 channel1 output to be connected internly to the IRTIMER */
  77. timer_primary_output_config(TIMER16,ENABLE);
  78. }
  79. {
  80. /* deinit TIMER15 */
  81. timer_deinit(TIMER15);
  82. /* elementary period 889 us */
  83. /* time base configuration for TIMER15 */
  84. timer_initpara.prescaler = 1;
  85. timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
  86. timer_initpara.counterdirection = TIMER_COUNTER_UP;
  87. timer_initpara.period = 96012 /2 - 1;
  88. timer_initpara.clockdivision = 0;
  89. timer_initpara.repetitioncounter = 0;
  90. timer_init(TIMER15,&timer_initpara);
  91. /* duty cycle = 25% */
  92. /* channel 1 configuration in timing mode */
  93. timer_ocintpara.outputstate = TIMER_CCX_ENABLE;
  94. timer_ocintpara.outputnstate = TIMER_CCXN_DISABLE;
  95. timer_ocintpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
  96. timer_ocintpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
  97. timer_ocintpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
  98. timer_ocintpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
  99. timer_channel_output_config(TIMER15,TIMER_CH_0,&timer_ocintpara);
  100. timer_channel_output_pulse_value_config(TIMER15,TIMER_CH_0,(96012 /2 /4));
  101. timer_channel_output_mode_config(TIMER15,TIMER_CH_0,TIMER_OC_MODE_TIMING);
  102. /* enable the TIMER15 interrupt */
  103. nvic_priority_group_set(NVIC_PRIGROUP_PRE0_SUB4);
  104. nvic_irq_enable(TIMER15_IRQn, 0, 0);
  105. /* TIMER15 main output enable */
  106. timer_primary_output_config(TIMER15,ENABLE);
  107. /* TIMER15 INT disable */
  108. timer_interrupt_disable(TIMER15,TIMER_INT_UP);
  109. /* TIMER15 disable */
  110. timer_disable(TIMER15);
  111. }
  112. }
  113. }
  114. /*!
  115. \brief generate and send the rc5 frame
  116. \param[in] rc5_address: the rc5 device destination
  117. \param[in] rc5_instruction: the rc5 command instruction
  118. \param[in] rc5_ctrl: the rc5 control bit
  119. \param[out] none
  120. \retval none
  121. */
  122. void rc5_encode_send_frame(uint8_t rc5_address, uint8_t rc5_instruction, rc5_ctrl_enum rc5_ctrl)
  123. {
  124. uint16_t rc5_frame_binary_format = 0;
  125. /* generate a binary format of the frame */
  126. rc5_frame_binary_format = rc5_bin_frame_generation(rc5_address, rc5_instruction, rc5_ctrl);
  127. /* generate a manchester format of the frame */
  128. rc5_frame_manchester_format = rc5_manchester_convert(rc5_frame_binary_format);
  129. /* set the send operation ready flag to indicate that the frame is ready to be sent */
  130. send_operation_ready = 1;
  131. /* TIMER15 INT enable */
  132. timer_interrupt_enable(TIMER15,TIMER_INT_UP);
  133. /* enable TIMER15 */
  134. timer_enable(TIMER15);
  135. }
  136. /*!
  137. \brief send by hardware manchester format rc5 frame
  138. \param[in] rc5_manchester_frame_format: the rc5 frame in manchester format
  139. \param[out] none
  140. \retval none
  141. */
  142. void rc5_encode_signal_generate( uint32_t rc5_manchester_frame_format )
  143. {
  144. uint8_t bit_msg = 0;
  145. if((1 == send_operation_ready ) && ((rc5_global_frame_length * 2) >= bits_sent_counter)){
  146. send_operation_completed = 0x00;
  147. bit_msg = (uint8_t)((rc5_manchester_frame_format >> bits_sent_counter) & 1);
  148. if(1 == bit_msg){
  149. timer_channel_output_mode_config(TIMER15, TIMER_CH_0, TIMER_OC_MODE_HIGH);
  150. }else{
  151. timer_channel_output_mode_config(TIMER15, TIMER_CH_0, TIMER_OC_MODE_LOW);
  152. }
  153. bits_sent_counter++;
  154. }else{
  155. send_operation_completed = 0x01;
  156. /* TIMER15 INT disable */
  157. timer_interrupt_disable(TIMER15, TIMER_INT_UP);
  158. timer_disable(TIMER15);
  159. send_operation_ready = 0;
  160. bits_sent_counter = 0;
  161. timer_channel_output_mode_config(TIMER15, TIMER_CH_0, TIMER_OC_MODE_LOW);
  162. }
  163. }
  164. /*!
  165. \brief generate the binary format of the rc5 frame
  166. \param[in] rc5_address: select the device adress
  167. \param[in] rc5_instruction: select the device instruction
  168. \param[in] rc5_ctrl: select the device control bit status
  169. \param[out] none
  170. \retval binary format of the rc5 frame
  171. */
  172. static uint16_t rc5_bin_frame_generation(uint8_t rc5_address, uint8_t rc5_instruction, rc5_ctrl_enum rc5_ctrl)
  173. {
  174. uint16_t star1 = 0x2000;
  175. uint16_t star2 = 0x1000;
  176. uint16_t addr = 0;
  177. while(0x00 == send_operation_completed);
  178. /* check if instruction is 128-bit length */
  179. if(64 <= rc5_instruction){
  180. /* reset field bit: command is 7-bit length */
  181. star2 = 0;
  182. /* keep the lowest 6 bits of the command */
  183. rc5_instruction &= 0x003F;
  184. }
  185. /* instruction is 64-bit length */
  186. else{
  187. /* set field bit: command is 6-bit length */
  188. star2 = 0x1000;
  189. }
  190. send_operation_ready = 0;
  191. rc5_frame_manchester_format = 0;
  192. rc5_frame_binary_format = 0;
  193. addr = ((uint16_t)(rc5_address))<<6;
  194. rc5_frame_binary_format = (star1) | (star2) | (rc5_ctrl) | (addr) | (rc5_instruction);
  195. return(rc5_frame_binary_format);
  196. }
  197. /*!
  198. \brief convert the rc5 frame from binary to manchester format
  199. \param[in] rc5_binary_frame_format: the rc5 frame in binary format
  200. \param[out] none
  201. \retval the rc5 frame in manchester format
  202. */
  203. static uint32_t rc5_manchester_convert(uint16_t rc5_binary_frame_format)
  204. {
  205. uint8_t i=0;
  206. uint16_t mask = 1;
  207. uint16_t bit_format = 0;
  208. uint32_t converted_msg =0;
  209. for(i = 0; i < rc5_real_frame_length; i++){
  210. bit_format = ((((uint16_t)(rc5_binary_frame_format))>>i)& mask)<<i;
  211. converted_msg = converted_msg << 2;
  212. if(0 != bit_format){
  213. /* manchester 1 -|_ */
  214. converted_msg |= RC5_HIGH_STATE;
  215. }else{
  216. /* manchester 0 _|- */
  217. converted_msg |= RC5_LOW_STATE;
  218. }
  219. }
  220. return(converted_msg);
  221. }