rc5_decode.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. /*!
  2. \file rc5_decode.c
  3. \brief the rc5 infrared decoding file
  4. */
  5. /*
  6. Copyright (C) 2017 GigaDevice
  7. 2017-06-06, V1.0.0, firmware for GD32F3x0
  8. */
  9. #include "rc5_decode.h"
  10. #include "ir_decode.h"
  11. /* logic table for rising edge: every line has values corresponding to previous bit.
  12. in columns are actual bit values for given bit time. */
  13. const trc5_last_bit_type rc5_logic_table_rising_edge[2][2] =
  14. {
  15. /* last_bit = ZERO */
  16. {RC5_ZER ,RC5_INV},
  17. /* last_bit = ONE */
  18. {RC5_NAN ,RC5_ZER},
  19. };
  20. /* logic table for falling edge: every line has values corresponding to previous bit.
  21. in columns are actual bit values for given bit time. */
  22. const trc5_last_bit_type rc5_logic_table_falling_edge[2][2] =
  23. {
  24. /* last_bit = ZERO */
  25. {RC5_NAN ,RC5_ONE},
  26. /* last_bit = ONE */
  27. {RC5_ONE ,RC5_INV},
  28. };
  29. /* rc5 frame state */
  30. __IO status_yes_or_no rc5_frame_received = NO;
  31. /* first empty packet */
  32. __IO trc5_packet_struct rc5_tmp_packet;
  33. /* rc5 bits time definitions */
  34. uint16_t rc5_mint = 0;
  35. uint16_t rc5_maxt = 0;
  36. uint16_t rc5_min2t = 0;
  37. uint16_t rc5_max2t = 0;
  38. uint32_t rc5_data = 0;
  39. /* timer clock */
  40. static uint32_t timer_clk_value_khz = 0;
  41. static uint8_t rc5_get_pulse_length (uint16_t pulse_length);
  42. static void rc5_modify_last_bit(trc5_last_bit_type bit);
  43. static void rc5_write_bit(uint8_t bit_val);
  44. static uint32_t timer_get_counter_clk_value(void);
  45. /*!
  46. \brief de-initializes the peripherals
  47. \param[in] none
  48. \param[out] none
  49. \retval none
  50. */
  51. void rc5_decode_deinit(void)
  52. {
  53. timer_deinit(IR_TIMER);
  54. gpio_deinit(IR_GPIO_PORT);
  55. }
  56. /*!
  57. \brief initialize the rc5 decoder module
  58. \param[in] none
  59. \param[out] none
  60. \retval none
  61. */
  62. void rc5_decode_init(void)
  63. {
  64. __IO uint16_t rc5_time_out = 0;
  65. /* clock configuration for TIMER */
  66. rcu_periph_clock_enable(IR_TIMER_CLK);
  67. /* enable GPIO clock */
  68. rcu_periph_clock_enable(IR_GPIO_PORT_CLK);
  69. /* IR_decode */
  70. /* GD32330R-EVAL:TIMER2_CH0 PC6
  71. GD32350R-EVAL:TIMER2_CH1 PA7
  72. */
  73. {
  74. /* configure the GPIO ports */
  75. gpio_mode_set(IR_GPIO_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, IR_GPIO_PIN);
  76. gpio_output_options_set(IR_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,IR_GPIO_PIN);
  77. }
  78. /* enable the TIMER global interrupt */
  79. nvic_irq_enable(IR_TIMER_IRQn, 0, 1);
  80. {
  81. timer_ic_parameter_struct timer_icinitpara;
  82. timer_parameter_struct timer_initpara;
  83. /* deinit IR_TIMER */
  84. rcu_periph_clock_enable(IR_TIMER_CLK);
  85. /* TIMER0 configuration */
  86. timer_deinit(IR_TIMER);
  87. /* timer base configuration for timer IR_TIMER */
  88. timer_initpara.prescaler = 0x0;
  89. timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
  90. timer_initpara.counterdirection = TIMER_COUNTER_UP;
  91. timer_initpara.period = 0x00;
  92. timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
  93. timer_initpara.repetitioncounter = 0;
  94. timer_init(IR_TIMER,&timer_initpara);
  95. /* prescaler configuration */
  96. timer_prescaler_config(IR_TIMER,TIMER_PRESCALER,TIMER_PSC_RELOAD_NOW);
  97. /* TIMER2 CH0 input capture configuration */
  98. timer_icinitpara.icpolarity = TIMER_IC_POLARITY_FALLING;
  99. timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
  100. timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
  101. timer_icinitpara.icfilter = 0x0;
  102. timer_input_pwm_capture_config(IR_TIMER,IR_TIMER_Channel,&timer_icinitpara);
  103. }
  104. /* timer clock */
  105. timer_clk_value_khz = timer_get_counter_clk_value()/1000;
  106. /* select the TIMER input trigger */
  107. timer_input_trigger_source_select(IR_TIMER, TIMER_SMCFG_TRGSEL_CI0FE0);
  108. /* select the slave mode: reset mode */
  109. timer_slave_mode_select(IR_TIMER, TIMER_SLAVE_MODE_RESTART);
  110. /* configures the TIMER update request interrupt source: counter overflow */
  111. timer_update_source_config( IR_TIMER, TIMER_UPDATE_SRC_REGULAR );
  112. rc5_time_out = timer_clk_value_khz * RC5_TIME_OUT_US/1000;
  113. /* set the TIMER auto-reload register for each IR protocol */
  114. TIMER_CAR(IR_TIMER) = rc5_time_out;
  115. /* clear flag */
  116. timer_interrupt_flag_clear(IR_TIMER, TIMER_INT_UP | TIMER_INT_CH0 | TIMER_INT_CH1);
  117. /* enable the CH1 interrupt request */
  118. timer_interrupt_enable(IR_TIMER, TIMER_INT_CH1);
  119. /* enable the CH0 interrupt request */
  120. timer_interrupt_enable(IR_TIMER, TIMER_INT_CH0);
  121. /* enable the timer */
  122. timer_enable(IR_TIMER);
  123. /* bit time range */
  124. rc5_mint = ( RC5_T_US - RC5_T_TOLERANCE_US ) * timer_clk_value_khz / 1000 ;
  125. rc5_maxt = ( RC5_T_US + RC5_T_TOLERANCE_US ) * timer_clk_value_khz / 1000 ;
  126. rc5_min2t = ( 2 * RC5_T_US - RC5_T_TOLERANCE_US ) * timer_clk_value_khz / 1000 ;
  127. rc5_max2t = ( 2 * RC5_T_US + RC5_T_TOLERANCE_US ) * timer_clk_value_khz / 1000 ;
  128. /* default state */
  129. rc5_reset_packet();
  130. }
  131. /*!
  132. \brief decode the IR frame when all the frame is received, the rc5_frame_received will equal to YES
  133. \param[in] rc5_frame: pointer to rc5_frame_struct structure that contains the IR protocol fields
  134. \param[out] none
  135. \retval none
  136. */
  137. void rc5_decode(rc5_frame_struct *rc5_frame)
  138. {
  139. /* if frame received */
  140. if(rc5_frame_received != NO){
  141. rc5_data = rc5_tmp_packet.data ;
  142. /* rc5 frame field decoding */
  143. rc5_frame->address = (rc5_tmp_packet.data >> 6) & 0x1F;
  144. rc5_frame->command = (rc5_tmp_packet.data) & 0x3F;
  145. rc5_frame->field_bit = (rc5_tmp_packet.data >> 12) & 0x1;
  146. rc5_frame->toggle_bit = (rc5_tmp_packet.data >> 11) & 0x1;
  147. /* check if command ranges between 64 to 127:upper field */
  148. if(rc5_frame->field_bit == 0x00){
  149. rc5_frame->command = (1<<6)| rc5_frame->command;
  150. }
  151. /* default state */
  152. rc5_frame_received = NO;
  153. rc5_reset_packet();
  154. }
  155. }
  156. /*!
  157. \brief set the incoming packet structure to default state
  158. \param[in] none
  159. \param[out] none
  160. \retval none
  161. */
  162. void rc5_reset_packet(void)
  163. {
  164. rc5_tmp_packet.data = 0;
  165. rc5_tmp_packet.bit_count = RC5_PACKET_BIT_COUNT - 1;
  166. rc5_tmp_packet.last_bit = RC5_ONE;
  167. rc5_tmp_packet.status = RC5_PACKET_STATUS_EMPTY;
  168. }
  169. /*!
  170. \brief identify the rc5 data bits
  171. \param[in] raw_pulse_length: low/high pulse duration
  172. \param[in] edge: '1' for rising or '0' for falling edge
  173. \param[out] none
  174. \retval none
  175. */
  176. void rc5_data_sampling(uint16_t raw_pulse_length, uint8_t edge)
  177. {
  178. uint8_t pulse;
  179. trc5_last_bit_type tmp_last_bit;
  180. /* decode the pulse length in protocol units */
  181. pulse = rc5_get_pulse_length(raw_pulse_length);
  182. /* on rising edge */
  183. if(1 == edge){
  184. if(pulse <= RC5_2T_TIME){
  185. /* bit determination by the rising edge */
  186. tmp_last_bit = rc5_logic_table_rising_edge[rc5_tmp_packet.last_bit][pulse];
  187. rc5_modify_last_bit(tmp_last_bit);
  188. }else{
  189. rc5_reset_packet();
  190. }
  191. }
  192. /* on falling edge */
  193. else {
  194. /* if this is the first falling edge - don't compute anything */
  195. if(rc5_tmp_packet.status & RC5_PACKET_STATUS_EMPTY){
  196. rc5_tmp_packet.status &= (uint8_t)~RC5_PACKET_STATUS_EMPTY;
  197. }else{
  198. if(pulse <= RC5_2T_TIME){
  199. /* bit determination by the falling edge */
  200. tmp_last_bit = rc5_logic_table_falling_edge[rc5_tmp_packet.last_bit][pulse];
  201. rc5_modify_last_bit(tmp_last_bit);
  202. }else{
  203. rc5_reset_packet();
  204. }
  205. }
  206. }
  207. }
  208. /*!
  209. \brief convert raw pulse length expressed in timer ticks to protocol bit times
  210. \param[in] pulse_length: pulse duration
  211. \param[out] none
  212. \retval bit time value
  213. */
  214. static uint8_t rc5_get_pulse_length (uint16_t pulse_length)
  215. {
  216. /* valid bit time */
  217. if((pulse_length > rc5_mint) && (pulse_length < rc5_maxt)){
  218. /* found the length,return the correct value */
  219. return (RC5_1T_TIME);
  220. }else if((pulse_length > rc5_min2t) && (pulse_length < rc5_max2t)){
  221. /* found the length,return the correct value */
  222. return (RC5_2T_TIME);
  223. }
  224. /* error */
  225. return RC5_WRONG_TIME;
  226. }
  227. /*!
  228. \brief perform checks if the last bit was not incorrect
  229. \param[in] bit: where bit can be RC5_NAN or RC5_INV or RC5_ZER or RC5_ONE
  230. \param[out] none
  231. \retval none
  232. */
  233. static void rc5_modify_last_bit(trc5_last_bit_type bit)
  234. {
  235. if(RC5_NAN != bit){
  236. if(RC5_INV != rc5_tmp_packet.last_bit){
  237. /* restore the last bit */
  238. rc5_tmp_packet.last_bit = bit;
  239. /* insert one bit into the rc5 packet */
  240. rc5_write_bit(rc5_tmp_packet.last_bit);
  241. }else{
  242. rc5_reset_packet();
  243. }
  244. }
  245. }
  246. /*!
  247. \brief insert one bit into the final data word
  248. \param[in] bit_val: bit value 'RC5_ONE' or 'RC5_ZER'
  249. \param[out] none
  250. \retval none
  251. */
  252. static void rc5_write_bit(uint8_t bit_val)
  253. {
  254. /* first convert rc5 symbols to ones and zeros */
  255. if(bit_val == RC5_ONE){
  256. bit_val = 1;
  257. }else if(bit_val == RC5_ZER){
  258. bit_val = 0;
  259. }else{
  260. rc5_reset_packet();
  261. return;
  262. }
  263. /* write this particular bit to data field */
  264. rc5_tmp_packet.data |= bit_val;
  265. /* test the bit number determined */
  266. /* if this is not the last bit */
  267. if(0 != rc5_tmp_packet.bit_count){
  268. /* shift the data field */
  269. rc5_tmp_packet.data = rc5_tmp_packet.data << 1;
  270. /* decrement the bit_count */
  271. rc5_tmp_packet.bit_count--;
  272. }else{
  273. rc5_frame_received = YES;
  274. }
  275. }
  276. /*!
  277. \brief identify TIMER clock
  278. \param[in] none
  279. \param[out] none
  280. \retval timer clock
  281. */
  282. static uint32_t timer_get_counter_clk_value(void)
  283. {
  284. uint32_t apb_prescaler = 0, apb_frequency = 0;
  285. uint32_t timer_prescaler = 0;
  286. rcu_clock_freq_get(CK_APB1);
  287. /* get the clock prescaler of APB1 */
  288. apb_prescaler = ((RCU_CFG0>> 8) & 0x7);
  289. apb_frequency=rcu_clock_freq_get(CK_APB1);
  290. timer_prescaler = TIMER_PRESCALER;
  291. /* if APBx clock div >= 4 */
  292. if(apb_prescaler >= 4){
  293. return((apb_frequency * 2)/(timer_prescaler + 1));
  294. }else{
  295. return(apb_frequency/(timer_prescaler+ 1));
  296. }
  297. }