i actually mixed up all 0 and 1 bits - "oups". Luckily this has no effect except...
[moodlight.git] / ircontrol.c
CommitLineData
2e7f4185 1/* $Id: ircontrol.c,v 1.3 2010/06/27 22:49:58 simimeie Exp $
17aea8ef 2 * Functions for the infrared receiver
3 *
4 * The infrared receiver is connected to PB0 / PCINT0.
5 */
6
7#include <avr/io.h>
8#include <avr/interrupt.h>
9#include "ircontrol.h"
8a1c848b 10#include "timers.h"
17aea8ef 11#include "console.h"
12
8a1c848b 13/* NOTE1: Note that the signal we get from the sensor is inverted. If we
14 * read a zero, it means there was infrared on, if we read a one, infrared
15 * is off.
16 * NOTE2: Only NEC is implemented here right now, because MY remote uses
17 * that protocol. However, there may be references to RC5 because I had
18 * already thought about that and just left them for possible future use. */
19
20/* For RC5, one bit length is 1778 us, when it toggles we see half
21 * of it, i.e. 889 us.
22 * that equals around 7100 cpu cycles at 8 MHz. */
23#define RC5HALFLENINCYCLES ((CPUFREQ * 889UL) / 1000000UL)
24
25/* For NEC, we start with a 9000 us pulse, then 4500 us silence.
26 * Then the bits follow:
2e7f4185 27 * a 1 is a 560 us pulse followed by 1690 us of silence.
28 * a 0 is a 560 us pulse followed by 560 us of silence.
8a1c848b 29 * These values equal the following cpu cycle counts:
30 * 9000 us = 72000 cc, 4500 us = 36000 cc, 560 us = 4480, 1690 us = 13520 cc
31 */
32#define NECSTARTLEN1 ((CPUFREQ * 9UL) / 1000UL)
33#define NECSTARTLEN2 ((CPUFREQ * 45UL) / 10000UL)
34#define NECPULSELEN ((CPUFREQ * 56UL) / 100000UL)
2e7f4185 35#define NECZEROLEN ((CPUFREQ * 112UL) / 100000UL)
36#define NECONELEN ((CPUFREQ * 225UL) / 100000UL)
8a1c848b 37
38/* the NEC code contains 4 bytes, sent with LSB first:
39 * 0+1 are either the "extended address" or "address and inverted address".
40 * 2 is the command code
41 * 3 is the inverted command code
42 */
43
44static struct timestamp last0irqts;
45static struct timestamp last1irqts;
46static uint8_t lastpin = 0;
47static uint8_t codebytes[4];
48static uint8_t curcodebit = 0xff;
49
50/* some example codes
51root@moodlight# !NSB! 11111111 00001000 11011111 00100000 (r)
52root@moodlight# !NSB! 11111111 00001000 01011111 10100000 (g)
53root@moodlight# !NSB! 11111111 00001000 10011111 01100000 (b)
54root@moodlight# !NSB! 11111111 00001000 00011111 11100000 (w)
55*/
56
17aea8ef 57ISR(PCINT0_vect) {
8a1c848b 58 uint8_t v;
59 struct timestamp curirqts;
60 uint32_t ts1diff; /* distance from last 1 */
61 uint32_t ts0diff; /* distance from last 0 */
62
63 v = PINB & _BV(PB0);
64 if (v == lastpin) { /* No change visible - spurious interrupt */
65 return;
66 }
67 curirqts = gettimestamp_noirq();
68 ts1diff = ((uint32_t)curirqts.ticks << 16) + curirqts.partticks;
69 ts0diff = ts1diff;
70 ts1diff -= ((uint32_t)last1irqts.ticks << 16) + last1irqts.partticks;
71 ts0diff -= ((uint32_t)last0irqts.ticks << 16) + last0irqts.partticks;
72 if (v) { /* Infrared just went away! */
73 if ((ts1diff >= (( 8 * NECSTARTLEN1) / 10))
74 && (ts1diff <= ((12 * NECSTARTLEN1) / 10))) {
75 /* NEC start bit */
76 /* console_printpgm_P(PSTR("!NSB!")); */
77 curcodebit = 0xfe; /* Wait for second part of start sequence */
78 } else {
79 if (curcodebit <= 32) { /* We're in a decoding attempt, so */
80 /* Check pulse length */
81 if ((ts1diff < (( 8 * NECPULSELEN) / 10))
82 || (ts1diff > ((12 * NECPULSELEN) / 10))) {
83 /* WRONG */
84 curcodebit = 0xff;
85 }
86 }
87 if (curcodebit == 32) {
88 if (codebytes[2] != (codebytes[3] ^ 0xff)) {
89 console_printpgm_P(PSTR("!CRC!"));
90 } else {
91 /* Successful decode! */
92 console_printpgm_P(PSTR(" DEC>"));
93 console_printhex8(codebytes[0]);
94 console_printhex8(codebytes[1]);
95 console_printhex8(codebytes[2]);
96 console_printhex8(codebytes[3]);
97 }
98 }
99 }
100 last0irqts = curirqts;
101 } else { /* Infrared went on */
102 if ((ts1diff >= (( 8 * NECZEROLEN) / 10))
103 && (ts1diff <= ((12 * NECZEROLEN) / 10))) {
104 /* console_printpgm_P(PSTR("0")); */
105 if (curcodebit < 32) {
106 curcodebit++;
107 }
108 } else if ((ts1diff >= (( 8 * NECONELEN) / 10))
109 && (ts1diff <= ((12 * NECONELEN) / 10))) {
110 /* console_printpgm_P(PSTR("1")); */
111 if (curcodebit < 32) {
112 codebytes[curcodebit >> 3] |= (1 << (curcodebit & 0x07));
113 curcodebit++;
114 } else {
115 curcodebit = 0xff;
116 }
117 } else if ((ts0diff >= (( 8 * NECSTARTLEN2) / 10))
118 && (ts0diff <= ((12 * NECSTARTLEN2) / 10))) {
119 if (curcodebit == 0xfe) { /* voila, correct start sequence */
120 curcodebit = 0;
121 codebytes[0] = codebytes[1] = codebytes[2] = codebytes[3] = 0;
122 }
123 }
124 last1irqts = curirqts;
125 }
126#if 0
127 console_printpgm_P(PSTR("!"));
128 console_printhex8(tsdiff >> 24);
129 console_printhex8(tsdiff >> 16);
130 console_printhex8(tsdiff >> 8);
131 console_printhex8(tsdiff >> 0);
132 console_printpgm_P(PSTR("!"));
133#endif
134#if 0
135 if (tsdiff > ((24 * HALFRC5LENINCYCLES) / 10)) {
136 /* Start of new transmission */
137 console_printpgm_P(PSTR("!1["));
138 console_printhex8(v);
139 lastbit = 1;
140 } else if (tsdiff > ((15 * HALFRC5LENINCYCLES) / 10)) {
141 /* Different bit than last time */
142 lastbit = !lastbit;
143 if (lastbit) {
144 console_printpgm_P(PSTR("1"));
145 } else {
146 console_printpgm_P(PSTR("0"));
147 }
148 } else if ((tsdiff < ((15 * HALFRC5LENINCYCLES) / 10))
149 && (tsdiff > (( 5 * HALFRC5LENINCYCLES) / 10))) {
150 /* Same bit as last time */
151 if (lastbit) {
152 console_printpgm_P(PSTR("1"));
153 } else {
154 console_printpgm_P(PSTR("0"));
155 }
17aea8ef 156 }
8a1c848b 157#endif
158 lastpin = v;
17aea8ef 159}
160
161void ircontrol_init(void)
162{
163 /* Activate pullup */
164 PORTB |= _BV(PB0);
165 /* enable PCINT0 */
166 PCICR |= _BV(PCIE0);
167 /* Enable pin change interrupt 0 (=PB0) in pcint0 */
168 PCMSK0 |= _BV(PCINT0);
169}
This page took 0.06039 seconds and 4 git commands to generate.