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