1 /*!
2     \file    gd32f3x0_cec.c
3     \brief   CEC driver
4 
5     \version 2017-06-06, V1.0.0, firmware for GD32F3x0
6     \version 2019-06-01, V2.0.0, firmware for GD32F3x0
7     \version 2020-09-30, V2.1.0, firmware for GD32F3x0
8 */
9 
10 /*
11     Copyright (c) 2020, GigaDevice Semiconductor Inc.
12 
13     Redistribution and use in source and binary forms, with or without modification,
14 are permitted provided that the following conditions are met:
15 
16     1. Redistributions of source code must retain the above copyright notice, this
17        list of conditions and the following disclaimer.
18     2. Redistributions in binary form must reproduce the above copyright notice,
19        this list of conditions and the following disclaimer in the documentation
20        and/or other materials provided with the distribution.
21     3. Neither the name of the copyright holder nor the names of its contributors
22        may be used to endorse or promote products derived from this software without
23        specific prior written permission.
24 
25     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 OF SUCH DAMAGE.
35 */
36 
37 #ifdef GD32F350
38 
39 #include "gd32f3x0_cec.h"
40 
41 /*!
42     \brief      reset HDMI-CEC controller
43     \param[in]  none
44     \param[out] none
45     \retval     none
46 */
cec_deinit(void)47 void cec_deinit(void)
48 {
49     rcu_periph_reset_enable(RCU_CECRST);
50     rcu_periph_reset_disable(RCU_CECRST);
51 }
52 
53 /*!
54     \brief      configure signal free time,the signal free time counter start option,own address
55     \param[in]  sftmopt: signal free time counter start option
56                 only one parameter can be selected which is shown as below:
57       \arg        CEC_SFT_START_STAOM: signal free time counter starts counting when STAOM is asserted
58       \arg        CEC_SFT_START_LAST: signal free time counter starts automatically after transmission/reception end
59     \param[in]  sft: signal free time
60                 only one parameter can be selected which is shown as below:
61       \arg        CEC_SFT_PROTOCOL_PERIOD: the signal free time will perform as HDMI-CEC protocol description
62       \arg        CEC_SFT_1POINT5_PERIOD: 1.5 nominal data bit periods
63       \arg        CEC_SFT_2POINT5_PERIOD: 2.5 nominal data bit periods
64       \arg        CEC_SFT_3POINT5_PERIOD: 3.5 nominal data bit periods
65       \arg        CEC_SFT_4POINT5_PERIOD: 4.5 nominal data bit periods
66       \arg        CEC_SFT_5POINT5_PERIOD: 5.5 nominal data bit periods
67       \arg        CEC_SFT_6POINT5_PERIOD: 6.5 nominal data bit periods
68       \arg        CEC_SFT_7POINT5_PERIOD: 7.5 nominal data bit periods
69     \param[in]  address: own address
70                 only one parameter can be selected which is shown as below:
71       \arg        CEC_OWN_ADDRESS_CLEAR: own address is cleared
72       \arg        CEC_OWN_ADDRESSx(x=0..14): own address is x
73     \param[out] none
74     \retval     none
75 */
cec_init(uint32_t sftmopt,uint32_t sft,uint32_t address)76 void cec_init(uint32_t sftmopt, uint32_t sft, uint32_t address)
77 {
78     uint32_t cfg;
79     cfg = CEC_CFG;
80     /* clear SFTMOPT bit,SFT[2:0] */
81     cfg &= ~(CEC_CFG_SFTOPT | CEC_CFG_SFT);
82     /* assign SFTMOPT bit,SFT[2:0] */
83     cfg |= (sftmopt | sft);
84     CEC_CFG = cfg;
85     if(CEC_OWN_ADDRESS_CLEAR == address){
86         CEC_CFG &= ~CEC_CFG_OAD;
87     }else{
88         CEC_CFG |= address;
89     }
90 }
91 
92 /*!
93     \brief      configure generate Error-bit when detected some abnormal situation or not,
94                 whether stop receive message when detected bit rising error
95     \param[in]  broadcast:
96                 only one parameter can be selected which is shown as below:
97       \arg        CEC_BROADCAST_ERROR_BIT_ON:generate Error-bit in broadcast
98       \arg        CEC_BROADCAST_ERROR_BIT_OFF:do not generate Error-bit in broadcast
99     \param[in]  singlecast_lbpe:
100                 only one parameter can be selected which is shown as below:
101       \arg        CEC_LONG_PERIOD_ERROR_BIT_ON:generate Error-bit on long bit period error
102       \arg        CEC_LONG_PERIOD_ERROR_BIT_OFF:do not generate Error-bit on long bit period error
103     \param[in]  singlecast_bre:
104                 only one parameter can be selected which is shown as below:
105       \arg        CEC_RISING_PERIOD_ERROR_BIT_ON:generate Error-bit on bit rising error
106       \arg        CEC_RISING_PERIOD_ERROR_BIT_OFF:do not generate Error-bit on bit rising error
107     \param[in]  rxbrestp:
108                 only one parameter can be selected which is shown as below:
109       \arg        CEC_STOP_RISING_ERROR_BIT_ON: stop reception when detected bit rising error
110       \arg        CEC_STOP_RISING_ERROR_BIT_OFF: do not stop reception when detected bit rising error
111     \param[out] none
112     \retval     none
113 */
cec_error_config(uint32_t broadcast,uint32_t singlecast_lbpe,uint32_t singlecast_bre,uint32_t rxbrestp)114 void cec_error_config(uint32_t broadcast, uint32_t singlecast_lbpe, uint32_t singlecast_bre, uint32_t rxbrestp)
115 {
116     uint32_t cfg;
117     cfg = CEC_CFG;
118     /* clear BCNG bit, BPLEG bit, BREG bit */
119     cfg &= ~(CEC_CFG_BCNG | CEC_CFG_BPLEG | CEC_CFG_BREG);
120     /* assign BCNG bit, BPLEG bit, BREG bit */
121     cfg |= (broadcast | singlecast_lbpe | singlecast_bre);
122     CEC_CFG = cfg;
123     if(CEC_STOP_RISING_ERROR_BIT_ON == rxbrestp){
124         CEC_CFG |= CEC_CFG_BRES;
125     }else{
126         CEC_CFG &= ~CEC_CFG_BRES;
127     }
128 }
129 
130 /*!
131     \brief      enable HDMI-CEC controller
132     \param[in]  none
133     \param[out] none
134     \retval     none
135 */
cec_enable(void)136 void cec_enable(void)
137 {
138     CEC_CTL |= CEC_CTL_CECEN;
139 }
140 
141 /*!
142     \brief      disable HDMI-CEC controller
143     \param[in]  none
144     \param[out] none
145     \retval     none
146 */
cec_disable(void)147 void cec_disable(void)
148 {
149     CEC_CTL &= ~CEC_CTL_CECEN;
150 }
151 
152 /*!
153     \brief      start CEC message transmission
154     \param[in]  none
155     \param[out] none
156     \retval     none
157 */
cec_transmission_start(void)158 void cec_transmission_start(void)
159 {
160     CEC_CTL |= CEC_CTL_STAOM;
161 }
162 
163 /*!
164     \brief      end CEC message transmission
165     \param[in]  none
166     \param[out] none
167     \retval     none
168 */
cec_transmission_end(void)169 void cec_transmission_end(void)
170 {
171     CEC_CTL |= CEC_CTL_ENDOM;
172 }
173 
174 /*!
175     \brief      enable CEC listen mode.
176     \param[in]  none
177     \param[out] none
178     \retval     none
179 */
cec_listen_mode_enable(void)180 void cec_listen_mode_enable(void)
181 {
182     CEC_CFG |= CEC_CFG_LMEN;
183 }
184 
185 /*!
186     \brief      disable CEC listen mode.
187     \param[in]  none
188     \param[out] none
189     \retval     none
190 */
cec_listen_mode_disable(void)191 void cec_listen_mode_disable(void)
192 {
193     CEC_CFG &= ~CEC_CFG_LMEN;
194 }
195 
196 /*!
197     \brief      configure and clear own address.the controller can be configured to multiple own address
198     \param[in]  address: own address
199                 one or more parameters can be selected which are shown as below:
200       \arg        CEC_OWN_ADDRESS_CLEAR: own address is cleared
201       \arg        CEC_OWN_ADDRESSx(x=0..14): own address is x
202     \param[out] none
203     \retval     none
204 */
cec_own_address_config(uint32_t address)205 void cec_own_address_config(uint32_t address)
206 {
207     if(CEC_OWN_ADDRESS_CLEAR == address){
208         CEC_CFG &= ~CEC_CFG_OAD;
209     } else {
210         CEC_CFG |= address;
211     }
212 }
213 
214 /*!
215     \brief      configure signal free time and the signal free time counter start option
216     \param[in]  sftmopt: signal free time counter start option
217                 only one parameter can be selected which is shown as below:
218       \arg        CEC_SFT_START_STAOM: signal free time counter starts counting when STAOM is asserted
219       \arg        CEC_SFT_START_LAST: signal free time counter starts automatically after transmission/reception end
220     \param[in]  sft: signal free time
221                 only one parameter can be selected which is shown as below:
222       \arg        CEC_SFT_PROTOCOL_PERIOD: the signal free time will perform as HDMI-CEC protocol description
223       \arg        CEC_SFT_1POINT5_PERIOD: 1.5 nominal data bit periods
224       \arg        CEC_SFT_2POINT5_PERIOD: 2.5 nominal data bit periods
225       \arg        CEC_SFT_3POINT5_PERIOD: 3.5 nominal data bit periods
226       \arg        CEC_SFT_4POINT5_PERIOD: 4.5 nominal data bit periods
227       \arg        CEC_SFT_5POINT5_PERIOD: 5.5 nominal data bit periods
228       \arg        CEC_SFT_6POINT5_PERIOD: 6.5 nominal data bit periods
229       \arg        CEC_SFT_7POINT5_PERIOD: 7.5 nominal data bit periods
230     \param[out] none
231     \retval     none
232 */
cec_sft_config(uint32_t sftmopt,uint32_t sft)233 void cec_sft_config(uint32_t sftmopt, uint32_t sft)
234 {
235     uint32_t cfg;
236     cfg = CEC_CFG;
237     /* clear SFTMOPT bit,SFT[2:0] */
238     cfg &= ~(CEC_CFG_SFTOPT | CEC_CFG_SFT);
239     /* assign SFTMOPT bit,SFT[2:0] */
240     cfg |= (sftmopt | sft);
241     CEC_CFG = cfg;
242 }
243 
244 /*!
245     \brief      configure generate Error-bit when detected some abnormal situation or not
246     \param[in]  broadcast:
247                 only one parameter can be selected which is shown as below:
248       \arg        CEC_BROADCAST_ERROR_BIT_ON:generate Error-bit in broadcast
249       \arg        CEC_BROADCAST_ERROR_BIT_OFF:do not generate Error-bit in broadcast
250     \param[in]  singlecast_lbpe:
251                 only one parameter can be selected which is shown as below:
252       \arg        CEC_LONG_PERIOD_ERROR_BIT_ON:generate Error-bit on long bit period error
253       \arg        CEC_LONG_PERIOD_ERROR_BIT_OFF:do not generate Error-bit on long bit period error
254     \param[in]  singlecast_bre:
255                 only one parameter can be selected which is shown as below:
256       \arg        CEC_RISING_PERIOD_ERROR_BIT_ON:generate Error-bit on bit rising error
257       \arg        CEC_RISING_PERIOD_ERROR_BIT_OFF:do not generate Error-bit on bit rising error
258     \param[out] none
259     \retval     none
260 */
cec_generate_errorbit_config(uint32_t broadcast,uint32_t singlecast_lbpe,uint32_t singlecast_bre)261 void cec_generate_errorbit_config(uint32_t broadcast, uint32_t singlecast_lbpe, uint32_t singlecast_bre)
262 {
263     uint32_t cfg;
264     cfg = CEC_CFG;
265     /* clear BCNG bit, RLBPEGEN bit, RBREGEN bit */
266     cfg &= ~(CEC_CFG_BCNG | CEC_CFG_BPLEG | CEC_CFG_BREG);
267     /* assign BCNG bit, RLBPEGEN bit, RBREGEN bit */
268     cfg |= (broadcast | singlecast_lbpe | singlecast_bre);
269     CEC_CFG = cfg;
270 }
271 
272 /*!
273     \brief      whether stop receive message when detected bit rising error
274     \param[in]  rxbrestp:
275                 only one parameter can be selected which is shown as below:
276       \arg        CEC_STOP_RISING_ERROR_BIT_ON: stop reception when detected bit rising error
277       \arg        CEC_STOP_RISING_ERROR_BIT_OFF: do not stop reception when detected bit rising error
278     \param[out] none
279     \retval     none
280 */
cec_stop_receive_bre_config(uint32_t rxbrestp)281 void cec_stop_receive_bre_config(uint32_t rxbrestp)
282 {
283     if(CEC_STOP_RISING_ERROR_BIT_ON == rxbrestp){
284         CEC_CFG |= CEC_CFG_BRES;
285     } else {
286         CEC_CFG &= ~CEC_CFG_BRES;
287     }
288 }
289 
290 /*!
291     \brief      enable reception bit timing tolerance
292     \param[in]  none
293     \param[out] none
294     \retval     none
295 */
cec_reception_tolerance_enable(void)296 void cec_reception_tolerance_enable(void)
297 {
298     CEC_CFG |= CEC_CFG_RTOL;
299 }
300 
301 /*!
302     \brief      disable reception bit timing tolerance
303     \param[in]  none
304     \param[out] none
305     \retval     none
306 */
cec_reception_tolerance_disable(void)307 void cec_reception_tolerance_disable(void)
308 {
309     CEC_CFG &= ~CEC_CFG_RTOL;
310 }
311 
312 /*!
313     \brief      send a data by the CEC peripheral
314     \param[in]  data: the data to transmit
315     \param[out] none
316     \retval     none
317 */
cec_data_send(uint8_t data)318 void cec_data_send(uint8_t data)
319 {
320     CEC_TDATA = (uint32_t)data;
321 }
322 
323 /*!
324     \brief      receive a data by the CEC peripheral
325     \param[in]  data: the data to receive
326     \param[out] none
327     \retval     none
328 */
cec_data_receive(void)329 uint8_t cec_data_receive(void)
330 {
331     return (uint8_t)CEC_RDATA;
332 }
333 
334 
335 /*!
336     \brief      enable interrupt
337     \param[in]  flag: specify which flag
338                 one or more parameters can be selected which are shown as below:
339       \arg        CEC_INT_BR: enable Rx-byte data received interrupt
340       \arg        CEC_INT_REND: enable end of reception interrupt
341       \arg        CEC_INT_RO: enable RX overrun interrupt
342       \arg        CEC_INT_BRE: enable bit rising error interrupt
343       \arg        CEC_INT_BPSE: enable short bit period error interrupt
344       \arg        CEC_INT_BPLE: enable long bit period error interrupt
345       \arg        CEC_INT_RAE: enable Rx ACK error interrupt
346       \arg        CEC_INT_ARBF: enable arbitration lost interrupt
347       \arg        CEC_INT_TBR: enable Tx-byte data request interrupt
348       \arg        CEC_INT_TEND: enable transmission successfully end interrupt
349       \arg        CEC_INT_TU: enable Tx data buffer underrun interrupt
350       \arg        CEC_INT_TERR: enable Tx-error interrupt
351       \arg        CEC_INT_TAERR: enable Tx ACK error interrupt
352     \param[out] none
353     \retval     none
354 */
cec_interrupt_enable(uint32_t flag)355 void cec_interrupt_enable(uint32_t flag)
356 {
357     CEC_INTEN |= flag;
358 }
359 
360 /*!
361     \brief      disable interrupt
362     \param[in]  flag: specify which flag
363                 one or more parameters can be selected which are shown as below:
364       \arg        CEC_INT_BR: disable Rx-byte data received interrupt
365       \arg        CEC_INT_REND: disable end of reception interrupt
366       \arg        CEC_INT_RO: disable RX overrun interrupt
367       \arg        CEC_INT_BRE: disable bit rising error interrupt
368       \arg        CEC_INT_BPSE: disable short bit period error interrupt
369       \arg        CEC_INT_BPLE: disable long bit period error interrupt
370       \arg        CEC_INT_RAE: disable Rx ACK error interrupt
371       \arg        CEC_INT_ARBF: disable arbitration lost interrupt
372       \arg        CEC_INT_TBR: disable Tx-byte data request interrupt
373       \arg        CEC_INT_TEND: disable transmission successfully end interrupt
374       \arg        CEC_INT_TU: disable Tx data buffer underrun interrupt
375       \arg        CEC_INT_TERR: disable Tx-error interrupt
376       \arg        CEC_INT_TAERR: disable Tx ACK error  interrupt
377 
378     \param[out] none
379     \retval     none
380 */
cec_interrupt_disable(uint32_t flag)381 void cec_interrupt_disable(uint32_t flag)
382 {
383     CEC_INTEN &= ~flag;
384 }
385 
386 
387 /*!
388     \brief      get CEC status
389     \param[in]  flag:  specify which flag
390                 one or more parameters can be selected which are shown as below:
391       \arg        CEC_FLAG_BR: Rx-byte data received
392       \arg        CEC_FLAG_REND: end of reception
393       \arg        CEC_FLAG_RO: RX overrun
394       \arg        CEC_FLAG_BRE: bit rising error
395       \arg        CEC_FLAG_BPSE: short bit period error
396       \arg        CEC_FLAG_BPLE: long bit period error
397       \arg        CEC_FLAG_RAE: Rx ACK error
398       \arg        CEC_FLAG_ARBF: arbitration lost
399       \arg        CEC_FLAG_TBR: Tx-byte data request
400       \arg        CEC_FLAG_TEND: transmission successfully end
401       \arg        CEC_FLAG_TU: Tx data buffer underrun
402       \arg        CEC_FLAG_TERR: Tx-error
403       \arg        CEC_FLAG_TAERR Tx ACK error flag
404     \param[out] none
405     \retval     FlagStatus: SET or RESET
406 */
cec_flag_get(uint32_t flag)407 FlagStatus cec_flag_get(uint32_t flag)
408 {
409     if(CEC_INTF & flag){
410         return SET;
411     }else{
412         return RESET;
413     }
414 }
415 
416 /*!
417     \brief      clear CEC status
418     \param[in]  flag:  specify which flag
419                 one or more parameters can be selected which are shown as below:
420       \arg        CEC_FLAG_BR: Rx-byte data received
421       \arg        CEC_FLAG_REND: end of reception
422       \arg        CEC_FLAG_RO: RX overrun
423       \arg        CEC_FLAG_BRE: bit rising error
424       \arg        CEC_FLAG_BPSE: short bit period error
425       \arg        CEC_FLAG_BPLE: long bit period error
426       \arg        CEC_FLAG_RAE: Rx ACK error
427       \arg        CEC_FLAG_ARBF: arbitration lost
428       \arg        CEC_FLAG_TBR: Tx-byte data request
429       \arg        CEC_FLAG_TEND: transmission successfully end
430       \arg        CEC_FLAG_TU: Tx data buffer underrun
431       \arg        CEC_FLAG_TERR: Tx-error
432       \arg        CEC_FLAG_TAERR: Tx ACK error flag
433 
434     \param[out] none
435     \retval     FlagStatus: SET or RESET
436 */
cec_flag_clear(uint32_t flag)437 void cec_flag_clear(uint32_t flag)
438 {
439     CEC_INTF |= flag;
440 }
441 
442 /*!
443     \brief      get CEC int flag and status
444     \param[in]  flag:  specify which flag
445                 one or more parameters can be selected which are shown as below:
446       \arg        CEC_INT_FLAG_BR: Rx-byte data received
447       \arg        CEC_INT_FLAG_REND: end of reception
448       \arg        CEC_INT_FLAG_RO: RX overrun
449       \arg        CEC_INT_FLAG_BRE: bit rising error
450       \arg        CEC_INT_FLAG_BPSE: short bit period error
451       \arg        CEC_INT_FLAG_BPLE: long bit period error
452       \arg        CEC_INT_FLAG_RAE: Rx ACK error
453       \arg        CEC_INT_FLAG_ARBF: arbitration lost
454       \arg        CEC_INT_FLAG_TBR: Tx-byte data request
455       \arg        CEC_INT_FLAG_TEND: transmission successfully end
456       \arg        CEC_INT_FLAG_TU: Tx data buffer underrun
457       \arg        CEC_INT_FLAG_TERR: Tx-error
458       \arg        CEC_INT_FLAG_TAERR: Tx ACK error flag
459     \param[out] none
460     \retval     FlagStatus: SET or RESET
461 */
cec_interrupt_flag_get(uint32_t flag)462 FlagStatus cec_interrupt_flag_get(uint32_t flag)
463 {
464     uint32_t interrupt_enable = 0U,interrupt_flag = 0U;
465     interrupt_flag = (CEC_INTF & flag);
466     interrupt_enable = (CEC_INTEN & flag);
467     if(interrupt_flag && interrupt_enable){
468         return SET;
469     }else{
470         return RESET;
471     }
472 }
473 
474 /*!
475     \brief      clear CEC int flag and status
476     \param[in]  flag:  specify which flag
477                 one or more parameters can be selected which are shown as below:
478       \arg        CEC_INT_FLAG_BR: Rx-byte data received
479       \arg        CEC_INT_FLAG_REND: end of reception
480       \arg        CEC_INT_FLAG_RO: RX overrun
481       \arg        CEC_INT_FLAG_BRE: bit rising error
482       \arg        CEC_INT_FLAG_BPSE: short bit period error
483       \arg        CEC_INT_FLAG_BPLE: long bit period error
484       \arg        CEC_INT_FLAG_RAE: Rx ACK error
485       \arg        CEC_INT_FLAG_ARBF: arbitration lost
486       \arg        CEC_INT_FLAG_TBR: Tx-byte data request
487       \arg        CEC_INT_FLAG_TEND: transmission successfully end
488       \arg        CEC_INT_FLAG_TU: Tx data buffer underrun
489       \arg        CEC_INT_FLAG_TERR: Tx-error
490       \arg        CEC_INT_FLAG_TAERR: Tx ACK error flag
491     \param[out] none
492     \retval     none
493 */
cec_interrupt_flag_clear(uint32_t flag)494 void cec_interrupt_flag_clear(uint32_t flag)
495 {
496     CEC_INTF = flag;
497 }
498 
499 
500 #endif
501