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