-
Notifications
You must be signed in to change notification settings - Fork 1
/
IRTinyTX.cpp
134 lines (119 loc) · 4.24 KB
/
IRTinyTX.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
* IRremote
* Version 0.11 August, 2009
* Copyright 2009 Ken Shirriff
* For details, see http://arcfn.com/2009/08/multi-protocol-infrared-remote-library.html
*
* Interrupt code based on NECIRrcv by Joe Knapp
* http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1210243556
* Also influenced by http://zovirl.com/2008/11/12/building-a-universal-remote-with-an-arduino/
*
* Modified by Kristian Lauszus to work with ATTiny85
* For details, see http://blog.tkjelectronics.dk
* Attiny85 adaptation by Nick Gammon http://arduino.cc/forum/index.php?topic=91488.msg687101#msg687101)
* Spilt into two lib by [email protected] www.tetalab.org (IRTinyTX-lib-v1)
*/
#include "IRTinyTX.h"
void IRsend::sendNEC(unsigned long data, int nbits)
{
enableIROut(38);
mark(NEC_HDR_MARK);
space(NEC_HDR_SPACE);
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
mark(NEC_BIT_MARK);
space(NEC_ONE_SPACE);
}
else {
mark(NEC_BIT_MARK);
space(NEC_ZERO_SPACE);
}
data <<= 1;
}
mark(NEC_BIT_MARK);
space(0);
}
// Added RC5 Transmission Function
// Note: first bit must be a one (start bit)
void IRsend::sendRC5(unsigned long data, int nbits)
{
enableIROut(36);
data = data << (32 - nbits);
mark(RC5_T1); // First start bit
space(RC5_T1); // Second start bit
mark(RC5_T1); // Second start bit
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
space(RC5_T1); // 1 is space, then mark
mark(RC5_T1);
}
else {
mark(RC5_T1);
space(RC5_T1);
}
data <<= 1;
}
space(0); // Turn off at end
}
void IRsend::sendJVC(uint32_t data, uint8_t nbits, uint8_t repeat)
{
//enableIROut(38);
data = data << (32 - nbits);
if (!repeat){
mark(JVC_HDR_MARK);
space(JVC_HDR_SPACE);
}
for (int i = 0; i < nbits; i++) {
if (data & TOPBIT) {
mark(JVC_BIT_MARK);
space(JVC_ONE_SPACE);
}
else {
mark(JVC_BIT_MARK);
space(JVC_ZERO_SPACE);
}
data <<= 1;
}
mark(JVC_BIT_MARK);
space(0); //Turn IR LED off
}
void IRsend::mark(int16_t time) {
// Sends an IR mark for the specified number of microseconds.
// The mark output is modulated at the PWM frequency.
// Clear OC0A/OC0B on Compare Match when up-counting.
// Set OC0A/OC0B on Compare Match when down-counting.
TCCR0A |= _BV(COM0B1); // Enable pin 6 (PB1) PWM output
delayMicroseconds(time);
}
/* Leave pin off for time (given in microseconds) */
void IRsend::space(int16_t time) {
// Sends an IR space for the specified number of microseconds.
// A space is no output, so the PWM output is disabled.
// Normal port operation, OC0A/OC0B disconnected.
TCCR0A &= ~(_BV(COM0B1)); // Disable pin 6 (PB1) PWM output
delayMicroseconds(time);
}
void IRsend::enableIROut(uint8_t khz) {
// Enables IR output. The khz value controls the modulation frequency in kilohertz.
// The IR output will be on pin 6 (OC0B).
// This routine is designed for 36-40KHz; if you use it for other values, it's up to you
// to make sure it gives reasonable results. (Watch out for overflow / underflow / rounding.)
// TIMER0 is used in phase-correct PWM mode, with OCR0A controlling the frequency and OCR0B
// controlling the duty cycle.
// There is no prescaling, so the output frequency is 16MHz / (2 * OCR0A)
// To turn the output on and off, we leave the PWM running, but connect and disconnect the output pin.
// A few hours staring at the ATmega documentation and this will all make sense.
// See my Secrets of Arduino PWM at http://arcfn.com/2009/07/secrets-of-arduino-pwm.html for details.
DDRB |= _BV(IRLED); // Set as output
PORTB &= ~(_BV(IRLED)); // When not sending PWM, we want it low
// Normal port operation, OC0A/OC0B disconnected
// COM0A = 00: disconnect OC0A
// COM0B = 00: disconnect OC0B; to send signal set to 10: OC0B non-inverted
// WGM0 = 101: phase-correct PWM with OCR0A as top
// CS0 = 000: no prescaling
TCCR0A = _BV(WGM00);
TCCR0B = _BV(WGM02) | _BV(CS00);
// The top value for the timer. The modulation frequency will be SYSCLOCK / 2 / OCR0A.
OCR0A = F_CPU / 2 / khz / 1000;
OCR0B = OCR0A / 3; // 33% duty cycle
}