]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F1/stm32f1xx_hal_cec.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / cmsis / TARGET_STM / TARGET_STM32F1 / stm32f1xx_hal_cec.c
1 /**
2   ******************************************************************************
3   * @file    stm32f1xx_hal_cec.c
4   * @author  MCD Application Team
5   * @version V1.0.0
6   * @date    15-December-2014
7   * @brief   CEC HAL module driver.
8   *          This file provides firmware functions to manage the following 
9   *          functionalities of the High Definition Multimedia Interface 
10   *          Consumer Electronics Control Peripheral (CEC).
11   *           + Initialization and de-initialization functions
12   *           + IO operation functions
13   *           + Peripheral Control functions
14   *          
15   *  @verbatim    
16   ==============================================================================
17                         ##### How to use this driver #####
18   ==============================================================================
19     [..]  
20     The CEC HAL driver can be used as follows:
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         (##) Enable the clock for the CEC GPIOs.
25         (##) Configure these CEC pins as alternate function pull-up.
26         (##) NVIC configuration if you need to use interrupt process (HAL_CEC_Transmit_IT()
27              and HAL_CEC_Receive_IT() APIs):
28         (##) Configure the CEC interrupt priority.
29         (##) Enable the NVIC CEC IRQ handle.
30         (##) The CEC interrupt is activated/deactivated by the HAL driver
31
32     (#) Program the Bit Timing Error Mode and the Bit Period Error Mode in the hcec Init structure.
33
34     (#) Initialize the CEC registers by calling the HAL_CEC_Init() API.
35         
36     (#) This API (HAL_CEC_Init()) configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
37         by calling the customized HAL_CEC_MspInit() API.
38
39   @endverbatim
40   ******************************************************************************
41   * @attention
42   *
43   * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
44   *
45   * Redistribution and use in source and binary forms, with or without modification,
46   * are permitted provided that the following conditions are met:
47   *   1. Redistributions of source code must retain the above copyright notice,
48   *      this list of conditions and the following disclaimer.
49   *   2. Redistributions in binary form must reproduce the above copyright notice,
50   *      this list of conditions and the following disclaimer in the documentation
51   *      and/or other materials provided with the distribution.
52   *   3. Neither the name of STMicroelectronics nor the names of its contributors
53   *      may be used to endorse or promote products derived from this software
54   *      without specific prior written permission.
55   *
56   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
57   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
58   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
59   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
60   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
61   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
62   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
63   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
64   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
65   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
66   *
67   ******************************************************************************  
68   */
69
70 /* Includes ------------------------------------------------------------------*/
71 #include "stm32f1xx_hal.h"
72
73 #ifdef HAL_CEC_MODULE_ENABLED
74
75 #if defined(STM32F100xB) || defined(STM32F100xE)
76
77 /** @addtogroup STM32F1xx_HAL_Driver
78   * @{
79   */
80
81 /** @defgroup CEC CEC
82   * @brief HAL CEC module driver
83   * @{
84   */
85     
86 /* Private typedef -----------------------------------------------------------*/
87 /* Private define ------------------------------------------------------------*/
88 /** @defgroup CEC_Private_Constants CEC Private Constants
89   * @{
90   */
91 #define CEC_CFGR_FIELDS (CEC_CFGR_BTEM | CEC_CFGR_BPEM )
92 #define CEC_FLAG_TRANSMIT_MASK (CEC_FLAG_TSOM|CEC_FLAG_TEOM|CEC_FLAG_TBTRF)
93 #define CEC_FLAG_RECEIVE_MASK (CEC_FLAG_RSOM|CEC_FLAG_REOM|CEC_FLAG_RBTF)
94 #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)
95 #define CEC_RXXFERSIZE_INITIALIZE 0xFFFF /*!< Value used to initialise the RxXferSize of the handle */
96 /**
97  * @}
98  */
99  
100 /* Private macro -------------------------------------------------------------*/
101 /* Private variables ---------------------------------------------------------*/
102 /* Private function prototypes -----------------------------------------------*/
103 /** @defgroup CEC_Private_Functions CEC Private Functions
104   * @{
105   */
106 static HAL_StatusTypeDef CEC_Transmit_IT(CEC_HandleTypeDef *hcec);
107 static HAL_StatusTypeDef CEC_Receive_IT(CEC_HandleTypeDef *hcec);
108 /**
109  * @}
110  */
111  
112 /* Exported functions ---------------------------------------------------------*/
113
114 /** @defgroup CEC_Exported_Functions CEC Exported Functions
115   * @{
116   */
117
118 /** @defgroup CEC_Exported_Functions_Group1 Initialization and de-initialization functions
119   *  @brief    Initialization and Configuration functions 
120   *
121 @verbatim                                               
122 ===============================================================================
123             ##### Initialization and Configuration functions #####
124  ===============================================================================  
125     [..]
126     This subsection provides a set of functions allowing to initialize the CEC
127       (+) The following parameters need to be configured: 
128         (++) TimingErrorFree
129         (++) PeriodErrorFree 
130         (++) InitiatorAddress
131
132 @endverbatim
133   * @{
134   */
135
136 /**
137   * @brief Initializes the CEC mode according to the specified
138   *         parameters in the CEC_InitTypeDef and creates the associated handle .
139   * @param hcec: CEC handle
140   * @retval HAL status
141   */
142 HAL_StatusTypeDef HAL_CEC_Init(CEC_HandleTypeDef *hcec)
143 {
144   /* Check the CEC handle allocation */
145   if(hcec == NULL)
146   {
147     return HAL_ERROR;
148   }
149
150   /* Check the parameters */ 
151   assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
152   assert_param(IS_CEC_BIT_TIMING_ERROR_MODE(hcec->Init.TimingErrorFree));
153   assert_param(IS_CEC_BIT_PERIOD_ERROR_MODE(hcec->Init.PeriodErrorFree));
154   assert_param(IS_CEC_ADDRESS(hcec->Init.InitiatorAddress));
155
156   if(hcec->State == HAL_CEC_STATE_RESET)
157   {
158     /* Allocate lock resource and initialize it */
159     hcec-> Lock = HAL_UNLOCKED;
160     /* Init the low level hardware : GPIO, CLOCK */
161     HAL_CEC_MspInit(hcec);
162   }
163   
164   hcec->State = HAL_CEC_STATE_BUSY;
165   
166   /* Disable the Peripheral */
167   __HAL_CEC_DISABLE(hcec);
168   
169   /* Write to CEC Control Register */
170   MODIFY_REG(hcec->Instance->CFGR, CEC_CFGR_FIELDS, hcec->Init.TimingErrorFree|hcec->Init.PeriodErrorFree);
171   
172   /* Write to CEC Own Address Register */
173   MODIFY_REG(hcec->Instance->OAR, CEC_OAR_OA, hcec->Init.InitiatorAddress);
174   
175   /* Configure the prescaler to generate the required 50 microseconds time base.*/
176   MODIFY_REG(hcec->Instance->PRES, CEC_PRES_PRES, 50*(HAL_RCC_GetPCLK1Freq()/1000000)-1);
177   
178   /* Enable the Peripheral */
179   __HAL_CEC_ENABLE(hcec);
180
181   hcec->State = HAL_CEC_STATE_READY;
182   
183   return HAL_OK;
184 }
185
186
187
188 /**
189   * @brief DeInitializes the CEC peripheral 
190   * @param hcec: CEC handle
191   * @retval HAL status
192   */
193 HAL_StatusTypeDef HAL_CEC_DeInit(CEC_HandleTypeDef *hcec)
194 {
195   /* Check the CEC handle allocation */
196   if(hcec == NULL)
197   {
198     return HAL_ERROR;
199   }
200
201   /* Check the parameters */
202   assert_param(IS_CEC_ALL_INSTANCE(hcec->Instance));
203
204   hcec->State = HAL_CEC_STATE_BUSY;
205   
206   /* Set peripheral to reset state */
207   hcec->Instance->CFGR = 0x0;
208   hcec->Instance->OAR = 0x0;
209   hcec->Instance->PRES = 0x0;
210   hcec->Instance->CFGR = 0x0;
211   hcec->Instance->ESR = 0x0;
212   hcec->Instance->CSR = 0x0;
213   hcec->Instance->TXD = 0x0;
214   hcec->Instance->RXD = 0x0;
215   
216   /* Disable the Peripheral */
217   __HAL_CEC_DISABLE(hcec);
218   
219   /* DeInit the low level hardware */
220   HAL_CEC_MspDeInit(hcec);
221   
222   hcec->ErrorCode = HAL_CEC_ERROR_NONE;
223   hcec->State = HAL_CEC_STATE_RESET;
224   
225   /* Process Unlock */
226   __HAL_UNLOCK(hcec);
227   
228   return HAL_OK;
229 }
230
231 /**
232   * @brief CEC MSP Init
233   * @param hcec: CEC handle
234   * @retval None
235   */
236  __weak void HAL_CEC_MspInit(CEC_HandleTypeDef *hcec)
237 {
238   /* NOTE : This function should not be modified, when the callback is needed,
239             the HAL_CEC_MspInit can be implemented in the user file
240    */ 
241 }
242
243 /**
244   * @brief CEC MSP DeInit
245   * @param hcec: CEC handle
246   * @retval None
247   */
248  __weak void HAL_CEC_MspDeInit(CEC_HandleTypeDef *hcec)
249 {
250   /* NOTE : This function should not be modified, when the callback is needed,
251             the HAL_CEC_MspDeInit can be implemented in the user file
252    */ 
253 }
254
255 /**
256   * @}
257   */
258
259 /** @defgroup CEC_Exported_Functions_Group2 Input and Output operation functions 
260   *  @brief CEC Transmit/Receive functions 
261   *
262 @verbatim   
263  ===============================================================================
264                       ##### IO operation functions ##### 
265  ===============================================================================  
266     [..]
267     This subsection provides a set of functions allowing to manage the CEC data transfers.
268
269     (#) There are two modes of transfer:
270        (##) Blocking mode: The communication is performed in polling mode. 
271             The HAL status of all data processing is returned by the same function 
272             after finishing transfer.  
273        (##) No-Blocking mode: The communication is performed using Interrupts. 
274            These API's return the HAL status.
275            The end of the data processing will be indicated through the 
276            dedicated CEC IRQ when using Interrupt mode.
277            The HAL_CEC_TxCpltCallback(), HAL_CEC_RxCpltCallback() user callbacks 
278            will be executed respectivelly at the end of the Transmit or Receive process.
279            The HAL_CEC_ErrorCallback()user callback will be executed when a communication 
280            error is detected
281     (#) Blocking mode API's are :
282         (##) HAL_CEC_Transmit()
283         (##) HAL_CEC_Receive() 
284     (#) Non-Blocking mode API's with Interrupt are :
285         (##) HAL_CEC_Transmit_IT()
286         (##) HAL_CEC_Receive_IT()
287         (##) HAL_CEC_IRQHandler()
288     (#) A set of Transfer Complete Callbacks are provided in No_Blocking mode:
289         (##) HAL_CEC_TxCpltCallback()
290         (##) HAL_CEC_RxCpltCallback()
291         (##) HAL_CEC_ErrorCallback()
292       
293 @endverbatim
294   * @{
295   */
296
297 /**
298   * @brief Send data in blocking mode 
299   * @param hcec: CEC handle
300   * @param DestinationAddress: destination logical address      
301   * @param pData: pointer to input byte data buffer
302   * @param Size: amount of data to be sent in bytes (without counting the header).
303   *              0 means only the header is sent (ping operation).
304   *              Maximum TX size is 15 bytes (1 opcode and up to 14 operands).    
305   * @param  Timeout: Timeout duration.
306   * @retval HAL status
307   */
308 HAL_StatusTypeDef HAL_CEC_Transmit(CEC_HandleTypeDef *hcec, uint8_t DestinationAddress, uint8_t *pData, uint32_t Size, uint32_t Timeout)
309 {
310   uint8_t  temp = 0;
311   uint32_t tickstart = 0;
312
313   /* If the IP is ready */
314   if((hcec->State == HAL_CEC_STATE_READY) 
315      && (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) == RESET)) 
316   {
317     /* Basic check on pData pointer */
318     if(((pData == NULL) && (Size > 0)) || (! IS_CEC_MSGSIZE(Size))) 
319     {
320       return  HAL_ERROR;
321     }
322
323     assert_param(IS_CEC_ADDRESS(DestinationAddress));
324     
325     /* Process Locked */
326     __HAL_LOCK(hcec);
327     
328     /* Enter the transmit mode */
329     hcec->State = HAL_CEC_STATE_BUSY_TX;
330     hcec->ErrorCode = HAL_CEC_ERROR_NONE;
331
332     /* Initialize the number of bytes to send,
333      * 0 means only one header is sent (ping operation) */
334     hcec->TxXferCount = Size;
335
336     /* Send header block */
337     temp = (uint8_t)((uint32_t)(hcec->Init.InitiatorAddress) << CEC_INITIATOR_LSB_POS) | DestinationAddress;
338     hcec->Instance->TXD = temp;
339
340     /* In case no data to be sent, sender is only pinging the system */
341     if (Size != 0)
342     {    
343       /* Set TX Start of Message (TXSOM) bit */
344       hcec->Instance->CSR = CEC_FLAG_TSOM;
345     }
346     else
347     {
348       /* Send a ping command */
349       hcec->Instance->CSR = CEC_FLAG_TEOM|CEC_FLAG_TSOM;
350     }
351
352     /* Polling TBTRF bit with timeout handling*/
353     while (hcec->TxXferCount > 0)
354     {
355       /* Decreasing of the number of remaining data to receive */
356       hcec->TxXferCount--;
357       
358       /* Timeout handling */
359       tickstart = HAL_GetTick();
360       
361       /* Waiting for the next data transmission */
362       while(HAL_IS_BIT_CLR(hcec->Instance->CSR, CEC_FLAG_TBTRF))
363       {
364         /* Timeout handling */
365         if(Timeout != HAL_MAX_DELAY)
366         {
367           if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
368           {
369             hcec->State = HAL_CEC_STATE_READY; 
370             /* Process Unlocked */
371             __HAL_UNLOCK(hcec);  
372             return HAL_TIMEOUT;
373           }
374         }        
375
376         /* Check if an error occured */
377         if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_TERR) || HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR))
378         {
379           /* Copy ESR for error handling purposes */
380           hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
381           
382           /* Acknowledgement of the error */
383           __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
384           __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
385           
386           hcec->State = HAL_CEC_STATE_READY;
387           __HAL_UNLOCK(hcec);
388           return  HAL_ERROR;                                    
389         }
390       }
391       
392       /* Write the next data to TX buffer */
393       hcec->Instance->TXD = *pData++;
394       
395       /* If this is the last byte of the ongoing transmission */
396       if (hcec->TxXferCount == 0)
397       {
398         /* Acknowledge byte request and signal end of message */
399         MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM);
400       }
401       else
402       {
403         /* Acknowledge byte request by writing 0x00 */
404         MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00);
405       }
406     }
407     
408     /* Timeout handling */
409     tickstart = HAL_GetTick();
410     
411     /* Wait for message transmission completion (TBTRF is set) */
412     while (HAL_IS_BIT_CLR(hcec->Instance->CSR, CEC_FLAG_TBTRF))
413     {
414       /* Timeout handling */
415       if(Timeout != HAL_MAX_DELAY)
416       {
417         if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
418         {
419           hcec->State = HAL_CEC_STATE_READY;
420           __HAL_UNLOCK(hcec);             
421           return HAL_TIMEOUT;
422         }
423       } 
424
425       /* Check of error during transmission of the last byte */
426       if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_TERR) || HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR))
427       {
428         /* Copy ESR for error handling purposes */
429         hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
430         
431         /* Acknowledgement of the error */
432         __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
433         __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
434         
435         hcec->State = HAL_CEC_STATE_READY;
436         __HAL_UNLOCK(hcec);
437         return  HAL_ERROR;                                    
438       }
439     }
440     
441     /* Check of error after the last byte transmission */
442     if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_TERR) || HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR))
443     {
444       /* Copy ESR for error handling purposes */
445       hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
446       
447       /* Acknowledgement of the error */
448       __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
449       __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
450       
451       hcec->State = HAL_CEC_STATE_READY;
452       __HAL_UNLOCK(hcec);
453       return  HAL_ERROR;
454     }
455     
456     /* Acknowledge successful completion by writing 0x00 */
457     MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00);
458     
459     hcec->State = HAL_CEC_STATE_READY;
460     __HAL_UNLOCK(hcec);
461     
462     return HAL_OK;
463   }
464   else
465   {
466     return HAL_BUSY;   
467   }
468 }
469
470 /**
471   * @brief Receive data in blocking mode. 
472   * @param hcec: CEC handle
473   * @param pData: pointer to received data buffer.
474   * @param Timeout: Timeout duration.
475   * @note  The received data size is not known beforehand, the latter is known
476   *        when the reception is complete and is stored in hcec->RxXferSize.  
477   *        hcec->RxXferSize is the sum of opcodes + operands (0 to 14 operands max).
478   *        If only a header is received, hcec->RxXferSize = 0    
479   * @retval HAL status
480   */
481 HAL_StatusTypeDef HAL_CEC_Receive(CEC_HandleTypeDef *hcec, uint8_t *pData, uint32_t Timeout)
482 {
483   uint32_t temp = 0;
484   uint32_t tickstart = 0;   
485
486   if(hcec->State == HAL_CEC_STATE_READY)
487   {
488     if(pData == NULL) 
489     {
490       return HAL_ERROR;
491     }
492     
493     /* When a ping is received, RxXferSize is 0*/
494     /* When a message is received, RxXferSize contains the number of received bytes */
495     hcec->RxXferSize = CEC_RXXFERSIZE_INITIALIZE; 
496     
497     /* Process Locked */
498     __HAL_LOCK(hcec);
499
500     hcec->ErrorCode = HAL_CEC_ERROR_NONE;
501     
502     /* Continue the reception until the End Of Message is received (CEC_FLAG_REOM) */
503     do
504     {
505       /* Timeout handling */
506       tickstart = HAL_GetTick();
507       
508       /* Wait for next byte to be received */
509       while (HAL_IS_BIT_CLR(hcec->Instance->CSR, CEC_FLAG_RBTF))
510       {
511         /* Timeout handling */
512         if(Timeout != HAL_MAX_DELAY)
513         {
514           if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
515           {
516             hcec->State = HAL_CEC_STATE_READY;
517             __HAL_UNLOCK(hcec);    
518             return HAL_TIMEOUT;
519           }
520         }
521         
522         /* Check if an error occured during the reception */
523         if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR))
524         {
525           /* Copy ESR for error handling purposes */
526           hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
527           
528           /* Acknowledgement of the error */
529           __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
530           
531           hcec->State = HAL_CEC_STATE_READY;
532           __HAL_UNLOCK(hcec);
533           return  HAL_ERROR;
534         }
535       }
536       
537       /* Keep the value of CSR register as the register is cleared during reception process */
538       temp = hcec->Instance->CSR;
539       
540       /* Read received data */
541       *pData++ = hcec->Instance->RXD;
542       
543       /* Acknowledge received byte by writing 0x00 */
544       CLEAR_BIT(hcec->Instance->CSR, CEC_FLAG_RECEIVE_MASK);
545       
546       /* Increment the number of received data */
547       if(hcec->RxXferSize == CEC_RXXFERSIZE_INITIALIZE)
548       {
549         hcec->RxXferSize = 0;
550       }
551       else
552       {
553         hcec->RxXferSize++;
554       }
555       
556     }while (HAL_IS_BIT_CLR(temp, CEC_FLAG_REOM));
557     
558     hcec->State = HAL_CEC_STATE_READY;
559     __HAL_UNLOCK(hcec);  
560     
561     if(IS_CEC_MSGSIZE(hcec->RxXferSize))
562     {
563       return HAL_OK;
564     }
565     else
566     {
567       return HAL_ERROR;
568     }
569   }
570   else
571   {
572     return HAL_BUSY;
573   }
574 }
575
576
577 /**
578   * @brief Send data in interrupt mode 
579   * @param hcec: CEC handle
580   * @param DestinationAddress: destination logical address      
581   * @param pData: pointer to input byte data buffer
582   * @param Size: amount of data to be sent in bytes (without counting the header).
583   *              0 means only the header is sent (ping operation).
584   *              Maximum TX size is 15 bytes (1 opcode and up to 14 operands).    
585   * @retval HAL status
586   */
587 HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t DestinationAddress, uint8_t *pData, uint32_t Size)
588 {
589   uint8_t  temp = 0;
590   uint32_t tmp_state = 0;
591   
592   tmp_state = hcec->State;
593   if(((tmp_state == HAL_CEC_STATE_READY) || (tmp_state == HAL_CEC_STATE_BUSY_RX))
594      && (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) == RESET)) 
595   {
596     
597     /* Basic check on pData pointer */
598     if(((pData == NULL) && (Size > 0)) || (! IS_CEC_MSGSIZE(Size))) 
599     {
600       return  HAL_ERROR;
601     }
602
603     assert_param(IS_CEC_ADDRESS(DestinationAddress));
604     
605     /* Process Locked */
606     __HAL_LOCK(hcec);
607     hcec->pTxBuffPtr = pData;
608     
609     /* Check if a receive process is ongoing or not */
610     if(hcec->State == HAL_CEC_STATE_BUSY_RX) 
611     {
612       hcec->State = HAL_CEC_STATE_BUSY_TX_RX;
613       
614       /* Interrupt are not enabled here because they are already enabled in the Reception process */
615     }
616     else
617     {
618       hcec->State = HAL_CEC_STATE_BUSY_TX;    
619       
620       /* Enable the CEC interrupt */
621       __HAL_CEC_ENABLE_IT(hcec, CEC_IT_IE);
622     }    
623     
624     hcec->ErrorCode = HAL_CEC_ERROR_NONE;
625     
626     /* initialize the number of bytes to send,
627      * 0 means only one header is sent (ping operation) */
628     hcec->TxXferCount = Size;
629
630     /* send header block */
631     temp = (uint8_t)((uint32_t)(hcec->Init.InitiatorAddress) << CEC_INITIATOR_LSB_POS) | DestinationAddress;
632     hcec->Instance->TXD = temp;
633     
634     /* Process Unlocked */
635     __HAL_UNLOCK(hcec); 
636
637     /* case no data to be sent, sender is only pinging the system */
638     if (Size != 0)
639     {    
640       /* Set TX Start of Message (TXSOM) bit */
641       MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TSOM);
642     }
643     else
644     {
645       /* Send a ping command */
646       MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM|CEC_FLAG_TSOM);
647     }
648     return HAL_OK;
649   }
650   else
651   {
652     return HAL_BUSY;   
653   }
654 }
655
656
657 /**
658   * @brief Receive data in interrupt mode. 
659   * @param hcec: CEC handle
660   * @param pData: pointer to received data buffer.
661   * @note  The received data size is not known beforehand, the latter is known
662   *        when the reception is complete and is stored in hcec->RxXferSize.  
663   *        hcec->RxXferSize is the sum of opcodes + operands (0 to 14 operands max).
664   *        If only a header is received, hcec->RxXferSize = 0    
665   * @retval HAL status
666   */
667 HAL_StatusTypeDef HAL_CEC_Receive_IT(CEC_HandleTypeDef *hcec, uint8_t *pData)
668 {
669   uint32_t tmp_state = 0;
670   tmp_state = hcec->State;
671   if((tmp_state == HAL_CEC_STATE_READY) || (tmp_state == HAL_CEC_STATE_BUSY_TX))
672   {
673     if(pData == NULL) 
674     {
675       return HAL_ERROR;                                    
676     }
677     
678     /* When a ping is received, RxXferSize is 0 */
679     /* When a message is received, RxXferSize contains the number of received bytes */
680     hcec->RxXferSize = CEC_RXXFERSIZE_INITIALIZE;
681     
682     /* Process Locked */
683     __HAL_LOCK(hcec);
684
685     hcec->pRxBuffPtr = pData;
686     hcec->ErrorCode = HAL_CEC_ERROR_NONE;
687
688     /* Process Unlocked */
689     __HAL_UNLOCK(hcec);
690     
691     /* Check if a transmit process is ongoing or not */
692     if(hcec->State == HAL_CEC_STATE_BUSY_TX)
693     {
694       hcec->State = HAL_CEC_STATE_BUSY_TX_RX;
695     }
696     else
697     {
698       hcec->State = HAL_CEC_STATE_BUSY_RX;    
699       
700       /* Enable CEC interrupt */
701       __HAL_CEC_ENABLE_IT(hcec, CEC_IT_IE);
702     }
703
704     return HAL_OK;
705   }
706   else
707   {
708     return HAL_BUSY; 
709   }
710 }
711
712 /**
713   * @brief Get size of the received frame.
714   * @param hcec: CEC handle
715   * @retval Frame size
716   */
717 uint32_t HAL_CEC_GetReceivedFrameSize(CEC_HandleTypeDef *hcec)
718 {
719   return hcec->RxXferSize;
720 }
721   
722 /**
723   * @brief This function handles CEC interrupt requests.
724   * @param hcec: CEC handle
725   * @retval None
726   */
727 void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec)
728 {
729   /* Save error status register for further error handling purposes */
730   hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
731
732   /* Transmit error */
733   if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TERR) != RESET))
734   {
735     /* Acknowledgement of the error */
736     __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
737     
738     /* Check if a receive process is ongoing or not */
739     if(hcec->State == HAL_CEC_STATE_BUSY_TX_RX) 
740     {
741       /* Interrupts are not disabled due to reception still ongoing */
742       
743       hcec->State = HAL_CEC_STATE_BUSY_RX;
744     }
745     else
746     {
747       /* Disable the CEC Transmission Interrupts */
748       __HAL_CEC_DISABLE_IT(hcec, CEC_IT_IE);
749     
750       hcec->State = HAL_CEC_STATE_READY;
751     }    
752   }
753   
754   /* Receive error */
755   if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RERR) != RESET))
756   {
757     /* Acknowledgement of the error */
758     __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
759     
760     /* Check if a transmit process is ongoing or not */
761     if(hcec->State == HAL_CEC_STATE_BUSY_TX_RX) 
762     {
763       /* Interrupts are not disabled due to reception still ongoing */
764       
765       hcec->State = HAL_CEC_STATE_BUSY_TX;
766     }
767     else
768     {
769       /* Disable the CEC Transmission Interrupts */
770       __HAL_CEC_DISABLE_IT(hcec, CEC_IT_IE);
771       
772       hcec->State = HAL_CEC_STATE_READY;
773     }
774   } 
775   
776   if ((hcec->ErrorCode & CEC_ESR_ALL_ERROR) != 0)
777   {
778     HAL_CEC_ErrorCallback(hcec);
779   }
780   
781   /* Transmit byte request or block transfer finished */
782   if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TBTRF) != RESET))
783   {
784     CEC_Transmit_IT(hcec);
785   }  
786
787   /* Receive byte or block transfer finished */
788   if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RBTF) != RESET))
789   {
790     CEC_Receive_IT(hcec);
791   }
792 }
793
794
795 /**
796   * @brief Tx Transfer completed callback
797   * @param hcec: CEC handle
798   * @retval None
799   */
800  __weak void HAL_CEC_TxCpltCallback(CEC_HandleTypeDef *hcec)
801 {
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   * @retval None
811   */
812 __weak void HAL_CEC_RxCpltCallback(CEC_HandleTypeDef *hcec)
813 {
814   /* NOTE : This function should not be modified, when the callback is needed,
815             the HAL_CEC_RxCpltCallback can be implemented in the user file
816    */
817 }
818
819 /**
820   * @brief CEC error callbacks
821   * @param hcec: CEC handle
822   * @retval None
823   */
824  __weak void HAL_CEC_ErrorCallback(CEC_HandleTypeDef *hcec)
825 {
826   /* NOTE : This function should not be modified, when the callback is needed,
827             the HAL_CEC_ErrorCallback can be implemented in the user file
828    */ 
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 functions #####
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 get the error code of a failed transmission or reception. 
846 @endverbatim
847   * @{
848   */
849
850 /**
851   * @brief return the CEC state
852   * @param hcec: CEC handle
853   * @retval HAL state
854   */
855 HAL_CEC_StateTypeDef HAL_CEC_GetState(CEC_HandleTypeDef *hcec)
856 {
857   return hcec->State;
858 }
859
860 /**
861 * @brief  Return the CEC error code
862 * @param  hcec : pointer to a CEC_HandleTypeDef structure that contains
863   *              the configuration information for the specified CEC.
864 * @retval CEC Error Code
865 */
866 uint32_t HAL_CEC_GetError(CEC_HandleTypeDef *hcec)
867 {
868   return hcec->ErrorCode;
869 }
870
871 /**
872   * @}
873   */
874
875 /**
876   * @}
877   */
878
879 /** @addtogroup CEC_Private_Functions
880   * @{
881   */
882
883  /**
884   * @brief Send data in interrupt mode 
885   * @param hcec: CEC handle. 
886   *         Function called under interruption only, once
887   *         interruptions have been enabled by HAL_CEC_Transmit_IT()   
888   * @retval HAL status
889   */  
890 static HAL_StatusTypeDef CEC_Transmit_IT(CEC_HandleTypeDef *hcec)
891 {
892   uint32_t tmp_state = 0;
893   
894   tmp_state = hcec->State;
895   /* if the IP is already busy or if there is a previous transmission
896      already pending due to arbitration loss */
897   if(((tmp_state == HAL_CEC_STATE_BUSY_TX) || (tmp_state == HAL_CEC_STATE_BUSY_TX_RX))
898         || (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) != RESET))
899   {
900     /* if all data have been sent */
901     if(hcec->TxXferCount == 0)
902     {
903       /* Acknowledge successful completion by writing 0x00 */
904       MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00);
905
906       /* Check if a receive process is ongoing or not */
907       if(hcec->State == HAL_CEC_STATE_BUSY_TX_RX) 
908       {
909         /* Interrupts are not disabled due to reception still ongoing */
910         
911         hcec->State = HAL_CEC_STATE_BUSY_RX;
912       }
913       else
914       {
915         /* Disable the CEC Transmission Interrupts */
916         __HAL_CEC_DISABLE_IT(hcec, CEC_IT_IE);
917       
918         hcec->State = HAL_CEC_STATE_READY;
919       }
920       
921       HAL_CEC_TxCpltCallback(hcec);
922       
923       return HAL_OK;
924     }
925     else
926     {
927       /* Reduce the number of bytes to transfer by one */
928       hcec->TxXferCount--;
929       
930       /* Write data to TX buffer*/
931       hcec->Instance->TXD = *hcec->pTxBuffPtr++;
932       
933       /* If this is the last byte of the ongoing transmission */
934       if (hcec->TxXferCount == 0)
935       {
936         /* Acknowledge byte request and signal end of message */
937         MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM);
938       }
939       else
940       {
941         /* Acknowledge byte request by writing 0x00 */
942         MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00);
943       }  
944       
945       return HAL_OK;
946     }
947   }
948   else
949   {
950     return HAL_BUSY;   
951   }
952 }
953
954 /**
955   * @brief Receive data in interrupt mode. 
956   * @param hcec: CEC handle.
957   *         Function called under interruption only, once
958   *         interruptions have been enabled by HAL_CEC_Receive_IT()   
959   * @retval HAL status
960   */  
961 static HAL_StatusTypeDef CEC_Receive_IT(CEC_HandleTypeDef *hcec)
962 {
963   static uint32_t temp;
964   uint32_t tmp_state = 0;
965
966   tmp_state = hcec->State; 
967   if((tmp_state == HAL_CEC_STATE_BUSY_RX) || (tmp_state == HAL_CEC_STATE_BUSY_TX_RX)) 
968   {
969     temp = hcec->Instance->CSR;
970     
971     /* Store received data */
972     *hcec->pRxBuffPtr++ = hcec->Instance->RXD;
973     
974     /* Acknowledge received byte by writing 0x00 */
975     MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_RECEIVE_MASK, 0x00);
976     
977     /* Increment the number of received data */
978     if(hcec->RxXferSize == CEC_RXXFERSIZE_INITIALIZE)
979     {
980       hcec->RxXferSize = 0;
981     }
982     else
983     {
984       hcec->RxXferSize++;
985     }
986     
987     /* If the End Of Message is reached */
988     if(HAL_IS_BIT_SET(temp, CEC_FLAG_REOM))
989     {
990       if(hcec->State == HAL_CEC_STATE_BUSY_TX_RX) 
991       {
992         /* Interrupts are not disabled due to transmission still ongoing */
993         
994         hcec->State = HAL_CEC_STATE_BUSY_TX;
995       }
996       else
997       {
998         /* Disable the CEC Transmission Interrupts */
999         __HAL_CEC_DISABLE_IT(hcec, CEC_IT_IE);
1000         
1001         hcec->State = HAL_CEC_STATE_READY;
1002       }
1003
1004       HAL_CEC_RxCpltCallback(hcec);
1005
1006       return HAL_OK;
1007     }    
1008     else
1009     {
1010       return HAL_BUSY; 
1011     }
1012   }
1013   else
1014   {
1015     return HAL_BUSY; 
1016   }
1017 }
1018
1019 /**
1020  * @}
1021  */ 
1022  
1023 /**
1024   * @}
1025   */
1026
1027 #endif /* defined(STM32F100xB) || defined(STM32F100xE) */
1028
1029 #endif /* HAL_CEC_MODULE_ENABLED */
1030 /**
1031   * @}
1032   */
1033
1034 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/