0 CEC协议
什么是cec协议呢?
CEC全称 consumer electronics control 消费电子控制协议,是一种单总线协议;
CEC被设计用来增强hdmi设备间的控制功能和互相联系功能,属于hdmi规范的一部分;
以hdmi1.4b规范为例,cec协议概括位于p217-351共135p;我们来看看都讲了啥?
本文主要讲cec协议的数据帧是如何构成的,以及一些零散的内容;
然后再整一篇来讲cec的地址是如何分配的?特别是有个动态地址分配的,看看是干嘛的;
最后再整一篇来把协议指令整理一下,他们之间是怎么搭配上代码;
最后再整一篇来讲如何通过mcu模拟cec协议;
最后再整几篇,关于tv和avr的通讯协议流程;这个可以不用写成blog;
1 introducion
没啥,告诉我们这个扩展章节主要是cec特性的概览;所以这个章节包含了hdmi1.4版的所有cec指令;
扩展章节简单将cec协议内容分为两部分,
一部分是低级别协议定义,包含电气特性,信号电平,协议框架;
另一部分是高级别协议定义,包含特性分类,单独消息描述;
2 definitions
没啥,简单讲了一下这个cec的supplement里常见的设备词汇,以及一些冗余描述;
initiator:发送cecMsg的设备,如果允许会等待follower设备的响应;
follower:接收cecMsg的设备,被要求需要响应cecMsg;ack位由follower响应;
deck:提供playback功能的recording device或者playback device;比如dvd和hard disk;
source:带有 an hdmiOutput的设备;
sink:带有an hdmiInput的设备;
repeater:带有hdmiInputs和hdmiOutputs的设备;
STB:set top box 机顶盒,连接电视机与外部信号源的设备;
AVR:audio/vedio Receiver 音频视频接收器;
3 feature overview
没啥,读此一席字,胜似一席字;花个5分钟有点印象即可;
将cec协议的功能分为两类特性进行概括,一类是终端用户特性,一类是支持的特性;
终端用户特性为 一键开关机,activeSrc可以在tv上叠加显示菜单,tv屏幕录制,以及音量控制;
支持的功能为 osd显示deviceName和deviceMenu,activeSrc自动切换,vendor私有指令,以及音量控制和HEAC;
3.1 终端用户使用的功能
one touch play: 一键播放,按了之后 a device会播放并且成为active source;
<active source>,<text view on>,<image view on>
system standby: 一键待机,按了之后 all device都会进入待机模式;
<standby>
one touch record: 一键记录,按了之后 tv screen上显示的东西都会记录到记录设备中;
timer programmming: 定时记录,允许用户设置定时,去记录tv或stb上即将播放的内容;
deck control: playback控制,比如play播放,fast forward快进,
tuner control: 谐调器控制,比如通过tv遥控器控制STB切换频道,收音机频道切换;
device menu control: 设备菜单控制,允许A device去控制B device的菜单,比如tv遥控可以控制小米盒子的菜单;
remote control pass through: 指令透传,因为cec线上的指令是所有设备都能收到的,所以就实现了指令透传;
system audio control: 音频控制,对于连接到tv上的avr,cec总线上的设备都可以控制其音量;
3.2 支持的功能
device osd name transfer: osdName反馈,设置在tv菜单上显示的OnScreenDisplayName;eg:XiaoMi
device power status: 电源状态反馈,允许device的电源状态被发现;
osd display : device可以使用tv的menu框架,在tv屏幕上叠加显示device的错误提示,交互提示;
routing control: src切换,当有新的src发现时,允许切换到新的src作为输入;
<activeSource>,<inactiveSource>,<requestActiveSource>,<setStreamPath>
<routingChange>,<routingInformation>
system information: 通过询问system来决定device的addr和language
<getCecVersion>,<cecVersion>,<getMenuLanguage>,<setMenuLanguage>
<givePhysicalAddress>,<reportPhysicalAddress>,<pollingMessage>
vendor specific commands: 允许device制造商定制cecMsg用在自家的系列device上;
audio rate control: 允许amplifier去控制playback或其它audioSrc的音量比例;
audio return channel control:这里说arc和以太网传输的支持部分主要在supplement2(HEAC)中指出,但是HEAC看起来没啥呀;
capability discovery and control:HDMI Ethenet Channel(HEC)通过hdmi传输以太网数据部分见supplement2;
4 electrical specification
没啥,开机和关机时的cec线上的电平特性,主要电压,电流,上电变化时间之类的电气特性;
5 signaling and bit timings
cecMsg数据帧实际波形抓取如下举例,由一个start bit后跟多个data bit构成;那么startBit和dataBit又是如何定义的呢?
这里补充一个简单的电平判断方式,电平周期内低电平时间长,为逻辑0;高电平时间长,为逻辑1;

5.1 start bit timing是如何接收呢?
开始bit的电平周期如下,那么软件中应该如何判断呢?
先把cec线拉高然后再去读取,如果读取到cec电平为高,说明其它设备也没有拉取cec,那不就是不满足start bit了吗;
如果读取到cec为低,说明其它设备拉了cec,那说明其它设备可能在发送start bit;
然后判断接下来的电平是不是先低电平,后高电平?这个低高电平的时间满足如下时序不?这样的话,单bit数据就接收完了;

5.2 data bit timing的0和1又是如何接收的呢?
在软件中的判断方式和上面start bit的判断逻辑一致,改下判断电平的时间即可;
注意的是,发送cecMsg时,如果后续没有bit了,需要把cec线拉回高阻态;

ques:这里有一个问题;后面还给了一张图,说是当initiator输出1,follower输出ack为0时,允许在safe sample period中拉取,
可是每个bit的时序都不一样,根本没可能会冲突需要在safe sample period中拉取呀,先放着,没啥用后续删掉;
6 frame description
cec的数据帧是咋构成的呢?
cec的数据帧由起始电平+headerBlock+opcodeBlock+operandBlock组成,最大16字节;table3中还指出了其它blocks的table,很实用;

6.1 block
数据帧的是由block构成的,那么block又是咋构成的呢?
每个block包含 8bit data + 1bit EOM结束标志位 + 1bit ACK;

6.1.1 EOM bit
end of message信息结束位;0:后续还有数据传输,1:数据传输完成;
如果数据还没传输完,eom已经置1了,那么eom置1后的数据就无视了;
如果数据已经传输完,eom确没有置1,那么当前接收的数据帧就无视了;
6.1.2 ACK bit
对于1对1的cec指令时
initiator始终将ack置1,如果initiator读取到ack为0,说明follower收到信息了;
follower在读取到dts是自己时,就将对应ack置0;此时其余设备禁止置0 ack;
对于广播时的cec指令时
initiator始终将ack置1,如果initiator读取到ack为1,说明没有follower拒绝广播指令;
follower在读取到想要拒绝的广播指令时,就将对应ack置0;此时其余设备也可以置0 ack;
initiator是始终发送cec信息的设备,follower是始终接收cec信息的设备;
6.1.3 <polling message>
[7:4]src+[3:0]dts+eom置1+ack的block,称之为<polling message>,eom置1表示告诉dst可以'ping'src;
ping src的目的是为了确认dst设备是否在线,确认一下接下来是否能向其发送操作指令;有啥用呢?
<polling message>还可以用来重新分配逻辑地址,此时dts和src是相同的;见章节10.2.1;先放着;
7 reliable communication mechanisms
如何确保frame传输机制可靠呢?
1 重新传输:*在收到ack不对的时候,重新发送;*最多发送5次;如果重新发送的时候收到了<polling message>那建议只重传一次;
2 流控制:要是follower目前不方便处理cec指令,那就回复一个negative ack;让initiator重新发送
3 帧校验:当接收到的字节少于opcode中指出的字节长度时,就不处理数据;
4 cec line错误处理:当follower检测到start bit之外的block的两个数据bit的下降沿时间间隔小于最小时间间隔,
follower就拉低cec line的数据为正常数据的1.5时长(2.4*1.5=3.6ms),告知initiator需要重新发送;
这些传输机制的可靠性代码目前我预计先不写,要是后面有空补充的话,再整理一下,先放着;
8 protocol extensions
没啥, 等于reserved;
就是说如果cec协议收到的operands多于opcode字节长度,认为是是扩展出来的信息;只处理可识别部分就行了;
9 cec arbitration
如果cec线上有多个设备想要发送指令应该怎么仲裁呢?
9.1 signal free time
设备开始传输之前需要确保总线上的设备都为非活跃状态,怎么确认呢?根据"singal free time"(帧与帧之间的空闲时间)规则判断,
这样的话其它initiator就可以在当前initiator的signal free time之前发送自己的数据帧;
设备传输过程中需要监控自己的header block的srcAddr,如果headerBlock的srcAddr有被其它设备拉低,视作失去总线;

9.2 msgTimeConstraints
cecMsg发送时的间隔时序又是如何约束的呢?
cecMsg对于responseMsg的最大期望响应值为200ms内;对于responseMsg的最大强制响应值为1s内;
那时间要是超过了会咋样呢?那cec就认为是响应失败咯;
10 device connectivity and addressing
物理地址和逻辑地址的分配
2.2 动态地址分配协议
2025-05-23 下面这段动态地址分配是之前写的,其实写的优点不对,先放着;后面再改;
对于CEC总线上的设备使用动态地址分配协议来区分彼此,动态地址分配协议又是如何工作的呢?
通常设置TV为根节点,根节点逻辑地址为0;
插入设备根据自身设备类型,预设自身的逻辑地址eg:0x04,通过<polling message>广播此地址;
如果总线上已有设备为该预设地址,就会应答;插入设备收到应答后,重新预设自身逻辑地址eg:0x08,继续<polling message>广播;
如果总线上没有设备应答该预设地址,插入设备主动分配该地址为自身逻辑地址;
如果总线上总有设备应答该预设地址,插入设备主动分配自身逻辑地址为eg:0x0f;
然后插入设备发送广播<report physical address>,广播自身的逻辑地址和物理地址,声明逻辑地址的占用;
pha的分配在8.7 section中使用ddc来分配;具体见8.7.3
当有一个新的pha时,(initiator 还是 follower)就会为其自动分配一个唯一的逻辑地址,
然后(initiator 还是 follower)广播<report physical address>来告知该物理地址和逻辑地址联系到一块了;
10.2 一个设备可能包含多个逻辑地址的功能,但是cec协议只能控制该设备分配的对应逻辑地址的功能;
一个设备的逻辑地址是如何分配的呢?是通过<polling message>来分配的;
当设备连接到cec总线时,它会先给自身预设一个逻辑地址;然后使用该逻辑地址作为src+dts地址,进行轮询;如果ack没有被应答,则将该地址作为自身逻辑地址;
11 switch requirements
cec switch是具有一个或多个hdmiIn和hdmiOut的设备,且每个hdmiPort实现了cec功能(有pha),且设备自身没有internalSource;
cec switch能为连接到自身的child设备分配pha,pha的主要作用就是让switch可以通过cecMsg切换自身的tmds stream;
cec switch的功能主要为routing control,要能响应<active source>和<set stream path>,能主动发<routing change>,具体章节13.2
笔记本不是switch;repeater或AVR或tv是switch;
12 high level protocol
//和第七章一起看看,可以删掉点啥;
//hdmi将带参数的cec指令就称之为高级协议,这章简单讲了下几条特殊指令;
//如果一个设备想要作为activeSource,那么就需要发送<activeSource>,有点废话,后面看看哪删了;
对点msg以广播地址发送则无效,广播msg以对点地址发送则无效;有些cecMsg既可以对点也可以广播;
cecMsg如果有多个字节,则以大端模式 >> 高字节在前传输;cecMsg的bit以MSB方式传输;
当initiator的logicAddr为f时,follower只有固定5条cecMsg可以响应,大概遇不到就不写了;
如果<cecMsg>的ack正常,但是收到了<feature abort>,那么initiator需要限制这条cecMsg的发送次数;
如果<pollingMsg>的ack不正常,那么initiator就需要限制<p>的发送次数;
如果<pollingMsg>作为backgroundTask固定发送,频率需要高于500ms每次,且不得打断<cecMsg>的通信;
如果<pollingMsg>作为background固定发送,ack未响应,那么initiator最多重新发起一次<cecMsg>通讯;
如果initiator发送了多条指令,允许follower的响应不按接收顺序响应;
12.1 <feature abort>
这条指令后面和tbl表一起看,有的reason不是看起来那回事;这里主要记录两点额外的;
一是[abort reason]为[unrecognized opcode 0]的时候,initiator就不该再发送这条<cecMsg>了;其它[reason]可以继续发;
一是<feature abort>只能作为对点cecMsg响应,不能作为广播cecMsg响应;
13 cec features description 特性描述:对18个cec指令进行了描述,先描述了一下<msg>需要的先后顺序。然后详细介绍一下用法;
13.2 <routing control>,13.17<AudioReturn >
14 device states 设备状态:每个逻辑设备在同一时刻只能有一种状态,状态之间可以互相转换;感觉讲了=没讲一样;
15 message descriptions 消息描述:table8-26 对主要的几个指令进行了描述
16 message dependencies 消息依赖性 :table 27-28
17 operand descriptions 操作数描述:
