Subversion Repositories DashDisplay

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 mjames 1
/**
2
  ******************************************************************************
3
  * @file    stm32f1xx_hal_cec.c
4
  * @author  MCD Application Team
5 mjames 5
  * @version V1.0.4
6
  * @date    29-April-2016
2 mjames 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
  *
5 mjames 43
  * <h2><center>&copy; COPYRIGHT(c) 2016 STMicroelectronics</center></h2>
2 mjames 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
{
5 mjames 238
  /* Prevent unused argument(s) compilation warning */
239
  UNUSED(hcec);
2 mjames 240
  /* NOTE : This function should not be modified, when the callback is needed,
241
            the HAL_CEC_MspInit can be implemented in the user file
242
   */
243
}
244
 
245
/**
246
  * @brief CEC MSP DeInit
247
  * @param hcec: CEC handle
248
  * @retval None
249
  */
250
 __weak void HAL_CEC_MspDeInit(CEC_HandleTypeDef *hcec)
251
{
5 mjames 252
  /* Prevent unused argument(s) compilation warning */
253
  UNUSED(hcec);
2 mjames 254
  /* NOTE : This function should not be modified, when the callback is needed,
255
            the HAL_CEC_MspDeInit can be implemented in the user file
256
   */
257
}
258
 
259
/**
260
  * @}
261
  */
262
 
263
/** @defgroup CEC_Exported_Functions_Group2 Input and Output operation functions
264
  *  @brief CEC Transmit/Receive functions
265
  *
266
@verbatim  
267
 ===============================================================================
268
                      ##### IO operation functions #####
269
 ===============================================================================  
270
    [..]
271
    This subsection provides a set of functions allowing to manage the CEC data transfers.
272
 
273
    (#) There are two modes of transfer:
274
       (##) Blocking mode: The communication is performed in polling mode.
275
            The HAL status of all data processing is returned by the same function
276
            after finishing transfer.  
277
       (##) No-Blocking mode: The communication is performed using Interrupts.
278
           These API's return the HAL status.
279
           The end of the data processing will be indicated through the
280
           dedicated CEC IRQ when using Interrupt mode.
281
           The HAL_CEC_TxCpltCallback(), HAL_CEC_RxCpltCallback() user callbacks
282
           will be executed respectivelly at the end of the Transmit or Receive process.
283
           The HAL_CEC_ErrorCallback()user callback will be executed when a communication
284
           error is detected
285
    (#) Blocking mode API's are :
286
        (##) HAL_CEC_Transmit()
287
        (##) HAL_CEC_Receive()
288
    (#) Non-Blocking mode API's with Interrupt are :
289
        (##) HAL_CEC_Transmit_IT()
290
        (##) HAL_CEC_Receive_IT()
291
        (##) HAL_CEC_IRQHandler()
292
    (#) A set of Transfer Complete Callbacks are provided in No_Blocking mode:
293
        (##) HAL_CEC_TxCpltCallback()
294
        (##) HAL_CEC_RxCpltCallback()
295
        (##) HAL_CEC_ErrorCallback()
296
 
297
@endverbatim
298
  * @{
299
  */
300
 
301
/**
302
  * @brief Send data in blocking mode
303
  * @param hcec: CEC handle
304
  * @param DestinationAddress: destination logical address      
305
  * @param pData: pointer to input byte data buffer
306
  * @param Size: amount of data to be sent in bytes (without counting the header).
307
  *              0 means only the header is sent (ping operation).
308
  *              Maximum TX size is 15 bytes (1 opcode and up to 14 operands).    
309
  * @param  Timeout: Timeout duration.
310
  * @retval HAL status
311
  */
312
HAL_StatusTypeDef HAL_CEC_Transmit(CEC_HandleTypeDef *hcec, uint8_t DestinationAddress, uint8_t *pData, uint32_t Size, uint32_t Timeout)
313
{
314
  uint8_t  temp = 0;
315
  uint32_t tickstart = 0;
316
 
317
  /* If the IP is ready */
318
  if((hcec->State == HAL_CEC_STATE_READY)
319
     && (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) == RESET))
320
  {
321
    /* Basic check on pData pointer */
322
    if(((pData == NULL) && (Size > 0)) || (! IS_CEC_MSGSIZE(Size)))
323
    {
324
      return  HAL_ERROR;
325
    }
326
 
327
    assert_param(IS_CEC_ADDRESS(DestinationAddress));
328
 
329
    /* Process Locked */
330
    __HAL_LOCK(hcec);
331
 
332
    /* Enter the transmit mode */
333
    hcec->State = HAL_CEC_STATE_BUSY_TX;
334
    hcec->ErrorCode = HAL_CEC_ERROR_NONE;
335
 
336
    /* Initialize the number of bytes to send,
337
     * 0 means only one header is sent (ping operation) */
338
    hcec->TxXferCount = Size;
339
 
340
    /* Send header block */
341
    temp = (uint8_t)((uint32_t)(hcec->Init.InitiatorAddress) << CEC_INITIATOR_LSB_POS) | DestinationAddress;
342
    hcec->Instance->TXD = temp;
343
 
344
    /* In case no data to be sent, sender is only pinging the system */
345
    if (Size != 0)
346
    {    
347
      /* Set TX Start of Message (TXSOM) bit */
348
      hcec->Instance->CSR = CEC_FLAG_TSOM;
349
    }
350
    else
351
    {
352
      /* Send a ping command */
353
      hcec->Instance->CSR = CEC_FLAG_TEOM|CEC_FLAG_TSOM;
354
    }
355
 
356
    /* Polling TBTRF bit with timeout handling*/
357
    while (hcec->TxXferCount > 0)
358
    {
359
      /* Decreasing of the number of remaining data to receive */
360
      hcec->TxXferCount--;
361
 
362
      /* Timeout handling */
363
      tickstart = HAL_GetTick();
364
 
365
      /* Waiting for the next data transmission */
366
      while(HAL_IS_BIT_CLR(hcec->Instance->CSR, CEC_FLAG_TBTRF))
367
      {
368
        /* Timeout handling */
369
        if(Timeout != HAL_MAX_DELAY)
370
        {
371
          if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
372
          {
373
            hcec->State = HAL_CEC_STATE_READY;
374
            /* Process Unlocked */
375
            __HAL_UNLOCK(hcec);  
376
            return HAL_TIMEOUT;
377
          }
378
        }        
379
 
380
        /* Check if an error occured */
381
        if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_TERR) || HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR))
382
        {
383
          /* Copy ESR for error handling purposes */
384
          hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
385
 
386
          /* Acknowledgement of the error */
387
          __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
388
          __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
389
 
390
          hcec->State = HAL_CEC_STATE_READY;
391
          __HAL_UNLOCK(hcec);
392
          return  HAL_ERROR;                                    
393
        }
394
      }
395
 
396
      /* Write the next data to TX buffer */
397
      hcec->Instance->TXD = *pData++;
398
 
399
      /* If this is the last byte of the ongoing transmission */
400
      if (hcec->TxXferCount == 0)
401
      {
402
        /* Acknowledge byte request and signal end of message */
403
        MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM);
404
      }
405
      else
406
      {
407
        /* Acknowledge byte request by writing 0x00 */
408
        MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00);
409
      }
410
    }
411
 
412
    /* Timeout handling */
413
    tickstart = HAL_GetTick();
414
 
415
    /* Wait for message transmission completion (TBTRF is set) */
416
    while (HAL_IS_BIT_CLR(hcec->Instance->CSR, CEC_FLAG_TBTRF))
417
    {
418
      /* Timeout handling */
419
      if(Timeout != HAL_MAX_DELAY)
420
      {
421
        if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
422
        {
423
          hcec->State = HAL_CEC_STATE_READY;
424
          __HAL_UNLOCK(hcec);            
425
          return HAL_TIMEOUT;
426
        }
427
      }
428
 
429
      /* Check of error during transmission of the last byte */
430
      if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_TERR) || HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR))
431
      {
432
        /* Copy ESR for error handling purposes */
433
        hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
434
 
435
        /* Acknowledgement of the error */
436
        __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
437
        __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
438
 
439
        hcec->State = HAL_CEC_STATE_READY;
440
        __HAL_UNLOCK(hcec);
441
        return  HAL_ERROR;                                    
442
      }
443
    }
444
 
445
    /* Check of error after the last byte transmission */
446
    if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_TERR) || HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR))
447
    {
448
      /* Copy ESR for error handling purposes */
449
      hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
450
 
451
      /* Acknowledgement of the error */
452
      __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
453
      __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
454
 
455
      hcec->State = HAL_CEC_STATE_READY;
456
      __HAL_UNLOCK(hcec);
457
      return  HAL_ERROR;
458
    }
459
 
460
    /* Acknowledge successful completion by writing 0x00 */
461
    MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00);
462
 
463
    hcec->State = HAL_CEC_STATE_READY;
464
    __HAL_UNLOCK(hcec);
465
 
466
    return HAL_OK;
467
  }
468
  else
469
  {
470
    return HAL_BUSY;  
471
  }
472
}
473
 
474
/**
475
  * @brief Receive data in blocking mode.
476
  * @param hcec: CEC handle
477
  * @param pData: pointer to received data buffer.
478
  * @param Timeout: Timeout duration.
479
  * @note  The received data size is not known beforehand, the latter is known
480
  *        when the reception is complete and is stored in hcec->RxXferSize.  
481
  *        hcec->RxXferSize is the sum of opcodes + operands (0 to 14 operands max).
482
  *        If only a header is received, hcec->RxXferSize = 0    
483
  * @retval HAL status
484
  */
485
HAL_StatusTypeDef HAL_CEC_Receive(CEC_HandleTypeDef *hcec, uint8_t *pData, uint32_t Timeout)
486
{
487
  uint32_t temp = 0;
488
  uint32_t tickstart = 0;  
489
 
490
  if(hcec->State == HAL_CEC_STATE_READY)
491
  {
492
    if(pData == NULL)
493
    {
494
      return HAL_ERROR;
495
    }
496
 
497
    /* When a ping is received, RxXferSize is 0*/
498
    /* When a message is received, RxXferSize contains the number of received bytes */
499
    hcec->RxXferSize = CEC_RXXFERSIZE_INITIALIZE;
500
 
501
    /* Process Locked */
502
    __HAL_LOCK(hcec);
503
 
504
    hcec->ErrorCode = HAL_CEC_ERROR_NONE;
505
 
506
    /* Continue the reception until the End Of Message is received (CEC_FLAG_REOM) */
507
    do
508
    {
509
      /* Timeout handling */
510
      tickstart = HAL_GetTick();
511
 
512
      /* Wait for next byte to be received */
513
      while (HAL_IS_BIT_CLR(hcec->Instance->CSR, CEC_FLAG_RBTF))
514
      {
515
        /* Timeout handling */
516
        if(Timeout != HAL_MAX_DELAY)
517
        {
518
          if((Timeout == 0) || ((HAL_GetTick()-tickstart) > Timeout))
519
          {
520
            hcec->State = HAL_CEC_STATE_READY;
521
            __HAL_UNLOCK(hcec);    
522
            return HAL_TIMEOUT;
523
          }
524
        }
525
 
526
        /* Check if an error occured during the reception */
527
        if(HAL_IS_BIT_SET(hcec->Instance->CSR, CEC_FLAG_RERR))
528
        {
529
          /* Copy ESR for error handling purposes */
530
          hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
531
 
532
          /* Acknowledgement of the error */
533
          __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
534
 
535
          hcec->State = HAL_CEC_STATE_READY;
536
          __HAL_UNLOCK(hcec);
537
          return  HAL_ERROR;
538
        }
539
      }
540
 
541
      /* Keep the value of CSR register as the register is cleared during reception process */
542
      temp = hcec->Instance->CSR;
543
 
544
      /* Read received data */
545
      *pData++ = hcec->Instance->RXD;
546
 
547
      /* Acknowledge received byte by writing 0x00 */
548
      CLEAR_BIT(hcec->Instance->CSR, CEC_FLAG_RECEIVE_MASK);
549
 
550
      /* Increment the number of received data */
551
      if(hcec->RxXferSize == CEC_RXXFERSIZE_INITIALIZE)
552
      {
553
        hcec->RxXferSize = 0;
554
      }
555
      else
556
      {
557
        hcec->RxXferSize++;
558
      }
559
 
560
    }while (HAL_IS_BIT_CLR(temp, CEC_FLAG_REOM));
561
 
562
    hcec->State = HAL_CEC_STATE_READY;
563
    __HAL_UNLOCK(hcec);  
564
 
565
    if(IS_CEC_MSGSIZE(hcec->RxXferSize))
566
    {
567
      return HAL_OK;
568
    }
569
    else
570
    {
571
      return HAL_ERROR;
572
    }
573
  }
574
  else
575
  {
576
    return HAL_BUSY;
577
  }
578
}
579
 
580
 
581
/**
582
  * @brief Send data in interrupt mode
583
  * @param hcec: CEC handle
584
  * @param DestinationAddress: destination logical address      
585
  * @param pData: pointer to input byte data buffer
586
  * @param Size: amount of data to be sent in bytes (without counting the header).
587
  *              0 means only the header is sent (ping operation).
588
  *              Maximum TX size is 15 bytes (1 opcode and up to 14 operands).    
589
  * @retval HAL status
590
  */
591
HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t DestinationAddress, uint8_t *pData, uint32_t Size)
592
{
593
  uint8_t  temp = 0;
594
  uint32_t tmp_state = 0;
595
 
596
  tmp_state = hcec->State;
597
  if(((tmp_state == HAL_CEC_STATE_READY) || (tmp_state == HAL_CEC_STATE_BUSY_RX))
598
     && (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) == RESET))
599
  {
600
 
601
    /* Basic check on pData pointer */
602
    if(((pData == NULL) && (Size > 0)) || (! IS_CEC_MSGSIZE(Size)))
603
    {
604
      return  HAL_ERROR;
605
    }
606
 
607
    assert_param(IS_CEC_ADDRESS(DestinationAddress));
608
 
609
    /* Process Locked */
610
    __HAL_LOCK(hcec);
611
    hcec->pTxBuffPtr = pData;
612
 
613
    /* Check if a receive process is ongoing or not */
614
    if(hcec->State == HAL_CEC_STATE_BUSY_RX)
615
    {
616
      hcec->State = HAL_CEC_STATE_BUSY_TX_RX;
617
 
618
      /* Interrupt are not enabled here because they are already enabled in the Reception process */
619
    }
620
    else
621
    {
622
      hcec->State = HAL_CEC_STATE_BUSY_TX;    
623
 
624
      /* Enable the CEC interrupt */
625
      __HAL_CEC_ENABLE_IT(hcec, CEC_IT_IE);
626
    }    
627
 
628
    hcec->ErrorCode = HAL_CEC_ERROR_NONE;
629
 
630
    /* initialize the number of bytes to send,
631
     * 0 means only one header is sent (ping operation) */
632
    hcec->TxXferCount = Size;
633
 
634
    /* send header block */
635
    temp = (uint8_t)((uint32_t)(hcec->Init.InitiatorAddress) << CEC_INITIATOR_LSB_POS) | DestinationAddress;
636
    hcec->Instance->TXD = temp;
637
 
638
    /* Process Unlocked */
639
    __HAL_UNLOCK(hcec);
640
 
641
    /* case no data to be sent, sender is only pinging the system */
642
    if (Size != 0)
643
    {    
644
      /* Set TX Start of Message (TXSOM) bit */
645
      MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TSOM);
646
    }
647
    else
648
    {
649
      /* Send a ping command */
650
      MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM|CEC_FLAG_TSOM);
651
    }
652
    return HAL_OK;
653
  }
654
  else
655
  {
656
    return HAL_BUSY;  
657
  }
658
}
659
 
660
 
661
/**
662
  * @brief Receive data in interrupt mode.
663
  * @param hcec: CEC handle
664
  * @param pData: pointer to received data buffer.
665
  * @note  The received data size is not known beforehand, the latter is known
666
  *        when the reception is complete and is stored in hcec->RxXferSize.  
667
  *        hcec->RxXferSize is the sum of opcodes + operands (0 to 14 operands max).
668
  *        If only a header is received, hcec->RxXferSize = 0    
669
  * @retval HAL status
670
  */
671
HAL_StatusTypeDef HAL_CEC_Receive_IT(CEC_HandleTypeDef *hcec, uint8_t *pData)
672
{
673
  uint32_t tmp_state = 0;
674
  tmp_state = hcec->State;
675
  if((tmp_state == HAL_CEC_STATE_READY) || (tmp_state == HAL_CEC_STATE_BUSY_TX))
676
  {
677
    if(pData == NULL)
678
    {
679
      return HAL_ERROR;                                    
680
    }
681
 
682
    /* When a ping is received, RxXferSize is 0 */
683
    /* When a message is received, RxXferSize contains the number of received bytes */
684
    hcec->RxXferSize = CEC_RXXFERSIZE_INITIALIZE;
685
 
686
    /* Process Locked */
687
    __HAL_LOCK(hcec);
688
 
689
    hcec->pRxBuffPtr = pData;
690
    hcec->ErrorCode = HAL_CEC_ERROR_NONE;
691
 
692
    /* Process Unlocked */
693
    __HAL_UNLOCK(hcec);
694
 
695
    /* Check if a transmit process is ongoing or not */
696
    if(hcec->State == HAL_CEC_STATE_BUSY_TX)
697
    {
698
      hcec->State = HAL_CEC_STATE_BUSY_TX_RX;
699
    }
700
    else
701
    {
702
      hcec->State = HAL_CEC_STATE_BUSY_RX;    
703
 
704
      /* Enable CEC interrupt */
705
      __HAL_CEC_ENABLE_IT(hcec, CEC_IT_IE);
706
    }
707
 
708
    return HAL_OK;
709
  }
710
  else
711
  {
712
    return HAL_BUSY;
713
  }
714
}
715
 
716
/**
717
  * @brief Get size of the received frame.
718
  * @param hcec: CEC handle
719
  * @retval Frame size
720
  */
721
uint32_t HAL_CEC_GetReceivedFrameSize(CEC_HandleTypeDef *hcec)
722
{
723
  return hcec->RxXferSize;
724
}
725
 
726
/**
727
  * @brief This function handles CEC interrupt requests.
728
  * @param hcec: CEC handle
729
  * @retval None
730
  */
731
void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec)
732
{
733
  /* Save error status register for further error handling purposes */
734
  hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
735
 
736
  /* Transmit error */
737
  if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TERR) != RESET))
738
  {
739
    /* Acknowledgement of the error */
740
    __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
741
 
742
    /* Check if a receive process is ongoing or not */
743
    if(hcec->State == HAL_CEC_STATE_BUSY_TX_RX)
744
    {
745
      /* Interrupts are not disabled due to reception still ongoing */
746
 
747
      hcec->State = HAL_CEC_STATE_BUSY_RX;
748
    }
749
    else
750
    {
751
      /* Disable the CEC Transmission Interrupts */
752
      __HAL_CEC_DISABLE_IT(hcec, CEC_IT_IE);
753
 
754
      hcec->State = HAL_CEC_STATE_READY;
755
    }    
756
  }
757
 
758
  /* Receive error */
759
  if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RERR) != RESET))
760
  {
761
    /* Acknowledgement of the error */
762
    __HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_RERR);
763
 
764
    /* Check if a transmit process is ongoing or not */
765
    if(hcec->State == HAL_CEC_STATE_BUSY_TX_RX)
766
    {
767
      /* Interrupts are not disabled due to reception still ongoing */
768
 
769
      hcec->State = HAL_CEC_STATE_BUSY_TX;
770
    }
771
    else
772
    {
773
      /* Disable the CEC Transmission Interrupts */
774
      __HAL_CEC_DISABLE_IT(hcec, CEC_IT_IE);
775
 
776
      hcec->State = HAL_CEC_STATE_READY;
777
    }
778
  }
779
 
780
  if ((hcec->ErrorCode & CEC_ESR_ALL_ERROR) != 0)
781
  {
782
    HAL_CEC_ErrorCallback(hcec);
783
  }
784
 
785
  /* Transmit byte request or block transfer finished */
786
  if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_TBTRF) != RESET))
787
  {
788
    CEC_Transmit_IT(hcec);
789
  }  
790
 
791
  /* Receive byte or block transfer finished */
792
  if((__HAL_CEC_GET_FLAG(hcec, CEC_FLAG_RBTF) != RESET))
793
  {
794
    CEC_Receive_IT(hcec);
795
  }
796
}
797
 
798
 
799
/**
800
  * @brief Tx Transfer completed callback
801
  * @param hcec: CEC handle
802
  * @retval None
803
  */
804
 __weak void HAL_CEC_TxCpltCallback(CEC_HandleTypeDef *hcec)
805
{
5 mjames 806
  /* Prevent unused argument(s) compilation warning */
807
  UNUSED(hcec);
2 mjames 808
  /* NOTE : This function should not be modified, when the callback is needed,
809
            the HAL_CEC_TxCpltCallback can be implemented in the user file
810
   */
811
}
812
 
813
/**
814
  * @brief Rx Transfer completed callback
815
  * @param hcec: CEC handle
816
  * @retval None
817
  */
818
__weak void HAL_CEC_RxCpltCallback(CEC_HandleTypeDef *hcec)
819
{
5 mjames 820
  /* Prevent unused argument(s) compilation warning */
821
  UNUSED(hcec);
2 mjames 822
  /* NOTE : This function should not be modified, when the callback is needed,
823
            the HAL_CEC_RxCpltCallback can be implemented in the user file
824
   */
825
}
826
 
827
/**
828
  * @brief CEC error callbacks
829
  * @param hcec: CEC handle
830
  * @retval None
831
  */
832
 __weak void HAL_CEC_ErrorCallback(CEC_HandleTypeDef *hcec)
833
{
5 mjames 834
  /* Prevent unused argument(s) compilation warning */
835
  UNUSED(hcec);
2 mjames 836
  /* NOTE : This function should not be modified, when the callback is needed,
837
            the HAL_CEC_ErrorCallback can be implemented in the user file
838
   */
839
}
840
 
841
/**
842
  * @}
843
  */
844
 
845
/** @defgroup CEC_Exported_Functions_Group3 Peripheral Control functions
846
  *  @brief   CEC control functions
847
  *
848
@verbatim  
849
 ===============================================================================
850
                      ##### Peripheral Control functions #####
851
 ===============================================================================  
852
    [..]
853
    This subsection provides a set of functions allowing to control the CEC.
854
     (+) HAL_CEC_GetState() API can be helpful to check in run-time the state of the CEC peripheral.
855
     (+) HAL_CEC_GetError() API can be helpful to get the error code of a failed transmission or reception.
856
@endverbatim
857
  * @{
858
  */
859
 
860
/**
861
  * @brief return the CEC state
862
  * @param hcec: CEC handle
863
  * @retval HAL state
864
  */
865
HAL_CEC_StateTypeDef HAL_CEC_GetState(CEC_HandleTypeDef *hcec)
866
{
867
  return hcec->State;
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
*/
876
uint32_t HAL_CEC_GetError(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
  */  
900
static HAL_StatusTypeDef CEC_Transmit_IT(CEC_HandleTypeDef *hcec)
901
{
902
  uint32_t tmp_state = 0;
903
 
904
  tmp_state = hcec->State;
905
  /* if the IP is already busy or if there is a previous transmission
906
     already pending due to arbitration loss */
907
  if(((tmp_state == HAL_CEC_STATE_BUSY_TX) || (tmp_state == HAL_CEC_STATE_BUSY_TX_RX))
908
        || (__HAL_CEC_GET_TRANSMISSION_START_FLAG(hcec) != RESET))
909
  {
910
    /* if all data have been sent */
911
    if(hcec->TxXferCount == 0)
912
    {
913
      /* Acknowledge successful completion by writing 0x00 */
914
      MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00);
915
 
916
      /* Check if a receive process is ongoing or not */
917
      if(hcec->State == HAL_CEC_STATE_BUSY_TX_RX)
918
      {
919
        /* Interrupts are not disabled due to reception still ongoing */
920
 
921
        hcec->State = HAL_CEC_STATE_BUSY_RX;
922
      }
923
      else
924
      {
925
        /* Disable the CEC Transmission Interrupts */
926
        __HAL_CEC_DISABLE_IT(hcec, CEC_IT_IE);
927
 
928
        hcec->State = HAL_CEC_STATE_READY;
929
      }
930
 
931
      HAL_CEC_TxCpltCallback(hcec);
932
 
933
      return HAL_OK;
934
    }
935
    else
936
    {
937
      /* Reduce the number of bytes to transfer by one */
938
      hcec->TxXferCount--;
939
 
940
      /* Write data to TX buffer*/
941
      hcec->Instance->TXD = *hcec->pTxBuffPtr++;
942
 
943
      /* If this is the last byte of the ongoing transmission */
944
      if (hcec->TxXferCount == 0)
945
      {
946
        /* Acknowledge byte request and signal end of message */
947
        MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, CEC_FLAG_TEOM);
948
      }
949
      else
950
      {
951
        /* Acknowledge byte request by writing 0x00 */
952
        MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_TRANSMIT_MASK, 0x00);
953
      }  
954
 
955
      return HAL_OK;
956
    }
957
  }
958
  else
959
  {
960
    return HAL_BUSY;  
961
  }
962
}
963
 
964
/**
965
  * @brief Receive data in interrupt mode.
966
  * @param hcec: CEC handle.
967
  *         Function called under interruption only, once
968
  *         interruptions have been enabled by HAL_CEC_Receive_IT()  
969
  * @retval HAL status
970
  */  
971
static HAL_StatusTypeDef CEC_Receive_IT(CEC_HandleTypeDef *hcec)
972
{
973
  static uint32_t temp;
974
  uint32_t tmp_state = 0;
975
 
976
  tmp_state = hcec->State;
977
  if((tmp_state == HAL_CEC_STATE_BUSY_RX) || (tmp_state == HAL_CEC_STATE_BUSY_TX_RX))
978
  {
979
    temp = hcec->Instance->CSR;
980
 
981
    /* Store received data */
982
    *hcec->pRxBuffPtr++ = hcec->Instance->RXD;
983
 
984
    /* Acknowledge received byte by writing 0x00 */
985
    MODIFY_REG(hcec->Instance->CSR, CEC_FLAG_RECEIVE_MASK, 0x00);
986
 
987
    /* Increment the number of received data */
988
    if(hcec->RxXferSize == CEC_RXXFERSIZE_INITIALIZE)
989
    {
990
      hcec->RxXferSize = 0;
991
    }
992
    else
993
    {
994
      hcec->RxXferSize++;
995
    }
996
 
997
    /* If the End Of Message is reached */
998
    if(HAL_IS_BIT_SET(temp, CEC_FLAG_REOM))
999
    {
1000
      if(hcec->State == HAL_CEC_STATE_BUSY_TX_RX)
1001
      {
1002
        /* Interrupts are not disabled due to transmission still ongoing */
1003
 
1004
        hcec->State = HAL_CEC_STATE_BUSY_TX;
1005
      }
1006
      else
1007
      {
1008
        /* Disable the CEC Transmission Interrupts */
1009
        __HAL_CEC_DISABLE_IT(hcec, CEC_IT_IE);
1010
 
1011
        hcec->State = HAL_CEC_STATE_READY;
1012
      }
1013
 
1014
      HAL_CEC_RxCpltCallback(hcec);
1015
 
1016
      return HAL_OK;
1017
    }    
1018
    else
1019
    {
1020
      return HAL_BUSY;
1021
    }
1022
  }
1023
  else
1024
  {
1025
    return HAL_BUSY;
1026
  }
1027
}
1028
 
1029
/**
1030
 * @}
1031
 */
1032
 
1033
/**
1034
  * @}
1035
  */
1036
 
1037
#endif /* defined(STM32F100xB) || defined(STM32F100xE) */
1038
 
1039
#endif /* HAL_CEC_MODULE_ENABLED */
1040
/**
1041
  * @}
1042
  */
1043
 
1044
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/