1 /**
2   ******************************************************************************
3   * @file    stm32f1xx_hal_cec.c
4   * @author  MCD Application Team
5   * @brief   CEC HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the High Definition Multimedia Interface
8   *          Consumer Electronics Control Peripheral (CEC).
9   *           + Initialization and de-initialization function
10   *           + IO operation function
11   *           + Peripheral Control function
12   *
13   *
14   ******************************************************************************
15   * @attention
16   *
17   * Copyright (c) 2016 STMicroelectronics.
18   * All rights reserved.
19   *
20   * This software is licensed under terms that can be found in the LICENSE file
21   * in the root directory of this software component.
22   * If no LICENSE file comes with this software, it is provided AS-IS.
23   *
24   ******************************************************************************
25   @verbatim
26  ===============================================================================
27                         ##### How to use this driver #####
28  ===============================================================================
29     [..]
30     The CEC HAL driver can be used as follow:
31 
32     (#) Declare a CEC_HandleTypeDef handle structure.
33     (#) Initialize the CEC low level resources by implementing the HAL_CEC_MspInit ()API:
34         (##) Enable the CEC interface clock.
35         (##) CEC pins configuration:
36             (+++) Enable the clock for the CEC GPIOs.
37             (+++) Configure these CEC pins as alternate function pull-up.
38         (##) NVIC configuration if you need to use interrupt process (HAL_CEC_Transmit_IT()
39              and HAL_CEC_Receive_IT() APIs):
40             (+++) Configure the CEC interrupt priority.
41             (+++) Enable the NVIC CEC IRQ handle.
42             (+++) The specific CEC interrupts (Transmission complete interrupt,
43                   RXNE interrupt and Error Interrupts) will be managed using the macros
44                   __HAL_CEC_ENABLE_IT() and __HAL_CEC_DISABLE_IT() inside the transmit
45                   and receive process.
46 
47     (#) Program the Bit Timing Error Mode and the Bit Period Error Mode in the hcec Init structure.
48 
49     (#) Initialize the CEC registers by calling the HAL_CEC_Init() API.
50 
51   [..]
52     (@) This API (HAL_CEC_Init()) configures also the low level Hardware (GPIO, CLOCK, CORTEX...etc)
53         by calling the customed HAL_CEC_MspInit() API.
54   *** Callback registration ***
55   =============================================
56 
57   The compilation define  USE_HAL_CEC_REGISTER_CALLBACKS when set to 1
58   allows the user to configure dynamically the driver callbacks.
59   Use Functions HAL_CEC_RegisterCallback() or HAL_CEC_RegisterXXXCallback()
60   to register an interrupt callback.
61 
62   Function HAL_CEC_RegisterCallback() allows to register following callbacks:
63     (+) TxCpltCallback     : Tx Transfer completed callback.
64     (+) ErrorCallback      : callback for error detection.
65     (+) MspInitCallback    : CEC MspInit.
66     (+) MspDeInitCallback  : CEC MspDeInit.
67   This function takes as parameters the HAL peripheral handle, the Callback ID
68   and a pointer to the user callback function.
69 
70   For specific callback HAL_CEC_RxCpltCallback use dedicated register callbacks
71   HAL_CEC_RegisterRxCpltCallback().
72 
73   Use function HAL_CEC_UnRegisterCallback() to reset a callback to the default
74   weak function.
75   HAL_CEC_UnRegisterCallback() takes as parameters the HAL peripheral handle,
76   and the Callback ID.
77   This function allows to reset following callbacks:
78     (+) TxCpltCallback     : Tx Transfer completed callback.
79     (+) ErrorCallback      : callback for error detection.
80     (+) MspInitCallback    : CEC MspInit.
81     (+) MspDeInitCallback  : CEC MspDeInit.
82 
83   For callback HAL_CEC_RxCpltCallback use dedicated unregister callback :
84   HAL_CEC_UnRegisterRxCpltCallback().
85 
86   By default, after the HAL_CEC_Init() and when the state is HAL_CEC_STATE_RESET
87   all callbacks are set to the corresponding weak functions :
88   examples HAL_CEC_TxCpltCallback() , HAL_CEC_RxCpltCallback().
89   Exception done for MspInit and MspDeInit functions that are
90   reset to the legacy weak function in the HAL_CEC_Init()/ HAL_CEC_DeInit() only when
91   these callbacks are null (not registered beforehand).
92   if not, MspInit or MspDeInit are not null, the HAL_CEC_Init() / HAL_CEC_DeInit()
93   keep and use the user MspInit/MspDeInit functions (registered beforehand)
94 
95   Callbacks can be registered/unregistered in HAL_CEC_STATE_READY state only.
96   Exception done MspInit/MspDeInit callbacks that can be registered/unregistered
97   in HAL_CEC_STATE_READY or HAL_CEC_STATE_RESET state,
98   thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
99   In that case first register the MspInit/MspDeInit user callbacks
100   using HAL_CEC_RegisterCallback() before calling HAL_CEC_DeInit()
101   or HAL_CEC_Init() function.
102 
103   When the compilation define USE_HAL_CEC_REGISTER_CALLBACKS is set to 0 or
104   not defined, the callback registration feature is not available and all callbacks
105   are set to the corresponding weak functions.
106   @endverbatim
107   ******************************************************************************
108   */
109 
110 /* Includes ------------------------------------------------------------------*/
111 #include "stm32f1xx_hal.h"
112 
113 #ifdef HAL_CEC_MODULE_ENABLED
114 
115 #if defined (CEC)
116 
117 /** @addtogroup STM32F1xx_HAL_Driver
118   * @{
119   */
120 
121 /** @defgroup CEC CEC
122   * @brief HAL CEC module driver
123   * @{
124   */
125 
126 /* Private typedef -----------------------------------------------------------*/
127 /* Private define ------------------------------------------------------------*/
128 /** @defgroup CEC_Private_Constants CEC Private Constants
129   * @{
130   */
131 #define CEC_CFGR_FIELDS (CEC_CFGR_BTEM | CEC_CFGR_BPEM )
132 #define CEC_FLAG_TRANSMIT_MASK (CEC_FLAG_TSOM|CEC_FLAG_TEOM|CEC_FLAG_TBTRF)
133 #define CEC_FLAG_RECEIVE_MASK (CEC_FLAG_RSOM|CEC_FLAG_REOM|CEC_FLAG_RBTF)
134 #define CEC_ESR_ALL_ERROR (CEC_ESR_BTE|CEC_ESR_BPE|CEC_ESR_RBTFE|CEC_ESR_SBE|CEC_ESR_ACKE|CEC_ESR_LINE|CEC_ESR_TBTFE)
135 #define CEC_RXXFERSIZE_INITIALIZE 0xFFFF /*!< Value used to initialise the RxXferSize of the handle */
136 /**
137   * @}
138   */
139 
140 /* Private macro -------------------------------------------------------------*/
141 /* Private variables ---------------------------------------------------------*/
142 /* Private function prototypes -----------------------------------------------*/
143 /** @defgroup CEC_Private_Functions CEC Private Functions
144   * @{
145   */
146 static HAL_StatusTypeDef CEC_Transmit_IT(CEC_HandleTypeDef *hcec);
147 static HAL_StatusTypeDef CEC_Receive_IT(CEC_HandleTypeDef *hcec);
148 /**
149   * @}
150   */
151 
152 /* Exported functions ---------------------------------------------------------*/
153 
154 /** @defgroup CEC_Exported_Functions CEC Exported Functions
155   * @{
156   */
157 
158 /** @defgroup CEC_Exported_Functions_Group1 Initialization and de-initialization functions
159   *  @brief    Initialization and Configuration functions
160   *
161 @verbatim
162 ===============================================================================
163             ##### Initialization and Configuration functions #####
164  ===============================================================================
165     [..]
166     This subsection provides a set of functions allowing to initialize the CEC
167       (+) The following parameters need to be configured:
168         (++) TimingErrorFree
169         (++) PeriodErrorFree
170         (++) InitiatorAddress
171 
172 @endverbatim
173   * @{
174   */
175 
176 /**
177   * @brief Initializes the CEC mode according to the specified
178   *         parameters in the CEC_InitTypeDef and creates the associated handle .
179   * @param hcec CEC handle
180   * @retval HAL status
181   */
HAL_CEC_Init(CEC_HandleTypeDef * hcec)182 HAL_StatusTypeDef HAL_CEC_Init(CEC_HandleTypeDef *hcec)
183 {
184   /* Check the CEC handle allocation */
185   if ((hcec == NULL) || (hcec->Init.RxBuffer == NULL))
186   {
187     return HAL_ERROR;
188   }
189 
190   /* Check the parameters */
191   assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
192   assert_param(IS_CEC_BIT_TIMING_ERROR_MODE(hcec->Init.TimingErrorFree));
193   assert_param(IS_CEC_BIT_PERIOD_ERROR_MODE(hcec->Init.PeriodErrorFree));
194   assert_param(IS_CEC_ADDRESS(hcec->Init.OwnAddress));
195 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
196   if (hcec->gState == HAL_CEC_STATE_RESET)
197   {
198     /* Allocate lock resource and initialize it */
199     hcec->Lock = HAL_UNLOCKED;
200 
201     hcec->TxCpltCallback  = HAL_CEC_TxCpltCallback;  /* Legacy weak TxCpltCallback  */
202     hcec->RxCpltCallback = HAL_CEC_RxCpltCallback;   /* Legacy weak RxCpltCallback */
203     hcec->ErrorCallback = HAL_CEC_ErrorCallback;     /* Legacy weak ErrorCallback */
204 
205     if (hcec->MspInitCallback == NULL)
206     {
207       hcec->MspInitCallback = HAL_CEC_MspInit; /* Legacy weak MspInit  */
208     }
209 
210     /* Init the low level hardware */
211     hcec->MspInitCallback(hcec);
212   }
213 #else
214   if (hcec->gState == HAL_CEC_STATE_RESET)
215   {
216     /* Allocate lock resource and initialize it */
217     hcec->Lock = HAL_UNLOCKED;
218     /* Init the low level hardware : GPIO, CLOCK */
219     HAL_CEC_MspInit(hcec);
220   }
221 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
222 
223   hcec->gState = HAL_CEC_STATE_BUSY;
224 
225   /* Disable the Peripheral */
226   __HAL_CEC_DISABLE(hcec);
227 
228   /* Write to CEC Control Register */
229   MODIFY_REG(hcec->Instance->CFGR, CEC_CFGR_FIELDS, hcec->Init.TimingErrorFree | hcec->Init.PeriodErrorFree);
230 
231   /* Write to CEC Own Address Register */
232   MODIFY_REG(hcec->Instance->OAR, CEC_OAR_OA, hcec->Init.OwnAddress);
233 
234   /* Configure the prescaler to generate the required 50 microseconds time base.*/
235   MODIFY_REG(hcec->Instance->PRES, CEC_PRES_PRES, 50U * (HAL_RCC_GetPCLK1Freq() / 1000000U) - 1U);
236 
237   /* Enable the following CEC Interrupt */
238   __HAL_CEC_ENABLE_IT(hcec, CEC_IT_IE);
239 
240   /* Enable the CEC Peripheral */
241   __HAL_CEC_ENABLE(hcec);
242 
243   hcec->ErrorCode = HAL_CEC_ERROR_NONE;
244   hcec->gState = HAL_CEC_STATE_READY;
245   hcec->RxState = HAL_CEC_STATE_READY;
246 
247   return HAL_OK;
248 }
249 
250 /**
251   * @brief DeInitializes the CEC peripheral
252   * @param hcec CEC handle
253   * @retval HAL status
254   */
HAL_CEC_DeInit(CEC_HandleTypeDef * hcec)255 HAL_StatusTypeDef HAL_CEC_DeInit(CEC_HandleTypeDef *hcec)
256 {
257   /* Check the CEC handle allocation */
258   if (hcec == NULL)
259   {
260     return HAL_ERROR;
261   }
262 
263   /* Check the parameters */
264   assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
265 
266   hcec->gState = HAL_CEC_STATE_BUSY;
267 
268 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
269   if (hcec->MspDeInitCallback == NULL)
270   {
271     hcec->MspDeInitCallback = HAL_CEC_MspDeInit; /* Legacy weak MspDeInit  */
272   }
273 
274   /* DeInit the low level hardware */
275   hcec->MspDeInitCallback(hcec);
276 
277 #else
278   /* DeInit the low level hardware */
279   HAL_CEC_MspDeInit(hcec);
280 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
281 
282   __HAL_RCC_CEC_FORCE_RESET();
283   __HAL_RCC_CEC_RELEASE_RESET();
284 
285   hcec->ErrorCode = HAL_CEC_ERROR_NONE;
286   hcec->gState = HAL_CEC_STATE_RESET;
287   hcec->RxState = HAL_CEC_STATE_RESET;
288 
289   /* Process Unlock */
290   __HAL_UNLOCK(hcec);
291 
292   return HAL_OK;
293 }
294 
295 /**
296   * @brief Initializes the Own Address of the CEC device
297   * @param hcec CEC handle
298   * @param  CEC_OwnAddress The CEC own address.
299   * @retval HAL status
300   */
HAL_CEC_SetDeviceAddress(CEC_HandleTypeDef * hcec,uint16_t CEC_OwnAddress)301 HAL_StatusTypeDef HAL_CEC_SetDeviceAddress(CEC_HandleTypeDef *hcec, uint16_t CEC_OwnAddress)
302 {
303   /* Check the parameters */
304   assert_param(IS_CEC_OWN_ADDRESS(CEC_OwnAddress));
305 
306   if ((hcec->gState == HAL_CEC_STATE_READY) && (hcec->RxState == HAL_CEC_STATE_READY))
307   {
308     /* Process Locked */
309     __HAL_LOCK(hcec);
310 
311     hcec->gState = HAL_CEC_STATE_BUSY;
312 
313     /* Disable the Peripheral */
314     __HAL_CEC_DISABLE(hcec);
315 
316     if (CEC_OwnAddress != CEC_OWN_ADDRESS_NONE)
317     {
318       MODIFY_REG(hcec->Instance->OAR, CEC_OAR_OA, hcec->Init.OwnAddress);
319     }
320     else
321     {
322       CLEAR_BIT(hcec->Instance->OAR, CEC_OAR_OA);
323     }
324 
325     hcec->gState = HAL_CEC_STATE_READY;
326     hcec->ErrorCode = HAL_CEC_ERROR_NONE;
327 
328     /* Process Unlocked */
329     __HAL_UNLOCK(hcec);
330 
331     /* Enable the Peripheral */
332     __HAL_CEC_ENABLE(hcec);
333 
334     return  HAL_OK;
335   }
336   else
337   {
338     return HAL_BUSY;
339   }
340 }
341 
342 /**
343   * @brief CEC MSP Init
344   * @param hcec CEC handle
345   * @retval None
346   */
HAL_CEC_MspInit(CEC_HandleTypeDef * hcec)347 __weak void HAL_CEC_MspInit(CEC_HandleTypeDef *hcec)
348 {
349   /* Prevent unused argument(s) compilation warning */
350   UNUSED(hcec);
351   /* NOTE : This function should not be modified, when the callback is needed,
352             the HAL_CEC_MspInit can be implemented in the user file
353    */
354 }
355 
356 /**
357   * @brief CEC MSP DeInit
358   * @param hcec CEC handle
359   * @retval None
360   */
HAL_CEC_MspDeInit(CEC_HandleTypeDef * hcec)361 __weak void HAL_CEC_MspDeInit(CEC_HandleTypeDef *hcec)
362 {
363   /* Prevent unused argument(s) compilation warning */
364   UNUSED(hcec);
365   /* NOTE : This function should not be modified, when the callback is needed,
366             the HAL_CEC_MspDeInit can be implemented in the user file
367    */
368 }
369 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
370 /**
371   * @brief  Register a User CEC Callback
372   *         To be used instead of the weak predefined callback
373   * @param  hcec CEC handle
374   * @param  CallbackID ID of the callback to be registered
375   *         This parameter can be one of the following values:
376   *          @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID
377   *          @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID
378   *          @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID
379   *          @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID
380   * @param  pCallback pointer to the Callback function
381   * @retval HAL status
382   */
HAL_CEC_RegisterCallback(CEC_HandleTypeDef * hcec,HAL_CEC_CallbackIDTypeDef CallbackID,pCEC_CallbackTypeDef pCallback)383 HAL_StatusTypeDef HAL_CEC_RegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID,
384                                            pCEC_CallbackTypeDef pCallback)
385 {
386   HAL_StatusTypeDef status = HAL_OK;
387 
388   if (pCallback == NULL)
389   {
390     /* Update the error code */
391     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
392     return HAL_ERROR;
393   }
394   /* Process locked */
395   __HAL_LOCK(hcec);
396 
397   if (hcec->gState == HAL_CEC_STATE_READY)
398   {
399     switch (CallbackID)
400     {
401       case HAL_CEC_TX_CPLT_CB_ID :
402         hcec->TxCpltCallback = pCallback;
403         break;
404 
405       case HAL_CEC_ERROR_CB_ID :
406         hcec->ErrorCallback = pCallback;
407         break;
408 
409       case HAL_CEC_MSPINIT_CB_ID :
410         hcec->MspInitCallback = pCallback;
411         break;
412 
413       case HAL_CEC_MSPDEINIT_CB_ID :
414         hcec->MspDeInitCallback = pCallback;
415         break;
416 
417       default :
418         /* Update the error code */
419         hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
420         /* Return error status */
421         status =  HAL_ERROR;
422         break;
423     }
424   }
425   else if (hcec->gState == HAL_CEC_STATE_RESET)
426   {
427     switch (CallbackID)
428     {
429       case HAL_CEC_MSPINIT_CB_ID :
430         hcec->MspInitCallback = pCallback;
431         break;
432 
433       case HAL_CEC_MSPDEINIT_CB_ID :
434         hcec->MspDeInitCallback = pCallback;
435         break;
436 
437       default :
438         /* Update the error code */
439         hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
440         /* Return error status */
441         status =  HAL_ERROR;
442         break;
443     }
444   }
445   else
446   {
447     /* Update the error code */
448     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
449     /* Return error status */
450     status =  HAL_ERROR;
451   }
452 
453   /* Release Lock */
454   __HAL_UNLOCK(hcec);
455 
456   return status;
457 }
458 
459 /**
460   * @brief  Unregister an CEC Callback
461   *         CEC callback is redirected to the weak predefined callback
462   * @param hcec uart handle
463   * @param CallbackID ID of the callback to be unregistered
464   *         This parameter can be one of the following values:
465   *          @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID
466   *          @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID
467   *          @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID
468   *          @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID
469   * @retval status
470   */
HAL_CEC_UnRegisterCallback(CEC_HandleTypeDef * hcec,HAL_CEC_CallbackIDTypeDef CallbackID)471 HAL_StatusTypeDef HAL_CEC_UnRegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID)
472 {
473   HAL_StatusTypeDef status = HAL_OK;
474 
475   /* Process locked */
476   __HAL_LOCK(hcec);
477 
478   if (hcec->gState == HAL_CEC_STATE_READY)
479   {
480     switch (CallbackID)
481     {
482       case HAL_CEC_TX_CPLT_CB_ID :
483         hcec->TxCpltCallback = HAL_CEC_TxCpltCallback;  /* Legacy weak  TxCpltCallback */
484         break;
485 
486       case HAL_CEC_ERROR_CB_ID :
487         hcec->ErrorCallback = HAL_CEC_ErrorCallback;  /* Legacy weak ErrorCallback   */
488         break;
489 
490       case HAL_CEC_MSPINIT_CB_ID :
491         hcec->MspInitCallback = HAL_CEC_MspInit;
492         break;
493 
494       case HAL_CEC_MSPDEINIT_CB_ID :
495         hcec->MspDeInitCallback = HAL_CEC_MspDeInit;
496         break;
497 
498       default :
499         /* Update the error code */
500         hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
501         /* Return error status */
502         status =  HAL_ERROR;
503         break;
504     }
505   }
506   else if (hcec->gState == HAL_CEC_STATE_RESET)
507   {
508     switch (CallbackID)
509     {
510       case HAL_CEC_MSPINIT_CB_ID :
511         hcec->MspInitCallback = HAL_CEC_MspInit;
512         break;
513 
514       case HAL_CEC_MSPDEINIT_CB_ID :
515         hcec->MspDeInitCallback = HAL_CEC_MspDeInit;
516         break;
517 
518       default :
519         /* Update the error code */
520         hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
521         /* Return error status */
522         status =  HAL_ERROR;
523         break;
524     }
525   }
526   else
527   {
528     /* Update the error code */
529     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
530     /* Return error status */
531     status =  HAL_ERROR;
532   }
533 
534   /* Release Lock */
535   __HAL_UNLOCK(hcec);
536 
537   return status;
538 }
539 
540 /**
541   * @brief  Register CEC RX complete Callback
542   *         To be used instead of the weak HAL_CEC_RxCpltCallback() predefined callback
543   * @param  hcec CEC handle
544   * @param  pCallback pointer to the Rx transfer compelete Callback function
545   * @retval HAL status
546   */
HAL_CEC_RegisterRxCpltCallback(CEC_HandleTypeDef * hcec,pCEC_RxCallbackTypeDef pCallback)547 HAL_StatusTypeDef HAL_CEC_RegisterRxCpltCallback(CEC_HandleTypeDef *hcec, pCEC_RxCallbackTypeDef pCallback)
548 {
549   HAL_StatusTypeDef status = HAL_OK;
550 
551   if (pCallback == NULL)
552   {
553     /* Update the error code */
554     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
555     return HAL_ERROR;
556   }
557   /* Process locked */
558   __HAL_LOCK(hcec);
559 
560   if (HAL_CEC_STATE_READY == hcec->RxState)
561   {
562     hcec->RxCpltCallback = pCallback;
563   }
564   else
565   {
566     /* Update the error code */
567     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
568     /* Return error status */
569     status =  HAL_ERROR;
570   }
571 
572   /* Release Lock */
573   __HAL_UNLOCK(hcec);
574   return status;
575 }
576 
577 /**
578   * @brief  UnRegister CEC RX complete Callback
579   *         CEC RX complete Callback is redirected to the weak HAL_CEC_RxCpltCallback() predefined callback
580   * @param  hcec CEC handle
581   * @retval HAL status
582   */
HAL_CEC_UnRegisterRxCpltCallback(CEC_HandleTypeDef * hcec)583 HAL_StatusTypeDef HAL_CEC_UnRegisterRxCpltCallback(CEC_HandleTypeDef *hcec)
584 {
585   HAL_StatusTypeDef status = HAL_OK;
586 
587   /* Process locked */
588   __HAL_LOCK(hcec);
589 
590   if (HAL_CEC_STATE_READY == hcec->RxState)
591   {
592     hcec->RxCpltCallback = HAL_CEC_RxCpltCallback; /* Legacy weak  CEC RxCpltCallback  */
593   }
594   else
595   {
596     /* Update the error code */
597     hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
598     /* Return error status */
599     status =  HAL_ERROR;
600   }
601 
602   /* Release Lock */
603   __HAL_UNLOCK(hcec);
604   return status;
605 }
606 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
607 
608 /**
609   * @}
610   */
611 
612 /** @defgroup CEC_Exported_Functions_Group2 Input and Output operation functions
613   *  @brief CEC Transmit/Receive functions
614   *
615 @verbatim
616  ===============================================================================
617                       ##### IO operation functions #####
618  ===============================================================================
619     This subsection provides a set of functions allowing to manage the CEC data transfers.
620 
621     (#) The CEC handle must contain the initiator (TX side) and the destination (RX side)
622         logical addresses (4-bit long addresses, 0xF for broadcast messages destination)
623 
624     (#) The communication is performed using Interrupts.
625            These API's return the HAL status.
626            The end of the data processing will be indicated through the
627            dedicated CEC IRQ when using Interrupt mode.
628            The HAL_CEC_TxCpltCallback(), HAL_CEC_RxCpltCallback() user callbacks
629            will be executed respectively at the end of the transmit or Receive process
630            The HAL_CEC_ErrorCallback() user callback will be executed when a communication
631            error is detected
632 
633     (#) API's with Interrupt are :
634          (+) HAL_CEC_Transmit_IT()
635          (+) HAL_CEC_IRQHandler()
636 
637     (#) A set of User Callbacks are provided:
638          (+) HAL_CEC_TxCpltCallback()
639          (+) HAL_CEC_RxCpltCallback()
640          (+) HAL_CEC_ErrorCallback()
641 
642 @endverbatim
643   * @{
644   */
645 
646 /**
647   * @brief Send data in interrupt mode
648   * @param hcec CEC handle
649   * @param InitiatorAddress Initiator address
650   * @param DestinationAddress destination logical address
651   * @param pData pointer to input byte data buffer
652   * @param Size amount of data to be sent in bytes (without counting the header).
653   *              0 means only the header is sent (ping operation).
654   *              Maximum TX size is 15 bytes (1 opcode and up to 14 operands).
655   * @retval HAL status
656   */
HAL_CEC_Transmit_IT(CEC_HandleTypeDef * hcec,uint8_t InitiatorAddress,uint8_t DestinationAddress,const uint8_t * pData,uint32_t Size)657 HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress, uint8_t DestinationAddress,
658                                       const uint8_t *pData, uint32_t Size)
659 {
660   /* if the peripheral isn't already busy and if there is no previous transmission
661      already pending due to arbitration lost */
662   if (hcec->gState == HAL_CEC_STATE_READY)
663   {
664     if ((pData == NULL) && (Size > 0U))
665     {
666       return  HAL_ERROR;
667     }
668 
669     assert_param(IS_CEC_ADDRESS(DestinationAddress));
670     assert_param(IS_CEC_ADDRESS(InitiatorAddress));
671     assert_param(IS_CEC_MSGSIZE(Size));
672 
673     /* Process Locked */
674     __HAL_LOCK(hcec);
675     hcec->pTxBuffPtr = pData;
676     hcec->gState = HAL_CEC_STATE_BUSY_TX;
677     hcec->ErrorCode = HAL_CEC_ERROR_NONE;
678 
679     /* initialize the number of bytes to send,
680      * 0 means only one header is sent (ping operation) */
681     hcec->TxXferCount = Size;
682 
683     /* send header block */
684     hcec->Instance->TXD = (uint8_t)((uint32_t)InitiatorAddress << CEC_INITIATOR_LSB_POS) | DestinationAddress;
685 
686     /* Process Unlocked */
687     __HAL_UNLOCK(hcec);
688 
689     /* case no data to be sent, sender is only pinging the system */
690     if (Size != 0)
691     {
692       /* Set TX Start of Message (TXSOM) bit */
693       MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TSOM);
694     }
695     else
696     {
697       /* Send a ping command */
698       MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM | CEC_FLAG_TSOM);
699     }
700     return HAL_OK;
701 
702   }
703   else
704   {
705     return HAL_BUSY;
706   }
707 }
708 
709 /**
710   * @brief Get size of the received frame.
711   * @param hcec CEC handle
712   * @retval Frame size
713   */
HAL_CEC_GetLastReceivedFrameSize(const CEC_HandleTypeDef * hcec)714 uint32_t HAL_CEC_GetLastReceivedFrameSize(const CEC_HandleTypeDef *hcec)
715 {
716   return hcec->RxXferSize;
717 }
718 
719 /**
720   * @brief Change Rx Buffer.
721   * @param hcec CEC handle
722   * @param Rxbuffer Rx Buffer
723   * @note  This function can be called only inside the HAL_CEC_RxCpltCallback()
724   * @retval Frame size
725   */
HAL_CEC_ChangeRxBuffer(CEC_HandleTypeDef * hcec,uint8_t * Rxbuffer)726 void HAL_CEC_ChangeRxBuffer(CEC_HandleTypeDef *hcec, uint8_t *Rxbuffer)
727 {
728   hcec->Init.RxBuffer = Rxbuffer;
729 }
730 
731 /**
732   * @brief This function handles CEC interrupt requests.
733   * @param hcec CEC handle
734   * @retval None
735   */
HAL_CEC_IRQHandler(CEC_HandleTypeDef * hcec)736 void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec)
737 {
738 
739   /* save interrupts register for further error or interrupts handling purposes */
740   uint32_t itflag;
741   itflag = hcec->Instance->CSR;
742 
743   /* Save error status register for further error handling purposes */
744   hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
745 
746   /* Transmit error */
747   if (HAL_IS_BIT_SET(itflag, CEC_FLAG_TERR))
748   {
749     /* Acknowledgement of the error */
750     __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
751 
752     hcec->gState = HAL_CEC_STATE_READY;
753   }
754 
755   /* Receive error */
756   if (HAL_IS_BIT_SET(itflag, CEC_FLAG_RERR))
757   {
758     /* Acknowledgement of the error */
759     __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
760     hcec->Init.RxBuffer -= hcec->RxXferSize;
761     hcec->RxXferSize = 0U;
762     hcec->RxState = HAL_CEC_STATE_READY;
763   }
764 
765   if ((hcec->ErrorCode & CEC_ESR_ALL_ERROR) != 0U)
766   {
767     /* Error  Call Back */
768 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
769     hcec->ErrorCallback(hcec);
770 #else
771     HAL_CEC_ErrorCallback(hcec);
772 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
773   }
774 
775   /* Transmit byte request or block transfer finished */
776   if (HAL_IS_BIT_SET(itflag, CEC_FLAG_TBTRF))
777   {
778     CEC_Transmit_IT(hcec);
779   }
780 
781   /* Receive byte or block transfer finished */
782   if (HAL_IS_BIT_SET(itflag, CEC_FLAG_RBTF))
783   {
784     if (hcec->RxXferSize == 0U)
785     {
786       /* reception is starting */
787       hcec->RxState = HAL_CEC_STATE_BUSY_RX;
788     }
789     CEC_Receive_IT(hcec);
790   }
791 }
792 
793 /**
794   * @brief Tx Transfer completed callback
795   * @param hcec CEC handle
796   * @retval None
797   */
HAL_CEC_TxCpltCallback(CEC_HandleTypeDef * hcec)798 __weak void HAL_CEC_TxCpltCallback(CEC_HandleTypeDef *hcec)
799 {
800   /* Prevent unused argument(s) compilation warning */
801   UNUSED(hcec);
802   /* NOTE : This function should not be modified, when the callback is needed,
803             the HAL_CEC_TxCpltCallback can be implemented in the user file
804    */
805 }
806 
807 /**
808   * @brief Rx Transfer completed callback
809   * @param hcec CEC handle
810   * @param RxFrameSize Size of frame
811   * @retval None
812   */
HAL_CEC_RxCpltCallback(CEC_HandleTypeDef * hcec,uint32_t RxFrameSize)813 __weak void HAL_CEC_RxCpltCallback(CEC_HandleTypeDef *hcec, uint32_t RxFrameSize)
814 {
815   /* Prevent unused argument(s) compilation warning */
816   UNUSED(hcec);
817   UNUSED(RxFrameSize);
818   /* NOTE : This function should not be modified, when the callback is needed,
819             the HAL_CEC_RxCpltCallback can be implemented in the user file
820    */
821 }
822 
823 /**
824   * @brief CEC error callbacks
825   * @param hcec CEC handle
826   * @retval None
827   */
HAL_CEC_ErrorCallback(CEC_HandleTypeDef * hcec)828 __weak void HAL_CEC_ErrorCallback(CEC_HandleTypeDef *hcec)
829 {
830   /* Prevent unused argument(s) compilation warning */
831   UNUSED(hcec);
832   /* NOTE : This function should not be modified, when the callback is needed,
833             the HAL_CEC_ErrorCallback can be implemented in the user file
834    */
835 }
836 /**
837   * @}
838   */
839 
840 /** @defgroup CEC_Exported_Functions_Group3 Peripheral Control functions
841   *  @brief   CEC control functions
842   *
843 @verbatim
844  ===============================================================================
845                       ##### Peripheral Control function #####
846  ===============================================================================
847     [..]
848     This subsection provides a set of functions allowing to control the CEC.
849      (+) HAL_CEC_GetState() API can be helpful to check in run-time the state of the CEC peripheral.
850      (+) HAL_CEC_GetError() API can be helpful to check in run-time the error of the CEC peripheral.
851 @endverbatim
852   * @{
853   */
854 /**
855   * @brief return the CEC state
856   * @param hcec pointer to a CEC_HandleTypeDef structure that contains
857   *              the configuration information for the specified CEC module.
858   * @retval HAL state
859   */
HAL_CEC_GetState(const CEC_HandleTypeDef * hcec)860 HAL_CEC_StateTypeDef HAL_CEC_GetState(const CEC_HandleTypeDef *hcec)
861 {
862   uint32_t temp1;
863   uint32_t temp2;
864   temp1 = hcec->gState;
865   temp2 = hcec->RxState;
866 
867   return (HAL_CEC_StateTypeDef)(temp1 | temp2);
868 }
869 
870 /**
871   * @brief  Return the CEC error code
872   * @param  hcec  pointer to a CEC_HandleTypeDef structure that contains
873   *              the configuration information for the specified CEC.
874   * @retval CEC Error Code
875   */
HAL_CEC_GetError(const CEC_HandleTypeDef * hcec)876 uint32_t HAL_CEC_GetError(const CEC_HandleTypeDef *hcec)
877 {
878   return hcec->ErrorCode;
879 }
880 
881 /**
882   * @}
883   */
884 
885 /**
886   * @}
887   */
888 
889 /** @addtogroup CEC_Private_Functions
890   * @{
891   */
892 
893 /**
894   * @brief Send data in interrupt mode
895   * @param hcec CEC handle.
896   *         Function called under interruption only, once
897   *         interruptions have been enabled by HAL_CEC_Transmit_IT()
898   * @retval HAL status
899  */
CEC_Transmit_IT(CEC_HandleTypeDef * hcec)900 static HAL_StatusTypeDef CEC_Transmit_IT(CEC_HandleTypeDef *hcec)
901 {
902   /* if the peripheral is already busy or if there is a previous transmission
903      already pending due to arbitration loss */
904   if ((hcec->gState == HAL_CEC_STATE_BUSY_TX) || (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) != RESET))
905   {
906     /* if all data have been sent */
907     if (hcec->TxXferCount == 0U)
908     {
909       /* Acknowledge successful completion by writing 0x00 */
910       MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00U);
911 
912       hcec->gState = HAL_CEC_STATE_READY;
913 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
914       hcec->TxCpltCallback(hcec);
915 #else
916       HAL_CEC_TxCpltCallback(hcec);
917 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
918 
919       return HAL_OK;
920     }
921     else
922     {
923       /* Reduce the number of bytes to transfer by one */
924       hcec->TxXferCount--;
925 
926       /* Write data to TX buffer*/
927       hcec->Instance->TXD = (uint8_t)*hcec->pTxBuffPtr++;
928 
929       /* If this is the last byte of the ongoing transmission */
930       if (hcec->TxXferCount == 0U)
931       {
932         /* Acknowledge byte request and signal end of message */
933         MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM);
934       }
935       else
936       {
937         /* Acknowledge byte request by writing 0x00 */
938         MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00U);
939       }
940 
941       return HAL_OK;
942     }
943   }
944   else
945   {
946     return HAL_BUSY;
947   }
948 }
949 
950 /**
951   * @brief Receive data in interrupt mode.
952   * @param hcec CEC handle.
953   *         Function called under interruption only, once
954   *         interruptions have been enabled by HAL_CEC_Receive_IT()
955   * @retval HAL status
956   */
CEC_Receive_IT(CEC_HandleTypeDef * hcec)957 static HAL_StatusTypeDef CEC_Receive_IT(CEC_HandleTypeDef *hcec)
958 {
959   static uint32_t temp;
960 
961   if (hcec->RxState == HAL_CEC_STATE_BUSY_RX)
962   {
963     temp = hcec->Instance->CSR;
964 
965     /* Store received data */
966     hcec->RxXferSize++;
967     *hcec->Init.RxBuffer++ = hcec->Instance->RXD;
968 
969     /* Acknowledge received byte by writing 0x00 */
970     MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_RECEIVE_MASK, 0x00U);
971 
972     /* If the End Of Message is reached */
973     if (HAL_IS_BIT_SET(temp, CEC_FLAG_REOM))
974     {
975       /* Interrupts are not disabled due to transmission still ongoing */
976       hcec->RxState = HAL_CEC_STATE_READY;
977 #if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
978       hcec->RxCpltCallback(hcec, hcec->RxXferSize);
979 #else
980       HAL_CEC_RxCpltCallback(hcec, hcec->RxXferSize);
981 #endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
982 
983       return HAL_OK;
984     }
985     else
986     {
987       return HAL_BUSY;
988     }
989   }
990   else
991   {
992     return HAL_BUSY;
993   }
994 }
995 
996 /**
997   * @}
998   */
999 
1000 /**
1001   * @}
1002   */
1003 
1004 #endif /* CEC */
1005 
1006 #endif /* HAL_CEC_MODULE_ENABLED */
1007 /**
1008   * @}
1009   */
1010