Subversion Repositories HomeAutomation

Rev

Rev 1972 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
547 andfri 1
/**
610 arune 2
 * IR receiver and transmitter driver.
547 andfri 3
 *
4
 * @date    2006-12-10
5
 *
610 arune 6
 * @author  Anders Runeson, Andreas Fritiofson
547 andfri 7
 *  
8
 */
9
 
10
/*-----------------------------------------------------------------------------
11
 * Includes
12
 *---------------------------------------------------------------------------*/
13
#include <config.h>
14
#include <drivers/ir/transceiver/irtransceiver.h>
608 arune 15
#include <drivers/ir/protocols.h>
547 andfri 16
#include <avr/io.h>
17
#include <avr/interrupt.h>
18
 
19
/*-----------------------------------------------------------------------------
20
 * Globals
21
 *---------------------------------------------------------------------------*/
1435 arune 22
#if IR_RX_ENABLE==1
23
uint16_t *rxbuf;
24
uint8_t rxlen;
25
#endif
26
#if IR_TX_ENABLE==1
27
uint16_t *txbuf;
28
uint8_t txlen;
29
#endif
608 arune 30
 
1435 arune 31
#if IR_TX_ENABLE==1
608 arune 32
static uint8_t bufIndex;                            //selects the pulse width in buffer to send
1435 arune 33
#endif
547 andfri 34
volatile uint8_t data_received;
552 andfri 35
volatile uint8_t data_transmitted;
547 andfri 36
uint8_t detect_edge;
37
uint8_t store;
38
 
39
/*-----------------------------------------------------------------------------
40
 * Prerequisites
41
 *---------------------------------------------------------------------------*/
1435 arune 42
#ifndef IR_RX_ACTIVE_LOW
43
#define IR_RX_ACTIVE_LOW    1
44
#endif
45
 
1431 arune 46
#ifndef IR_TX_ACTIVE_LOW
47
#define IR_TX_ACTIVE_LOW    0
48
#endif
601 arune 49
 
1435 arune 50
#ifndef IR_TX_ENABLE
51
#define IR_TX_ENABLE    0
52
#endif
53
 
54
#ifndef IR_RX_ENABLE
55
#define IR_RX_ENABLE    0
56
#endif
57
 
1480 arune 58
#ifndef IR_TX_HACK
59
#define IR_TX_HACK 0
60
#endif
1435 arune 61
 
1480 arune 62
 
547 andfri 63
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
64
#define TIMSK1  TIMSK
65
#define TIFR1   TIFR
66
#define ICIE1   TICIE1
67
#endif
68
 
552 andfri 69
#define IR_COMPARE_VECTOR       TIMER1_COMPB_vect
70
#define IR_TIMEOUT_VECTOR       TIMER1_COMPA_vect
71
#define IR_CAPTURE_VECTOR       TIMER1_CAPT_vect
72
#define IR_TIMEOUT_REG          OCR1A
73
#define IR_COMPARE_REG          OCR1B
74
#define IR_CAPTURE_REG          ICR1
75
#define IR_COUNT_REG            TCNT1
608 arune 76
#define IR_MODULATION_REG       OCR0A
552 andfri 77
#define IR_TIMER_INIT()         TCCR1A = 0; \
78
                                TCCR1B = (1<<ICNC1)|(2<<CS10);
79
#define IR_MASK_COMPARE()       TIMSK1 &= ~(1<<OCIE1B);
80
#define IR_UNMASK_COMPARE()     TIFR1 = (1<<OCF1B); TIMSK1 |= (1<<OCIE1B);
81
#define IR_MASK_TIMEOUT()       TIMSK1 &= ~(1<<OCIE1A);
82
#define IR_UNMASK_TIMEOUT()     TIFR1 = (1<<OCF1A); TIMSK1 |= (1<<OCIE1A);
83
#define IR_MASK_CAPTURE()       TIMSK1 &= ~(1<<ICIE1);
84
#define IR_UNMASK_CAPTURE()     TIFR1 = (1<<ICF1); TIMSK1 |= (1<<ICIE1);
85
#define IR_CAPTURE_FALLING()    TCCR1B &= ~(1<<ICES1); \
86
                                TIFR1 = (1<<ICF1);
87
#define IR_CAPTURE_RISING()     TCCR1B |= (1<<ICES1); \
88
                                TIFR1 = (1<<ICF1);
547 andfri 89
 
1480 arune 90
#if IR_TX_HACK==0
601 arune 91
#define IR_OUTP_HIGH()          TCCR0A |= (1<<COM0A0);
92
#define IR_OUTP_LOW()           TCCR0A &= ~(1<<COM0A0);
1480 arune 93
#endif
547 andfri 94
 
1480 arune 95
#if IR_TX_HACK==1
96
#define IR_T_PORT_HACK          PORTD
97
#define IR_T_PIN_HACK           PIND
98
#define IR_T_DDR_HACK           DDRD
99
#define IR_T_BIT_HACK           PD5
601 arune 100
 
1480 arune 101
#define IR_OUTP_HIGH()          IR_T_PORT_HACK &= ~(1<<IR_T_BIT_HACK);
102
#define IR_OUTP_LOW()           IR_T_PORT_HACK |= (1<<IR_T_BIT_HACK);
103
#endif
104
 
105
 
106
 
547 andfri 107
/*-----------------------------------------------------------------------------
108
 * Interrupt Handlers
109
 *---------------------------------------------------------------------------*/
110
 
1435 arune 111
#if IR_TX_ENABLE==1
552 andfri 112
ISR(IR_COMPARE_VECTOR)
547 andfri 113
{
608 arune 114
    if ((bufIndex&1) == 1) {        /* if odd, ir-pause */
601 arune 115
        IR_OUTP_LOW();
116
    } else {
117
        IR_OUTP_HIGH();
118
    }
119
 
727 noddan 120
    //The following three lines is just to allow a start signal to be zero.
121
/*  bufIndex++;
122
    while (txbuf[bufIndex] == 0){
123
        bufIndex++;
124
    }*/
125
 
608 arune 126
    if (bufIndex < txlen)
727 noddan 127
    {      
608 arune 128
        IR_COMPARE_REG += txbuf[bufIndex++];       
129
        //IR_COMPARE_REG += *(txbuf + bufIndex++);      
552 andfri 130
    }
131
    else
132
    {
133
        IR_MASK_COMPARE();
134
        data_transmitted = 1;
135
    }
547 andfri 136
}
1435 arune 137
#endif
547 andfri 138
 
1435 arune 139
#if IR_RX_ENABLE==1
552 andfri 140
ISR(IR_TIMEOUT_VECTOR)
547 andfri 141
{
608 arune 142
    if (rxlen)
547 andfri 143
    {
144
        /* Disable interrupts until the application has taken action on the
145
         * current data and reenabled reception. */
552 andfri 146
        IR_MASK_CAPTURE();
147
        IR_MASK_TIMEOUT();
547 andfri 148
        /* Notify the application that a pulse train has been received. */
149
        data_received = 1;
150
    }
151
    store = 0;
152
}
1435 arune 153
#endif
547 andfri 154
 
1435 arune 155
#if IR_RX_ENABLE==1
552 andfri 156
ISR(IR_CAPTURE_VECTOR)
547 andfri 157
{
552 andfri 158
    static uint16_t prev_time;
159
    uint16_t pulsewidth;
160
 
161
    /* Read the measured transition time from the capture register. */
162
    uint16_t time = IR_CAPTURE_REG;
547 andfri 163
 
164
    /* Toggle the edge detection. */
165
    if (detect_edge == 0)
166
    {
552 andfri 167
        IR_CAPTURE_RISING();
547 andfri 168
        detect_edge = 1;
169
    }
170
    else
171
    {
552 andfri 172
        IR_CAPTURE_FALLING();
547 andfri 173
        detect_edge = 0;
174
    }
175
 
552 andfri 176
    /* Subtract the current measurement from the previous to get the pulse
177
     * width. */
178
    pulsewidth = time - prev_time;
179
    prev_time = time;
180
 
181
    /* Set the timeout. */
182
    IR_TIMEOUT_REG = time + IR_MAX_PULSE_WIDTH;
183
 
547 andfri 184
    if (store)
185
    {
186
        /* Store the measurement. */
608 arune 187
        rxbuf[rxlen++] = pulsewidth;
188
        //*(rxbuf+rxlen++) = pulsewidth;
547 andfri 189
        /* Disable future measurements if we've filled the buffer. */
190
        //TODO: Report overflow to application
608 arune 191
        if (rxlen == MAX_NR_TIMES)
547 andfri 192
        {
552 andfri 193
            IR_MASK_CAPTURE();
547 andfri 194
        }
195
    }
196
    else
197
    {
198
        /* The first edge of the pulse train has been detected. Enable the
199
         * storage of the following pulsewidths. */
200
        store = 1;
201
        /* Enable timeout interrupt for detection of the end of the pulse
202
         * train. */
552 andfri 203
        IR_UNMASK_TIMEOUT();
547 andfri 204
    }
205
}
1435 arune 206
#endif
547 andfri 207
 
208
 
209
/*-----------------------------------------------------------------------------
210
 * Public Functions
211
 *---------------------------------------------------------------------------*/
212
 
213
void IrTransceiver_Init(void)
214
{
1435 arune 215
    IR_TIMER_INIT();
216
#if IR_RX_ENABLE==1
601 arune 217
    /* Set up receiver */
547 andfri 218
    IR_TIMEOUT_REG = IR_MAX_PULSE_WIDTH;
601 arune 219
    IR_R_DDR &= ~(1<<IR_R_BIT);
220
    //DDRC |= (1<<PC5);
1435 arune 221
#endif
601 arune 222
 
1435 arune 223
#if IR_TX_ENABLE==1
601 arune 224
    /* Set up transmitter */
225
    IR_T_DDR |= (1<<IR_T_BIT);
1468 arune 226
    #if defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
601 arune 227
    TCCR0A = (0<<COM0A1)|(0<<COM0A0)|(1<<WGM01)|(0<<WGM00);
228
    TCCR0B = (0<<WGM02)|(1<<CS00)|(0<<CS01)|(0<<CS02);
229
    #endif
1431 arune 230
 
1480 arune 231
#if IR_TX_HACK==0
1431 arune 232
#if IR_TX_ACTIVE_LOW==1
233
    /* when pwm is disconnected from port (during low) the port should output 5V */
234
    IR_T_PORT |= (1<<IR_T_BIT);
235
#else
236
    /* when pwm is disconnected from port (during low) the port should output 0V */
237
    IR_T_PORT &= ~(1<<IR_T_BIT);
238
#endif
1480 arune 239
#endif
1435 arune 240
 
1480 arune 241
#if IR_TX_HACK==1
242
    /* Set up transmitter */
243
    IR_T_DDR_HACK |= (1<<IR_T_BIT_HACK);
244
 
245
    /* when pwm is disconnected from port (during low) the port should output 5V */
246
    IR_T_PORT_HACK |= (1<<IR_T_BIT_HACK);
247
 
248
    IR_MODULATION_REG = (((F_CPU/2000)/38) -1);
249
 
250
    /* start pwm generator */
251
    TCCR0A |= (1<<COM0A0);
1435 arune 252
#endif
1480 arune 253
 
254
#endif
547 andfri 255
}
256
 
610 arune 257
void IrTransceiver_Receive_Start(uint16_t *buffer)
547 andfri 258
{
1435 arune 259
#if IR_RX_ENABLE==1
608 arune 260
     /* Setup buffer and arm the edge detection. */
261
    rxbuf = buffer;
262
    rxlen = 0;
547 andfri 263
    data_received = 0;
264
    store = 0;
265
#if (IR_RX_ACTIVE_LOW == 1)
552 andfri 266
    IR_CAPTURE_FALLING();
547 andfri 267
    detect_edge = 0;
268
#else
552 andfri 269
    IR_CAPTURE_RISING();
547 andfri 270
    detect_edge = 1;
271
#endif
552 andfri 272
    IR_UNMASK_CAPTURE();
1435 arune 273
#endif
547 andfri 274
}
275
 
613 arune 276
uint8_t IrTransceiver_Receive_Poll(uint8_t *len)
547 andfri 277
{
1435 arune 278
#if IR_RX_ENABLE==1
613 arune 279
    *len = rxlen;
547 andfri 280
    if (data_received)
281
    {
613 arune 282
        return IR_OK;
547 andfri 283
    }
613 arune 284
    else if (rxlen > 0)
547 andfri 285
    {
613 arune 286
        return IR_NOT_FINISHED;
287
    } else {
288
        return IR_NO_DATA;
547 andfri 289
    }
1435 arune 290
#else
291
    return 0;
292
#endif
547 andfri 293
}
294
 
601 arune 295
uint8_t IrTransceiver_Transmit_Poll(void) {
1435 arune 296
#if IR_TX_ENABLE==1
601 arune 297
    if (data_transmitted == 0) {
298
        return IR_NOT_FINISHED;
299
    } else {
300
        return IR_OK;
301
    }
1435 arune 302
#else
303
    return 0;
304
#endif
601 arune 305
}
306
 
608 arune 307
uint8_t IrTransceiver_Transmit(uint16_t *buffer, uint8_t length, uint8_t modfreq)
601 arune 308
{
1435 arune 309
#if IR_TX_ENABLE==1
601 arune 310
    data_transmitted = 0;
311
 
608 arune 312
    if (length == 0) return IR_NO_DATA;
601 arune 313
 
608 arune 314
    txbuf = buffer;
315
    txlen = length;
316
    bufIndex = 1;
547 andfri 317
 
1972 arune 318
    IR_MODULATION_REG = (((F_CPU/2000)/modfreq) -1);
547 andfri 319
 
608 arune 320
    IR_COMPARE_REG = IR_COUNT_REG + txbuf[0];
547 andfri 321
 
608 arune 322
    IR_OUTP_HIGH();
547 andfri 323
 
608 arune 324
    IR_UNMASK_COMPARE();
547 andfri 325
 
608 arune 326
    //while (!data_transmitted);
547 andfri 327
 
328
    return IR_OK;
1435 arune 329
#else
330
    return 0;
331
#endif
547 andfri 332
}