как передать ИК команды без участия ИК диода и ИК приемника(по кабелю)

liseratum
Offline
Зарегистрирован: 13.09.2016

Всем доброго времени суток, имеются команды ик пульта в HEX виде. Ардуина спокойно передаёт в приёмник, команды распознаются устройством, в моём случае магнитолой JVC. Проблема в реализации, ик диод примотан к ик приёмнику изолентой. Можно ли соеденить передатчик и приёмник (нонга out ик приемника) напрямую кабелем, и в каком виде передавать команды? Если такая проблемам уже решалась прошу ткнуть носом.

diger67
Offline
Зарегистрирован: 25.07.2015

Что такое сигнал дистанционного управления. Как правило это несущая частота и наложенная на него закодированная последовательность импульсов. Значит надо детектировать сигнал и выделять несущую, потом подовать на обычный цифровой вход и обрабатывать. Или формировать закодированный сигнал без поднесущей и подовать минуя приемник с детектором.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

liseratum пишет:
ик диод примотан к ик приёмнику изолентой

А зачем? Если правильно подобрана частота модуляции (36КГц, 38КГц, 40КГц и т.д.), то ИК-приёмник должен улавливать сигнал от ИК-светодиода на гораздо бОльшем расстоянии, а не впритык. И даже переотраженный сигнал, если он направлен в сторону.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Если всё же хотите по кабелю, то вот Вам картинки. Чтобы Вы понимали, чем отличается сигнал излучаемый светодиодом от сигнала, который после "преобразования" приёмником передаётся непосредственно устройству. То есть, разницу сигнала на ножках ИК-светодиода и ножках ИК-приёмника.

 

a5021
Offline
Зарегистрирован: 07.07.2013

Разобрать магнитолу, найти ик-приемник, отыскать, где у него выход, выпаять его из платы, в ту же дырку запаять провод от ноги ардуины, с которой сигнал до этого шел к ик-диоду. Единственное, стоит уточнить, с пятивольтовыми ли уровнями работал ик-приемник в магнитоле. Еще скорее всего придется убрать несущую (36-38кгц обычно) из сигнала формируемого ардуиной.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

a5021 пишет:

Еще скорее всего придется убрать несущую (36-38кгц обычно) из сигнала формируемого ардуиной.

И логические уровни инвертировать.

ВН
Offline
Зарегистрирован: 25.02.2016

мда.. вот тока зачем вся эта затея .....

a5021
Offline
Зарегистрирован: 07.07.2013

Мож он кнопками на руле хочет управлять ей.

liseratum
Offline
Зарегистрирован: 13.09.2016

Да, всё дело в кнопках

liseratum
Offline
Зарегистрирован: 13.09.2016

Нашел на просторах интернета такую схемку, прокатит? 

a5021
Offline
Зарегистрирован: 07.07.2013

Не совсем понятно, как вы хотите ее применить.

liseratum
Offline
Зарегистрирован: 13.09.2016

На магнитоле ещё есть провод, сине желтый, для выносных кнопок, вот к нему попробовать. На нем 3,3в

a5021
Offline
Зарегистрирован: 07.07.2013

Блин, вы зачем-то валите все в одну кучу. Ик-приемник -- это одно, провода для выносных кнопок -- это другое. Совершенно точно, что там все по разному.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Ну очевидно, что эта схема предназначеня для подключения к тому контакту на плате, куда впаян ИК-приёмник (точнее, его ножка OUT). Потому что в схеме реализовано аппаратное "сглаживание" несущей и инвертирование сигнала. Что там за сине желтый провод с 3,3В без понятия.

liseratum
Offline
Зарегистрирован: 13.09.2016

Подскажи как за счет чего "реализовано "аппаратное" сглаживание несущей и инвертирование сигнала. " ? Я просто в сигналах не очень. И как мне подключится к ик приемнику, в таком случае

a5021
Offline
Зарегистрирован: 07.07.2013

Jeka_M пишет:
Ну очевидно, что эта схема предназначеня для подключения к тому контакту на плате, куда впаян ИК-приёмник (точнее, его ножка OUT). Потому что в схеме реализовано аппаратное "сглаживание" несущей и инвертирование сигнала.

Я могу, конечно, путать, но на выходе приемника уже не должно быть несущей. Я к контату, куда (был) запаян выход приемника, предлагал сразу цеплять выход ардуины. Там больше никаких схем не нужно. Только проверить, чтобы по лог. уровням все совпадало.

ВН
Offline
Зарегистрирован: 25.02.2016

a5021 пишет:
Я могу, конечно, путать, но на выходе приемника уже не должно быть несущей. 

обычно так и есть  

a5021 пишет:
 к контату, куда (был) запаян выход приемника, предлагал сразу цеплять выход ардуины. Там больше никаких схем не нужно. Только проверить, чтобы по лог. уровням все совпадало. 

а тут не так, т.к. на ИК-светодиод передатчика подается модулированный сигнал (обычное заполнение  36, 38 и т.п.  кГц ) 

т.е. напрямую цеплять нельзя, только после детектирования и фильтрации

liseratum
Offline
Зарегистрирован: 13.09.2016

И как это проверить, если у меня в скетче коды кнопок прописаны. Скетч скину с утра

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

a5021 пишет:

Я могу, конечно, путать, но на выходе приемника уже не должно быть несущей. 

Да, не должно быть. В схеме конденсатор (RC-цепочка?) для этого же стоит? На входе схемы имеем сигнал модулированный несущей. После сглаживания (фильтрации) несущая убирается и остаётся чистый сигнал, который затем инвертируется транзистором.

a5021 пишет:

Я к контату, куда (был) запаян выход приемника, предлагал сразу цеплять выход ардуины. Там больше никаких схем не нужно. Только проверить, чтобы по лог. уровням все совпадало.

Без аппаратной или программной доработки не получится. По лог. уровням точно совпадать не будет, т.к. на выходе ИК-приёмника лог. 0 - это высокий уровень, а лог. 1 - низкий уровень. Я не вкурсе, есть ли уже готовые библиотеки, которые будут работать в таком специфичном режиме.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

liseratum пишет:

Подскажи как за счет чего "реализовано "аппаратное" сглаживание несущей и инвертирование сигнала. " ?

За счет конденсатора и транзистора.

liseratum пишет:

И как мне подключится к ик приемнику, в таком случае

Писал выше - контакт на плате, куда запаяна ножка OUT ИК-приёмника (да, надо ещё распиновку знать)

ВН
Offline
Зарегистрирован: 25.02.2016

liseratum пишет:
И как это проверить, если у меня в скетче коды кнопок прописаны. Скетч скину с утра 

может таки стоит поискать мануал на магнитолу, если у нее уже штатно есть провод для кнопок?

там должна быть система типа аналоговой клавиатуры ардуины, т.е. просто набор резисторов подцепляется и коммутируется кнопками.

a5021
Offline
Зарегистрирован: 07.07.2013

Jeka_M пишет:
Без аппаратной или программной доработки не получится. По лог. уровням точно совпадать не будет, т.к. на выходе ИК-приёмника лог. 0 - это высокий уровень, а лог. 1 - низкий уровень. Я не вкурсе, есть ли уже готовые библиотеки, которые будут работать в таком специфичном режиме.

Необходимость в аппаратной доработке не видится мне обязательной. Ардуино-трансмиттер формирует модулированный сигнал, подключая или отключая пин к шим-каналу таймера. Если найти в коде, где это делается (а найти таки можно) и заменить действие на опускание/поднимание ноги (в том числе и с нужной инверсией) то на этом все модификации можно считать законченными.

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

А, ну так-то да. Только, боюсь, топикстартёр не осилит самостоятельно и попросит переделать ему библиотеку.

a5021
Offline
Зарегистрирован: 07.07.2013

Да по любому нужна или какая-то минимальная квалификация или желание ее получить. Отпаять/запаять потребуется, чуть подправить код тоже. Захочет -- разберется. Не захочет, из раздела "Ищу исполнителя" тоже никого еще не выгоняли. :)

liseratum
Offline
Зарегистрирован: 13.09.2016

Я имел ввиду какие ножки транзистора куда цеплять к ИК приемнику. Так?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

liseratum, похоже вы из вышесказанного не поняли ничего. В кратце : (1) выход ардуины подключается к входу для TSOP приёмника на магнитоле, никакие посредники в виде транзисторов не нужны.  (2) нужно полностью менять код программы. Существующие IR библиотеки скорее всего не умеют посылать немодулированный сигнал. Если вы не в состоянии самостоятельно написать код для эмуляции нужной посылки - оставьте всё как есть )

a5021
Offline
Зарегистрирован: 07.07.2013

dimax пишет:
(2) нужно полностью менять код программы. Существующие IR библиотеки скорее всего не умеют посылать немодулированный сигнал.

Уметь-то они может и не умеют, но научить их не так и сложно. Я все-таки полез посмотреть, как там оно работает и мои предположения, похоже, подтверждаются. IR-посылка "набирается" из нужного количества вызовов "space" и "mark", где сами эти методы выглядят довольно просто:

01//+=============================================================================
02// Sends an IR mark for the specified number of microseconds.
03// The mark output is modulated at the PWM frequency.
04//
05void  IRsend::mark (unsigned int time)
06{
07    TIMER_ENABLE_PWM; // Enable pin 3 PWM output
08    if (time > 0) custom_delay_usec(time);
09}
10 
11//+=============================================================================
12// Leave pin off for time (given in microseconds)
13// Sends an IR space for the specified number of microseconds.
14// A space is no output, so the PWM output is disabled.
15//
16void  IRsend::space (unsigned int time)
17{
18    TIMER_DISABLE_PWM; // Disable pin 3 PWM output
19    if (time > 0) IRsend::custom_delay_usec(time);
20}

Каждый метод либо включает, либо выключает таймер с помощью макросов TIMER_xxx_PWM. Смотрим, из чего они состоят:

1#define TIMER_ENABLE_PWM    (TCCR2A |= _BV(COM2B1))
2#define TIMER_DISABLE_PWM   (TCCR2A &= ~(_BV(COM2B1)))

Так и есть, нога ардуины тупо подключается к каналу таймера или отключается от него. Тут уж и начинающий справится, переписав эти макры, да хоть бы так:

1#define TIMER_ENABLE_PWM    digitalWrite(IRPin, LOW)
2#define TIMER_DISABLE_PWM   digitalWrite(IRPin, HIGH)

Где HIGH, где LOW я сейчас не соображу, можно так попробовать, можно так.

liseratum
Offline
Зарегистрирован: 13.09.2016

Да я понял все. Но думал обойдется малой кровью. Сначала попробую с проводом по схеме, потом, с ногой out tsop, потом попробую библиотеку исправить и перезалить все. В любом случае если что либо из этого получится я буду безмерно рад счастлив и благодарен всем участникам.

liseratum
Offline
Зарегистрирован: 13.09.2016

Спасибо огромное!! У меня получилось!!! Изменил в библиотеке ВСЕ параметры (TIMER_*****_PWM ) следующим образом, и оно заработало по кабелю! Хотя я сомневался до последнего, и на последних изменениях заработало! На ножке ик приемника OUT замерено 0,12В. Поэтому и сомневался. 

#define TIMER_ENABLE_PWM     digitalWrite(3, LOW)
#define TIMER_DISABLE_PWM    digitalWrite(3, HIGH)
 
Спасибо всем! Примного благодарен!
001/*
002 * IRremote
003 * Version 0.1 July, 2009
004 * Copyright 2009 Ken Shirriff
006 *
007 * Modified by Paul Stoffregen <paul@pjrc.com> to support other boards and timers
008 *
009 * Interrupt code based on NECIRrcv by Joe Knapp
012 *
013 * JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
014 */
015 
016#ifndef IRremoteint_h
017#define IRremoteint_h
018 
019#if defined(ARDUINO) && ARDUINO >= 100
020#include <Arduino.h>
021#else
022#include <WProgram.h>
023#endif
024 
025// define which timer to use
026//
027// Uncomment the timer you wish to use on your board.  If you
028// are using another library which uses timer2, you have options
029// to switch IRremote to use a different timer.
030 
031// Arduino Mega
032#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
033  //#define IR_USE_TIMER1   // tx = pin 11
034  #define IR_USE_TIMER2     // tx = pin 9
035  //#define IR_USE_TIMER3   // tx = pin 5
036  //#define IR_USE_TIMER4   // tx = pin 6
037  //#define IR_USE_TIMER5   // tx = pin 46
038 
039// Teensy 1.0
040#elif defined(__AVR_AT90USB162__)
041  #define IR_USE_TIMER1     // tx = pin 17
042 
043// Teensy 2.0
044#elif defined(__AVR_ATmega32U4__)
045  //#define IR_USE_TIMER1   // tx = pin 14
046  //#define IR_USE_TIMER3   // tx = pin 9
047  #define IR_USE_TIMER4_HS  // tx = pin 10
048 
049// Teensy++ 1.0 & 2.0
050#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
051  //#define IR_USE_TIMER1   // tx = pin 25
052  #define IR_USE_TIMER2     // tx = pin 1
053  //#define IR_USE_TIMER3   // tx = pin 16
054 
055// Sanguino
056#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
057  //#define IR_USE_TIMER1   // tx = pin 13
058  #define IR_USE_TIMER2     // tx = pin 14
059 
060// Atmega8
061#elif defined(__AVR_ATmega8P__) || defined(__AVR_ATmega8__)
062  #define IR_USE_TIMER1   // tx = pin 9
063 
064#elif defined( __AVR_ATtinyX4__ )
065  #define IR_USE_TIMER1   // tx = pin 6
066 
067// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, etc
068#else
069  //#define IR_USE_TIMER1   // tx = pin 9
070  #define IR_USE_TIMER2     // tx = pin 3
071#endif
072 
073 
074 
075#ifdef F_CPU
076#define SYSCLOCK F_CPU     // main Arduino clock
077#else
078#define SYSCLOCK 16000000  // main Arduino clock
079#endif
080 
081#define ERR 0
082#define DECODED 1
083 
084 
085// defines for setting and clearing register bits
086#ifndef cbi
087#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
088#endif
089#ifndef sbi
090#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
091#endif
092 
093// Pulse parms are *50-100 for the Mark and *50+100 for the space
094// First MARK is the one after the long gap
095// pulse parameters in usec
096#define NEC_HDR_MARK  9000
097#define NEC_HDR_SPACE 4500
098#define NEC_BIT_MARK  560
099#define NEC_ONE_SPACE 1600
100#define NEC_ZERO_SPACE  560
101#define NEC_RPT_SPACE 2250
102 
103#define SONY_HDR_MARK 2400
104#define SONY_HDR_SPACE  600
105#define SONY_ONE_MARK 1200
106#define SONY_ZERO_MARK  600
107#define SONY_RPT_LENGTH 45000
108#define SONY_DOUBLE_SPACE_USECS  500  // usually ssee 713 - not using ticks as get number wrapround
109 
110// SA 8650B
111#define SANYO_HDR_MARK  3500  // seen range 3500
112#define SANYO_HDR_SPACE 950 //  seen 950
113#define SANYO_ONE_MARK  2400 // seen 2400 
114#define SANYO_ZERO_MARK 700 //  seen 700
115#define SANYO_DOUBLE_SPACE_USECS  800  // usually ssee 713 - not using ticks as get number wrapround
116#define SANYO_RPT_LENGTH 45000
117 
118// Mitsubishi RM 75501
119// 14200 7 41 7 42 7 42 7 17 7 17 7 18 7 41 7 18 7 17 7 17 7 18 7 41 8 17 7 17 7 18 7 17 7
120 
121// #define MITSUBISHI_HDR_MARK  250  // seen range 3500
122#define MITSUBISHI_HDR_SPACE  350 //  7*50+100
123#define MITSUBISHI_ONE_MARK 1950 // 41*50-100
124#define MITSUBISHI_ZERO_MARK  750 // 17*50-100
125// #define MITSUBISHI_DOUBLE_SPACE_USECS  800  // usually ssee 713 - not using ticks as get number wrapround
126// #define MITSUBISHI_RPT_LENGTH 45000
127 
128 
129#define RC5_T1    889
130#define RC5_RPT_LENGTH  46000
131 
132#define RC6_HDR_MARK  2666
133#define RC6_HDR_SPACE 889
134#define RC6_T1    444
135#define RC6_RPT_LENGTH  46000
136 
137#define SHARP_BIT_MARK 245
138#define SHARP_ONE_SPACE 1805
139#define SHARP_ZERO_SPACE 795
140#define SHARP_GAP 600000
141#define SHARP_TOGGLE_MASK 0x3FF
142#define SHARP_RPT_SPACE 3000
143 
144#define DISH_HDR_MARK 400
145#define DISH_HDR_SPACE 6100
146#define DISH_BIT_MARK 400
147#define DISH_ONE_SPACE 1700
148#define DISH_ZERO_SPACE 2800
149#define DISH_RPT_SPACE 6200
150#define DISH_TOP_BIT 0x8000
151 
152#define PANASONIC_HDR_MARK 3502
153#define PANASONIC_HDR_SPACE 1750
154#define PANASONIC_BIT_MARK 502
155#define PANASONIC_ONE_SPACE 1244
156#define PANASONIC_ZERO_SPACE 400
157 
158#define JVC_HDR_MARK 8000
159#define JVC_HDR_SPACE 4000
160#define JVC_BIT_MARK 600
161#define JVC_ONE_SPACE 1600
162#define JVC_ZERO_SPACE 550
163#define JVC_RPT_LENGTH 60000
164 
165#define SHARP_BITS 15
166#define DISH_BITS 16
167 
168#define TOLERANCE 25  // percent tolerance in measurements
169#define LTOL (1.0 - TOLERANCE/100.)
170#define UTOL (1.0 + TOLERANCE/100.)
171 
172#define _GAP 5000 // Minimum map between transmissions
173#define GAP_TICKS (_GAP/USECPERTICK)
174 
175#define TICKS_LOW(us) (int) (((us)*LTOL/USECPERTICK))
176#define TICKS_HIGH(us) (int) (((us)*UTOL/USECPERTICK + 1))
177 
178#ifndef DEBUG
179int MATCH(int measured, int desired) {return measured >= TICKS_LOW(desired) && measured <= TICKS_HIGH(desired);}
180int MATCH_MARK(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us + MARK_EXCESS));}
181int MATCH_SPACE(int measured_ticks, int desired_us) {return MATCH(measured_ticks, (desired_us - MARK_EXCESS));}
182// Debugging versions are in IRremote.cpp
183#endif
184 
185// receiver states
186#define STATE_IDLE     2
187#define STATE_MARK     3
188#define STATE_SPACE    4
189#define STATE_STOP     5
190 
191// information for the interrupt handler
192typedef struct {
193  uint8_t recvpin;           // pin for IR data from detector
194  uint8_t rcvstate;          // state machine
195  uint8_t blinkflag;         // TRUE to enable blinking of pin 13 on IR processing
196  unsigned int timer;     // state timer, counts 50uS ticks.
197  unsigned int rawbuf[RAWBUF]; // raw data
198  uint8_t rawlen;         // counter of entries in rawbuf
199}
200irparams_t;
201 
202// Defined in IRremote.cpp
203extern volatile irparams_t irparams;
204 
205// IR detector output is active low
206#define MARK  0
207#define SPACE 1
208 
209#define TOPBIT 0x80000000
210 
211#define NEC_BITS 32
212#define SONY_BITS 12
213#define SANYO_BITS 12
214#define MITSUBISHI_BITS 16
215#define MIN_RC5_SAMPLES 11
216#define MIN_RC6_SAMPLES 1
217#define PANASONIC_BITS 48
218#define JVC_BITS 16
219 
220 
221 
222 
223// defines for timer2 (8 bits)
224#if defined(IR_USE_TIMER2)
225#define TIMER_RESET
226#define TIMER_ENABLE_PWM     digitalWrite(3, LOW)
227#define TIMER_DISABLE_PWM    digitalWrite(3, HIGH)
228#define TIMER_ENABLE_INTR    (TIMSK2 = _BV(OCIE2A))
229#define TIMER_DISABLE_INTR   (TIMSK2 = 0)
230#define TIMER_INTR_NAME      TIMER2_COMPA_vect
231#define TIMER_CONFIG_KHZ(val) ({ \
232  const uint8_t pwmval = SYSCLOCK / 2000 / (val); \
233  TCCR2A = _BV(WGM20); \
234  TCCR2B = _BV(WGM22) | _BV(CS20); \
235  OCR2A = pwmval; \
236  OCR2B = pwmval / 3; \
237})
238#define TIMER_COUNT_TOP      (SYSCLOCK * USECPERTICK / 1000000)
239#if (TIMER_COUNT_TOP < 256)
240#define TIMER_CONFIG_NORMAL() ({ \
241  TCCR2A = _BV(WGM21); \
242  TCCR2B = _BV(CS20); \
243  OCR2A = TIMER_COUNT_TOP; \
244  TCNT2 = 0; \
245})
246#else
247#define TIMER_CONFIG_NORMAL() ({ \
248  TCCR2A = _BV(WGM21); \
249  TCCR2B = _BV(CS21); \
250  OCR2A = TIMER_COUNT_TOP / 8; \
251  TCNT2 = 0; \
252})
253#endif
254#if defined(CORE_OC2B_PIN)
255#define TIMER_PWM_PIN        CORE_OC2B_PIN  /* Teensy */
256#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
257#define TIMER_PWM_PIN        9  /* Arduino Mega */
258#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
259#define TIMER_PWM_PIN        14 /* Sanguino */
260#else
261#define TIMER_PWM_PIN        3  /* Arduino Duemilanove, Diecimila, LilyPad, etc */
262#endif
263 
264 
265// defines for timer1 (16 bits)
266#elif defined(IR_USE_TIMER1)
267#define TIMER_RESET
268#define TIMER_ENABLE_PWM     digitalWrite(3, LOW)
269#define TIMER_DISABLE_PWM    digitalWrite(3, HIGH)
270#if defined(__AVR_ATmega8P__) || defined(__AVR_ATmega8__)
271  #define TIMER_ENABLE_INTR    (TIMSK = _BV(OCIE1A))
272  #define TIMER_DISABLE_INTR   (TIMSK = 0)
273#else
274  #define TIMER_ENABLE_INTR    (TIMSK1 = _BV(OCIE1A))
275  #define TIMER_DISABLE_INTR   (TIMSK1 = 0)
276#endif
277 
278#if defined(__AVR_ATtinyX4__)
279  #define TIMER_INTR_NAME      TIM1_COMPA_vect
280#else
281  #define TIMER_INTR_NAME      TIMER1_COMPA_vect
282#endif
283 
284#define TIMER_CONFIG_KHZ(val) ({ \
285  const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
286  TCCR1A = _BV(WGM11); \
287  TCCR1B = _BV(WGM13) | _BV(CS10); \
288  ICR1 = pwmval; \
289  OCR1A = pwmval / 3; \
290})
291#define TIMER_CONFIG_NORMAL() ({ \
292  TCCR1A = 0; \
293  TCCR1B = _BV(WGM12) | _BV(CS10); \
294  OCR1A = SYSCLOCK * USECPERTICK / 1000000; \
295  TCNT1 = 0; \
296})
297#if defined(CORE_OC1A_PIN)
298#define TIMER_PWM_PIN        CORE_OC1A_PIN  /* Teensy */
299#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
300#define TIMER_PWM_PIN        11  /* Arduino Mega */
301#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
302#define TIMER_PWM_PIN        13 /* Sanguino */
303#elif defined(__AVR_ATtinyX4__)
304#define TIMER_PWM_PIN        6 /* ATTiny84 */
305#else
306#define TIMER_PWM_PIN        9  /* Arduino Duemilanove, Diecimila, LilyPad, etc */
307#endif
308 
309 
310// defines for timer3 (16 bits)
311#elif defined(IR_USE_TIMER3)
312#define TIMER_RESET
313#define TIMER_ENABLE_PWM     digitalWrite(3, LOW)
314#define TIMER_DISABLE_PWM    digitalWrite(3, HIGH)
315#define TIMER_ENABLE_INTR    (TIMSK3 = _BV(OCIE3A))
316#define TIMER_DISABLE_INTR   (TIMSK3 = 0)
317#define TIMER_INTR_NAME      TIMER3_COMPA_vect
318#define TIMER_CONFIG_KHZ(val) ({ \
319  const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
320  TCCR3A = _BV(WGM31); \
321  TCCR3B = _BV(WGM33) | _BV(CS30); \
322  ICR3 = pwmval; \
323  OCR3A = pwmval / 3; \
324})
325#define TIMER_CONFIG_NORMAL() ({ \
326  TCCR3A = 0; \
327  TCCR3B = _BV(WGM32) | _BV(CS30); \
328  OCR3A = SYSCLOCK * USECPERTICK / 1000000; \
329  TCNT3 = 0; \
330})
331#if defined(CORE_OC3A_PIN)
332#define TIMER_PWM_PIN        CORE_OC3A_PIN  /* Teensy */
333#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
334#define TIMER_PWM_PIN        5  /* Arduino Mega */
335#else
336#error "Please add OC3A pin number here\n"
337#endif
338 
339 
340// defines for timer4 (10 bits, high speed option)
341#elif defined(IR_USE_TIMER4_HS)
342#define TIMER_RESET
343#define TIMER_ENABLE_PWM     digitalWrite(3, LOW)
344#define TIMER_DISABLE_PWM    digitalWrite(3, HIGH)
345#define TIMER_ENABLE_INTR    (TIMSK4 = _BV(TOIE4))
346#define TIMER_DISABLE_INTR   (TIMSK4 = 0)
347#define TIMER_INTR_NAME      TIMER4_OVF_vect
348#define TIMER_CONFIG_KHZ(val) ({ \
349  const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
350  TCCR4A = (1<<PWM4A); \
351  TCCR4B = _BV(CS40); \
352  TCCR4C = 0; \
353  TCCR4D = (1<<WGM40); \
354  TCCR4E = 0; \
355  TC4H = pwmval >> 8; \
356  OCR4C = pwmval; \
357  TC4H = (pwmval / 3) >> 8; \
358  OCR4A = (pwmval / 3) & 255; \
359})
360#define TIMER_CONFIG_NORMAL() ({ \
361  TCCR4A = 0; \
362  TCCR4B = _BV(CS40); \
363  TCCR4C = 0; \
364  TCCR4D = 0; \
365  TCCR4E = 0; \
366  TC4H = (SYSCLOCK * USECPERTICK / 1000000) >> 8; \
367  OCR4C = (SYSCLOCK * USECPERTICK / 1000000) & 255; \
368  TC4H = 0; \
369  TCNT4 = 0; \
370})
371#if defined(CORE_OC4A_PIN)
372#define TIMER_PWM_PIN        CORE_OC4A_PIN  /* Teensy */
373#elif defined(__AVR_ATmega32U4__)
374#define TIMER_PWM_PIN        13  /* Leonardo */
375#else
376#error "Please add OC4A pin number here\n"
377#endif
378 
379 
380// defines for timer4 (16 bits)
381#elif defined(IR_USE_TIMER4)
382#define TIMER_RESET
383#define TIMER_ENABLE_PWM     digitalWrite(3, LOW)
384#define TIMER_DISABLE_PWM    digitalWrite(3, HIGH)
385#define TIMER_ENABLE_INTR    (TIMSK4 = _BV(OCIE4A))
386#define TIMER_DISABLE_INTR   (TIMSK4 = 0)
387#define TIMER_INTR_NAME      TIMER4_COMPA_vect
388#define TIMER_CONFIG_KHZ(val) ({ \
389  const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
390  TCCR4A = _BV(WGM41); \
391  TCCR4B = _BV(WGM43) | _BV(CS40); \
392  ICR4 = pwmval; \
393  OCR4A = pwmval / 3; \
394})
395#define TIMER_CONFIG_NORMAL() ({ \
396  TCCR4A = 0; \
397  TCCR4B = _BV(WGM42) | _BV(CS40); \
398  OCR4A = SYSCLOCK * USECPERTICK / 1000000; \
399  TCNT4 = 0; \
400})
401#if defined(CORE_OC4A_PIN)
402#define TIMER_PWM_PIN        CORE_OC4A_PIN
403#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
404#define TIMER_PWM_PIN        6  /* Arduino Mega */
405#else
406#error "Please add OC4A pin number here\n"
407#endif
408 
409 
410// defines for timer5 (16 bits)
411#elif defined(IR_USE_TIMER5)
412#define TIMER_RESET
413#define TIMER_ENABLE_PWM     digitalWrite(3, LOW)
414#define TIMER_DISABLE_PWM    digitalWrite(3, HIGH)
415#define TIMER_ENABLE_INTR    (TIMSK5 = _BV(OCIE5A))
416#define TIMER_DISABLE_INTR   (TIMSK5 = 0)
417#define TIMER_INTR_NAME      TIMER5_COMPA_vect
418#define TIMER_CONFIG_KHZ(val) ({ \
419  const uint16_t pwmval = SYSCLOCK / 2000 / (val); \
420  TCCR5A = _BV(WGM51); \
421  TCCR5B = _BV(WGM53) | _BV(CS50); \
422  ICR5 = pwmval; \
423  OCR5A = pwmval / 3; \
424})
425#define TIMER_CONFIG_NORMAL() ({ \
426  TCCR5A = 0; \
427  TCCR5B = _BV(WGM52) | _BV(CS50); \
428  OCR5A = SYSCLOCK * USECPERTICK / 1000000; \
429  TCNT5 = 0; \
430})
431#if defined(CORE_OC5A_PIN)
432#define TIMER_PWM_PIN        CORE_OC5A_PIN
433#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
434#define TIMER_PWM_PIN        46  /* Arduino Mega */
435#else
436#error "Please add OC5A pin number here\n"
437#endif
438 
439 
440#else // unknown timer
441#error "Internal code configuration error, no known IR_USE_TIMER# defined\n"
442#endif
443 
444 
445// defines for blinking the LED
446#if defined(CORE_LED0_PIN)
447#define BLINKLED       CORE_LED0_PIN
448#define BLINKLED_ON()  (digitalWrite(CORE_LED0_PIN, HIGH))
449#define BLINKLED_OFF() (digitalWrite(CORE_LED0_PIN, LOW))
450#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
451#define BLINKLED       13
452#define BLINKLED_ON()  (PORTB |= B10000000)
453#define BLINKLED_OFF() (PORTB &= B01111111)
454#elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__)
455#define BLINKLED       0
456#define BLINKLED_ON()  (PORTD |= B00000001)
457#define BLINKLED_OFF() (PORTD &= B11111110)
458#else
459#define BLINKLED       13
460#define BLINKLED_ON()  (PORTB |= B00100000)
461#define BLINKLED_OFF() (PORTB &= B11011111)
462#endif
463 
464#endif