Skip to content

Commit bd7229c

Browse files
author
MA Laforge
committed
Suport ATmega328 & sysclock/timer2 transmission.
1 parent a4c6cb1 commit bd7229c

File tree

16 files changed

+335
-167
lines changed

16 files changed

+335
-167
lines changed

README.md

Lines changed: 52 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,37 @@
1-
[IRremote]: http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html "IRremote (Ken Shirriff)"
1+
[IRremote]: <http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html> "IRremote (Ken Shirriff)"
22

33
# ArduinoCIR: Consumer IR Control
44

55
## Description
66

7-
ArduinoCIR provides the ir\_messaging library, a ready-to-use solution for sending/receiving consumer IR (remote-control) signals on the Arduino platform.
7+
ArduinoCIR provides the ir\_messaging library, a ready-to-use solution for sending/receiving consumer IR (remote-control) signals on Arduino platforms.
88

99
<a name="SupportedHW"></a>
1010
### Supported Hardware
1111

12-
Only a single chipset is supported at the moment: the ATmega2560. Nonetheless, ir\_messaging was designed to be extensible to other Arduino platforms. Of course, no effort was yet placed on the mechanics of *how* to conditionally build for different platforms.
13-
14-
- Arduino Mega 2560 / Arduino Mega ADK.
12+
ArduinoCIR was designed to support multiple Atmel platforms. At the moment, only a few are supported:
13+
14+
- Atmel ATmega328/328P
15+
- Arduino Uno
16+
- Arduino Redboard (Tested)
17+
- Arduino Pro
18+
- Arduino Fio
19+
- Arduino Mini
20+
- Arduino Nano
21+
- Arduino LilyPad
22+
- Arduino BT
23+
- Arduino Ethernet
24+
- Atmel ATmega1280
25+
- Arduino Mega
26+
- Atmel ATmega2560
27+
- Arduino Mega 2560 (Tested)
28+
- Arduino Mega ADK (Tested)
1529

1630
### Supported Protocols
1731

1832
The list of supported protocols is listed below. Note that certain protocols might only be implemented for either transmit (tx) or receive (rx).
1933

20-
- **NEC**: (tx/untested rx).
34+
- **NEC**: (tx/rx).
2135
- **RC-MM**: (tx only).
2236
- **RC-5**: (untested tx/untested rx).
2337
- **Sony SIRC**: (untested tx/rx).
@@ -26,18 +40,18 @@ New protocols can be added to [libraries/ir\_messaging/ir\_protocol.cpp](librari
2640

2741
### Purpose (Is there not IRremote already?)
2842

29-
Indeed, the IRremote library already exists to interface Arduino platforms with consumer IR products. The main differating factor of the ir\_messaging library is that it does not hardcode which timer/IO pin is used.
43+
Indeed, the IRremote library already exists to interface Arduino platforms with consumer IR products. The main differating factor of the ir\_messaging library is that it does not hardcode the allocation of hadware timers.
3044

3145
Here are a few advantages of ir\_messaging:
3246

3347
- *Designed* to simultaneously transmit & receive IR messages.
3448
- Last version of IRremote I checked used the same timer hardware for both transmit & receive (contention). Moreover, the trival time-interleaved (tx &hArr; rx) solution is not very robust.
3549
- Easier to select which timers & I/O pins to use for transmit/receive function.
3650
- No need to read/modify core library files.
37-
- Can be easily deduced from sample sketches (+ minimal info about hardware timers).
51+
- Hardware select can be easily deduced from sample sketches (+ minimal knowldege of hardware timers).
3852
- Uses `IRMsg` class to simplify API (protocol, data & message length stay together).
3953
- More modular approach to supporting different chipsets.
40-
- Seems to be a more robust solution (but cannot remember exact reason why that is).
54+
- Seems to be a *slightly* more robust solution (but cannot remember exact reason why that is).
4155

4256
Untested advantages:
4357

@@ -50,38 +64,28 @@ Untested advantages:
5064
Definitely. There are a few reasons to use IRremote instead of the ir\_messaging library. Some that come to mind are listed below:
5165

5266
- At the moment, IRremote supports more IR protocols.
53-
- Potentially a problem if the project *must* communicate with an un-supported protocol.
67+
- Only an advantage if your project *must* communicate with a given (un-supported) protocol.
5468
- NOTE: Possible to add support for other protocols in ir\_messaging.
5569
- At the moment, IRremote supports more Arduino platforms.
56-
- NOTE: Can use ATmega2560/ADK implementation as a model for adding platforms to ir\_messaging.
57-
- IRremote uses `delayMicroseconds()` (Timer0) to modulate the transmit carrier (mark/space).
58-
- Does not need a dedicated timer to implement modulation (less hardware).
59-
- Might not be as comfortable making customizations to ir\_messaging library.
70+
- Might not be as comfortable making customizations to the ir\_messaging library.
6071
- Implementation makes heavy use of C++ constructs (ex: objects).
6172
- Code is divided into more files (This might not fit the way you work).
6273
- Object/module hierarchy is more elaborate than IRremote.
74+
- Currently generates smaller binaries.
75+
- Larger community for support.
6376

6477
## Sample Sketches
6578

6679
ir\_messaging provides 3 sample sketches under the [libraries/ir\_messaging/samples](libraries/ir_messaging/samples) sub-directory:
6780

68-
- **ir\_repeater**: Simple sketch that re-transmits valid incomming IR messages.
69-
- **ir\_rx\_sniff**: Simple sketch that dumps recieved signal to serial output.
7081
- **ir\_tx\_onbutton**: Simple sketch that transmits a hard-coded IR message when a button is pressed.
71-
72-
### Sample Sketch Pinouts
73-
74-
The sample sketches listed above come pre-configured for the ATmega2560/ADK using the following I/O configuration:
75-
76-
- **IR receiver module**: Pin 3.
77-
- **IR transmitter diode**: Pin 5.
78-
- **Push button**: Pin 2.
79-
80-
If, for whatever reason, this pin list cannot be located: simply load one of the sample sketches and read the serial monitor upon device reset. The sample sketches all dump the relevant software-configured pins.
82+
- **ir\_rx\_sniff**: Simple sketch that dumps recieved signal to serial output.
83+
- **ir\_repeater**: Simple sketch that re-transmits valid incomming IR messages.
84+
- Note that this sketch only supports the Arduino Mega platforms. Due to interrupt priorities, platforms that use the system clock (Timer0) for modulating the IR output will not successfully receive all incomming signals. This task requires a bit more synchronization of the IR traffic.
8185

8286
## Usage Tips
8387

84-
### Atmel `timer0`: Time & Delays
88+
### Atmel Timer0: Time & Delays
8589

8690
On what appears to be all Atmel chipsets, the Arduino software uses `timer0` to measure time & implement delays (`delay()`, `delayMicroseconds()`, `millis()`, `micros()`). Better not appropriate this timer for anything else.
8791

@@ -114,9 +118,17 @@ Similarly, a wiring diagram for the *push button* signal required by the ir\_tx\
114118
<a name="HWPinout"></a>
115119
### Hardware/Pinout Selection
116120

117-
The ir\_messaging library is very flexible. It allows the user to control which timers/pin drive the IR transmitter, and which are used by the IR receiver.
121+
The ir\_messaging library is relatively flexible. The IR receiver software can be configured to listen on any available pin. However, the **transmitter output pin** is controlled by whatever timer generates the **output carrier**:
118122

119-
Please refer to the appropriate [datasheet](#ArduinoDatasheets) for more details regarding the capabilities of your particular Arduino platform.
123+
- ATmega328/328P
124+
- Timer2: Pin 3.
125+
- ATmega1280/2560
126+
- Timer1: Pin 11.
127+
- Timer2: Pin 9.
128+
- Timer3: Pin 5.
129+
- Timer4: Pin 6.
130+
131+
Please refer to the appropriate [datasheet](#Datasheets) for more details regarding the capabilities of your particular Arduino platform.
120132

121133
## Libraries (Dependencies)
122134

@@ -137,6 +149,7 @@ The following lists a few key classes:
137149
- **`IRCtrl::IRProtocol::pktInfo[]`**: Details how each consumer IR protocol transmits/receives IR messages.
138150

139151
And some low-level classes that might be useful for supporting more hardware:
152+
140153
- **`ArduinoHW::Timer16b::Timer` class**: Facilitates the control of 16-bit timers (hopefully works for most arduino platforms).
141154

142155
## Compiling
@@ -146,12 +159,15 @@ The ir\_messaging library was tested on the version 1.0.5+dfsg2-2 (Linux) of the
146159
## Known Limitations
147160

148161
- IR receiver currently only works using a 16-bit timer (`IRCtrl::Timer16b::RxHw`).
149-
- IR transmitter currently only works using *two* 16-bit timers (`IRCtrl::Timer16b::TxHw`).
162+
- IR transmitter currently supports two resource allocations:
163+
- System clock (Timer0) + an 8-bit timer (`IRCtrl::Timer8b::TxHw`),
164+
- or *two* 16-bit timers (`IRCtrl::Timer16b::TxHw`).
150165
- ...
151166

152167
## Resources/Acknowledgments
153168

154-
### Ken Shirriff
169+
<a name="Shirriff_et_al"></a>
170+
### Ken Shirriff (et al.)
155171

156172
Ken Shirriff's IRremote library provides an interesting solution to consumer IR (remote-control) communication. Ken's library is very inspiring:
157173

@@ -169,12 +185,13 @@ The SB-Projects website contains useful information on selected consumer IR (rem
169185

170186
- **IR Remote Control Theory**: <http://www.sbprojects.net/knowledge/ir/index.php>
171187

172-
<a name="ArduinoDatasheets"></a>
173-
### Arduino Datasheets
188+
<a name="Datasheets"></a>
189+
### Datasheets
174190

175-
The following list provides hyperlinks to some useful Arduino datasheets. Please note the chipset corresponding to your particular Arduino platform.
191+
The following lists a few datasheets might be of use.
176192

177-
- **ATmega2560**: <http://www.atmel.com/devices/atmega2560.aspx?tab=documents>
193+
- **ATmega328/328P**: <http://www.atmel.com/devices/atmega328p.aspx>
194+
- **ATmega1280/2560**: <http://www.atmel.com/devices/atmega2560.aspx>
178195

179196
## Disclaimer
180197

libraries/arduino_timers/arduino_timers.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,26 @@ namespace Timer16b {
2121
void Config::SetCOMnB(CmpOMode::ID oMode) {
2222
_AHW_WRITE8_2B(TCCRnA, COM1B0, oMode);
2323
}
24+
#ifdef _AHW_TIMERS_HAS16B3OC
2425
void Config::SetCOMnC(CmpOMode::ID oMode) {
2526
_AHW_WRITE8_2B(TCCRnA, COM1C0, oMode);
2627
}
27-
28+
#endif
2829
};
2930

3031
namespace Timer8b {
3132

3233
void Config::SetMode(Mode::ID mode, Timer16b::Presc::ID presc) {
3334
TCCRnA = 0; TCCRnB = 0; //Reset options
34-
_AHW_WRITE8_2B(TCCRnA, WGM10, mode); //Write lower mode bits
35-
_AHW_WRITE8_1B(TCCRnB, WGM12, mode>>2); //Write upper mode bits
36-
_AHW_WRITE8_3B(TCCRnB, CS10, presc); //Write prescaler bits
35+
_AHW_WRITE8_2B(TCCRnA, WGM20, mode); //Write lower mode bits
36+
_AHW_WRITE8_1B(TCCRnB, WGM22, mode>>2); //Write upper mode bits
37+
_AHW_WRITE8_3B(TCCRnB, CS20, presc); //Write prescaler bits
3738
}
3839
void Config::SetCOMnA(Timer16b::CmpOMode::ID oMode) {
39-
_AHW_WRITE8_2B(TCCRnA, COM1A0, oMode);
40+
_AHW_WRITE8_2B(TCCRnA, COM2A0, oMode);
41+
}
42+
void Config::SetCOMnB(Timer16b::CmpOMode::ID oMode) {
43+
_AHW_WRITE8_2B(TCCRnA, COM2B0, oMode);
4044
}
4145
};
4246

libraries/arduino_timers/arduino_timers.h

Lines changed: 32 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,29 @@ from any platform in order to set the PWM period & duty-cycle at a high level.
88
This is probably not a trivial task.
99
1010
REMARKS:
11+
-I don't like how constants are shared across different timers...
12+
Some more thought would be needed here.
1113
-NOT FULLY CONFIRMED!!!
12-
-Arduino HW access is odd in a few respects:
14+
-Arduino HW access is a little odd in a few respects:
1315
-Not obvious to which register a given bit constant applies
1416
(ex: is WGM10 for TCCRnA or B?)
1517
-WGMnx not a contiguous bit field.
16-
-All TCCRnA/B values are the same for timers 1,3,4,5, but multiple bit
17-
constants are defined (one for each timer).
18-
-Timer 0 flags are therefore used here for all Timer8b timers (is this valid?).
19-
(OCIE0A, ...)
18+
-On ATmega2560, all TCCRnA/B values are the same for timers 1,3,4,5, but
19+
multiple bit constants are defined (one for each timer).
20+
-Timer 0 is not supported. Probably a bad idea to take control of it.
21+
Used to measure time & implement delays (millis(), delay(), ...).
2022
-Timer 1 flags are therefore used here for all Timer16b timers (is this valid?).
2123
(OCIE1A, TOIE1, COM1A0, COM1B0, COM1C0, WGM10, WGM12, CS10, ...)
22-
-Timer 2 flags are therefore used here for all Timer8bAsync timers (is this valid?).
23-
(OCIE2A, ...)
24-
-Timer8b & Timer8bAsync were never actually used... might not work.
24+
-Timer 2 flags are therefore used here for all Timer8b timers (is this valid?).
25+
(OCIE2A, COM2A0, WGM20, WGM22, CS20, ...)
2526
*/
2627

2728
//TODO: Move Timer16b::Mode/Presc/CmpOMode/Config up one namespace???
28-
//TODO: Timer8b & Timer8bAsync were never actually used... Pls verify before using.
2929

3030
#ifndef ARDUINO_TIMERS_H
3131
#define ARDUINO_TIMERS_H
3232

33-
#include <arduino_timers.h>
33+
#include <arduino_timers_hwdetect.h>
3434
#include <arduino_ext.h>
3535
#include <arduino_hwext.h>
3636

@@ -53,7 +53,7 @@ namespace ArduinoHw {
5353
//Internal refclk:
5454
const hz_t refclk = F_CPU; //Hardcoded for now
5555

56-
//Abstraction of ATMEL's 16-bit timers (Timers 1, 3, 4, 5):
56+
//Abstraction of ATMEL's 16-bit timers:
5757
namespace Timer16b {
5858

5959
//Appears to work for Timer8b as well - but some settings are invalid
@@ -114,7 +114,7 @@ namespace Timer16b {
114114
};
115115
};
116116

117-
//Configuration object (abstracts away bitfields):
117+
//Timer16b Configuration object (abstracts away bitfields):
118118
//Multiple copies can be created, and used to apply onto "Timer"
119119
class Config {
120120
public:
@@ -126,16 +126,16 @@ namespace Timer16b {
126126
//Select desired compare output mode:
127127
void SetCOMnA(CmpOMode::ID oMode);
128128
void SetCOMnB(CmpOMode::ID oMode);
129+
#ifdef _AHW_TIMERS_HAS16B3OC
129130
void SetCOMnC(CmpOMode::ID oMode);
130-
131-
//TODO: Set COMnB/C. Maybe add Get functions?
131+
#endif
132132

133133
inline Config(Mode::ID mode = Mode::Normal, Presc::ID presc = Presc::Div1)
134134
{SetMode(mode, presc);};
135135
};
136136

137-
//Abstraction for timer registers
138-
//Not a direct memory map; Not sure if all platforms would be suitable.
137+
//Abstraction for Timer16b registers
138+
//NOTE: Not a direct memory map. Not sure if code will suit all platforms.
139139
class Timer {
140140
public:
141141
//Access to registers:
@@ -144,7 +144,9 @@ namespace Timer16b {
144144
v_uint16_t &ICRn; //Input compare register (can reset/reverse timer)
145145
v_uint16_t &OCRnA; //Output compare register (can toggle output pin)
146146
v_uint16_t &OCRnB; //Output compare register (can toggle output pin)
147+
#ifdef _AHW_TIMERS_HAS16B3OC
147148
v_uint16_t &OCRnC; //Output compare register (can toggle output pin)
149+
#endif
148150
v_uint8_t &TIMSKn; //Interrupt register
149151

150152
inline void SetConfig(const Config &cfg)
@@ -164,8 +166,9 @@ namespace Timer16b {
164166
//TODO Clear individual interupts, set other interupts
165167

166168
//Not really registers, but good place to store pin #:
167-
const uint8_t ioPinA, ioPinB, ioPinC;
168-
//TODO: Add to constructor
169+
const uint8_t ioPinA, ioPinB;
170+
#ifdef _AHW_TIMERS_HAS16B3OC
171+
const uint8_t ioPinC;
169172

170173
inline Timer(v_uint8_t &TCCRnA, v_uint8_t &TCCRnB, v_uint16_t &TCNTn,
171174
v_uint16_t &ICRn, v_uint16_t &OCRnA, uint8_t ioPinA,
@@ -174,37 +177,19 @@ namespace Timer16b {
174177
TCNTn(TCNTn), ICRn(ICRn),
175178
OCRnA(OCRnA), ioPinA(ioPinA), OCRnB(OCRnB), ioPinB(ioPinB),
176179
OCRnC(OCRnC), ioPinC(ioPinC), TIMSKn(TIMSKn) {;};
177-
};
178-
};
179-
180-
//Abstraction of ATMEL's 8-bit asynchronous timers w/PWM (Timer 2):
181-
namespace Timer8bAsync {
182-
183-
//Not fully implemented:
184-
class Timer {
185-
public:
186-
187-
//Access to registers:
188-
v_uint8_t &TCCRnA, &TCCRnB; //Main configuration
189-
v_uint8_t &OCRnA; //Output compare register (can toggle output pin)
190-
v_uint8_t &OCRnB; //Output compare register (can toggle output pin)
191-
v_uint8_t &TIMSKn; //Interrupt register
192-
193-
inline void ClearAllInt() {TIMSKn = 0;}
194-
inline void SetIEOCnA(int val) {_AHW_WRITE8_1B(TIMSKn, OCIE2A, val);}
195-
196-
//Not really registers, but good place to store pin #:
197-
// const uint8_t ioPinA, ioPinB;
198-
199-
inline Timer(v_uint8_t &TCCRnA, v_uint8_t &TCCRnB,
200-
v_uint8_t &OCRnA, v_uint8_t &OCRnB,
180+
#else
181+
inline Timer(v_uint8_t &TCCRnA, v_uint8_t &TCCRnB, v_uint16_t &TCNTn,
182+
v_uint16_t &ICRn, v_uint16_t &OCRnA, uint8_t ioPinA,
183+
v_uint16_t &OCRnB, uint8_t ioPinB,
201184
v_uint8_t &TIMSKn): TCCRnA(TCCRnA), TCCRnB(TCCRnB),
202-
OCRnA(OCRnA), OCRnB(OCRnB),
185+
TCNTn(TCNTn), ICRn(ICRn),
186+
OCRnA(OCRnA), ioPinA(ioPinA), OCRnB(OCRnB), ioPinB(ioPinB),
203187
TIMSKn(TIMSKn) {;};
188+
#endif
204189
};
205190
};
206191

207-
//Abstraction of ATMEL's 8-bit timers w/PWM (Timer/Counter 0):
192+
//Abstraction of ATMEL's 8-bit asynchronous timers w/PWM (Timer 2):
208193
namespace Timer8b {
209194
namespace Mode {
210195
enum ID {
@@ -230,6 +215,7 @@ namespace Timer8b {
230215

231216
//Select desired compare output mode:
232217
void SetCOMnA(Timer16b::CmpOMode::ID oMode);
218+
void SetCOMnB(Timer16b::CmpOMode::ID oMode);
233219

234220
inline Config(Mode::ID mode = Mode::Normal, Timer16b::Presc::ID presc = Timer16b::Presc::Div1)
235221
{SetMode(mode, presc);};
@@ -250,7 +236,7 @@ namespace Timer8b {
250236
//TODO: Make sure TCCRnx is written in correct order?
251237

252238
inline void ClearAllInt() {TIMSKn = 0;}
253-
inline void SetIEOCnA(int val) {_AHW_WRITE8_1B(TIMSKn, OCIE0A, val);}
239+
inline void SetIEOCnA(int val) {_AHW_WRITE8_1B(TIMSKn, OCIE2A, val);}
254240

255241
//Not really registers, but good place to store pin #:
256242
const uint8_t ioPinA, ioPinB;
@@ -267,7 +253,7 @@ namespace Timer8b {
267253

268254
//Include timer definitions for all supported platforms
269255
//******************************************************************************
270-
#include <arduino_timers_ATmega2560.h>
256+
#include <arduino_timers_atmel.h>
271257

272258
#endif //#ifndef ARDUINO_TIMERS_H
273259
//Last Line

0 commit comments

Comments
 (0)