Amplify passive buzzer

I have a passive buzzer id like to amplify. I have am assortment of small transistors but I'm not sure which one to use.

I dont have any datasheet for my buzzer. Its about a half inch diameter.

If I use a transistor an 12v I can amplify the output from the arduino. How could i also adjust the volume of the buzzer either through code or hardware?

I know the buzzer can handle a lot of current. I hooked it up to dc dc stepup and ran it at 24v. Just before it blew the transistor. I need a way to adjust the volume.

I know the arduino pin can handle 40mA

If it makes sound with DC it's not a "passive" buzzer/transducer.

And it's kind-of weird to blow the transistor if you have a piezo buzzer and if you connected the transistor correctly. (Piezo buzzers are low current.)

Here is a transistor driver circuit. It's shown as a relay driver and since you don't have an inductive load you can leave-out the flyback diode. With a piezo transducer it's the voltage that's important. A 1K base resistor should be fine and the transistor isn't too critical with a piezo transducer.

You can look-up how to wire a potentiometer as a volume control. A 1K pot should be fine for a piezo. The pot goes in the "load" part of the circuit, not to the transistor base (in this application).

In software you can adjust the volume by adjusting the pulse width but that does affect the "character" of the sound and you can't use the tone() function which puts-out a square wave. A pulse width of 50% (a square wave) gives the loudest volume.

Try the toneAC() library instead of the tone() library.
That library drives the buzzer between two Arduino pins,
for twice the voltage (10volt peak/peak) on the buzzer.
That library also has volume control and a wider frequency range.
Available through the library manager of the IDE.
Leo..

This is some sort of peizo driver. On the back of the buzzer it says 2-24v. No applying a dc signal does not do anything other than pop and blow the buzzer.

I wired 2n2222 to the buzzer. I use my signal generator at an amplitude of 5v to drive the base of the transistor through a 5kohm resitor. This works okay except its too loud.

I wired an 10k potentiometer on th +12 side of the buzzer. Wheb I turn the buzzer to the right to get the volume I want, the potentiometer gets pretty hot.

I will try the toneAC() right now im using my signal generator. Could toneAc() be used to adjust the output amplitutde?

No.

So then I guess its okay for the pot to take the heat. I would be using short chirps. So it sounds in theory get that hot? I just don't want to replace a transistor after I get it hooked up

Edit: aperntly not. The potentiometer just sits there and gets hot.

I must not understand how to lower the volume of this thing.

How exactly can I do this?

Edit: I had the potentiometer wired to 12v and gnd instead of 12v and emitter. Not it dont get hot while off. Only while on. This will probably be okay if I dont have the buzzer on for a long duration right?

Okay so i got it sort of working like i posted above. but now when i call tone it breaks the IRremote library. i think ir remote and tone are using the same timer. where at in here can i define to use a different timer??

IRRemoteint.h

/**
 * @file IRremoteInt.h
 * @brief Contains all declarations required for the interface to IRremote.
 * Could not be named IRremote.h, since this has another semantic (it must include all *.hpp files) for old example code found in the wild.
 *
 * This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
 *
 *
 ************************************************************************************
 * MIT License
 *
 * Copyright (c) 2015-2021 Ken Shirriff http://www.righto.com, Rafi Khan, Armin Joachimsmeyer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************************
 */
#ifndef IRremoteInt_h
#define IRremoteInt_h

#include <Arduino.h>

#if !defined(RAW_BUFFER_LENGTH)
#error Seems you use #include IRremoteInt.h in a file not containing main(). Please define RAW_BUFFER_LENGTH with the same value as in the main program and check if the macros IR_SEND_PIN and SEND_PWM_BY_TIMER are defined in the main program.
#endif
//#define RAW_BUFFER_LENGTH  100 // 100 is default
//#define RAW_BUFFER_LENGTH  112 //  MagiQuest requires 112 bytes. enable this if DECODE_MAGIQUEST is enabled
//#define SEND_PWM_BY_TIMER
//#define IR_SEND_PIN            // here it is only interesting if it is defined, the value does not matter here

#define MARK   1
#define SPACE  0

#define MILLIS_IN_ONE_SECOND 1000L
#define MICROS_IN_ONE_SECOND 1000000L
#define MICROS_IN_ONE_MILLI 1000L

#if defined(PARTICLE)
#define F_CPU 16000000 // definition for a board for which F_CPU is not defined
#elif defined(ARDUINO_ARCH_MBED_RP2040)
#define F_CPU 133000000
#elif defined(ARDUINO_ARDUINO_NANO33BLE)
#define F_CPU 64000000
#endif
#if defined(F_CPU)
#define CLOCKS_PER_MICRO (F_CPU / MICROS_IN_ONE_SECOND)
#else
#error F_CPU not defined, please define it for your board in IRremoteInt.h
#endif

/*
 * For backwards compatibility
 */
#if defined(SYSCLOCK) // allow for processor specific code to define F_CPU
#undef F_CPU
#define F_CPU SYSCLOCK // Clock frequency to be used for timing.
#endif

//#define DEBUG // Activate this for lots of lovely debug output from the IRremote core and all protocol decoders.
//#define TRACE // Activate this for more debug output.

/**
 * For better readability of code
 */
#define DISABLE_LED_FEEDBACK false
#define ENABLE_LED_FEEDBACK true
#define USE_DEFAULT_FEEDBACK_LED_PIN 0

#include "IRProtocol.h"

/****************************************************
 * Declarations for the receiver Interrupt Service Routine
 ****************************************************/
// ISR State-Machine : Receiver States
#define IR_REC_STATE_IDLE      0
#define IR_REC_STATE_MARK      1
#define IR_REC_STATE_SPACE     2
#define IR_REC_STATE_STOP      3 // set to IR_REC_STATE_IDLE only by resume()

/**
 * This struct contains the data and control used for receiver static functions and the ISR (interrupt service routine)
 * Only StateForISR needs to be volatile. All the other fields are not written by ISR after data available and before start/resume.
 */
struct irparams_struct {
    // The fields are ordered to reduce memory over caused by struct-padding
    volatile uint8_t StateForISR;   ///< State Machine state
    uint8_t IRReceivePin;           ///< Pin connected to IR data from detector
#if defined(__AVR__)
    volatile uint8_t *IRReceivePinPortInputRegister;
    uint8_t IRReceivePinMask;
#endif
    uint16_t TickCounterForISR;     ///< Counts 50uS ticks. The value is copied into the rawbuf array on every transition.

    bool OverflowFlag;              ///< Raw buffer OverflowFlag occurred
#if RAW_BUFFER_LENGTH <= 254        // saves around 75 bytes program space and speeds up ISR
    uint8_t rawlen;                 ///< counter of entries in rawbuf
#else
    unsigned int rawlen;            ///< counter of entries in rawbuf
#endif
    uint16_t rawbuf[RAW_BUFFER_LENGTH]; ///< raw data / tick counts per mark/space, first entry is the length of the gap between previous and current command
};

/*
 * Info directives
 * Can be disabled to save program space
 */
#ifdef INFO
#  define IR_INFO_PRINT(...)    Serial.print(__VA_ARGS__)
#  define IR_INFO_PRINTLN(...)  Serial.println(__VA_ARGS__)
#else
/**
 * If INFO, print the arguments, otherwise do nothing.
 */
#  define IR_INFO_PRINT(...) void()
/**
 * If INFO, print the arguments as a line, otherwise do nothing.
 */
#  define IR_INFO_PRINTLN(...) void()
#endif

/*
 * Debug directives
 */
#ifdef DEBUG
#  define IR_DEBUG_PRINT(...)    Serial.print(__VA_ARGS__)
#  define IR_DEBUG_PRINTLN(...)  Serial.println(__VA_ARGS__)
#else
/**
 * If DEBUG, print the arguments, otherwise do nothing.
 */
#  define IR_DEBUG_PRINT(...) void()
/**
 * If DEBUG, print the arguments as a line, otherwise do nothing.
 */
#  define IR_DEBUG_PRINTLN(...) void()
#endif

#ifdef TRACE
#  define IR_TRACE_PRINT(...)    Serial.print(__VA_ARGS__)
#  define IR_TRACE_PRINTLN(...)  Serial.println(__VA_ARGS__)
#else
#  define IR_TRACE_PRINT(...) void()
#  define IR_TRACE_PRINTLN(...) void()
#endif

/****************************************************
 *                     RECEIVING
 ****************************************************/
/*
 * Definitions for member IRData.flags
 */
#define IRDATA_FLAGS_EMPTY              0x00
#define IRDATA_FLAGS_IS_REPEAT          0x01
#define IRDATA_FLAGS_IS_AUTO_REPEAT     0x02
#define IRDATA_FLAGS_PARITY_FAILED      0x04 ///< the current (autorepeat) frame violated parity check
#define IRDATA_TOGGLE_BIT_MASK          0x08
#define IRDATA_FLAGS_EXTRA_INFO         0x10 ///< there is unexpected extra info not contained in address and data (e.g. Kaseikyo unknown vendor ID)
#define IRDATA_FLAGS_WAS_OVERFLOW       0x40 ///< irparams.rawlen is 0 in this case to avoid endless OverflowFlag
#define IRDATA_FLAGS_IS_LSB_FIRST       0x00
#define IRDATA_FLAGS_IS_MSB_FIRST       0x80 ///< Just for info. Value is simply determined by the protocol

/**
 * Data structure for the user application, available as decodedIRData.
 * Filled by decoders and read by print functions or user application.
 */
struct IRData {
    decode_type_t protocol;  ///< UNKNOWN, NEC, SONY, RC5, ...
    uint16_t address;        ///< Decoded address
    uint16_t command;        ///< Decoded command
    uint16_t extra;          ///< Used by MagiQuest and for Kaseikyo unknown vendor ID. Ticks used for decoding Distance protocol.
    uint16_t numberOfBits; ///< Number of bits received for data (address + command + parity) - to determine protocol length if different length are possible.
    uint8_t flags;               ///< See IRDATA_FLAGS_* definitions above
    uint32_t decodedRawData;     ///< Up to 32 bit decoded raw data, used for sendRaw functions.
    irparams_struct *rawDataPtr; ///< Pointer of the raw timing data to be decoded. Mainly the data buffer filled by receiving ISR.
};


/**
 * Results returned from old decoders !!!deprecated!!!
 */
struct decode_results {
    decode_type_t decode_type;  // deprecated, moved to decodedIRData.protocol ///< UNKNOWN, NEC, SONY, RC5, ...
    uint16_t address;           ///< Used by Panasonic & Sharp [16-bits]
    uint32_t value;             // deprecated, moved to decodedIRData.decodedRawData ///< Decoded value / command [max 32-bits]
    uint8_t bits;               // deprecated, moved to decodedIRData.numberOfBits ///< Number of bits in decoded value
    uint16_t magnitude;         // deprecated, moved to decodedIRData.extra ///< Used by MagiQuest [16-bits]
    bool isRepeat;              // deprecated, moved to decodedIRData.flags ///< True if repeat of value is detected

// next 3 values are copies of irparams values - see IRremoteint.h
    uint16_t *rawbuf;           // deprecated, moved to decodedIRData.rawDataPtr->rawbuf ///< Raw intervals in 50uS ticks
    uint16_t rawlen;            // deprecated, moved to decodedIRData.rawDataPtr->rawlen ///< Number of records in rawbuf
    bool overflow;              // deprecated, moved to decodedIRData.flags ///< true if IR raw code too long
};

/**
 * Main class for receiving IR signals
 */
class IRrecv {
public:

    IRrecv();
    IRrecv(uint8_t aReceivePin);
    IRrecv(uint8_t aReceivePin, uint8_t aFeedbackLEDPin);
    void setReceivePin(uint8_t aReceivePinNumber);

    void enableIRIn();
    void disableIRIn();

    /*
     * Stream like API
     */
    void begin(uint8_t aReceivePin, bool aEnableLEDFeedback = false, uint8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN);
    void start(); // alias for enableIRIn
    void start(uint32_t aMicrosecondsToAddToGapCounter);
    bool available();
    IRData* read(); // returns decoded data
    // write is a method of class IRsend below
    // size_t write(IRData *aIRSendData, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
    void stop(); // alias for disableIRIn
    void end();

    bool isIdle();

    /*
     * The main functions
     */
    bool decode();  // Check if available and try to decode
    void resume();  // Enable receiving of the next value

    /*
     * Useful info and print functions
     */
    void printIRResultShort(Print *aSerial);
    void printIRResultMinimal(Print *aSerial);
    void printIRResultRawFormatted(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true);
    void printIRResultAsCVariables(Print *aSerial);

    void compensateAndPrintIRResultAsCArray(Print *aSerial, bool aOutputMicrosecondsInsteadOfTicks = true);
    void compensateAndPrintIRResultAsPronto(Print *aSerial, unsigned int frequency = 38000U);

    /*
     * Store the data for further processing
     */
    void compensateAndStoreIRResultInArray(uint8_t *aArrayPtr);
    size_t compensateAndStorePronto(String *aString, unsigned int frequency = 38000U);

    /*
     * The main decoding functions used by the individual decoders
     */
    bool decodePulseDistanceData(uint8_t aNumberOfBits, uint8_t aStartOffset, uint16_t aBitMarkMicros, uint16_t aOneSpaceMicros,
            uint16_t aZeroSpaceMicros, bool aMSBfirst);

    bool decodePulseWidthData(uint8_t aNumberOfBits, uint8_t aStartOffset, uint16_t aOneMarkMicros, uint16_t aZeroMarkMicros,
            uint16_t aBitSpaceMicros, bool aMSBfirst);

    bool decodeBiPhaseData(uint_fast8_t aNumberOfBits, uint_fast8_t aStartOffset, uint_fast8_t aStartClockCount,
            uint_fast8_t aValueOfSpaceToMarkTransition, uint16_t aBiphaseTimeUnit);

    void initBiphaselevel(uint8_t aRCDecodeRawbuffOffset, uint16_t aBiphaseTimeUnit);
    uint8_t getBiphaselevel();

    /*
     * All standard (decode address + command) protocol decoders
     */
    bool decodeBoseWave();
    bool decodeDenon();
    bool decodeJVC();
    bool decodeKaseikyo();
    bool decodeLegoPowerFunctions();
    bool decodeLG();
    bool decodeMagiQuest(); // not completely standard
    bool decodeNEC();
    bool decodeRC5();
    bool decodeRC6();
    bool decodeSamsung();
    bool decodeSharp(); // redirected to decodeDenon()
    bool decodeSony();
    bool decodeWhynter();

    bool decodeDistance();

    bool decodeHash();

    // Template function :-)
    bool decodeShuzu();

    /*
     * Old functions
     */
    bool decodeDenonOld(decode_results *aResults);
    bool decodeJVCMSB(decode_results *aResults);
    bool decodeLGMSB(decode_results *aResults);
    bool decodeNECMSB(decode_results *aResults);
    bool decodePanasonicMSB(decode_results *aResults);
    bool decodeSonyMSB(decode_results *aResults);
    bool decodeSAMSUNG(decode_results *aResults);
    bool decodeHashOld(decode_results *aResults);

    bool decode(
            decode_results *aResults)
                    __attribute__ ((deprecated ("Please use IrReceiver.decode() without a parameter and IrReceiver.decodedIRData.<fieldname> ."))); // deprecated

    // for backward compatibility. Now in IRFeedbackLED.hpp
    void blink13(bool aEnableLEDFeedback)
            __attribute__ ((deprecated ("Please use setLEDFeedback() or enableLEDFeedback() / disableLEDFeedback()."))); // deprecated

    /*
     * Internal functions
     */
    void initDecodedIRData();
    uint8_t compare(unsigned int oldval, unsigned int newval);

    IRData decodedIRData;       // New: decoded IR data for the application

    // Last decoded IR data for repeat detection
    decode_type_t lastDecodedProtocol;
    uint32_t lastDecodedAddress;
    uint32_t lastDecodedCommand;

    uint8_t repeatCount;        // Used e.g. for Denon decode for autorepeat decoding.
};

extern uint8_t sBiphaseDecodeRawbuffOffset; //

/*
 * Mark & Space matching functions
 */
bool matchTicks(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros);
bool matchMark(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros);
bool matchSpace(uint16_t aMeasuredTicks, uint16_t aMatchValueMicros);

/*
 * Old function names
 */
bool MATCH(uint16_t measured, uint16_t desired);
bool MATCH_MARK(uint16_t measured_ticks, uint16_t desired_us);
bool MATCH_SPACE(uint16_t measured_ticks, uint16_t desired_us);

int getMarkExcessMicros();
void printActiveIRProtocols(Print *aSerial);
void printIRResultShort(Print *aSerial, IRData *aIRDataPtr, uint16_t aLeadingSpaceDuration = 0);

/****************************************************
 * Feedback LED related functions
 ****************************************************/
void setFeedbackLED(bool aSwitchLedOn);
void setLEDFeedback(uint8_t aFeedbackLEDPin, bool aEnableLEDFeedback); // if aFeedbackLEDPin == 0, then take board BLINKLED_ON() and BLINKLED_OFF() functions
void setLEDFeedback(bool aEnableLEDFeedback); // Direct replacement for blink13()
void enableLEDFeedback();
void disableLEDFeedback();

void setBlinkPin(uint8_t aFeedbackLEDPin) __attribute__ ((deprecated ("Please use setLEDFeedback()."))); // deprecated

/**
 * microseconds per clock interrupt tick
 */
#if ! defined(MICROS_PER_TICK)
#define MICROS_PER_TICK    50
#endif

/*
 * Pulse parms are ((X*50)-100) for the Mark and ((X*50)+100) for the Space.
 * First MARK is the one after the long gap
 * Pulse parameters in uSec
 */
/** Relative tolerance (in percent) for some comparisons on measured data. */
#define TOLERANCE       25

/** Lower tolerance for comparison of measured data */
//#define LTOL            (1.0 - (TOLERANCE/100.))
#define LTOL            (100 - TOLERANCE)
/** Upper tolerance for comparison of measured data */
//#define UTOL            (1.0 + (TOLERANCE/100.))
#define UTOL            (100 + TOLERANCE)

//#define TICKS_LOW(us)   ((int)(((us)*LTOL/MICROS_PER_TICK)))
//#define TICKS_HIGH(us)  ((int)(((us)*UTOL/MICROS_PER_TICK + 1)))
#if MICROS_PER_TICK == 50 && TOLERANCE == 25           // Defaults
#define TICKS_LOW(us)   ((us)/67 )     // (us) / ((MICROS_PER_TICK:50 / LTOL:75 ) * 100)
#define TICKS_HIGH(us)  ((us)/40 + 1)  // (us) / ((MICROS_PER_TICK:50 / UTOL:125) * 100) + 1
#else
    #define TICKS_LOW(us)   ((uint16_t) ((long) (us) * LTOL / (MICROS_PER_TICK * 100) ))
    #define TICKS_HIGH(us)  ((uint16_t) ((long) (us) * UTOL / (MICROS_PER_TICK * 100) + 1))
#endif

/*
 * The receiver instance
 */
extern IRrecv IrReceiver;

/****************************************************
 *                     SENDING
 ****************************************************/

/**
 * Just for better readability of code
 */
#define NO_REPEATS  0
#define SEND_STOP_BIT true
#define SEND_REPEAT_COMMAND true ///< used for e.g. NEC, where a repeat is different from just repeating the data.

/**
 * Duty cycle in percent for sent signals.
 */
#if ! defined(IR_SEND_DUTY_CYCLE)
#define IR_SEND_DUTY_CYCLE 30 // 30 saves power and is compatible to the old existing code
#endif

/**
 * Main class for sending IR signals
 */
class IRsend {
public:
    IRsend();

#if defined(IR_SEND_PIN) || defined(SEND_PWM_BY_TIMER)
    void begin();
#endif
#if !defined(IR_SEND_PIN) && !defined(SEND_PWM_BY_TIMER)
    IRsend(uint8_t aSendPin);
    void setSendPin(uint8_t aSendPinNumber);
#endif

    void begin(bool aEnableLEDFeedback, uint8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN);
    void begin(uint8_t aSendPin);

    // Not guarded for backward compatibility
    void begin(uint8_t aSendPin, bool aEnableLEDFeedback, uint8_t aFeedbackLEDPin = USE_DEFAULT_FEEDBACK_LED_PIN);

    size_t write(IRData *aIRSendData, uint_fast8_t aNumberOfRepeats = NO_REPEATS);

    void enableIROut(uint8_t aFrequencyKHz);

    void sendPulseDistanceWidthData(unsigned int aOneMarkMicros, unsigned int aOneSpaceMicros, unsigned int aZeroMarkMicros,
            unsigned int aZeroSpaceMicros, uint32_t aData, uint8_t aNumberOfBits, bool aMSBfirst, bool aSendStopBit = false);
    void sendBiphaseData(unsigned int aBiphaseTimeUnit, uint32_t aData, uint_fast8_t aNumberOfBits);

    void mark(unsigned int aMarkMicros);
    void space(unsigned int aSpaceMicros);
    void IRLedOff();

// 8 Bit array
    void sendRaw(const uint8_t aBufferWithTicks[], uint_fast8_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
    void sendRaw_P(const uint8_t aBufferWithTicks[], uint_fast8_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);

// 16 Bit array
    void sendRaw(const uint16_t aBufferWithMicroseconds[], uint_fast8_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);
    void sendRaw_P(const uint16_t aBufferWithMicroseconds[], uint_fast8_t aLengthOfBuffer, uint_fast8_t aIRFrequencyKilohertz);

    /*
     * New send functions
     */
    void sendBoseWave(uint8_t aCommand, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
    void sendDenon(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aSendSharp = false);
    void sendDenonRaw(uint16_t aRawData, uint_fast8_t aNumberOfRepeats = 0)
#if !defined (DOXYGEN)
            __attribute__ ((deprecated ("Please use sendDenon(aAddress, aCommand, aNumberOfRepeats).")));
#endif
    void sendJVC(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats);

    void sendLGRepeat(bool aUseLG2Protocol = false);
    void sendLG(uint8_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false, bool aUseLG2Protocol =
            false);
    void sendLGRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats = 0, bool aIsRepeat = false, bool aUseLG2Protocol = false);

    void sendNECRepeat();
    void sendNEC(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
    void sendNECRaw(uint32_t aRawData, uint_fast8_t aNumberOfRepeats = 0, bool aIsRepeat = false);
    // NEC variants
    void sendOnkyo(uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
    void sendApple(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);

    void sendKaseikyo(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats, uint16_t aVendorCode); // LSB first
    void sendPanasonic(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
    void sendKaseikyo_Denon(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
    void sendKaseikyo_Mitsubishi(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
    void sendKaseikyo_Sharp(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first
    void sendKaseikyo_JVC(uint16_t aAddress, uint8_t aData, uint_fast8_t aNumberOfRepeats); // LSB first

    void sendRC5(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true);
    void sendRC6(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, bool aEnableAutomaticToggle = true);
    void sendSamsungRepeat();
    void sendSamsung(uint16_t aAddress, uint16_t aCommand, uint_fast8_t aNumberOfRepeats, bool aIsRepeat = false);
    void sendSharp(uint8_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats); // redirected to sendDenon
    void sendSony(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats, uint8_t numberOfBits = SIRCS_12_PROTOCOL);

    void sendLegoPowerFunctions(uint8_t aChannel, uint8_t tCommand, uint8_t aMode, bool aDoSend5Times = true);
    void sendLegoPowerFunctions(uint16_t aRawData, bool aDoSend5Times = true);
    void sendLegoPowerFunctions(uint16_t aRawData, uint8_t aChannel, bool aDoSend5Times = true);

    void sendMagiQuest(uint32_t wand_id, uint16_t magnitude);

    void sendPronto(const __FlashStringHelper *str, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
    void sendPronto(const char *prontoHexString, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
    void sendPronto(const uint16_t *data, unsigned int length, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
#if defined(__AVR__)
    void sendPronto_PF(uint_farptr_t str, uint_fast8_t aNumberOfRepeats = NO_REPEATS);
    void sendPronto_P(const char *str, uint_fast8_t aNumberOfRepeats);
#endif

// Template protocol :-)
    void sendShuzu(uint16_t aAddress, uint8_t aCommand, uint_fast8_t aNumberOfRepeats);

    /*
     * OLD send functions
     */
    void sendDenon(unsigned long data, int nbits);
    void sendDISH(unsigned long data, int nbits);
    void sendJVC(unsigned long data, int nbits,
            bool repeat)
                    __attribute__ ((deprecated ("This old function sends MSB first! Please use sendJVC(aAddress, aCommand, aNumberOfRepeats)."))) {
        sendJVCMSB(data, nbits, repeat);
    }
    void sendJVCMSB(unsigned long data, int nbits, bool repeat = false);

    void sendLG(unsigned long data, int nbits);

    void sendNEC(uint32_t aRawData,
            uint8_t nbits)
                    __attribute__ ((deprecated ("This old function sends MSB first! Please use sendNEC(aAddress, aCommand, aNumberOfRepeats)."))) {
        sendNECMSB(aRawData, nbits);
    }
    void sendNECMSB(uint32_t data, uint8_t nbits, bool repeat = false);
    void sendPanasonic(uint16_t aAddress,
            uint32_t aData)
                    __attribute__ ((deprecated ("This old function sends MSB first! Please use sendPanasonic(aAddress, aCommand, aNumberOfRepeats).")));
    void sendRC5(uint32_t data, uint8_t nbits);
    void sendRC5ext(uint8_t addr, uint8_t cmd, bool toggle);
    void sendRC6(uint32_t data, uint8_t nbits);
    void sendRC6(uint64_t data, uint8_t nbits);
    void sendSharpRaw(unsigned long data, int nbits);
    void sendSharp(unsigned int address, unsigned int command);
    void sendSAMSUNG(unsigned long data, int nbits);
    __attribute__ ((deprecated ("This old function sends MSB first! Please use sendSamsung().")));
    void sendSony(unsigned long data,
            int nbits)
                    __attribute__ ((deprecated ("This old function sends MSB first! Please use sendSony(aAddress, aCommand, aNumberOfRepeats).")));
    ;
    void sendWhynter(unsigned long data, int nbits);

#if !defined(IR_SEND_PIN) && !defined(SEND_PWM_BY_TIMER)
    uint8_t sendPin;
#endif
    unsigned int periodTimeMicros;
    unsigned int periodOnTimeMicros; // compensated with PULSE_CORRECTION_NANOS for duration of digitalWrite.
    unsigned int getPulseCorrectionNanos();

    void customDelayMicroseconds(unsigned long aMicroseconds);
};

/*
 * The sender instance
 */
extern IRsend IrSender;

#endif // IRremoteInt_h

#pragma once


Did you read the toneAC documentation?
"volume - [optional] Set a volume level. (default: 10, range: 0 to 10 [0 = off])"
Did you try it?

That shouldn't work with a piezo, so maybe it isn't a piezo.
Did you measure it's resistance?

Post diagrams, not meaningless words.
Leo..

I was getting ready to try it but then i realized my remote quit working im using iIRremote to control the device. but if i call tone at anytime it will break IRremote until restart. Where do i tell IRremote to use a different internal timer other than Timer2?

i dont see any mention of timer in that file. do you? how do i change it?

I found this file in the IR library its called IRTimer.hpp. it mentions timers.

/**
 * @file IRTimer.hpp
 *
 * @brief All timer specific definitions are contained in this file.
 *
 *  This file is part of Arduino-IRremote https://github.com/Arduino-IRremote/Arduino-IRremote.
 *
 *************************************************************************************
 * MIT License
 *
 * Copyright (c) 2021 Armin Joachimsmeyer
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************************
 */
#ifndef IR_TIMER_HPP
#define IR_TIMER_HPP

#include "IRremoteInt.h"
/** \addtogroup HardwareDependencies CPU / board dependent definitions
 * @{
 */
/** \addtogroup Timer Usage of timers for the different CPU / boards
 * @{
 */
#if defined(SEND_PWM_BY_TIMER) && !defined(ESP32)
#undef IR_SEND_PIN // send pin is determined by timer except for ESP32
#warning Since SEND_PWM_BY_TIMER is defined, the existing value of IR_SEND_PIN is discarded and replaced by the value determined by timer used for PWM generation
#endif

#if defined (DOXYGEN)
/**
 * Hardware / timer dependent pin number for sending IR if SEND_PWM_BY_TIMER is defined. Otherwise used as default for IrSender.sendPin.
 */
#define IR_SEND_PIN

#elif defined(__AVR__)
/**********************************************************************************************************************
 * Mapping of AVR boards to AVR timers
 * For some CPU's you have the option to switch the timer and the hardware send pin
 **********************************************************************************************************************/

/***************************************
 * Plain AVR CPU's, no boards
 ***************************************/
// Arduino Duemilanove, Diecimila, LilyPad, Mini, Fio, Nano, etc
// ATmega328 and ATmega88
#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega88P__) || defined(__AVR_ATmega88PB__)
#  if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2)
//#define IR_USE_AVR_TIMER1   // send pin = pin 9
#define IR_USE_AVR_TIMER2     // send pin = pin 3
#  endif

// Arduino Mega
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#  if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4) && !defined(IR_USE_AVR_TIMER5)
//#define IR_USE_AVR_TIMER1   // send pin = pin 11
#define IR_USE_AVR_TIMER2     // send pin = pin 9
//#define IR_USE_AVR_TIMER3   // send pin = pin 5
//#define IR_USE_AVR_TIMER4   // send pin = pin 6
//#define IR_USE_AVR_TIMER5   // send pin = pin 46
#  endif

// Leonardo
#elif defined(__AVR_ATmega32U4__) && ! defined(TEENSYDUINO) && ! defined(ARDUINO_AVR_PROMICRO)
#  if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
//#define IR_USE_AVR_TIMER1     // send pin = pin 9
#define IR_USE_AVR_TIMER3       // send pin = pin 5
//#define IR_USE_AVR_TIMER4_HS  // send pin = pin 13
#  endif

// Nano Every, Uno WiFi Rev2 and similar
#elif defined(__AVR_ATmega808__) || defined(__AVR_ATmega809__) || defined(__AVR_ATmega3208__) || defined(__AVR_ATmega3209__) \
     || defined(__AVR_ATmega1608__) || defined(__AVR_ATmega1609__) || defined(__AVR_ATmega4808__) || defined(__AVR_ATmega4809__) || defined(__AVR_ATtiny1604__)
#  if !defined(IR_USE_AVR_TIMER_B)
#define IR_USE_AVR_TIMER_B     //  send pin = pin 6 on ATmega4809 1 on ATmega4809
#  endif

// ATmega8u2, ATmega16U2, ATmega32U2
#elif defined(__AVR_ATmega8U2__) || defined(__AVR_ATmega16U2__)  || defined(__AVR_ATmega32U2__)
#  if !defined(IR_USE_AVR_TIMER1)
#define IR_USE_AVR_TIMER1     // send pin = pin C6
#  endif

// Atmega8
#elif defined(__AVR_ATmega8__)
#  if !defined(IR_USE_AVR_TIMER1)
#define IR_USE_AVR_TIMER1     // send pin = pin 9
#  endif

// ATtiny84
#elif defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny88__)
#  if !defined(IR_USE_AVR_TIMER1)
#define IR_USE_AVR_TIMER1     // send pin = pin 6
#  endif

#elif  defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#  if !defined(IR_USE_AVR_TIMER1)
#define IR_USE_AVR_TIMER1   // send pin = pin PB1 / 8
#  endif
#define USE_TIMER_CHANNEL_B

//ATtiny85
#elif defined(__AVR_ATtiny85__)
#  if !defined(IR_USE_AVR_TIMER_TINY0) && !defined(IR_USE_AVR_TIMER_TINY1)
#    if defined(ARDUINO_AVR_DIGISPARK) // tested with 16 and 8 MHz
#define IR_USE_AVR_TIMER_TINY0   // send pin = pin 1
// standard Digispark settings use timer 1 for millis() and micros()
#    else
// standard ATTinyCore settings use timer 0 for millis() and micros()
#define IR_USE_AVR_TIMER_TINY1   // send pin = pin 4
#    endif
#  endif

/***************************************
 * SPARKFUN Pro Micro board
 ***************************************/
#elif defined(ARDUINO_AVR_PROMICRO)
#  if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
//#define IR_USE_AVR_TIMER1     // send pin = pin 9
#define IR_USE_AVR_TIMER3       // send pin = pin 5
//#define IR_USE_AVR_TIMER4_HS  // send pin = pin 13
#  endif

/***************************************
 * TEENSY Boards
 ***************************************/
// Teensy 1.0
#elif defined(__AVR_AT90USB162__)
#  if !defined(IR_USE_AVR_TIMER1)
#define IR_USE_AVR_TIMER1     // send pin = pin 17
#  endif

// Teensy++ 1.0 & 2.0
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
#  if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3)
//#define IR_USE_AVR_TIMER1   // send pin = pin 25
#define IR_USE_AVR_TIMER2     // send pin = pin 1
//#define IR_USE_AVR_TIMER3   // send pin = pin 16
#  endif

// Teensy 2.0
#elif defined(__AVR_ATmega32U4__) && defined(TEENSYDUINO)
#  if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4_HS)
//#define IR_USE_AVR_TIMER1     // send pin = pin 14 (Teensy 2.0 - physical pin: B5)
//#define IR_USE_AVR_TIMER3     // send pin = pin 9  (Teensy 2.0 - physical pin: C6)
#define IR_USE_AVR_TIMER4_HS    // send pin = pin 10 (Teensy 2.0 - physical pin: C7)
#  endif

/***************************************
 * CPU's with MegaCore
 ***************************************/
// MegaCore - ATmega64, ATmega128
#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2560__)
#  if !defined(IR_USE_AVR_TIMER1)
#define IR_USE_AVR_TIMER1     // send pin = pin 13
#  endif

/***************************************
 * CPU's with MajorCore
 ***************************************/
#elif defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
#  if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER3)
#define IR_USE_AVR_TIMER1     // send pin = pin 13
//#define IR_USE_AVR_TIMER3   // send pin = pin 12 - ATmega162 only
#  endif

/***************************************
 * CPU's with MightyCore
 ***************************************/
// MightyCore - ATmega1284
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
#  if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3)
//#define IR_USE_AVR_TIMER1   // send pin = pin 13
#define IR_USE_AVR_TIMER2     // send pin = pin 14
//#define IR_USE_AVR_TIMER3   // send pin = pin 6
#  endif

// MightyCore - ATmega164, ATmega324, ATmega644
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
|| defined(__AVR_ATmega164P__)
#  if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2)
//#define IR_USE_AVR_TIMER1   // send pin = pin 13
#define IR_USE_AVR_TIMER2     // send pin = pin 14
#  endif

// MightyCore - ATmega8535, ATmega16, ATmega32
#elif defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__)
#  if !defined(IR_USE_AVR_TIMER1)
#define IR_USE_AVR_TIMER1     // send pin = pin 13
#  endif

/***************************************
 * CPU's with TinyCore
 ***************************************/
#elif defined(__AVR_ATtiny1616__)  || defined(__AVR_ATtiny3216__) || defined(__AVR_ATtiny3217__) // TinyCore boards
#define IR_USE_AVR_TIMER_D

#endif // AVR CPU's
/**********************************************************************************************************************
 * End of AVR mapping, start of AVR timers
 **********************************************************************************************************************/
/*
 * AVR Timer1 (16 bits)
 */
#if defined(IR_USE_AVR_TIMER1)
#  if defined(SEND_PWM_BY_TIMER)
#    if defined(CORE_OC1A_PIN)
#define IR_SEND_PIN  CORE_OC1A_PIN  // Teensy

#    elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define IR_SEND_PIN  11             // Arduino Mega

// MightyCore, MegaCore, MajorCore
#    elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
|| defined(__AVR_ATmega164P__) || defined(__AVR_ATmega32__) \
|| defined(__AVR_ATmega16__) || defined(__AVR_ATmega8535__) \
|| defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \
|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) \
|| defined(__AVR_ATmega8515__) || defined(__AVR_ATmega162__)
#define IR_SEND_PIN  13

#    elif defined(__AVR_ATtiny84__)
#define IR_SEND_PIN  6

#    elif defined(__AVR_ATtiny88__)
#define IR_SEND_PIN  8

#    elif defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
#define IR_SEND_PIN  PIN_PB1 // OC1BU / PB1 / Pin8 at ATTinyCore (BU/PB1, BV/PB3, BW/PB5 and BX/PB7 are available) see ENABLE_SEND_PWM_BY_TIMER

#    else
#define IR_SEND_PIN  9              // OC1A Arduino Duemilanove, Diecimila, LilyPad, Sparkfun Pro Micro, Leonardo, MH-ET Tiny88 etc.
#    endif // defined(CORE_OC1A_PIN)

#    if defined(__AVR_ATtiny87__) || defined(__AVR_ATtiny167__)
// Clear OC1A/OC1B on Compare Match when up-counting. Set OC1A/OC1B on Compare Match when downcounting.
#define ENABLE_SEND_PWM_BY_TIMER   TCNT1 = 0;  (TCCR1A |= _BV(COM1A1); (TCCR1D |= _BV(OC1BU)) // + enable OC1BU as output
#define DISABLE_SEND_PWM_BY_TIMER  (TCCR1D = 0)
#    else
#define ENABLE_SEND_PWM_BY_TIMER   TCNT1 = 0; (TCCR1A |= _BV(COM1A1))  // Clear OC1A/OC1B on Compare Match when up-counting. Set OC1A/OC1B on Compare Match when downcounting.
#define DISABLE_SEND_PWM_BY_TIMER  (TCCR1A &= ~(_BV(COM1A1)))
#    endif
#  endif // defined(SEND_PWM_BY_TIMER)

#define TIMER_RESET_INTR_PENDING

#  if defined(__AVR_ATmega8__) || defined(__AVR_ATmega8515__) \
|| defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) \
|| defined(__AVR_ATmega32__) || defined(__AVR_ATmega64__) \
|| defined(__AVR_ATmega128__) || defined(__AVR_ATmega162__)
#define TIMER_ENABLE_RECEIVE_INTR   (TIMSK |= _BV(OCIE1A))
#define TIMER_DISABLE_RECEIVE_INTR  (TIMSK &= ~_BV(OCIE1A))
#  else
#define TIMER_ENABLE_RECEIVE_INTR   (TIMSK1 = _BV(OCIE1A))          // Timer/Counter1, Output Compare A Match Interrupt Enable
#define TIMER_DISABLE_RECEIVE_INTR  (TIMSK1 = 0)
#  endif

#  if defined(USE_TIMER_CHANNEL_B)
#    if defined(TIMER1_COMPB_vect)
#define TIMER_INTR_NAME       TIMER1_COMPB_vect
#    elif defined(TIM1_COMPB_vect)
#define TIMER_INTR_NAME       TIM1_COMPB_vect
#    endif
#else
#    if defined(TIMER1_COMPA_vect)
#define TIMER_INTR_NAME       TIMER1_COMPA_vect
#    elif defined(TIM1_COMPA_vect)
#define TIMER_INTR_NAME       TIM1_COMPA_vect
#    endif
#  endif

void timerConfigForSend(uint8_t aFrequencyKHz) {
#  if (((F_CPU / 2000) / 38) < 256)
    const uint16_t pwmval = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
    TCCR1A = _BV(WGM11);// PWM, Phase Correct, Top is ICR1
    TCCR1B = _BV(WGM13) | _BV(CS10);// CS10 -> no prescaling
    ICR1 = pwmval - 1;
#    if defined(USE_TIMER_CHANNEL_B)
    OCR1A = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
#    else
    OCR1A = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
#    endif
    TCNT1 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible
#  else
    const uint16_t pwmval = ((F_CPU / 8) / 2000) / (aFrequencyKHz); // 2000 instead of 1000 because of Phase Correct PWM
    TCCR1A = _BV(WGM11);// PWM, Phase Correct, Top is ICR1
    TCCR1B = _BV(WGM13) | _BV(CS11);// CS11 -> Prescaling by 8
    ICR1 = pwmval - 1;
#    if defined(USE_TIMER_CHANNEL_B)
    OCR1A = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
#    else
    OCR1A = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
#    endif
    TCNT1 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible
#  endif
}

void timerConfigForReceive() {
    TCCR1A = 0;
    TCCR1B = _BV(WGM12) | _BV(CS10);
    OCR1A = F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND;
    TCNT1 = 0;
}

/*
 * AVR Timer2 (8 bits)
 */
#elif defined(IR_USE_AVR_TIMER2)
#  if defined(SEND_PWM_BY_TIMER)
#    if defined(CORE_OC2B_PIN)
#define IR_SEND_PIN  CORE_OC2B_PIN  // Teensy

#    elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define IR_SEND_PIN  9              // Arduino Mega

#    elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) \
|| defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) \
|| defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324A__) \
|| defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega164A__) \
|| defined(__AVR_ATmega164P__)
#define IR_SEND_PIN  14             // MightyCore, MegaCore

#    else
#define IR_SEND_PIN  3              // Arduino Duemilanove, Diecimila, LilyPad, etc
#    endif // defined(CORE_OC2B_PIN)

#define ENABLE_SEND_PWM_BY_TIMER    TCNT2 = 0; (TCCR2A |= _BV(COM2B1))  // Clear OC2B on Compare Match
#define DISABLE_SEND_PWM_BY_TIMER   (TCCR2A &= ~(_BV(COM2B1)))          // Normal port operation, OC2B disconnected.
#  endif // defined(SEND_PWM_BY_TIMER)

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   (TIMSK2 = _BV(OCIE2B))              // Output Compare Match A Interrupt Enable
#define TIMER_DISABLE_RECEIVE_INTR  (TIMSK2 = 0)
#define TIMER_INTR_NAME             TIMER2_COMPB_vect                   // We use TIMER2_COMPB_vect to be compatible with tone() library

// The top value for the timer.  The modulation frequency will be F_CPU / 2 / OCR2A.
#pragma GCC diagnostic ignored "-Wunused-function"
/*
 * timerConfigForSend() is used exclusively by IRsend::enableIROut()
 */
void timerConfigForSend(uint8_t aFrequencyKHz) {
#  if (((F_CPU / 2000) / 38) < 256)
    const uint16_t pwmval = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
    TCCR2A = _BV(WGM20);// PWM, Phase Correct, Top is OCR2A
    TCCR2B = _BV(WGM22) | _BV(CS20);// CS20 -> no prescaling
    OCR2A = pwmval - 1;
    OCR2B = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
    TCNT2 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible
#  else
    const uint16_t pwmval = ((F_CPU / 8) / 2000) / (aFrequencyKHz); // 2000 instead of 1000 because of Phase Correct PWM
    TCCR2A = _BV(WGM20);// PWM, Phase Correct, Top is OCR2A
    TCCR2B = _BV(WGM22) | _BV(CS21);// CS21 -> Prescaling by 8
    OCR2A = pwmval - 1;
    OCR2B = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
    TCNT2 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible
#  endif
}

#define TIMER_COUNT_TOP  (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
/*
 * timerConfigForReceive() is used exclusively by IRrecv::enableIRIn()
 * It generates an interrupt each 50 (MICROS_PER_TICK) us.
 */
void timerConfigForReceive() {
#  if (TIMER_COUNT_TOP < 256)
    TCCR2A = _BV(WGM21);
    TCCR2B = _BV(CS20);
    OCR2A = TIMER_COUNT_TOP;
    OCR2B = TIMER_COUNT_TOP;
    TCNT2 = 0;
#  else
    TCCR2A = _BV(WGM21);
    TCCR2B = _BV(CS21);
    OCR2A = TIMER_COUNT_TOP / 8;
    OCR2B = TIMER_COUNT_TOP / 8;
    TCNT2 = 0;
#  endif
}

/*
 * AVR Timer3 (16 bits)
 */
#elif defined(IR_USE_AVR_TIMER3)
#  if defined(SEND_PWM_BY_TIMER)
#    if defined(CORE_OC3A_PIN)
#define IR_SEND_PIN  CORE_OC3A_PIN  // Teensy

#    elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) \
|| defined(__AVR_ATmega32U4__) || defined(ARDUINO_AVR_PROMICRO)
#define IR_SEND_PIN  5              // Arduino Mega, Arduino Leonardo, Sparkfun Pro Micro

#    elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
#define IR_SEND_PIN  6              // MightyCore, MegaCore

#    else
#error Please add OC3A pin number here
#    endif

#define ENABLE_SEND_PWM_BY_TIMER    TCNT3 = 0; (TCCR3A |= _BV(COM3A1))
#define DISABLE_SEND_PWM_BY_TIMER   (TCCR3A &= ~(_BV(COM3A1)))
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   (TIMSK3 = _BV(OCIE3B))
#define TIMER_DISABLE_RECEIVE_INTR  (TIMSK3 = 0)
#define TIMER_INTR_NAME             TIMER3_COMPB_vect

void timerConfigForSend(uint8_t aFrequencyKHz) {
#if defined(SEND_PWM_BY_TIMER) && F_CPU > 16000000
#error "Creating timer PWM with timer 3 is not supported for F_CPU > 16 MHz"
#endif
    const uint16_t pwmval = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
    TCCR3A = _BV(WGM31);
    TCCR3B = _BV(WGM33) | _BV(CS30);// PWM, Phase Correct, ICRn as TOP, complete period is double of pwmval
    ICR3 = pwmval - 1;
    OCR3A = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
    TCNT3 = 0;// required, since we have an 16 bit counter
}

void timerConfigForReceive() {
    TCCR3A = 0;
    TCCR3B = _BV(WGM32) | _BV(CS30);
    OCR3A = F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND;
    OCR3B = F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND;
    TCNT3 = 0;
}

/*
 * AVR Timer4 (16 bits)
 */
#elif defined(IR_USE_AVR_TIMER4)
#  if defined(SEND_PWM_BY_TIMER)
#    if defined(CORE_OC4A_PIN)
#define IR_SEND_PIN  CORE_OC4A_PIN
#    elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define IR_SEND_PIN  6  // Arduino Mega
#    else
#error Please add OC4A pin number here
#    endif

#define ENABLE_SEND_PWM_BY_TIMER    TCNT4 = 0; (TCCR4A |= _BV(COM4A1))
#define DISABLE_SEND_PWM_BY_TIMER   (TCCR4A &= ~(_BV(COM4A1)))
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   (TIMSK4 = _BV(OCIE4A))
#define TIMER_DISABLE_RECEIVE_INTR  (TIMSK4 = 0)
#define TIMER_INTR_NAME             TIMER4_COMPA_vect

void timerConfigForSend(uint8_t aFrequencyKHz) {
#if defined(SEND_PWM_BY_TIMER) && F_CPU > 16000000
#error "Creating timer PWM with timer 4 is not supported for F_CPU > 16 MHz"
#endif
    const uint16_t pwmval = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
    TCCR4A = _BV(WGM41);
    TCCR4B = _BV(WGM43) | _BV(CS40);
    ICR4 = pwmval - 1;
    OCR4A = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
    TCNT4 = 0;// required, since we have an 16 bit counter
}

void timerConfigForReceive() {
    TCCR4A = 0;
    TCCR4B = _BV(WGM42) | _BV(CS40);
    OCR4A = F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND;
    TCNT4 = 0;
}

/*
 * AVR Timer4 (10 bits, high speed option)
 */
#elif defined(IR_USE_AVR_TIMER4_HS)
#  if defined(SEND_PWM_BY_TIMER)
#    if defined(CORE_OC4A_PIN)
#define IR_SEND_PIN  CORE_OC4A_PIN  // Teensy 2.0
#    elif defined(ARDUINO_AVR_PROMICRO)
#define IR_SEND_PIN  5              // Sparkfun Pro Micro
#    elif defined(__AVR_ATmega32U4__)
#define IR_SEND_PIN  13             // Leonardo
#    else
#error Please add OC4A pin number here
#    endif

#    if defined(ARDUINO_AVR_PROMICRO) // Sparkfun Pro Micro
#define ENABLE_SEND_PWM_BY_TIMER    TCNT4 = 0; (TCCR4A |= _BV(COM4A0))     // Use complementary OC4A output on pin 5
#define DISABLE_SEND_PWM_BY_TIMER   (TCCR4A &= ~(_BV(COM4A0)))  // (Pro Micro does not map PC7 (32/ICP3/CLK0/OC4A)
// of ATmega32U4 )
#    else
#define ENABLE_SEND_PWM_BY_TIMER    TCNT4 = 0; (TCCR4A |= _BV(COM4A1)); DDRC |= (1<<7)
#define DISABLE_SEND_PWM_BY_TIMER   (TCCR4A &= ~(_BV(COM4A1)))
#    endif
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   (TIMSK4 = _BV(TOIE4))
#define TIMER_DISABLE_RECEIVE_INTR  (TIMSK4 = 0)
#define TIMER_INTR_NAME             TIMER4_OVF_vect

void timerConfigForSend(uint8_t aFrequencyKHz) {
#if defined(SEND_PWM_BY_TIMER) && F_CPU > 16000000
#error "Creating timer PWM with timer 4 HS is not supported for F_CPU > 16 MHz"
#endif
    const uint16_t pwmval = ((F_CPU / 2000) / (aFrequencyKHz)) - 1; // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
    TCCR4A = (1 << PWM4A);
    TCCR4B = _BV(CS40);
    TCCR4C = 0;
    TCCR4D = (1 << WGM40);
    TCCR4E = 0;
    TC4H = pwmval >> 8;
    OCR4C = pwmval;
    TC4H = (pwmval * IR_SEND_DUTY_CYCLE / 100) >> 8;
    OCR4A = (pwmval * IR_SEND_DUTY_CYCLE / 100) & 255;
    TCNT4 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible
}

void timerConfigForReceive() {
    TCCR4A = 0;
    TCCR4B = _BV(CS40);
    TCCR4C = 0;
    TCCR4D = 0;
    TCCR4E = 0;
    TC4H = (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND) >> 8;
    OCR4C = (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND) & 255;
    TC4H = 0;
    TCNT4 = 0;
}

/*
 * AVR Timer5 (16 bits)
 */
#elif defined(IR_USE_AVR_TIMER5)
#  if defined(SEND_PWM_BY_TIMER)
#    if defined(CORE_OC5A_PIN)
#define IR_SEND_PIN  CORE_OC5A_PIN
#    elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#define IR_SEND_PIN  46  // Arduino Mega
#    else
#error Please add OC5A pin number here
#    endif

#define ENABLE_SEND_PWM_BY_TIMER    TCNT5 = 0; (TCCR5A |= _BV(COM5A1))
#define DISABLE_SEND_PWM_BY_TIMER   (TCCR5A &= ~(_BV(COM5A1)))
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   (TIMSK5 = _BV(OCIE5A))
#define TIMER_DISABLE_RECEIVE_INTR  (TIMSK5 = 0)
#define TIMER_INTR_NAME             TIMER5_COMPA_vect

void timerConfigForSend(uint8_t aFrequencyKHz) {
#if defined(SEND_PWM_BY_TIMER) && F_CPU > 16000000
#error "Creating timer PWM with timer 5 is not supported for F_CPU > 16 MHz"
#endif
    const uint16_t pwmval = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
    TCCR5A = _BV(WGM51);
    TCCR5B = _BV(WGM53) | _BV(CS50);
    ICR5 = pwmval - 1;
    OCR5A = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
    TCNT5 = 0;// required, since we have an 16 bit counter
}

void timerConfigForReceive() {
    TCCR5A = 0;
    TCCR5B = _BV(WGM52) | _BV(CS50);
    OCR5A = F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND;
    TCNT5 = 0;
}

/*
 * AVR Timer0 for ATtinies (8 bits)
 */
#elif defined(IR_USE_AVR_TIMER_TINY0)
#  if defined(SEND_PWM_BY_TIMER)
#define IR_SEND_PIN        1

#define ENABLE_SEND_PWM_BY_TIMER        TCNT0 = 0; (TCCR0A |= _BV(COM0B1))
#define DISABLE_SEND_PWM_BY_TIMER       (TCCR0A &= ~(_BV(COM0B1)))
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR       (TIMSK |= _BV(OCIE0A))
#define TIMER_DISABLE_RECEIVE_INTR      (TIMSK &= ~(_BV(OCIE0A)))
#define TIMER_INTR_NAME                 TIMER0_COMPA_vect

void timerConfigForSend(uint8_t aFrequencyKHz) {
#if defined(SEND_PWM_BY_TIMER) && F_CPU > 16000000
#error "Creating timer PWM with timer TINY0 is not supported for F_CPU > 16 MHz"
#endif
    const uint16_t pwmval = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of Phase Correct PWM
    TCCR0A = _BV(WGM00);// PWM, Phase Correct, Top is OCR0A
    TCCR0B = _BV(WGM02) | _BV(CS00);// CS00 -> no prescaling
    OCR0A = pwmval - 1;
    OCR0B = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
    TCNT0 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible
}

#define TIMER_COUNT_TOP  (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
void timerConfigForReceive() {
#  if (TIMER_COUNT_TOP < 256)
    TCCR0A = _BV(WGM01); // CTC, Top is OCR0A
    TCCR0B = _BV(CS00);// No prescaling
    OCR0A = TIMER_COUNT_TOP;
    TCNT0 = 0;
#  else
    TCCR0A = _BV(WGM01);
    TCCR0B = _BV(CS01); // prescaling by 8
    OCR0A = TIMER_COUNT_TOP / 8;
    TCNT0 = 0;
#  endif
}

/*
 * AVR Timer1 for ATtinies (8 bits)
 */
#elif defined(IR_USE_AVR_TIMER_TINY1)
#  if defined(SEND_PWM_BY_TIMER)
#define IR_SEND_PIN        4

#define ENABLE_SEND_PWM_BY_TIMER    TCNT1 = 0; GTCCR |= _BV(PWM1B) | _BV(COM1B0) // Enable pin 4 PWM output (PB4 - Arduino D4)
#define DISABLE_SEND_PWM_BY_TIMER   (GTCCR &= ~(_BV(PWM1B) | _BV(COM1B0)))
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   (TIMSK |= _BV(OCIE1B))
#define TIMER_DISABLE_RECEIVE_INTR  (TIMSK &= ~(_BV(OCIE1B)))
#define TIMER_INTR_NAME             TIMER1_COMPB_vect

void timerConfigForSend(uint8_t aFrequencyKHz) {
#  if (((F_CPU / 1000) / 38) < 256)
    const uint16_t pwmval = (F_CPU / 1000) / (aFrequencyKHz); // 421 @16 MHz, 26 @1 MHz and 38 kHz
    TCCR1 = _BV(CTC1) | _BV(CS10);// CTC1 = 1: TOP value set to OCR1C, CS10 No Prescaling
    OCR1C = pwmval - 1;
    OCR1B = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
    TCNT1 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible
    GTCCR = _BV(PWM1B) | _BV(COM1B0);// PWM1B = 1: Enable PWM for OCR1B, COM1B0 Clear on compare match
#  else
    const uint16_t pwmval = ((F_CPU / 2) / 1000) / (aFrequencyKHz); // 210 for 16 MHz and 38 kHz
    TCCR1 = _BV(CTC1) | _BV(CS11);// CTC1 = 1: TOP value set to OCR1C, CS11 Prescaling by 2
    OCR1C = pwmval - 1;
    OCR1B = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1;
    TCNT1 = 0;// not really required, since we have an 8 bit counter, but makes the signal more reproducible
    GTCCR = _BV(PWM1B) | _BV(COM1B0);// PWM1B = 1: Enable PWM for OCR1B, COM1B0 Clear on compare match
#  endif
}

#define TIMER_COUNT_TOP  (F_CPU * MICROS_PER_TICK / MICROS_IN_ONE_SECOND)
void timerConfigForReceive() {
#  if (TIMER_COUNT_TOP < 256)
    TCCR1 = _BV(CTC1) | _BV(CS10); // Clear Timer/Counter on Compare Match, Top is OCR1C, No prescaling
    GTCCR = 0; // normal, non-PWM mode
    OCR1C = TIMER_COUNT_TOP;
    TCNT1 = 0;
#  else
    TCCR1 = _BV(CTC1) | _BV(CS12); // Clear Timer/Counter on Compare Match, Top is OCR1C, prescaling by 8
    GTCCR = 0; // normal, non-PWM mode
    OCR1C = TIMER_COUNT_TOP / 8;
    TCNT1 = 0;
#  endif
}

/*
 * AVR TimerB  (8 bits) for ATmega4809 (Nano Every, Uno WiFi Rev2)
 */
#elif defined(IR_USE_AVR_TIMER_B)
#  if defined(SEND_PWM_BY_TIMER)
#    if defined(__AVR_ATmega4808__) || defined(__AVR_ATmega4809__)
#define IR_SEND_PIN        6 // PF4 on ATmega4809 / Nano Every (see pins_arduino.h digital_pin_to_timer)
#    else
#error SEND_PWM_BY_TIMER not yet supported for this CPU
#    endif

#define ENABLE_SEND_PWM_BY_TIMER    TCB0.CNT = 0; (TCB0.CTRLB |= TCB_CCMPEN_bm) // set Compare/Capture Output Enable
#define DISABLE_SEND_PWM_BY_TIMER   (TCB0.CTRLB &= ~(TCB_CCMPEN_bm))
#  endif

// ATmega4809 TCB0
#define TIMER_RESET_INTR_PENDING    TCB0.INTFLAGS = TCB_CAPT_bm
#define TIMER_ENABLE_RECEIVE_INTR   (TCB0.INTCTRL = TCB_CAPT_bm)
#define TIMER_DISABLE_RECEIVE_INTR  (TCB0.INTCTRL &= ~(TCB_CAPT_bm))
#define TIMER_INTR_NAME             TCB0_INT_vect

void timerConfigForSend(uint8_t aFrequencyKHz) {
#if defined(SEND_PWM_BY_TIMER) && F_CPU > 16000000
    // we have only prescaler 2 or must take clock of timer A (which is non deterministic)
#error "Creating timer PWM with timer TCB0 is not possible for F_CPU > 16 MHz"
#endif
    const uint16_t pwmval = (F_CPU / 2000) / (aFrequencyKHz); // 210,52 for 38 kHz @16 MHz clock, 2000 instead of 1000 because of using CLK / 2
    TCB0.CTRLB = TCB_CNTMODE_PWM8_gc;   // 8 bit PWM mode
    TCB0.CCMPL = pwmval - 1;            // Period of 8 bit PWM
    TCB0.CCMPH = ((pwmval * IR_SEND_DUTY_CYCLE) / 100) - 1; // Duty cycle of waveform of 8 bit PWM
    TCB0.CTRLA = (TCB_CLKSEL_CLKDIV2_gc) | (TCB_ENABLE_bm); // use CLK / 2
    TCB0.CNT = 0; // not really required, since we have an 8 bit counter, but makes the signal more reproducible
}

void timerConfigForReceive() {
    TCB0.CTRLB = (TCB_CNTMODE_INT_gc);  // Periodic interrupt mode
    TCB0.CCMP = ((F_CPU * MICROS_PER_TICK) / MICROS_IN_ONE_SECOND);
    TCB0.INTFLAGS = TCB_CAPT_bm;         // reset interrupt flags
    TCB0.CTRLA = (TCB_CLKSEL_CLKDIV1_gc) | (TCB_ENABLE_bm);
}

/*
 * AVR TimerD for TinyCore 32 (16 bits)
 */
#elif defined(IR_USE_AVR_TIMER_D)
#  if defined(SEND_PWM_BY_TIMER)
#define IR_SEND_PIN 13

#define ENABLE_SEND_PWM_BY_TIMER    (timerEnablSendPWM())
#define DISABLE_SEND_PWM_BY_TIMER   (TCD0.CTRLA = 0) // do not disable output, disable complete timer
#  endif

#define TIMER_RESET_INTR_PENDING    (TCD0.INTFLAGS = TCD_OVF_bm)
#define TIMER_ENABLE_RECEIVE_INTR   (TCD0.INTCTRL = TCD_OVF_bm)
#define TIMER_DISABLE_RECEIVE_INTR  (TCD0.INTCTRL = 0)
#define TIMER_INTR_NAME             TCD0_OVF_vect

void timerEnablSendPWM() {
    TCD0.CTRLA = 0;                                                 // reset enable bit in order to unprotect the other bits
    _PROTECTED_WRITE(TCD0.FAULTCTRL, FUSE_CMPAEN_bm);// enable WOA output at pin 13/PA4
//    _PROTECTED_WRITE(TCD0.FAULTCTRL, FUSE_CMPAEN_bm | FUSE_CMPBEN_bm); // enable WOA + WOB output pins at 13/PA4 + 14/PA5
    TCD0.CTRLA = TCD_ENABLE_bm | TCD_CLKSEL_SYSCLK_gc| TCD_CNTPRES_DIV1_gc;// System clock, no prescale, no synchronization prescaler
}

void timerConfigForSend(uint8_t aFrequencyKHz) {
    const uint16_t pwmval = (F_CPU / 1000) / (aFrequencyKHz);    // 526,31 for 38 kHz @20 MHz clock
    // use one ramp mode and overflow interrupt
    TCD0.CTRLA = 0;// reset enable bit in order to unprotect the other bits
//    while ((TCD0.STATUS & TCD_ENRDY_bm) == 0);                      // Wait for Enable Ready to be high - I guess it is not required
    TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc;// must be set since it is used by PWM
    TCD0.CTRLC = 0;// reset WOx output settings
//    TCD0.CMPBSET = 80;
    TCD0.CMPBCLR = pwmval - 1;

    // Generate duty cycle signal for debugging etc.
    TCD0.CMPASET = 0;
    TCD0.CMPACLR = (pwmval * IR_SEND_DUTY_CYCLE / 100) - 1;// duty cycle for WOA

    TCD0.INTFLAGS = TCD_OVF_bm;// reset interrupt flags
    TCD0.INTCTRL = TCD_OVF_bm;// overflow interrupt
    // Do not enable timer, this is done at timerEnablSendPWM()
}

void timerConfigForReceive() {
    TCD0.CTRLA = 0;                                                 // reset enable bit in order to unprotect the other bits
    TCD0.CTRLB = TCD_WGMODE_ONERAMP_gc;// must be set since it is used by PWM
//    TCD0.CMPBSET = 80;
    TCD0.CMPBCLR = ((F_CPU * MICROS_PER_TICK) / MICROS_IN_ONE_SECOND) - 1;

    _PROTECTED_WRITE(TCD0.FAULTCTRL, 0);// must disable WOA output at pin 13/PA4

    TCD0.INTFLAGS = TCD_OVF_bm;         // reset interrupt flags
//    TCD0.INTCTRL = TCD_OVF_bm;          // overflow interrupt
    // check enable ready
//    while ((TCD0.STATUS & TCD_ENRDY_bm) == 0); // Wait for Enable Ready to be high - I guess it is not required
    // enable timer - this locks the other bits and static registers and activates values in double buffered registers
    TCD0.CTRLA = TCD_ENABLE_bm | TCD_CLKSEL_SYSCLK_gc| TCD_CNTPRES_DIV1_gc;// System clock, no prescale, no synchronization prescaler
}

#else
#error Internal code configuration error, no timer functions implemented for this AVR CPU / board
#endif //defined(IR_USE_AVR_TIMER*)
/**********************************************************************************************************************
 * End of AVR timers
 **********************************************************************************************************************/

/***************************************
 * Teensy 3.0 / Teensy 3.1 boards
 ***************************************/
#elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__)
#  if defined(SEND_PWM_BY_TIMER)
#define IR_SEND_PIN  5

#define ENABLE_SEND_PWM_BY_TIMER    do { CORE_PIN5_CONFIG = PORT_PCR_MUX(2) | PORT_PCR_DSE | PORT_PCR_SRE; } while(0)
#define DISABLE_SEND_PWM_BY_TIMER   do { CORE_PIN5_CONFIG = PORT_PCR_MUX(1) | PORT_PCR_DSE | PORT_PCR_SRE; } while(0)
#  endif

// Special carrier modulator timer for Teensy 3.0 / Teensy 3.1
#define TIMER_RESET_INTR_PENDING    uint8_t tmp __attribute__((unused)) = CMT_MSC; CMT_CMD2 = 30
#define TIMER_ENABLE_RECEIVE_INTR   NVIC_ENABLE_IRQ(IRQ_CMT), NVIC_SET_PRIORITY(IRQ_CMT, 48)
#define TIMER_DISABLE_RECEIVE_INTR  NVIC_DISABLE_IRQ(IRQ_CMT)
#define TIMER_INTR_NAME     cmt_isr

#  ifdef ISR
#undef ISR
#  endif
#define ISR(f) void f(void)

#define CMT_PPS_DIV  ((F_BUS + 7999999) / 8000000)
#  if F_BUS < 8000000
#error IRremote requires at least 8 MHz on Teensy 3.x
#  endif

void timerConfigForSend(uint8_t aFrequencyKHz) {
    SIM_SCGC4 |= SIM_SCGC4_CMT;
    SIM_SOPT2 |= SIM_SOPT2_PTD7PAD;
    CMT_PPS = CMT_PPS_DIV - 1;
    CMT_CGH1 = ((F_BUS / CMT_PPS_DIV / 3000) + ((aFrequencyKHz) / 2)) / (aFrequencyKHz);
    CMT_CGL1 = ((F_BUS / CMT_PPS_DIV / 1500) + ((aFrequencyKHz) / 2)) / (aFrequencyKHz);
    CMT_CMD1 = 0;
    CMT_CMD2 = 30;
    CMT_CMD3 = 0;
    CMT_CMD4 = 0;
    CMT_OC = 0x60;
    CMT_MSC = 0x01;
}

void timerConfigForReceive() {
    SIM_SCGC4 |= SIM_SCGC4_CMT;
    CMT_PPS = CMT_PPS_DIV - 1;
    CMT_CGH1 = 1;
    CMT_CGL1 = 1;
    CMT_CMD1 = 0;
    CMT_CMD2 = 30;
    CMT_CMD3 = 0;
    CMT_CMD4 = (F_BUS / 160000 + CMT_PPS_DIV / 2) / CMT_PPS_DIV - 31;
    CMT_OC = 0;
    CMT_MSC = 0x03;
}

/***************************************
 * Teensy-LC board
 ***************************************/
#elif defined(__MKL26Z64__)
#  if defined(SEND_PWM_BY_TIMER)
#define IR_SEND_PIN        16

#define ENABLE_SEND_PWM_BY_TIMER        FTM1_CNT = 0; CORE_PIN16_CONFIG = PORT_PCR_MUX(3)|PORT_PCR_DSE|PORT_PCR_SRE
#define DISABLE_SEND_PWM_BY_TIMER       CORE_PIN16_CONFIG = PORT_PCR_MUX(1)|PORT_PCR_SRE
#  endif

// defines for TPM1 timer on Teensy-LC
#define TIMER_RESET_INTR_PENDING        FTM1_SC |= FTM_SC_TOF;
#define TIMER_ENABLE_RECEIVE_INTR       NVIC_ENABLE_IRQ(IRQ_FTM1), NVIC_SET_PRIORITY(IRQ_FTM1, 0)
#define TIMER_DISABLE_RECEIVE_INTR      NVIC_DISABLE_IRQ(IRQ_FTM1)
#define TIMER_INTR_NAME                 ftm1_isr
#  ifdef ISR
#undef ISR
#  endif
#define ISR(f) void f(void)

void timerConfigForSend(uint8_t aFrequencyKHz) {
    SIM_SCGC6 |= SIM_SCGC6_TPM1;
    FTM1_SC = 0;
    FTM1_CNT = 0;
    FTM1_MOD = ((F_PLL / 2000) / aFrequencyKHz) - 1;
    FTM1_C0V = ((F_PLL / 6000) / aFrequencyKHz) - 1;
    FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0);
}

void timerConfigForReceive() {
    SIM_SCGC6 |= SIM_SCGC6_TPM1;
    FTM1_SC = 0;
    FTM1_CNT = 0;
    FTM1_MOD = (F_PLL / 40000) - 1;
    FTM1_C0V = 0;
    FTM1_SC = FTM_SC_CLKS(1) | FTM_SC_PS(0) | FTM_SC_TOF | FTM_SC_TOIE;
}

/***************************************
 * Teensy 4.0, 4.1, MicroMod boards
 ***************************************/
#elif defined(__IMXRT1062__)
#  if defined(SEND_PWM_BY_TIMER)
#define IR_SEND_PIN        7
#define ENABLE_SEND_PWM_BY_TIMER        FLEXPWM1_OUTEN |= FLEXPWM_OUTEN_PWMA_EN(8), \
                                        IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 6
#define DISABLE_SEND_PWM_BY_TIMER       IOMUXC_SW_MUX_CTL_PAD_GPIO_B1_00 = 5, \
                                        FLEXPWM1_OUTEN &= ~FLEXPWM_OUTEN_PWMA_EN(8)
#  endif

// defines for FlexPWM1 timer on Teensy 4
#define TIMER_RESET_INTR_PENDING        FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF;
#define TIMER_ENABLE_RECEIVE_INTR       attachInterruptVector(IRQ_FLEXPWM1_3, pwm1_3_isr),\
                                        FLEXPWM1_SM3STS = FLEXPWM_SMSTS_RF, \
                                        FLEXPWM1_SM3INTEN = FLEXPWM_SMINTEN_RIE, \
                                        NVIC_ENABLE_IRQ(IRQ_FLEXPWM1_3), \
                                        NVIC_SET_PRIORITY(IRQ_FLEXPWM1_3, 48)
#define TIMER_DISABLE_RECEIVE_INTR      NVIC_DISABLE_IRQ(IRQ_FLEXPWM1_3)
#define TIMER_INTR_NAME                 pwm1_3_isr
#  ifdef ISR
#undef ISR
#  endif
#define ISR(f) void (f)(void)
void pwm1_3_isr();

void timerConfigForSend(uint8_t aFrequencyKHz) {
    uint32_t period = (float)F_BUS_ACTUAL / (float)((aFrequencyKHz) * 2000);
    uint32_t prescale = 0;
    while (period > 32767) {
        period = period >> 1;
        if (prescale < 7) prescale++;
    }
    FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(8);
    FLEXPWM1_FSTS0 = 0x0008;
    FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
    FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP;
    FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale);
    FLEXPWM1_SM3INIT = -period;
    FLEXPWM1_SM3VAL0 = 0;
    FLEXPWM1_SM3VAL1 = period;
    FLEXPWM1_SM3VAL2 = -(period / 3);
    FLEXPWM1_SM3VAL3 = period / 3;
    FLEXPWM1_SM3VAL4 = 0;
    FLEXPWM1_SM3VAL5 = 0;
    FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8) | FLEXPWM_MCTRL_RUN(8);
}

void timerConfigForReceive() {
    uint32_t period = (float)F_BUS_ACTUAL * (float)(MICROS_PER_TICK) * 0.0000005f;
    uint32_t prescale = 0;
    while (period > 32767) {
        period = period >> 1;
        if (prescale < 7) prescale++;
    }
    FLEXPWM1_FCTRL0 |= FLEXPWM_FCTRL0_FLVL(8);
    FLEXPWM1_FSTS0 = 0x0008;
    FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_CLDOK(8);
    FLEXPWM1_SM3CTRL2 = FLEXPWM_SMCTRL2_INDEP;
    FLEXPWM1_SM3CTRL = FLEXPWM_SMCTRL_HALF | FLEXPWM_SMCTRL_PRSC(prescale);
    FLEXPWM1_SM3INIT = -period;
    FLEXPWM1_SM3VAL0 = 0;
    FLEXPWM1_SM3VAL1 = period;
    FLEXPWM1_SM3VAL2 = 0;
    FLEXPWM1_SM3VAL3 = 0;
    FLEXPWM1_SM3VAL4 = 0;
    FLEXPWM1_SM3VAL5 = 0;
    FLEXPWM1_MCTRL |= FLEXPWM_MCTRL_LDOK(8) | FLEXPWM_MCTRL_RUN(8);
}


#elif defined(ESP8266)
#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   timer1_attachInterrupt(&IRTimerInterruptHandler) // enables interrupt too
#define TIMER_DISABLE_RECEIVE_INTR  timer1_detachInterrupt() // disables interrupt too

// Redefinition of ISR macro which creates a plain function now
#  ifdef ISR
#undef ISR
#  endif
#define ISR() IRAM_ATTR void IRTimerInterruptHandler()
IRAM_ATTR void IRTimerInterruptHandler();

#ifdef SEND_PWM_BY_TIMER
#error "No support for hardware PWM generation for ESP8266"
#endif
void timerConfigForSend(uint8_t aFrequencyKHz) {
    (void) aFrequencyKHz;
}

/*
 * Set timer for interrupts every MICROS_PER_TICK (50 us)
 */
void timerConfigForReceive() {
    timer1_isr_init();
    /*
     * TIM_DIV1 = 0,   //80MHz (80 ticks/us - 104857.588 us max)
     * TIM_DIV16 = 1,  //5MHz (5 ticks/us - 1677721.4 us max)
     * TIM_DIV256 = 3  //312.5Khz (1 tick = 3.2us - 26843542.4 us max)
     */
    timer1_enable(TIM_DIV16, TIM_EDGE, TIM_LOOP);
    timer1_write((80 / 16) * MICROS_PER_TICK); // 80 for 80 and 160! MHz clock, 16 for TIM_DIV16 above
}

/***************************************
 * ESP32 boards - can use any pin for timer
 ***************************************/
#elif defined(ESP32)

#  if ! defined(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL)
#define SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL 0 // The channel used for PWM 0 to 7 are high speed PWM channels
#  endif

#  if defined(SEND_PWM_BY_TIMER)
#    if !defined(IR_SEND_PIN)
#define IR_SEND_PIN 4 // can use any pin, no timer restrictions
#    endif

#define ENABLE_SEND_PWM_BY_TIMER    ledcWrite(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, IR_SEND_DUTY_CYCLE) // we must use channel here not pin number
#define DISABLE_SEND_PWM_BY_TIMER   ledcWrite(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, 0)
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   timerAlarmEnable(sESP32Timer)
#define TIMER_DISABLE_RECEIVE_INTR  if (sESP32Timer != NULL) {timerEnd(sESP32Timer); timerDetachInterrupt(sESP32Timer);}
// Redefinition of ISR macro which creates a plain function now
#  ifdef ISR
#undef ISR
#  endif
#define ISR() IRAM_ATTR void IRTimerInterruptHandler()
IRAM_ATTR void IRTimerInterruptHandler();

// Variables specific to the ESP32.
// the ledc functions behave like hardware timers for us :-), so we do not require our own soft PWM generation code.
hw_timer_t *sESP32Timer;

void timerConfigForSend(uint8_t aFrequencyKHz) {
    ledcSetup(SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL, aFrequencyKHz * 1000, 8);  // 8 bit PWM resolution
#if defined(IR_SEND_PIN)
    ledcAttachPin(IR_SEND_PIN, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL);// bind pin to channel
#else
    ledcAttachPin(IrSender.sendPin, SEND_AND_RECEIVE_TIMER_LEDC_CHANNEL);// bind pin to channel
#endif
}

/*
 * Set timer for interrupts every MICROS_PER_TICK (50 us)
 */
void timerConfigForReceive() {
    // ESP32 has a proper API to setup timers, no weird chip macros needed
    // simply call the readable API versions :)
    // 3 timers, choose #1, 80 divider for microsecond precision @80MHz clock, count_up = true
    sESP32Timer = timerBegin(1, 80, true);
    timerAttachInterrupt(sESP32Timer, &IRTimerInterruptHandler, 1);
    // every 50 us, autoreload = true
    timerAlarmWrite(sESP32Timer, MICROS_PER_TICK, true);
}

/***************************************
 * SAMD boards like DUE and Zero
 ***************************************/
#elif defined(ARDUINO_ARCH_SAMD)
#  if defined(SEND_PWM_BY_TIMER)
#error PWM generation by hardware not implemented for SAMD
#  endif

// use Timer TC3 here
#  if !defined(IR_SAMD_TIMER)
#define IR_SAMD_TIMER       TC3
#define IR_SAMD_TIMER_ID    GCLK_CLKCTRL_ID_TCC2_TC3
#endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   NVIC_EnableIRQ(TC3_IRQn)
#define TIMER_DISABLE_RECEIVE_INTR  NVIC_DisableIRQ(TC3_IRQn) // or TC3->COUNT16.CTRLA.reg &= ~TC_CTRLA_ENABLE;
// Redefinition of ISR macro which creates a plain function now
#  ifdef ISR
#undef ISR
#  endif
#define ISR(f) void IRTimerInterruptHandler(void)
// ATSAMD Timer IRQ functions
void IRTimerInterruptHandler();

#define TIMER_PRESCALER_DIV 64

void setTimerFrequency(unsigned int aFrequencyHz) {
    int compareValue = (F_CPU / (TIMER_PRESCALER_DIV * aFrequencyHz)) - 1;
    //Serial.println(compareValue);
    TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
    TC->COUNT.reg = 0;
    TC->CC[0].reg = compareValue;
    while (TC->STATUS.bit.SYNCBUSY == 1) {
    }
}

/*
 * Set timer for interrupts every MICROS_PER_TICK (50 us)
 */
void timerConfigForReceive() {
    // Clock source is Generic clock generator 0; enable
    REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | IR_SAMD_TIMER_ID);
    while (GCLK->STATUS.bit.SYNCBUSY == 1) {
    }

    TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER; // Timer 3

    // The TC should be disabled before the TC is reset in order to avoid undefined behavior.
    TC->CTRLA.reg &= ~TC_CTRLA_ENABLE;
    // When write-synchronization is ongoing for a register, any subsequent write attempts to this register will be discarded, and an error will be reported.
    while (TC->STATUS.bit.SYNCBUSY == 1) {
    } // wait for sync
      // Reset TCx
    TC->CTRLA.reg = TC_CTRLA_SWRST;
    // When writing a �1� to the CTRLA.SWRST bit it will immediately read as �1�.
    // CTRL.SWRST will be cleared by hardware when the peripheral has been reset.
    while (TC->CTRLA.bit.SWRST) {
    }

    // Use the 16-bit timer
    // Use match mode so that the timer counter resets when the count matches the compare register
    // Set prescaler to 64
    TC->CTRLA.reg |= TC_CTRLA_MODE_COUNT16 | TC_CTRLA_WAVEGEN_MFRQ | TC_CTRLA_PRESCALER_DIV64 | TC_CTRLA_ENABLE;

    setTimerFrequency(MICROS_IN_ONE_SECOND / MICROS_PER_TICK);

    // Enable the compare interrupt
    TC->INTENSET.reg = 0;
    TC->INTENSET.bit.MC0 = 1;
}

void TC3_Handler(void) {
    TcCount16 *TC = (TcCount16*) IR_SAMD_TIMER;
    // Check for right interrupt bit
    if (TC->INTFLAG.bit.MC0 == 1) {
        // reset bit for next turn
        TC->INTFLAG.bit.MC0 = 1;
        IRTimerInterruptHandler();
    }
}

/***************************************
 * Mbed based boards
 ***************************************/
#elif defined(ARDUINO_ARCH_MBED) // Arduino Nano 33 BLE + Sparkfun Apollo3
#include "mbed.h"
#  if defined(SEND_PWM_BY_TIMER)
#error PWM generation by hardware not implemented for MBED
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   sMbedTimer.attach(IRTimerInterruptHandler, std::chrono::microseconds(MICROS_PER_TICK));
#define TIMER_DISABLE_RECEIVE_INTR  sMbedTimer.detach();

// Redefinition of ISR macro which creates a plain function now
#  ifdef ISR
#undef ISR
#  endif
#define ISR() void IRTimerInterruptHandler(void)
void IRTimerInterruptHandler();

mbed::Ticker sMbedTimer;

/*
 * Set timer for interrupts every MICROS_PER_TICK (50 us)
 */
void timerConfigForReceive() {
    sMbedTimer.attach(IRTimerInterruptHandler, std::chrono::microseconds(MICROS_PER_TICK));
}

/***************************************
 * NRF5 boards like the BBC:Micro
 ***************************************/
#elif defined(NRF5) || defined(ARDUINO_ARCH_NRF52840)
#  if defined(SEND_PWM_BY_TIMER)
#error PWM generation by hardware not implemented for NRF5
#  endif

#  if defined(SEND_PWM_BY_TIMER)
// The default pin used used for sending. 3, A0 - left pad
#define IR_SEND_PIN   3 // dummy since sending not yet supported
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   NVIC_EnableIRQ(TIMER2_IRQn);
#define TIMER_DISABLE_RECEIVE_INTR  NVIC_DisableIRQ(TIMER2_IRQn);
#  ifdef ISR
#undef ISR
#  endif
#define ISR(f) void IRTimerInterruptHandler(void)
void IRTimerInterruptHandler();

/*
 * Set timer for interrupts every MICROS_PER_TICK (50 us)
 */
void timerConfigForReceive() {
    NRF_TIMER2->MODE = TIMER_MODE_MODE_Timer;              // Set the timer in Timer Mode
    NRF_TIMER2->TASKS_CLEAR = 1;// clear the task first to be usable for later
    NRF_TIMER2->PRESCALER = 4;// f TIMER = 16 MHz / (2 ^ PRESCALER ) : 4 -> 1 MHz, 1 uS
    NRF_TIMER2->BITMODE = TIMER_BITMODE_BITMODE_16Bit;//Set counter to 16 bit resolution
    NRF_TIMER2->CC[0] = MICROS_PER_TICK;//Set value for TIMER2 compare register 0, to trigger every 50 uS
    NRF_TIMER2->CC[1] = 0;//Set value for TIMER2 compare register 1

    // Enable interrupt on Timer 2, for CC[0] compare match events
    NRF_TIMER2->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos);
    NRF_TIMER2->TASKS_START = 1;// Start TIMER2

    // timerAttachInterrupt(timer, &IRTimerInterruptHandler, 1);
}

/** TIMTER2 peripheral interrupt handler. This interrupt handler is called whenever there it a TIMER2 interrupt
 * Don't mess with this line. really.
 */
extern "C" {
    void TIMER2_IRQHandler(void) {
        // Interrupt Service Routine - Fires every 50uS
        if ((NRF_TIMER2->EVENTS_COMPARE[0] != 0) && ((NRF_TIMER2->INTENSET & TIMER_INTENSET_COMPARE0_Msk) != 0)) {
            NRF_TIMER2->EVENTS_COMPARE[0] = 0;          //Clear compare register 0 event
            IRTimerInterruptHandler();// call the IR-receive function
            NRF_TIMER2->CC[0] += 50;
        }
    }
}

/**********************************************************************************************************************
 * BluePill in 2 flavors see https://samuelpinches.com.au/3d-printer/cutting-through-some-confusion-on-stm32-and-arduino/
 *
 * Recommended original Arduino_STM32 by Roger Clark.
 * http://dan.drown.org/stm32duino/package_STM32duino_index.json
 * STM32F1 architecture for "Generic STM32F103C series" from "STM32F1 Boards (Arduino_STM32)" of Arduino Board manager
 **********************************************************************************************************************/
#elif defined(__STM32F1__) || defined(ARDUINO_ARCH_STM32F1)
#include <HardwareTimer.h> // 4 timers and 4. timer (4.channel) is used for tone()
#  if defined(SEND_PWM_BY_TIMER)
#error PWM generation by hardware not implemented for STM32
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   sSTM32Timer.resume()
#define TIMER_DISABLE_RECEIVE_INTR  sSTM32Timer.pause()

// Redefinition of ISR macro which creates a plain function now
#  ifdef ISR
#undef ISR
#  endif
#define ISR() void IRTimerInterruptHandler(void)
void IRTimerInterruptHandler();

/*
 * Use timer 3 as IR timer.
 * Timer 3 blocks PA6, PA7, PB0, PB1, so if you require one of them as tone() or Servo output, you must choose another timer.
 */
HardwareTimer sSTM32Timer(3);

/*
 * Set timer for interrupts every MICROS_PER_TICK (50 us)
 */
void timerConfigForReceive() {
    sSTM32Timer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
    sSTM32Timer.setPrescaleFactor(1);
    sSTM32Timer.setOverflow((F_CPU / MICROS_IN_ONE_SECOND) * MICROS_PER_TICK);
    sSTM32Timer.attachInterrupt(TIMER_CH1, IRTimerInterruptHandler);
    sSTM32Timer.refresh();
}

/**********************************************************************************************************************
 * STM32duino by ST Microsystems.
 * https://github.com/stm32duino/BoardManagerFiles/raw/master/STM32/package_stm_index.json
 * stm32 architecture for "Generic STM32F1 series" from "STM32 Boards (selected from submenu)" of Arduino Board manager
 **********************************************************************************************************************/
#elif defined(STM32F1xx) || defined(ARDUINO_ARCH_STM32)
#include <HardwareTimer.h> // 4 timers and 3. timer is used for tone(), 2. for Servo
#  if defined(SEND_PWM_BY_TIMER)
#error PWM generation by hardware not implemented for STM32
#  endif

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   sSTM32Timer.resume()
#define TIMER_DISABLE_RECEIVE_INTR  sSTM32Timer.pause()

// Redefinition of ISR macro which creates a plain function now
#  ifdef ISR
#undef ISR
#  endif
#define ISR() void IRTimerInterruptHandler(void)
void IRTimerInterruptHandler();

/*
 * Use timer 4 as IR timer.
 * Timer 4 blocks PB6, PB7, PB8, PB9, so if you need one them as tone() or Servo output, you must choose another timer.
 */
#  if defined(TIM4)
HardwareTimer sSTM32Timer(TIM4);
#  else
HardwareTimer sSTM32Timer(TIM2);
#  endif

/*
 * Set timer for interrupts every MICROS_PER_TICK (50 us)
 */
void timerConfigForReceive() {
    sSTM32Timer.setOverflow(MICROS_PER_TICK, MICROSEC_FORMAT); // 50 uS
    sSTM32Timer.attachInterrupt(IRTimerInterruptHandler);
    sSTM32Timer.resume();
}

/***************************************
 * Particle special IntervalTimer
 * !!!UNTESTED!!!
 ***************************************/
#elif defined(PARTICLE)
#  ifndef __INTERVALTIMER_H__
#include "SparkIntervalTimer.h" // SparkIntervalTimer.h is required if PARTICLE is defined.
#  endif

#  if defined(SEND_PWM_BY_TIMER)
#define IR_SEND_PIN         A5 // Particle supports multiple pins
#    if defined(IR_SEND_PIN)
#define ENABLE_SEND_PWM_BY_TIMER    analogWrite(IR_SEND_PIN, 128, ir_out_kHz*1000)
#define DISABLE_SEND_PWM_BY_TIMER   analogWrite(IR_SEND_PIN, 0, ir_out_kHz*1000)
#    else
#define ENABLE_SEND_PWM_BY_TIMER    analogWrite(IrSender.sendPin, 128, ir_out_kHz*1000)
#define DISABLE_SEND_PWM_BY_TIMER   analogWrite(IrSender.sendPin, 0, ir_out_kHz*1000)
#    endif
#  endif

#  ifndef IR_OUT_KHZ
#define IR_OUT_KHZ          38 // default set to 38 KHz
#  endif

extern IntervalTimer timer;
extern int ir_out_kHz;
//void IRTimerInterruptHandler();

#define TIMER_RESET_INTR_PENDING
#define TIMER_ENABLE_RECEIVE_INTR   timer.begin(IRTimerInterruptHandler, MICROS_PER_TICK, uSec)
#define TIMER_DISABLE_RECEIVE_INTR  timer.end()

// Redefinition of ISR macro which creates a plain function now
#  ifdef ISR
#undef ISR
#  endif
#define ISR() void IRTimerInterruptHandler(void)

void timerConfigForSend(uint8_t aFrequencyKHz) {
    ir_out_kHz = aFrequencyKHz;
}

void timerConfigForReceive() {
}

 /***************************************
  * Unknown CPU coard
  ***************************************/
#else
#error Internal code configuration error, no timer functions implemented for this CPU / board
/*
 * Dummy definitions to avoid more irritating compile errors
 */
#define TIMER_RESET_INTR_PENDING
#define ENABLE_SEND_PWM_BY_TIMER
#define DISABLE_SEND_PWM_BY_TIMER
#define TIMER_ENABLE_RECEIVE_INTR
#define TIMER_DISABLE_RECEIVE_INTR

#  ifdef ISR
#undef ISR
#  endif
#define ISR() void notImplemented(void)

void timerConfigForSend(uint8_t aFrequencyKHz) {
    (void) aFrequencyKHz;
}
void timerConfigForReceive() {
}
#endif // defined(DOXYGEN / CPU_TYPES)

/** @}*/
/** @}*/
#endif // #ifndef IR_TIMER_HPP
#pragma once

how am i suppose to change this? Am i suppose to open a new thread to ask this question?

Okay i figured it out. i was trying to use TIME0 which i guess dont exist. so instead i change from timer 2 to timer 1

// Arduino Mega
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
#  if !defined(IR_USE_AVR_TIMER1) && !defined(IR_USE_AVR_TIMER2) && !defined(IR_USE_AVR_TIMER3) && !defined(IR_USE_AVR_TIMER4) && !defined(IR_USE_AVR_TIMER5)
//#define IR_USE_AVR_TIMER1   // send pin = pin 11
#define IR_USE_AVR_TIMER1     // send pin = pin 9
//#define IR_USE_AVR_TIMER3   // send pin = pin 5
//#define IR_USE_AVR_TIMER4   // send pin = pin 6
//#define IR_USE_AVR_TIMER5   // send pin = pin 46
#  endif

this is in IRTimer.hpp not IRRemoteint.h

now it appears to be working. 

toneAC() looks promising but im afraid its too involved to switch over to this. it looks like it would interfere with IRRemote and requires me to use pins im already using.

Well maybe not interfere with IRRemote because it uses timer1 instead of timer2. but it still requires a specific pin configuration. thanks for the recommendation. it does sound more promising than tone(). but not as flexible

i quoted this from another place,

Disadvantages of using toneAC compared to the standard tone library:

You must use certain pins (9 & 10 on Uno, 11 & 12 on Mega).
Uses two pins instead of one.
Tone duration doesn't run as an interrupt, just a simple delay(). This actually may be an advantage to some for simplicity sake.
But, if you're flexible with your pin choices, this is a great upgrade. It also uses timer 1 instead of timer 2, which may free up a conflict you have with the tone library. It also exclusively uses port registers for the fastest and smallest code possible.

Tim