1 | /*
|
2 | Button codes Olympus:
|
3 |
|
4 | Fire 0110 0001 1101 1100 1000 0000 0111 1111
|
5 | W 0110 0001 1101 1100 0100 0000 1011 1111
|
6 | T 0110 0001 1101 1100 1100 0000 0011 1111
|
7 | - 0110 0001 1101 1100 0010 0000 1101 1111
|
8 | + 0110 0001 1101 1100 1010 0000 0101 1111
|
9 |
|
10 | Each command starts with 8ms pulsed with 40khz followed by
|
11 | 4ms of low level followed by 550us pulsed with 40khz.
|
12 | After that header sequence the bits above are sent:
|
13 | "Zero" is represented by 559us of low level followed by 559us pulsed.
|
14 | "One" is represented by 1677us of low level followed by 559us pulsed.
|
15 | */
|
16 |
|
17 |
|
18 | #include <avr/io.h>
|
19 | #include <avr/interrupt.h>
|
20 | #include <util/delay.h>
|
21 |
|
22 |
|
23 | volatile unsigned int cnt = 0;
|
24 |
|
25 | // prototypes:
|
26 | void send_0(void);
|
27 | void send_1(void);
|
28 | void send_header(void);
|
29 | void send_cmd(unsigned char cmd);
|
30 |
|
31 |
|
32 | int main(void)
|
33 | {
|
34 | DDRC = 0x00; // Buttons at PC5 - PC1
|
35 | PORTC = 0xFF;
|
36 | DDRB |= (1<<PB0); // IR-LED at PB0
|
37 | PORTB |= (1<<PB0);
|
38 |
|
39 | TIMSK |= (1<<OCIE2); // TIMER2 compare match interrupt
|
40 | TCCR2 |= ((1<<WGM21) | (1<<CS20)); // TIMER2 CTC; presc = 1
|
41 | OCR2 = 99;
|
42 |
|
43 | sei();
|
44 |
|
45 |
|
46 | while(1)
|
47 | {
|
48 | if(!(PINC & (1<<PC5))) send_cmd(0);
|
49 | if(!(PINC & (1<<PC4))) send_cmd(1);
|
50 | if(!(PINC & (1<<PC3))) send_cmd(2);
|
51 | if(!(PINC & (1<<PC2))) send_cmd(3);
|
52 | if(!(PINC & (1<<PC1))) send_cmd(4);
|
53 | }
|
54 | }
|
55 |
|
56 |
|
57 |
|
58 | void send_cmd(unsigned char cmd)
|
59 | {
|
60 | unsigned char i = 0;
|
61 | // Bytes for Fire, W, T, +, -; bits in reverse order!
|
62 | const unsigned char byte[5] = {0xE1, 0xD2, 0xC3, 0xB4, 0xA5};
|
63 |
|
64 | send_header();
|
65 |
|
66 | for(i=0; i<4; i++) // first 4 bits
|
67 | {
|
68 | if((byte[cmd] >> i) & 0x01) send_1();
|
69 | else send_0();
|
70 | }
|
71 |
|
72 | for(i=0; i<4; i++) send_0();
|
73 |
|
74 | for(i=4; i<8; i++) // last 4 bits
|
75 | {
|
76 | if((byte[cmd] >> i) & 0x01) send_1();
|
77 | else send_0();
|
78 | }
|
79 |
|
80 | for(i=0; i<4; i++) send_1();
|
81 |
|
82 | _delay_ms(600); // delay before return
|
83 | }
|
84 |
|
85 |
|
86 |
|
87 |
|
88 | void send_header(void)
|
89 | {
|
90 | unsigned char i = 0;
|
91 | const unsigned int header = 0x3B86; // first two bytes in reverse bit order
|
92 |
|
93 | DDRB |= (1<<PB0); // 8ms pulse 40khz
|
94 | cnt = 0;
|
95 | while(cnt < 641);
|
96 | DDRB &= ~(1<<PB0); // 4ms space
|
97 | cnt = 0;
|
98 | while(cnt < 321);
|
99 | DDRB |= (1<<PB0); // 550us pulse 40khz
|
100 | cnt = 0;
|
101 | while(cnt < 45);
|
102 | DDRB &= ~(1<<PB0);
|
103 |
|
104 | for(i=0; i<16; i++) // send first 16 bits
|
105 | {
|
106 | if((header >> i) & 0x01) send_1();
|
107 | else send_0();
|
108 | }
|
109 | }
|
110 |
|
111 |
|
112 | void send_1(void)
|
113 | {
|
114 | DDRB &= ~(1<<PB0); // 1677us space
|
115 | cnt = 0;
|
116 | while(cnt < 135);
|
117 | DDRB |= (1<<PB0); // 559us pulse 40khz
|
118 | cnt = 0;
|
119 | while(cnt < 46);
|
120 | DDRB &= ~(1<<PB0);
|
121 | }
|
122 |
|
123 | void send_0(void)
|
124 | {
|
125 | DDRB &= ~(1<<PB0); // 559us space
|
126 | cnt = 0;
|
127 | while(cnt < 46);
|
128 | DDRB |= (1<<PB0); // 559us pulse 40khz
|
129 | cnt = 0;
|
130 | while(cnt < 46);
|
131 | DDRB &= ~(1<<PB0);
|
132 | }
|
133 |
|
134 |
|
135 |
|
136 |
|
137 | ISR(TIMER2_COMP_vect)
|
138 | {
|
139 | PORTB ^= (1<<PB0);
|
140 | cnt++;
|
141 | }
|