TimerOne.h Library and getting an exact frequency--ICR1 and Frequency Modes

I am working on a project where I am using 2 PWM signals and want to set the frequency. I am looking to change the frequency from 100Khz up to around 160Khz, possibly as high as 200Khz.

I am using a DF Robot MEGA 2560 board with 16Mhz clock and the ATMega2560 chip. I also have an oscilloscope to verify output frequencies.

I found some code and modified it to make it simpler for testing purposes and am using the TimerOne library and pins 11 and 12 on Timer 1 (16 bit Timer).

Problem:
When I try to change the frequency to say 110Khz I get 111Khz and if I try to get 120 I get 125Khz. I believe this has to do with the ICR1 setting in the library but am not sure. It seems like it is only taking a
whole number and not a decimal. I don't know if ICR1 can accept decimals or not. I am also not sure if I need to modify the library or make some adjustments in my code. I am thinking the ICR1 is limiting my accuracy. I was thinking I could just change the setPeriod to change the frequency and that works but that frequencies are limited.

I have spent about 3 days searching forums and reading through the Atmega PDF document. The parts about the registers are a bit confusing to me and most examples I found weren't done for a Mega2560 chip.

Future Goals:
Have 2 PWM signals on Timer1 at 120Khz and 2 PWM signals on another timer (thinking Timer3) at 150Khz running at the same time.

Thanks for any advice or help!

#include <TimerOne.h>

int pwm_on1 = 11;
int pwm_on2 = 12;
float pwm_duty_cycle1 = 512;
float pwm_duty_cycle2 = 100;
float period_freq = 120000;

void setup()
{
  Timer1.initialize(period_freq);
  Timer1.pwm(11, pwm_duty_cycle1);
  Timer1.pwm(12, pwm_duty_cycle2);
}

void loop()
{
  static float val = 115000;

  Timer1.pwm(11, pwm_duty_cycle1);
  Timer1.pwm(12, pwm_duty_cycle2);
  period_freq = 1000000.0 / val;
  Timer1.setPeriod(period_freq);

}


//////////////////////////////////////////////////////////////////////////////////
Here is part of the TimerOne.h file that I think is relevant.
I can post the whole thing if needed. 
This is not part of my test code. Just posting a part of it for easy access.




#ifndef TimerOne_h_
#define TimerOne_h_

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "config/known_16bit_timers.h"

#define TIMER1_RESOLUTION 65536UL  // Timer1 is 16 bit


// Placing nearly all the code in this .h file allows the functions to be
// inlined by the compiler.  In the very common case with constant values
// the compiler will perform all calculations and simply write constants
// to the hardware registers (for example, setPeriod).


class TimerOne
{


#if defined(__AVR__)
  public:
    //****************************
    //  Configuration
    //****************************
    void initialize(unsigned long microseconds=1000000) __attribute__((always_inline)) {
	TCCR1B = _BV(WGM13);        // set mode as phase and frequency correct pwm, stop the timer
	TCCR1A = 0;                 // clear control register A 
	setPeriod(microseconds);
    }
    void setPeriod(unsigned long microseconds) __attribute__((always_inline)) {
	const unsigned long cycles = (F_CPU / 2000000) * microseconds;
	if (cycles < TIMER1_RESOLUTION) {
		clockSelectBits = _BV(CS10);
		pwmPeriod = cycles;
	} else
	if (cycles < TIMER1_RESOLUTION * 8) {
		clockSelectBits = _BV(CS11);
		pwmPeriod = cycles / 8;
	} else
	if (cycles < TIMER1_RESOLUTION * 64) {
		clockSelectBits = _BV(CS11) | _BV(CS10);  
		pwmPeriod = cycles / 64;
	} else
	if (cycles < TIMER1_RESOLUTION * 256) {
		clockSelectBits = _BV(CS12);
		pwmPeriod = cycles / 256;
	} else
	if (cycles < TIMER1_RESOLUTION * 1024) {
		clockSelectBits = _BV(CS12) | _BV(CS10);
		pwmPeriod = cycles / 1024;
	} else {
		clockSelectBits = _BV(CS12) | _BV(CS10);
		pwmPeriod = TIMER1_RESOLUTION - 1;
	}
	ICR1 = pwmPeriod;
	TCCR1B = _BV(WGM13) | clockSelectBits;
    }

It seems like it is only taking a whole number and not a decimal.

If decimal means floating point, that's correct. As the resulting frequency is built by a prescaler and a counter from the actual CPU clock, not every frequency is exactly possible. If you want optimal results I strongly encourage you not to use higher level libraries but modify the registers directly.

pylon...thank you. Sounds like you are confirming my suspicion that the frequency options were/are being limited by the library itself.

I have searched for hours on how to modify the registers but am still confused in that regard. Most of the examples I found don't use the same chip that I have. Do you have any examples you could share with me or recommend any articles/forums for the AtMega 2560 specifically?

Do you think its possible to get more exact frequencies by modifying the registers?

I was nervous to modify registers as I wasn't sure if it would screw up the board and be permanent.

I have searched for hours on how to modify the registers but am still confused in that regard. Most of the examples I found don't use the same chip that I have. Do you have any examples you could share with me or recommend any articles/forums for the AtMega 2560 specifically?

I recommend the official datasheet.

Do you think its possible to get more exact frequencies by modifying the registers?

Yes, you get more frequencies but maybe not the ones you desire.

I was nervous to modify registers as I wasn't sure if it would screw up the board and be permanent.

To my knowledge you cannot damage the board by simply modifying these registers.