Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
157 arune 1
/**
2
 * IR receiver driver.
3
 *
4
 * @date    2006-12-10
5
 *
6
 * @author  Anders Runeson
7
 *  
8
 */
9
 
10
/*-----------------------------------------------------------------------------
11
 * Includes
12
 *---------------------------------------------------------------------------*/
13
#include "irreceiver.h"
14
#include <avr/io.h>
15
 
201 arune 16
/*-----------------------------------------------------------------------------
17
 * Globals
18
 *---------------------------------------------------------------------------*/
19
volatile uint16_t lastProtoTimeout = 0;
157 arune 20
 
201 arune 21
 
157 arune 22
/*-----------------------------------------------------------------------------
23
 * Prerequisites
24
 *---------------------------------------------------------------------------*/
25
 
26
 
27
/*-----------------------------------------------------------------------------
28
 * Public Functions
29
 *---------------------------------------------------------------------------*/
30
 
31
void initTimer(void) {
32
    //sätt upp timer
33
    #if defined(__AVR_ATmega8__)
34
    TCCR1B = (0<<CS11) | (1<<CS10); // prescaler: 1
35
    TIFR  |= (1<<TOV1);             // clear overflow flag.
36
    TCNT1 = 0;
37
    #endif
38
    #if defined(__AVR_ATmega88__)
39
    TCCR1B = (0<<CS11) | (1<<CS10); // prescaler: 1
40
    TIFR1  |= (1<<TOV1);            // clear overflow flag.
41
    TCNT1 = 0;
42
    #endif
43
}
44
 
45
int isTimerOvfl(void) {
46
    #if defined(__AVR_ATmega8__)
47
    if (TIFR  & (1<<TOV1)) return 1;
48
    #endif
49
    #if defined(__AVR_ATmega88__)
50
    if (TIFR1  & (1<<TOV1)) return 1;
51
    #endif
52
 
53
    return 0;
54
}
55
 
56
uint16_t getTimerVal(void) {
57
    #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega88__)
58
    return TCNT1;
59
    #endif
60
}
61
 
62
void setTimerVal(uint16_t value) {
63
    #if defined(__AVR_ATmega8__)
64
    TCNT1 = value;
65
    TIFR |= (1<<TOV1);  // clear overflow flag.
66
    #endif
67
    #if defined(__AVR_ATmega88__)
68
    TCNT1 = value;
69
    TIFR1 |= (1<<TOV1);  // clear overflow flag.
70
    #endif
71
}
72
 
73
/**
74
 * Receive RC5 data
75
 *
76
 * @param address
77
 *      Pointer to store the address of the received data
78
 * @param command
79
 *      Pointer to store the command of the received data
80
 */
81
int receiveRC5(uint8_t *address, uint8_t *command) {
82
    //printf("startbit of RC5!\n");
83
    uint8_t i;
84
    //read second startbit, togglebit and the 5 addressbits
85
    for (i=0; i<7; i++) {
86
        //set up a quarter of a bit period time
87
        setTimerVal(0xFFFF-(IR_RC5_BIT/4));
88
        //and wait for time to elapse
89
        while(!isTimerOvfl());
90
        //reset timer ovfl flag
91
        setTimerVal(0);
92
        if (IRPIN & (1<<IRBIT)) {
93
            //save a one
94
            *address |= (1<<(6-i));
95
            //wait for negative slope, while checking timer overflow
96
            while ((IRPIN & (1<<IRBIT))) {
97
                //om timeout (om timer-ovflow-flaggan sätt)
98
                if (isTimerOvfl() == 1) return IR_TIME_OVFL;
99
            }
100
        } else {
101
            //save a zero
102
 
103
            //wait for positiv slope
104
            while (!(IRPIN & (1<<IRBIT))) {
105
                //om timeout (om timer-ovflow-flaggan sätt)
106
                if (isTimerOvfl() == 1) return IR_TIME_OVFL;
107
            }
108
        }
109
        //set up a half a bit period time
110
        setTimerVal(0xFFFF-(IR_RC5_BIT/2));
111
        //and wait for time to elapse
112
        while(!isTimerOvfl());
113
    }
114
 
115
    //read 5 command bits
116
    for (i=0; i<6; i++) {
117
        //set up a quarter of a bit period time
118
        setTimerVal(0xFFFF-(IR_RC5_BIT/4));
119
        //and wait for time to elapse
120
        while(!isTimerOvfl());
121
        //reset timer ovfl flag
122
        setTimerVal(0);
123
        if (IRPIN & (1<<IRBIT)) {
124
            //save a one
125
            *command |= (1<<(5-i));
126
            //wait for negative slope, while checking timer overflow
127
            while ((IRPIN & (1<<IRBIT))) {
128
                //om timeout (om timer-ovflow-flaggan sätt).
129
                if (isTimerOvfl() == 1) return IR_TIME_OVFL;
130
            }
131
        } else {
132
            //save a zero
133
 
134
            //wait for positiv slope
135
            while (!(IRPIN & (1<<IRBIT))) {
136
                //om timeout (om timer-ovflow-flaggan sätt)
137
                if (isTimerOvfl() == 1) return IR_TIME_OVFL;
138
            }
139
        }
140
        //set up a half a bit period time
141
        setTimerVal(0xFFFF-(IR_RC5_BIT/2));
142
        //and wait for time to elapse
143
        while(!isTimerOvfl());
144
    }
145
 
146
    //wait for positiv slope to ensure that ir sequence is over
147
    setTimerVal(0);
148
    while (!(IRPIN & (1<<IRBIT))) {
149
        //om timeout (om timer-ovflow-flaggan sätt)
150
        if (isTimerOvfl() == 1) return IR_TIME_OVFL;
151
    }
152
 
153
    //support RC5-extended by putting the inversion of startbit 2 as the 7th commandbit
154
    *command |= (~(*address) & 0x40);
155
    *address &= 0x1f;
156
    //printf("address %i\n", *address);
157
    //printf("command %i\n", *command);
158
 
159
    return IR_OK;
160
}
161
 
201 arune 162
uint16_t getLastProtoTimeout(void) {
163
    return lastProtoTimeout;
164
}
165
 
157 arune 166
/**
167
 * Checks if ir-receiver is outputting data, if so then receive it
168
 *
169
 * @param proto
170
 *      Pointer to store the protocol of the received data
171
 * @param address
172
 *      Pointer to store the address of the received data
173
 * @param command
174
 *      Pointer to store the command of the received data
175
 * @return
176
 *      IR_OK if data received successfully, one of several errormessages if not
177
 */
178
int checkIr(uint8_t *proto, uint8_t *address, uint8_t *command) {
179
    if (IRPIN & (1<<IRBIT)) return IR_NO_DATA;      //om irmodulen ger en etta så återgå
180
 
181
    //nu lägger irmodulen ut en nolla, "startbiten" alltså
182
 
183
    uint16_t timerVal;
184
 
185
    *address = 0;
186
    *command = 0;
187
 
188
    //Läs in längden på startbiten
189
    initTimer();
190
    while (!(IRPIN & (1<<IRBIT))) {     //vänta på att irmodulen lägger ut en etta
191
        //om timeout (om timer-ovflow-flaggan sätt)
192
        if (isTimerOvfl() == 1) return IR_TIME_OVFL;
193
    }
194
    timerVal = getTimerVal();
195
 
196
    /*
197
     * Anropa olika funktioner beroende på längden
198
     * för vissa protokoll behöver längden på första biten skickas med till funktionen?
199
     * t.ex. sharp?
200
     * */
201
 
202
    if ((timerVal < IR_RC5_ST_BIT+500) && (timerVal > IR_RC5_ST_BIT-500)) {
203
        *proto = IR_PROTO_RC5;
204
        return receiveRC5(&*address, &*command);
205
    } //else if ...
206
 
207
 
208
    return IR_NO_PROTOCOL;
209
}
201 arune 210
 
211
 
212
int checkIrIdle(void) {
213
    if (IRPIN & (1<<IRBIT)) return IR_NO_DATA;      //om irmodulen ger en etta så återgå
214
 
215
    //nu lägger irmodulen ut en nolla, "startbiten" alltså
216
 
217
    uint16_t timerVal;
218
 
219
    //Läs in längden på startbiten
220
    initTimer();
221
    while (!(IRPIN & (1<<IRBIT))) {     //vänta på att irmodulen lägger ut en etta
222
        //om timeout (om timer-ovflow-flaggan sätt)
223
        if (isTimerOvfl() == 1) return IR_TIME_OVFL;
224
    }
225
    timerVal = getTimerVal();
226
 
227
    if ((timerVal < IR_MAX_REPEATE_PULSE_WIDTH) && (timerVal > IR_MIN_REPEATE_PULSE_WIDTH)) {
228
        return IR_OK;
229
    } //else if ...
230
 
231
 
232
    return IR_NO_PROTOCOL;
233
}