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