📄 stm32100e_eval_cec.c
字号:
/**
******************************************************************************
* @file stm32100e_eval_cec.c
* @author MCD Application Team
* @version V4.5.0
* @date 07-March-2011
* @brief This file provides all the STM32100E-EVAL HDMI-CEC firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32100e_eval_cec.h"
/** @addtogroup Utilities
* @{
*/
/** @addtogroup STM32_EVAL
* @{
*/
/** @addtogroup STM32100E_EVAL
* @{
*/
/** @defgroup STM32100E_EVAL_CEC
* @brief This file includes the CEC Stack driver for HDMI-CEC Module
* of STM32100E-EVAL board.
* @{
*/
/** @defgroup STM32100E_EVAL_CEC_Private_Types
* @{
*/
/**
* @}
*/
/** @defgroup STM32100E_EVAL_CEC_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup STM32100E_EVAL_CEC_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup STM32100E_EVAL_CEC_Private_Variables
* @{
*/
__IO uint32_t ReceivedFrame = 0;
__IO uint32_t SendFrame = 0;
__IO uint32_t BufferCount = 0, TxCounter = 0, RxCounter = 0;
__IO uint8_t BufferPointer[15];
__IO uint32_t ReceiveStatus = 0;
__IO uint32_t SendStatus = 0;
__IO uint8_t TransErrorCode = 0;
__IO uint8_t RecepErrorCode = 0;
__IO uint8_t MyLogicalAddress = 0;
__IO uint16_t MyPhysicalAddress = 0;
__IO uint8_t DeviceType = 0;
#ifdef HDMI_CEC_USE_DDC
__IO uint8_t pBuffer[256];
__IO uint16_t NumByteToRead = 255;
#endif
__IO uint8_t CECDevicesNumber = 0;
HDMI_CEC_Message HDMI_CEC_TX_MessageStructPrivate;
HDMI_CEC_Message HDMI_CEC_RX_MessageStructPrivate;
HDMI_CEC_Message HDMI_CEC_TX_MessageStructure;
__IO uint8_t FeatureOpcode = 0;
__IO uint8_t AbortReason = 0;
__IO uint8_t DeviceCount = 0;
HDMI_CEC_Map HDMI_CEC_MapStruct;
HDMI_CEC_Map HDMI_CEC_DeviceMap[14];
/* CEC follower addresses */
uint8_t* HDMI_CEC_Follower_String[13][2] =
{
{(uint8_t*)" TV ", (uint8_t*)"0"},
{(uint8_t*)"Recording Device 1 ", (uint8_t*)"0"},
{(uint8_t*)"Recording Device 2 ", (uint8_t*)"0"},
{(uint8_t*)" Tuner 1 ", (uint8_t*)"0"},
{(uint8_t*)" Playback Device 1 ", (uint8_t*)"0"},
{(uint8_t*)" Audio System ", (uint8_t*)"0"},
{(uint8_t*)" Tuner 2 ", (uint8_t*)"0"},
{(uint8_t*)" Tuner 3 ", (uint8_t*)"0"},
{(uint8_t*)" Playback Device 2 ", (uint8_t*)"0"},
{(uint8_t*)"Recording Device 3 ", (uint8_t*)"0"},
{(uint8_t*)" Tuner 4 ", (uint8_t*)"0"},
{(uint8_t*)" Playback Device 3 ", (uint8_t*)"0"},
{(uint8_t*)" Broadcast ", (uint8_t*)"1"}
};
/**
* @}
*/
/** @defgroup STM32100E_EVAL_CEC_Private_Function_Prototypes
* @{
*/
static HDMI_CEC_Error PhysicalAddressDiscovery(void);
static HDMI_CEC_Error LogicalAddressAllocation(void);
/**
* @}
*/
/** @defgroup STM32100E_EVAL_CEC_Private_Functions
* @{
*/
/**
* @brief Initializes the HDMI CEC.
* @param None
* @retval HDMI_CEC_Error: CEC Error code
*/
HDMI_CEC_Error HDMI_CEC_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
CEC_InitTypeDef CEC_InitStructure;
HDMI_CEC_Error errorstatus = HDMI_CEC_OK;
uint8_t sendcount = 0;
#ifdef HDMI_CEC_USE_DDC
I2C_InitTypeDef I2C_InitStructure;
/* Enable CEC_I2C clocks */
RCC_APB1PeriphClockCmd(HDMI_CEC_I2C_CLK, ENABLE);
/* Enable CEC_I2C_GPIO and CEC_HPD_GPIO clocks */
RCC_APB2PeriphClockCmd(HDMI_CEC_I2C_GPIO_CLK | HDMI_CEC_HPD_GPIO_CLK, ENABLE);
#endif
/* Enable CEC clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_CEC, ENABLE);
/* Enable CEC_LINE_GPIO clocks */
RCC_APB2PeriphClockCmd(HDMI_CEC_LINE_GPIO_CLK, ENABLE);
/* Configure CEC_LINE_GPIO as Output open drain */
GPIO_InitStructure.GPIO_Pin = HDMI_CEC_LINE_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(HDMI_CEC_LINE_GPIO_PORT, &GPIO_InitStructure);
#ifdef HDMI_CEC_USE_DDC
/* Configure CEC_I2C_SCL_PIN and CEC_I2C_SDA_PIN as Output open drain */
GPIO_InitStructure.GPIO_Pin = HDMI_CEC_I2C_SCL_PIN | HDMI_CEC_I2C_SDA_PIN;
GPIO_Init(HDMI_CEC_I2C_GPIO_PORT, &GPIO_InitStructure);
/* This configuration is only when the HDMI CEC is configured as source.
The HDMI source has to provide the +5V Power signal to the sink.
On STM32100E-EVAL borad, you have to solder the SB4 Solder bridge.
Then, the source will wait for HPD signal to be asserted from the sink.
Once the HPD signal is detected the source shall read the EDID structure
throuhgh the DDC channel. */
/* Configure CEC_HPD_GPIO as Input pull down */
GPIO_InitStructure.GPIO_Pin = HDMI_CEC_HPD_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(HDMI_CEC_HPD_GPIO_PORT, &GPIO_InitStructure);
/* This configuration is only when the HDMI CEC is configured as sink.
The HDMI sink has to wait for the +5V Power signal from the source.
On STM32100E-EVAL borad, SB4 Solder bridge should be open (default configuration).
Then, the sink will assert the HPD signal to inform the source that the EDID
is ready for read through DDC channel. In this implementation, the EDID structure
is not implemented. */
/* GPIO_InitStructure.GPIO_Pin = HDMI_CEC_HPD_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(HDMI_CEC_HPD_GPIO_PORT, &GPIO_InitStructure);
HDMI_CEC_HPD_HIGH(); // Set the Hot plug detect signal */
/* Enable CEC_I2C */
I2C_Cmd(HDMI_CEC_I2C, ENABLE);
/* I2C configuration */
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStructure.I2C_OwnAddress1 = HDMI_CEC_I2C_SLAVE_ADDRESS7;
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_InitStructure.I2C_ClockSpeed = HDMI_CEC_I2C_CLOCK_SPEED;
I2C_Init(HDMI_CEC_I2C, &I2C_InitStructure);
#endif
/* Physical Address discovery */
errorstatus = PhysicalAddressDiscovery();
if (errorstatus != HDMI_CEC_OK)
{
/* Device not connected (Physical Address lost) */
return(errorstatus);
}
/* CEC DeInit */
CEC_DeInit();
/* Configure CEC */
CEC_InitStructure.CEC_BitTimingMode = CEC_BitTimingStdMode;
CEC_InitStructure.CEC_BitPeriodMode = CEC_BitPeriodStdMode;
CEC_Init(&CEC_InitStructure);
/* Set Prescaler value for APB1 clock = 24MHz */
CEC_SetPrescaler(0x4AF);
/* Enable CEC */
CEC_Cmd(ENABLE);
/* Logical Address Allocation */
sendcount = 0;
errorstatus = LogicalAddressAllocation();
while ((errorstatus != HDMI_CEC_OK) && sendcount < 0x5)
{
sendcount++;
errorstatus = LogicalAddressAllocation();
}
if (errorstatus != HDMI_CEC_OK)
{
/* Device Unregistred */
return(errorstatus);
}
HDMI_CEC_CheckConnectedDevices();
/* Set the CEC initiator address */
CEC_OwnAddressConfig(MyLogicalAddress);
/* Activate CEC interrupts associated to the set of RBTF,RERR, TBTF, TERR flags */
CEC_ITConfig(ENABLE);
/* Report physical address*/
errorstatus = HDMI_CEC_ReportPhysicalAddress();
sendcount = 0;
while ((errorstatus != HDMI_CEC_OK) && sendcount < 0x5)
{
sendcount++;
errorstatus = HDMI_CEC_ReportPhysicalAddress();
}
if (errorstatus != HDMI_CEC_OK)
{
/* Device Unregistred */
return(errorstatus);
}
return errorstatus;
}
/**
* @brief Transmit message by taking data from typedef struct CEC_Meassage
* @param CEC_TX_MessageStructure: pointer to an CEC_Message structure that contains
* the message to be sent.
* @retval HDMI_CEC_Error: CEC Error code
*/
HDMI_CEC_Error HDMI_CEC_TransmitMessage(HDMI_CEC_Message *HDMI_CEC_TX_MessageStructure)
{
HDMI_CEC_Error errorstatus = HDMI_CEC_OK;
__IO uint32_t count = 0, j = 0;
SendFrame = 0;
SendStatus = 0;
TxCounter = 0;
BufferCount = 0;
HDMI_CEC_TX_MessageStructPrivate = *HDMI_CEC_TX_MessageStructure;
/* Initialize BufferPointer */
for (j = 0; j < 15; j++)
{
BufferPointer[j] = 0;
}
BufferPointer[0] = HDMI_CEC_TX_MessageStructPrivate.Opcode;
for (BufferCount = 1; BufferCount < HDMI_CEC_TX_MessageStructPrivate.TxMessageLength + 1; BufferCount++)
{
BufferPointer[BufferCount] = HDMI_CEC_TX_MessageStructPrivate.Operande[BufferCount-1];
}
CEC_ClearFlag(CEC_FLAG_TBTRF | CEC_FLAG_TERR);
/* Write single Data in the TX Buffer to Transmit through the CEC peripheral */
CEC_SendDataByte(HDMI_CEC_TX_MessageStructPrivate.Header);
/* Initiate Message Transmission */
CEC_StartOfMessage();
while ((SendFrame == 0) && (count < HDMI_CEC_TIMEOUT_VALUE))
{
count++;
}
if (count >= HDMI_CEC_TIMEOUT_VALUE)
{
errorstatus = HDMI_CEC_TIMEOUT;
return(errorstatus);
}
if (SendStatus == 0)
{
errorstatus = (HDMI_CEC_Error) TransErrorCode;
}
return errorstatus;
}
/**
* @brief Get the ESR register status.
* @param None
* @retval HDMI_CEC_Error: CEC Error code
*/
HDMI_CEC_Error HDMI_CEC_GetErrorStatus (void)
{
HDMI_CEC_Error errorstatus = HDMI_CEC_OK;
/* Bit timing error case*/
if (CEC_GetFlagStatus(CEC_FLAG_BTE) != RESET)
{
errorstatus = HDMI_CEC_BIT_TIMING;
}
/* Bit period error case */
if (CEC_GetFlagStatus(CEC_FLAG_BPE) != RESET)
{
errorstatus = HDMI_CEC_BIT_PERIOD;
}
/* Recieve error case */
if (CEC_GetFlagStatus(CEC_FLAG_RBTFE) != RESET)
{
errorstatus = HDMI_CEC_RX_BLOCK_FINISHED;
}
/* Start bit error case*/
if (CEC_GetFlagStatus(CEC_FLAG_SBE) != RESET)
{
errorstatus = HDMI_CEC_START_BIT;
}
/* Acknowledge error case*/
if (CEC_GetFlagStatus(CEC_FLAG_ACKE) != RESET)
{
errorstatus = HDMI_CEC_BLOCK_ACKNOWLEDGE;
}
/* Line error case */
if (CEC_GetFlagStatus(CEC_FLAG_LINE) != RESET)
{
errorstatus = HDMI_CEC_LINE;
}
/* Transfert error case*/
if (CEC_GetFlagStatus(CEC_FLAG_TBTFE) != RESET)
{
errorstatus = HDMI_CEC_TX_BLOCK_FINISHED;
}
/* Clear All errors */
CEC_ClearFlag(CEC_FLAG_RERR);
CEC_ClearFlag(CEC_FLAG_TERR);
return errorstatus;
}
/**
* @brief Allows to process all the interrupts that are high.
* @param None
* @retval None
*/
void HDMI_CEC_ProcessIRQSrc(void)
{
/********************** Reception *********************************************/
/* Check if a reception error occured */
if (CEC_GetFlagStatus(CEC_FLAG_RERR))
{
/* Set receive status bit (Error) */
ReceiveStatus = 0;
ReceivedFrame = 1;
RecepErrorCode = HDMI_CEC_GetErrorStatus();
CEC_ClearFlag(CEC_FLAG_RERR | CEC_FLAG_RSOM | CEC_FLAG_REOM | CEC_FLAG_RBTF);
}
else if (CEC_GetFlagStatus(CEC_FLAG_RBTF))
{
/* Check if the byte received is the last one of the message */
if (CEC_GetFlagStatus(CEC_FLAG_REOM))
{
HDMI_CEC_RX_MessageStructPrivate.Operande[RxCounter-1] = CEC_ReceiveDataByte();
HDMI_CEC_RX_MessageStructPrivate.RxMessageLength = RxCounter;
ReceiveStatus = SUCCESS;
ReceivedFrame = 1;
}
/* Check if the byte received is a Header */
else if (CEC_GetFlagStatus(CEC_FLAG_RSOM))
{
ReceiveStatus = 0;
HDMI_CEC_RX_MessageStructPrivate.Header = CEC_ReceiveDataByte();
RxCounter = 0;
}
/* Receive each byte except header in the reception buffer */
else
{
if (RxCounter != 0)
{
HDMI_CEC_RX_MessageStructPrivate.Operande[RxCounter-1] = CEC_ReceiveDataByte();
RxCounter++;
}
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -