Infrared4Arduino
IrWidget.h
Go to the documentation of this file.
1 /* IR Widget: capture a raw IR signal and dump the timing of the non-demodulated signal
2 
3 http://www.piclist.com/images/boards/irwidget/index.htm
4 http://www.hifi-remote.com/forums/dload.php?action=file&file_id=2044
5 http://www.hifi-remote.com/wiki/index.php?title=IR_Scope_and_IR_Widget_User%27s_Guide
6 http://www.compendiumarcana.com/irwidget/
7 
8 Arduino digital pin numbers for the input capture pin (ICP) and the logic analyzer debugging pin (LA Dbg):
9 Board name / MCU | ICP pin | LA Dbg pin
10 -------------------------------------------|--------------.-----------|------------------------
11 Duemilanove/Uno (ATmega328P / ATmega168) | ICP1/PB0, Arduino pin 8 | PD6, Arduino pin 6
12 Leonardo (ATmega32U4) | ICP1/PD4, Arduino pin 4 | PD6, Arduino pin 12
13 Arduino Mega 2560 (ATmega2560) | ICP4/PL0, Arduino pin 49 | PL6, Arduino pin 43
14 
15 see also here:
16 http://arduino.cc/en/Hacking/PinMapping168 (also for ATmega328P)
17 http://arduino.cc/en/Hacking/PinMapping32u4
18 http://arduino.cc/en/Hacking/PinMapping2560
19  */
20 
21 // Copyright (c) 2012 Michael Dreher <michael(at)5dot1.de>
22 // this code may be distributed under the terms of the General Public License V2 (GPL V2)
23 
24 // Code slighty reorganized by Bengt Martensson
25 
26 //#define ALTERNATE_PIN
27 #ifndef IRWIDGET_H
28 #define IRWIDGET_H
29 
30 #include <Arduino.h>
31 #include "IrReader.h"
32 
33 #define ENABLE_PULL_UP
34 //#define DEBUG_PORT D
35 //#define DEBUG_PIN 6
36 //#define DEBUG_PORT L
37 
38 #define USE_PRESCALER_FACTOR_8 1
39 
44 class IrWidget : public IrReader {
45 public:
46  static const int16_t defaultMarkExcess = 0;
47 
48 protected:
50 
51  IrWidget(size_t captureLength = defaultCaptureLength,
52  boolean pullup = false,
53  int16_t markExcess = defaultMarkExcess,
56  virtual ~IrWidget();
57 public:
58  static const boolean invertingSensor = true;
59 
60  virtual void capture() = 0;
61 
63  void receive() {
64  capture();
65  }
66 
67  size_t getDataLength() const { // was: getCaptureCount()
68  return captureCount;
69  }
70 
71  boolean isReady() const {
72  return timeouted || !isEmpty();
73  }
74 
75  void reset() {
76  captureCount = 0;
77  }
78 
79  microseconds_t inline getDuration(unsigned int i) const {
81  + (i & 1 ? markExcess : -markExcess);
82  }
83 
84  //void setBeginningTimeout(milliseconds_t timeOut) { beginningTimeout = timeOut; }
85 
86  //milliseconds_t getBeginningTimeout() const { return beginningTimeout; }
87 
93  void setEndingTimeout(milliseconds_t timeout);
94 
96 
98  return frequency;
99  }
100 
101  void dump(Stream &stream) const;
102 
103 private:
104  void setup(boolean setup);
105 
107  // Internal defines, don't change
109 protected:
110 #if USE_PRESCALER_FACTOR_8
111 #define CAPTURE_PRESCALER_SETTING (_BV(CAT3(CS, CAP_TIM, 1)))
112 #define CAPTURE_PRESCALER_BITS (3)
113 #else
114 #define CAPTURE_PRESCALER_SETTING (_BV(CAT3(CS, CAP_TIM, 0)))
115 #define CAPTURE_PRESCALER_BITS (0)
116 #endif
117 #define CAPTURE_PRESCALER_FACTOR (_BV(CAPTURE_PRESCALER_BITS))
118 
119 #if RANGE_EXTENSION_BITS > 8
120  typedef uint16_t ovlBitsDataType;
121 #else
122  typedef uint8_t ovlBitsDataType;
123 #endif
124  //static const uint16_t bufSize = ((RAMEND - 0x100 - projectRamUsage) / sizeof (uint16_t)); // use as much RAM as possible
125  //uint16_t bufSize;
126  static const uint8_t RANGE_EXTENSION_BITS = 4; // factor for upper measurement range = 2^(RANGE_EXTENSION_BITS+1)
127 
128  //public: // FIXME
129  ovlBitsDataType endingTimeout; // = _BV(RANGE_EXTENSION_BITS) - 1;
130 private:
132  // Adaption to different MCUs and clk values
134 #if defined(_AVR_IOM32U4_H_)
135 #ifndef ALTERNATE_PIN
136  // Digital pin 4, ICP1
137 #define CAP_PORT D
138 #define CAP_PIN 4
139 #define CAP_TIM 1
140 #define CAP_TIM_OC A
141 #else // Alternate pin
142  // Digital pin 13, ICP3
143 #define CAP_PORT C
144 #define CAP_PIN 7
145 #define CAP_TIM 3
146 #define CAP_TIM_OC A
147 #endif // ALTERNATE_PIN
148 #elif defined(_AVR_IOM2560_H_)
149 #ifndef ALTERNATE_PIN
150  // Digital pin 49, ICP4
151 #define CAP_PORT L
152 #define CAP_PIN 0
153 #define CAP_TIM 4
154 #define CAP_TIM_OC A
155 #else // ALTERNATE_PIN
156  // Digital pin 48, ICP5
157 #define CAP_PORT L
158 #define CAP_PIN 1
159 #define CAP_TIM 5
160 #define CAP_TIM_OC A
161 #endif // ALTERNATE_PIN
162 #else
163  // the default is the setting for the ATmega328P / ATmega168
164  // Digital pin 8, ICP1
165 #define CAP_PORT B
166 #define CAP_PIN 0
167 #define CAP_TIM 1
168 #define CAP_TIM_OC A
169 #endif
170 
172  // Helper macros
174 #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) // clear bit
175 #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) // set bit
176 #define __CAT2(base, portname) base##portname // internally needed by CAT2
177 #define CAT2(prefix, num) __CAT2(prefix, num) // build a define name from 2 params
178 #define __CAT3(prefix, num, postfix) prefix##num##postfix // internally needed by CAT3
179 #define CAT3(prefix, num, postfix) __CAT3(prefix, num, postfix) // build a define name from 3 params
180 
181  // these macros are used to debug the timing with an logic analyzer or oscilloscope on a port pin
182 protected:
183  inline void debugPinToggle(void) {
184 #if defined(DEBUG_PIN) && defined(DEBUG_PORT)
185  CAT2(PIN, DEBUG_PORT) = _BV(DEBUG_PIN);
186 #endif
187  }
188 
189  inline void debugPinClear(void) {
190 #if defined(DEBUG_PIN) && defined(DEBUG_PORT)
191  cbi(CAT2(PORT, DEBUG_PORT), DEBUG_PIN);
192 #endif
193  }
194  uint16_t *captureData; //[bufSize]; // the buffer where the catured data is stored
195  uint16_t captureCount; // number of values stored in captureData
196  uint16_t period/* = 0*/; // the time of one period in CPU clocks
197  // Only inverting sensors are supported in this version
198  //static const bool sensorIsInverting = true;///* = false*/; // true means the sensor signal is inverted (low = signal on)
199  static const uint8_t sampleSize = 2;
200 
201  virtual uint32_t unpackTimeVal(uint32_t val) const = 0;
202 
203  // convert number of clocks to nanoseconds, try to use integer arithmetic and avoid
204  // overflow and too much truncation (double arithmetic costs additional 800 byte of code)
205  static uint32_t inline timerValueToNanoSeconds(uint32_t x) {
206 #if (F_CPU % 8000000) == 0
207  return (x * (125UL << CAPTURE_PRESCALER_BITS)) / (F_CPU / 8000000UL);
208 #elif (F_CPU % 1000000) == 0
209  return (x * (1000UL << CAPTURE_PRESCALER_BITS)) / (F_CPU / 1000000UL);
210 #elif (F_CPU % 115200) == 0 // serial bps rate compatible cpu clocks, e.g. 7372800 or 14745600
211  // TODO: this has to be tested, especially the accuracy
212  return (((x * (1000UL << CAPTURE_PRESCALER_BITS)) / (F_CPU / 115200UL)) * 625UL) / 72UL;
213 #else
214  // TODO: this has to be tested
215  return (uint32_t) (((double) x * (1.0E9 * (double) CAPTURE_PRESCALER_FACTOR)) / (double) F_CPU); // use double precision floating point arithmetic
216 #endif
217  }
218 };
219 
220 #endif /* IRWIDGET_H */
221 
size_t getDataLength() const
Returns the number of collected durations.
Definition: IrWidget.h:67
void setEndingTimeout(milliseconds_t timeout)
Sets the ending timeout.
Definition: IrWidget.cpp:53
static const milliseconds_t defaultBeginningTimeout
Definition: IrReader.h:33
boolean isReady() const
Returns true if there is collected data.
Definition: IrWidget.h:71
void debugPinToggle(void)
Definition: IrWidget.h:183
uint16_t microseconds_t
Type for durations in micro seconds.
Definition: InfraredTypes.h:16
static const uint8_t sampleSize
Definition: IrWidget.h:199
static const milliseconds_t defaultEndingTimeout
Definition: IrReader.h:34
static const int16_t defaultMarkExcess
Definition: IrWidget.h:46
virtual uint32_t unpackTimeVal(uint32_t val) const =0
static const boolean invertingSensor
Definition: IrWidget.h:58
uint8_t ovlBitsDataType
Definition: IrWidget.h:122
milliseconds_t getEndingTimeout() const
Definition: IrWidget.cpp:57
virtual boolean isEmpty() const
Definition: IrReader.h:119
uint16_t milliseconds_t
Type for durations in milli seconds.
Definition: InfraredTypes.h:26
microseconds_t getDuration(unsigned int i) const
Returns the index-th duration, if possible.
Definition: IrWidget.h:79
IrWidget(size_t captureLength=defaultCaptureLength, boolean pullup=false, int16_t markExcess=defaultMarkExcess, milliseconds_t beginningTimeout=defaultBeginningTimeout, milliseconds_t endingTimeout=defaultEndingTimeout)
Definition: IrWidget.cpp:32
Base class for classes based upon ICP pins capture.
Definition: IrWidget.h:44
Abstract base class for all IR readers, capturing or receiving.
Definition: IrReader.h:30
boolean timeouted
True if last receive ended with a timeout.
Definition: IrReader.h:47
#define cbi(sfr, bit)
Definition: IrWidget.h:174
uint16_t * captureData
Definition: IrWidget.h:194
virtual ~IrWidget()
Definition: IrWidget.cpp:49
frequency_t getFrequency() const
Definition: IrWidget.h:97
uint16_t frequency_t
Type for modulation frequency in Hz.
Definition: InfraredTypes.h:33
static uint32_t timerValueToNanoSeconds(uint32_t x)
Definition: IrWidget.h:205
uint16_t captureCount
Definition: IrWidget.h:195
#define CAPTURE_PRESCALER_FACTOR
Definition: IrWidget.h:117
#define CAPTURE_PRESCALER_BITS
Definition: IrWidget.h:112
frequency_t frequency
Definition: IrWidget.h:49
void dump(Stream &stream) const
Prints a textual representation of the received data to the Stream supplied.
Definition: IrWidget.cpp:62
milliseconds_t beginningTimeout
Definition: IrReader.h:38
void debugPinClear(void)
Definition: IrWidget.h:189
static const uint8_t RANGE_EXTENSION_BITS
Definition: IrWidget.h:126
static const size_t defaultCaptureLength
Definition: IrReader.h:35
ovlBitsDataType endingTimeout
Definition: IrWidget.h:129
uint16_t period
Definition: IrWidget.h:196
#define CAT2(prefix, num)
Definition: IrWidget.h:177
void receive()
For compatibility with the receiver classes, receive is a synonym for capture.
Definition: IrWidget.h:63
void reset()
Definition: IrWidget.h:75
int16_t markExcess
Microseconds subtracted from pulses and added to gaps.
Definition: IrReader.h:44
virtual void capture()=0