Nut/OS  4.10.3
API Reference
irsony.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 /*
00035  * $Log$
00036  * Revision 1.2  2008/08/11 06:59:17  haraldkipp
00037  * BSD types replaced by stdint types (feature request #1282721).
00038  *
00039  * Revision 1.1  2005/07/26 18:02:27  haraldkipp
00040  * Moved from dev.
00041  *
00042  * Revision 1.3  2005/01/28 12:13:14  freckle
00043  * changed NutEventPostFromIRQ into NutEventPostFromIrq
00044  *
00045  * Revision 1.2  2004/03/18 18:41:18  haraldkipp
00046  * Bugfix. Now works with ICCAVR
00047  *
00048  * Revision 1.1  2003/07/21 18:07:54  haraldkipp
00049  * Sony infrared remote control driver added
00050  *
00051  */
00052 
00053 #include <cfg/medianut.h>
00054 #include <sys/atom.h>
00055 #include <sys/event.h>
00056 
00057 #ifdef __IMAGECRAFT__
00058 #pragma interrupt_handler SIG_INTERRUPT4:iv_INT4
00059 #pragma interrupt_handler SIG_OVERFLOW2:iv_TIMER2_OVF
00060 #endif
00061 
00066 
00067 #include <dev/irsony.h>
00068 
00069 #define IRTIMER_START   0xF0
00070 #define IRTIMER_SCALE   0x01
00071 
00075 long nut_ircode;
00076 
00080 HANDLE nut_irqueue;
00081 
00082 /*
00083  * Tick counter, incremented on each timer overflow and
00084  * cleared on each edge detection on the infrared signal.
00085  */
00086 static uint16_t irticks;
00087 
00088 /*
00089  * Number of bits received from infrared decoder.
00090  */
00091 static uint8_t irbitnum;
00092 
00096 SIGNAL(SIG_OVERFLOW2)
00097 {
00098     /* Set the timer value. */
00099     outb(TCNT2, IRTIMER_START);
00100 
00101     /*
00102      * Increment our tick counter. If it overflows, then wait
00103      * for the next start bit and disable the timer.
00104      */
00105     if (++irticks == 0) {
00106         irbitnum = 0;
00107         cbi(TIMSK, 6);
00108     }
00109 }
00110 
00114 SIGNAL(SIG_INTERRUPT4)
00115 {
00116     static uint16_t minset;      /* Min. length of bit value 1, calculated from start bit. */
00117     static uint16_t ccode;       /* Current code. */
00118     static uint16_t lcode;       /* Last code. */
00119     static uint8_t ncode;        /* Number of equal codes. */
00120     uint16_t bitlen = irticks;   /* Length of the current bit. */
00121 
00122     irticks = 0;
00123 
00124     /* Rising egde marks end of bit. */
00125     if (inb(IR_SIGNAL_PIN) & _BV(IR_SIGNAL_BIT)) {
00126         /* Start bit. */
00127         if (irbitnum++ == 0) {
00128             ccode = 0;
00129             minset = bitlen / 3;
00130         }
00131         /* Data bits. */
00132         else {
00133             /* If its length is greater than a third of the start bit,
00134                then we assume this bit set. */
00135             if (bitlen >= minset)
00136                 ccode |= _BV(12);
00137             ccode >>= 1;
00138             /* All data bits collected? */
00139             if (irbitnum > 12) {
00140                 cbi(TIMSK, 6);
00141                 irbitnum = 0;
00142                 if (ncode++) {
00143                     if (lcode != ccode)
00144                         ncode = 0;
00145                     /* If we have two equal codes, pass it to the 
00146                        application. */
00147                     else if (ncode > 1) {
00148                         ncode = 0;
00149                         nut_ircode = ccode;
00150                         NutEventPostFromIrq(&nut_irqueue);
00151                     }
00152                 } else
00153                     lcode = ccode;
00154             }
00155         }
00156     }
00157     /* Falling edges mark the start of a bit. Enable timer
00158        overflow interrupts. */
00159     else if (irbitnum == 0) {
00160         sbi(TIMSK, 6);
00161     }
00162 
00163 }
00164 
00168 int NutIrInitSony(void)
00169 {
00170     NutEnterCritical();
00171     /* 
00172      * Initialize timer 2 and enable overflow interrupts.
00173      */
00174     outb(TCNT2, IRTIMER_START);
00175     outb(TCCR2, IRTIMER_SCALE);
00176     sbi(TIMSK, 6);
00177 
00178     /* 
00179      * Enable infrared decoder interrupts on both edges. 
00180      */
00181     cbi(IR_SIGNAL_DDR, IR_SIGNAL_BIT);
00182     sbi(EICR, 0);
00183     cbi(EICR, 1);
00184     sbi(EIMSK, IR_SIGNAL_BIT);
00185 
00186     NutExitCritical();
00187 
00188     return 0;
00189 }
00190