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 #pragma once
28 
29 #if defined (DOXYGEN) || !defined(ARDUINO) || defined ARDUINO_ARCH_AVR
30 
31 #include <Arduino.h>
32 #include "IrReader.h"
33 
34 #define ENABLE_PULL_UP
35 //#define DEBUG_PORT D
36 //#define DEBUG_PIN 6
37 //#define DEBUG_PORT L
38 
39 #define USE_PRESCALER_FACTOR_8 1
40 
45 class IrWidget : public IrReader {
46 public:
47  static const int16_t defaultMarkExcess = 0;
48 
49 protected:
51 
52  IrWidget(size_t captureLength = defaultCaptureLength,
53  bool pullup = false,
54  int16_t markExcess = defaultMarkExcess,
57  virtual ~IrWidget();
58 
59 public:
64  static const bool invertingSensor = true;
65 
66  virtual void capture() = 0;
67 
71  void receive() {
72  capture();
73  }
74 
75  size_t getDataLength() const { // was: getCaptureCount()
76  return captureCount;
77  }
78 
79  bool isReady() const {
80  return timeouted || !isEmpty();
81  }
82 
83  void reset() {
84  captureCount = 0;
85  }
86 
87  microseconds_t inline getDuration(unsigned int i) const {
88  uint32_t result32 = timerValueToNanoSeconds(unpackTimeVal(captureData[i])) / 1000
89  + (i & 1 ? markExcess : -markExcess);
90  return result32 <= MICROSECONDS_T_MAX ? (microseconds_t) result32 : MICROSECONDS_T_MAX;
91  }
92 
98  void setEndingTimeout(milliseconds_t timeout);
99 
101 
103  return frequency;
104  }
105 
106  void dump(Stream &stream) const;
107 
108 private:
109  void setup(bool setup);
110 
112  // Internal defines, don't change
114 
115 protected:
116 #if USE_PRESCALER_FACTOR_8
117 #define CAPTURE_PRESCALER_SETTING (_BV(CAT3(CS, CAP_TIM, 1)))
118 #define CAPTURE_PRESCALER_BITS (3)
119 #else
120 #define CAPTURE_PRESCALER_SETTING (_BV(CAT3(CS, CAP_TIM, 0)))
121 #define CAPTURE_PRESCALER_BITS (0)
122 #endif
123 #define CAPTURE_PRESCALER_FACTOR (_BV(CAPTURE_PRESCALER_BITS))
124 
125 #if RANGE_EXTENSION_BITS > 8
126  typedef uint16_t ovlBitsDataType;
127 #else
128  typedef uint8_t ovlBitsDataType;
129 #endif
130 
131  static const uint8_t RANGE_EXTENSION_BITS = 4; // factor for upper measurement range = 2^(RANGE_EXTENSION_BITS+1)
132 
133  ovlBitsDataType endingTimeout; // = _BV(RANGE_EXTENSION_BITS) - 1;
134 
135 private:
137  // Adaption to different MCUs and clk values
139 #if defined(_AVR_IOM32U4_H_)
140 #ifndef ALTERNATE_PIN
141  // Digital pin 4, ICP1
142 #define CAP_PORT D
143 #define CAP_PIN 4
144 #define CAP_TIM 1
145 #define CAP_TIM_OC A
146 #else // Alternate pin
147  // Digital pin 13, ICP3
148 #define CAP_PORT C
149 #define CAP_PIN 7
150 #define CAP_TIM 3
151 #define CAP_TIM_OC A
152 #endif // ALTERNATE_PIN
153 #elif defined(_AVR_IOM2560_H_)
154 #ifndef ALTERNATE_PIN
155  // Digital pin 49, ICP4
156 #define CAP_PORT L
157 #define CAP_PIN 0
158 #define CAP_TIM 4
159 #define CAP_TIM_OC A
160 #else // ALTERNATE_PIN
161  // Digital pin 48, ICP5
162 #define CAP_PORT L
163 #define CAP_PIN 1
164 #define CAP_TIM 5
165 #define CAP_TIM_OC A
166 #endif // ALTERNATE_PIN
167 #else
168  // the default is the setting for the ATmega328P / ATmega168
169  // Digital pin 8, ICP1
170 #define CAP_PORT B
171 #define CAP_PIN 0
172 #define CAP_TIM 1
173 #define CAP_TIM_OC A
174 #endif
175 
177  // Helper macros
179 #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) // clear bit
180 #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) // set bit
181 #define __CAT2(base, portname) base##portname // internally needed by CAT2
182 #define CAT2(prefix, num) __CAT2(prefix, num) // build a define name from 2 params
183 #define __CAT3(prefix, num, postfix) prefix##num##postfix // internally needed by CAT3
184 #define CAT3(prefix, num, postfix) __CAT3(prefix, num, postfix) // build a define name from 3 params
185 
186  // these macros are used to debug the timing with an logic analyzer or oscilloscope on a port pin
187 protected:
188  inline void debugPinToggle(void) {
189 #if defined(DEBUG_PIN) && defined(DEBUG_PORT)
190  CAT2(PIN, DEBUG_PORT) = _BV(DEBUG_PIN);
191 #endif
192  }
193 
194  inline void debugPinClear(void) {
195 #if defined(DEBUG_PIN) && defined(DEBUG_PORT)
196  cbi(CAT2(PORT, DEBUG_PORT), DEBUG_PIN);
197 #endif
198  }
199  uint16_t *captureData; //[bufSize]; // the buffer where the catured data is stored
200  uint16_t captureCount; // number of values stored in captureData
201  static const uint8_t sampleSize = 2;
202 
203  virtual uint32_t unpackTimeVal(uint32_t val) const = 0;
204 
205  // convert number of clocks to nanoseconds, try to use integer arithmetic and avoid
206  // overflow and too much truncation (double arithmetic costs additional 800 byte of code)
207  static uint32_t inline timerValueToNanoSeconds(uint32_t x) {
208 #if (F_CPU % 8000000) == 0
209  return (x * (125UL << CAPTURE_PRESCALER_BITS)) / (F_CPU / 8000000UL);
210 #elif (F_CPU % 1000000) == 0
211  return (x * (1000UL << CAPTURE_PRESCALER_BITS)) / (F_CPU / 1000000UL);
212 #elif (F_CPU % 115200) == 0 // serial bps rate compatible cpu clocks, e.g. 7372800 or 14745600
213  // TODO: this has to be tested, especially the accuracy
214  return (((x * (1000UL << CAPTURE_PRESCALER_BITS)) / (F_CPU / 115200UL)) * 625UL) / 72UL;
215 #else
216  // TODO: this has to be tested
217  return (uint32_t) (((double) x * (1.0E9 * (double) CAPTURE_PRESCALER_FACTOR)) / (double) F_CPU); // use double precision floating point arithmetic
218 #endif
219  }
220 };
221 
222 #endif // ARDUINO_ARCH_AVR
bool timeouted
True if last receive ended with a timeout.
Definition: IrReader.h:47
void setEndingTimeout(milliseconds_t timeout)
Sets the ending timeout.
Definition: IrWidget.cpp:55
static const milliseconds_t defaultBeginningTimeout
Definition: IrReader.h:33
void debugPinToggle(void)
Definition: IrWidget.h:188
uint16_t microseconds_t
Type for durations in micro seconds.
Definition: InfraredTypes.h:15
milliseconds_t getEndingTimeout() const
Definition: IrWidget.cpp:59
uint32_t frequency_t
Type for modulation frequency in Hz.
Definition: InfraredTypes.h:32
static const uint8_t sampleSize
Definition: IrWidget.h:201
static const milliseconds_t defaultEndingTimeout
Definition: IrReader.h:34
static const int16_t defaultMarkExcess
Definition: IrWidget.h:47
#define MICROSECONDS_T_MAX
Largest microseconds_t number possible.
Definition: InfraredTypes.h:18
uint8_t ovlBitsDataType
Definition: IrWidget.h:128
uint16_t milliseconds_t
Type for durations in milli seconds.
Definition: InfraredTypes.h:25
Base class for classes based upon ICP pins capture.
Definition: IrWidget.h:45
Abstract base class for all IR readers, capturing or receiving.
Definition: IrReader.h:30
size_t getDataLength() const
Returns the number of collected durations.
Definition: IrWidget.h:75
#define cbi(sfr, bit)
Definition: IrWidget.h:179
uint16_t * captureData
Definition: IrWidget.h:199
virtual ~IrWidget()
Definition: IrWidget.cpp:51
static const bool invertingSensor
Set true means if sensor signal is inverted (low = signal on) (false has not been tested,...
Definition: IrWidget.h:64
microseconds_t getDuration(unsigned int i) const
Returns the index-th duration, if possible.
Definition: IrWidget.h:87
frequency_t getFrequency() const
Returns frequency of received signal.
Definition: IrWidget.h:102
static uint32_t timerValueToNanoSeconds(uint32_t x)
Definition: IrWidget.h:207
uint16_t captureCount
Definition: IrWidget.h:200
#define CAPTURE_PRESCALER_FACTOR
Definition: IrWidget.h:123
virtual uint32_t unpackTimeVal(uint32_t val) const =0
#define CAPTURE_PRESCALER_BITS
Definition: IrWidget.h:118
frequency_t frequency
Definition: IrWidget.h:50
milliseconds_t beginningTimeout
Definition: IrReader.h:38
void debugPinClear(void)
Definition: IrWidget.h:194
void dump(Stream &stream) const
Prints a textual representation of the received data to the Stream supplied.
Definition: IrWidget.cpp:64
static const uint8_t RANGE_EXTENSION_BITS
Definition: IrWidget.h:131
static const size_t defaultCaptureLength
Definition: IrReader.h:35
ovlBitsDataType endingTimeout
Definition: IrWidget.h:133
#define CAT2(prefix, num)
Definition: IrWidget.h:182
void receive()
For compatibility with the receiver classes, receive is a synonym for capture.
Definition: IrWidget.h:71
bool isReady() const
Returns true if there is collected data.
Definition: IrWidget.h:79
void reset()
Definition: IrWidget.h:83
int16_t markExcess
Microseconds subtracted from pulses and added to gaps.
Definition: IrReader.h:44
IrWidget(size_t captureLength=defaultCaptureLength, bool pullup=false, int16_t markExcess=defaultMarkExcess, milliseconds_t beginningTimeout=defaultBeginningTimeout, milliseconds_t endingTimeout=defaultEndingTimeout)
Definition: IrWidget.cpp:34
virtual bool isEmpty() const
Definition: IrReader.h:126
virtual void capture()=0