1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 |
|
4 | // Für alte avr-gcc Versionen
|
5 | #ifndef SIGNAL
|
6 | #include <avr/signal.h>
|
7 | #endif // SIGNAL
|
8 |
|
9 | #include "rc5.h"
|
10 |
|
11 | #ifndef RC5_INT
|
12 | #define RC5_INT RC5_INT0
|
13 | #endif /* RC5_INT */
|
14 |
|
15 | #ifndef RC5_PRESCALE
|
16 | #define RC5_PRESCALE 1024
|
17 | #endif /* RC5_PRESCALE */
|
18 |
|
19 | /* ******************************************************************************** */
|
20 |
|
21 | rc5_t rc5;
|
22 |
|
23 | /* ******************************************************************************** */
|
24 |
|
25 | #ifndef F_CPU
|
26 | #error Please define F_CPU
|
27 | #endif /* !F_CPU */
|
28 |
|
29 | /* µs for a whole bit of RC5 (first & second part) */
|
30 | #define RC5_BIT_US (64*27)
|
31 |
|
32 | #define RC5_TICKS \
|
33 | ((uint8_t) ((uint32_t) (F_CPU / 1000 * RC5_BIT_US / 1000 / RC5_PRESCALE)))
|
34 |
|
35 | #define RC5_DELTA \
|
36 | (RC5_TICKS / 6)
|
37 |
|
38 | typedef union
|
39 | {
|
40 | uint16_t w;
|
41 | uint8_t b[2];
|
42 | } code_t;
|
43 |
|
44 | static code_t code;
|
45 | static uint8_t rc5_addr;
|
46 |
|
47 | /* Number of Bits received so far */
|
48 | /* Number of Interrupts occured so far */
|
49 | static uint8_t nbits;
|
50 | static uint8_t nint;
|
51 |
|
52 | /* ******************************************************************************** */
|
53 |
|
54 | void rc5_init (uint8_t addr)
|
55 | {
|
56 | nint = 0;
|
57 | nbits = 0;
|
58 | rc5.flip = -1;
|
59 |
|
60 | rc5_addr = addr;
|
61 |
|
62 | #if (RC5_PRESCALE==1024)
|
63 | TCCR0B = (1 << CS02) | (1 << CS00);
|
64 | #elif (RC5_PRESCALE==256)
|
65 | TCCR0B = (1 << CS02);
|
66 | #elif (RC5_PRESCALE==64)
|
67 | TCCR0B = (1 << CS01) | (1 << CS00);
|
68 | #else
|
69 | #error This RC5_PRESCALE is not supported
|
70 | #endif /* RC5_PRESCALE */
|
71 |
|
72 | /* INTx on falling edge */
|
73 | /* clear pending INTx */
|
74 | /* enable INTx interrupt */
|
75 | #if (RC5_INT == RC5_INT0)
|
76 | MCUCR = (MCUCR | (1 << ISC01)) & ~ (1 << ISC00);
|
77 | EIFR = (1 << INTF0);
|
78 | EIMSK |= (1 << INT0);
|
79 | #elif (RC5_INT == RC5_INT1)
|
80 | MCUCR = (MCUCR | (1 << ISC11)) & ~ (1 << ISC10);
|
81 | EIFR = (1 << INTF1);
|
82 | EIMSK |= (1 << INT1);
|
83 | #else
|
84 | #error please define RC5_INT
|
85 | #endif /* RC5_INT */
|
86 | }
|
87 |
|
88 | /* ******************************************************************************** */
|
89 |
|
90 | SIGNAL (SIG_OVERFLOW0)
|
91 | {
|
92 | TIMSK0 &= ~(1 << TOIE0);
|
93 |
|
94 | uint8_t _nbits = nbits;
|
95 | code_t _code = code;
|
96 |
|
97 | if (26 == _nbits)
|
98 | {
|
99 | _nbits++;
|
100 | _code.w <<= 1;
|
101 | }
|
102 |
|
103 | if (27 == _nbits
|
104 | && _code.b[1] >= 0x30 /* AGC == 3 */
|
105 | && 0 > rc5.flip)
|
106 | {
|
107 | uint8_t _rc5_code;
|
108 | uint8_t _rc5_addr;
|
109 | /* we do the bit manipulation stuff by hand, because of code size */
|
110 | _rc5_code = _code.b[0] & 0x3f; /* 0b00111111 : #0..#5 */
|
111 | _code.w <<= 2;
|
112 | _rc5_addr = _code.b[1] & 0x1f; /* 0b00011111 : #6..#10 */
|
113 |
|
114 | if (rc5_addr & 0x80
|
115 | || rc5_addr == _rc5_addr)
|
116 | {
|
117 | rc5.code = _rc5_code;
|
118 | rc5.addr = _rc5_addr;
|
119 | signed char flip = 0;
|
120 | if (_code.b[1] & 0x20) /* 0b00100000 : #11 */
|
121 | flip = 1;
|
122 | rc5.flip = flip;
|
123 | }
|
124 | }
|
125 |
|
126 | nint = 0;
|
127 | nbits = 0;
|
128 |
|
129 | /* INTx on falling edge */
|
130 | /* clear pending INTx */
|
131 | /* enable INTx interrupt */
|
132 | #if (RC5_INT == RC5_INT0)
|
133 | MCUCR = (MCUCR | (1 << ISC01)) & ~ (1 << ISC00);
|
134 | EIFR = (1 << INTF0);
|
135 | EIMSK |= (1 << INT0);
|
136 | #elif (RC5_INT == RC5_INT1)
|
137 | MCUCR = (MCUCR | (1 << ISC11)) & ~ (1 << ISC10);
|
138 | EIFR = (1 << INTF1);
|
139 | EIMSK |= (1 << INT1);
|
140 | #endif
|
141 | }
|
142 |
|
143 | /* ******************************************************************************** */
|
144 |
|
145 | #if (RC5_INT == RC5_INT0)
|
146 | SIGNAL (SIG_INTERRUPT0)
|
147 | #elif (RC5_INT == RC5_INT1)
|
148 | SIGNAL (SIG_INTERRUPT1)
|
149 | #endif /* RC5_INT */
|
150 | {
|
151 | code_t _code = code;
|
152 | uint8_t _nint = nint;
|
153 |
|
154 | uint8_t tcnt0 = TCNT0;
|
155 | TCNT0 = 0;
|
156 |
|
157 | if (0 == _nint)
|
158 | {
|
159 | /* INTx on both edges */
|
160 | #if (RC5_INT == RC5_INT0)
|
161 | MCUCR = (MCUCR | (1 << ISC00)) & ~ (1 << ISC01);
|
162 | #elif (RC5_INT == RC5_INT1)
|
163 | MCUCR = (MCUCR | (1 << ISC10)) & ~ (1 << ISC11);
|
164 | #endif /* RC5_INT */
|
165 |
|
166 | TIFR0 = (1 << TOV0);
|
167 | TIMSK0 |= (1 << TOIE0);
|
168 | _code.w = 0;
|
169 | }
|
170 | else
|
171 | {
|
172 | /* Number of bits of the just elapsed period */
|
173 | uint8_t n = 1;
|
174 |
|
175 | /* Bits received so far */
|
176 | uint8_t _nbits = nbits;
|
177 |
|
178 | /* is TCNT0 close to RC5_TICKS or RC5_TICKS/2 ? */
|
179 | if (tcnt0 > RC5_TICKS + RC5_DELTA)
|
180 | goto invalid;
|
181 | else if (tcnt0 < RC5_TICKS/2 - RC5_DELTA)
|
182 | goto invalid;
|
183 | else if (tcnt0 > RC5_TICKS - RC5_DELTA)
|
184 | n = 2;
|
185 | else if (tcnt0 > RC5_TICKS/2 + RC5_DELTA)
|
186 | goto invalid;
|
187 |
|
188 | /* store the just received 1 or 2 bits */
|
189 | do
|
190 | {
|
191 | _nbits++;
|
192 | if (_nbits & 1)
|
193 | {
|
194 | _code.w <<= 1;
|
195 | _code.b[0] |= _nint & 1;
|
196 | }
|
197 | }
|
198 | while (--n);
|
199 |
|
200 | if (0)
|
201 | {
|
202 | invalid:
|
203 |
|
204 | /* disable INTx, run into Overflow0 */
|
205 | #if (RC5_INT == RC5_INT0)
|
206 | EIMSK &= ~(1 << INT0);
|
207 | #elif (RC5_INT == RC5_INT1)
|
208 | EIMSK &= ~(1 << INT1);
|
209 | #endif /* RC5_INT */
|
210 |
|
211 | _nbits = 0;
|
212 | }
|
213 |
|
214 | nbits = _nbits;
|
215 | }
|
216 |
|
217 | code = _code;
|
218 | nint = 1+_nint;
|
219 | }
|