1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 |
|
4 | #include "rc5.h"
|
5 |
|
6 | #ifndef RC5_PRESCALE
|
7 | #define RC5_PRESCALE 64
|
8 | #endif /* RC5_PRESCALE */
|
9 |
|
10 | /* ******************************************************************************** */
|
11 |
|
12 | rc5_t rc5;
|
13 |
|
14 | /* ******************************************************************************** */
|
15 |
|
16 | #ifndef F_CPU
|
17 | #error Please define F_CPU
|
18 | #endif /* !F_CPU */
|
19 |
|
20 | /* µs for a whole bit of RC5 (first & second part) */
|
21 | #define RC5_BIT_US (64*27)
|
22 |
|
23 | #define RC5_TICKS \
|
24 | ((uint8_t) ((uint32_t) (F_CPU / 1000 * RC5_BIT_US / 1000 / RC5_PRESCALE)))
|
25 |
|
26 | #define RC5_DELTA \
|
27 | (RC5_TICKS / 6)
|
28 |
|
29 | typedef union
|
30 | {
|
31 | uint16_t w;
|
32 | uint8_t b[2];
|
33 | } code_t;
|
34 |
|
35 | static code_t code;
|
36 | static uint8_t rc5_addr;
|
37 |
|
38 | /* Number of Bits received so far */
|
39 | /* Number of Interrupts occured so far */
|
40 | static uint8_t nbits;
|
41 | static uint8_t nint;
|
42 |
|
43 | /* ******************************************************************************** */
|
44 |
|
45 | void rc5_init (uint8_t addr)
|
46 | {
|
47 | nint = 0;
|
48 | nbits = 0;
|
49 | rc5.flip = -1;
|
50 |
|
51 | rc5_addr = addr;
|
52 |
|
53 | #if (RC5_PRESCALE==1024)
|
54 | TCCR2 |= ((1 << CS22) | (1 << CS20) | (1 << CS21));
|
55 | #elif (RC5_PRESCALE==256)
|
56 | TCCR2 |= ((1 << CS22) | (1 << CS21));
|
57 | #elif (RC5_PRESCALE==64)
|
58 | TCCR2 |= (1 << CS22);
|
59 | #else
|
60 | #error This RC5_PRESCALE is not supported
|
61 | #endif /* RC5_PRESCALE */
|
62 |
|
63 | /* INTx on falling edge */
|
64 | /* clear pending INTx */
|
65 | /* enable INTx interrupt */
|
66 | MCUCR &= ~(1 << ISC2);
|
67 | GIFR |= (1 << INTF2);
|
68 | GICR |= (1 << INT2);
|
69 | }
|
70 |
|
71 | /* ******************************************************************************** */
|
72 |
|
73 | ISR(TIMER2_OVF_vect)
|
74 | {
|
75 | TIMSK &= ~(1 << TOIE2);
|
76 |
|
77 | uint8_t _nbits = nbits;
|
78 | code_t _code = code;
|
79 |
|
80 | if (26 == _nbits)
|
81 | {
|
82 | _nbits++;
|
83 | _code.w <<= 1;
|
84 | }
|
85 |
|
86 | if (27 == _nbits
|
87 | && _code.b[1] >= 0x30 /* AGC == 3 */
|
88 | && 0 > rc5.flip)
|
89 | {
|
90 | uint8_t _rc5_code;
|
91 | uint8_t _rc5_addr;
|
92 | /* we do the bit manipulation stuff by hand, because of code size */
|
93 | _rc5_code = _code.b[0] & 0x3f; /* 0b00111111 : #0..#5 */
|
94 | _code.w <<= 2;
|
95 | _rc5_addr = _code.b[1] & 0x1f; /* 0b00011111 : #6..#10 */
|
96 |
|
97 | if ((rc5_addr & 0x80)
|
98 | || rc5_addr == _rc5_addr)
|
99 | {
|
100 | rc5.code = _rc5_code;
|
101 | rc5.addr = _rc5_addr;
|
102 | signed char flip = 0;
|
103 | if (_code.b[1] & 0x20) /* 0b00100000 : #11 */
|
104 | flip = 1;
|
105 | rc5.flip = flip;
|
106 | }
|
107 | }
|
108 |
|
109 | nint = 0;
|
110 | nbits = 0;
|
111 |
|
112 | /* INTx on falling edge */
|
113 | /* clear pending INTx */
|
114 | /* enable INTx interrupt */
|
115 |
|
116 | MCUCR &= ~(1 << ISC2);
|
117 | GIFR |= (1 << INTF2);
|
118 | GICR |= (1 << INT2);
|
119 |
|
120 | }
|
121 |
|
122 | /* ******************************************************************************** */
|
123 |
|
124 |
|
125 | ISR(INT2_vect)
|
126 | {
|
127 | code_t _code = code;
|
128 | uint8_t _nint = nint;
|
129 |
|
130 | uint8_t tcnt0 = TCNT2;
|
131 | TCNT2 = 0;
|
132 |
|
133 | if (0 == _nint)
|
134 | {
|
135 |
|
136 | MCUCR &= ~(1 << ISC2);
|
137 |
|
138 | TIFR |= (1 << TOV2);
|
139 | TIMSK |= (1 << TOIE2);
|
140 | _code.w = 0;
|
141 | }
|
142 | else
|
143 | {
|
144 | /* Number of bits of the just elapsed period */
|
145 | uint8_t n = 1;
|
146 |
|
147 | /* Bits received so far */
|
148 | uint8_t _nbits = nbits;
|
149 |
|
150 | /* is TCNT0 close to RC5_TICKS or RC5_TICKS/2 ? */
|
151 | if (tcnt0 > RC5_TICKS + RC5_DELTA)
|
152 | goto invalid;
|
153 | else if (tcnt0 < RC5_TICKS/2 - RC5_DELTA)
|
154 | goto invalid;
|
155 | else if (tcnt0 > RC5_TICKS - RC5_DELTA)
|
156 | n = 2;
|
157 | else if (tcnt0 > RC5_TICKS/2 + RC5_DELTA)
|
158 | goto invalid;
|
159 |
|
160 | /* store the just received 1 or 2 bits */
|
161 | do
|
162 | {
|
163 | _nbits++;
|
164 | if (_nbits & 1)
|
165 | {
|
166 | _code.w <<= 1;
|
167 | _code.b[0] |= _nint & 1;
|
168 | }
|
169 | }
|
170 | while (--n);
|
171 |
|
172 | if (0)
|
173 | {
|
174 | invalid:
|
175 |
|
176 | /* disable INTx, run into Overflow0 */
|
177 | GICR &= ~(1 << INT2);
|
178 |
|
179 | _nbits = 0;
|
180 | }
|
181 |
|
182 | nbits = _nbits;
|
183 | }
|
184 |
|
185 | code = _code;
|
186 | nint = 1+_nint;
|
187 | }
|