-
Notifications
You must be signed in to change notification settings - Fork 2
/
cec_addr_dev_type.c
114 lines (100 loc) · 3.15 KB
/
cec_addr_dev_type.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
* This is the traditional address assignment. We find an available logical
* address based on our device type.
*
* Copyright (C) 2016 Russ Dill <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "cec.h"
#include "cec_spec.h"
#ifdef CEC_LOGICAL_ADDRESS_REG
register unsigned char logical_address CEC_LOGICAL_ADDRESS_REG;
#else
static unsigned char logical_address;
#endif
static unsigned char cec_dev_idx;
/* Static table of which addresses are available given a device type */
PROGMEM static const unsigned char cec_dev_addrs[] = {
#ifndef CEC_DEV_TYPE
#error "CEC_DEV_TYPE not defined"
#elif CEC_DEV_TYPE == CEC_DEV_TV
CEC_DEV_TV_ADDRS
#elif CEC_DEV_TYPE == CEC_DEV_RECORDING_DEVICE
CEC_DEV_RECORDING_DEVICE_ADDRS
#elif CEC_DEV_TYPE == CEC_DEV_TUNER
CEC_DEV_TUNER_ADDRS
#elif CEC_DEV_TYPE == CEC_DEV_PLAYBACK_DEVICE
CEC_DEV_PLAYBACK_DEVICE_ADDRS
#elif CEC_DEV_TYPE == CEC_DEV_AUDIO_SYSTEM
CEC_DEV_AUDIO_SYSTEM_ADDRS
#elif CEC_DEV_TYPE == CEC_DEV_SWITCH
CEC_DEV_SWITCH_ADDRS
#elif CEC_DEV_TYPE == CEC_DEV_VIDEO_PROCESSOR
CEC_DEV_VIDEO_PROCESSOR_ADDRS
#else
#error "Unknown CEC_DEV_TYPE"
#endif
};
/* source is always our assigned logical address */
CEC_PUBLIC unsigned char cec_addr_build(unsigned char source, unsigned char target)
{
unsigned char ret = logical_address;
asm("swap %[ret]" : [ret] "+r"(ret));
return ret | target;
}
/* 0xff indicates we aren't ready */
CEC_PUBLIC bool cec_addr_ready(void)
{
return logical_address != 0xff;
}
CEC_PUBLIC bool cec_addr_match(unsigned char addr)
{
return addr == logical_address;
}
CEC_PUBLIC void cec_addr_init(void)
{
logical_address = 0xff;
cec_dev_idx = 0;
transmit_state = TRANSMIT_IDLE;
}
/*
* This will do work until we have a valid address or fallback to
* the unregistered address.
*/
CEC_PUBLIC void cec_addr_periodic(void)
{
if (cec_addr_ready())
return;
/* Throw away any messages */
cec_receive_buf[CEC_RECEIVE_BUF_HDR] = 0;
if (transmit_state == TRANSMIT_IDLE) {
if (cec_dev_idx == sizeof(cec_dev_addrs))
/* We failed, every address returned a reply */
logical_address = CEC_ADDR_UNREGISTERED;
else {
/* Keep trying until we find a non-acked address */
transmit_buf[0] = pgm_read_byte(cec_dev_addrs + cec_dev_idx);
cec_dev_idx++;
transmit_buf_end = 0;
transmit_state = TRANSMIT_PEND;
}
} else if (transmit_state == TRANSMIT_FAILED)
/* Found a non-acked address */
logical_address = transmit_buf[0] & 0xf;
}