Square wave FFT results show frequency that seems too low?
The frequency resolution of your FFT is determined by its length and the sampling rate.

In your second plot you show Fs = 10e6 and 3200 samples. Assuming you don't zero-pad these samples when you pass them to the FFT this gives you a frequency resolution of 3125Hz:

$$ 3215 = \frac{10 \times 10^6}{3200} $$

So at lower frequencies you have frequency bins as 0Hz, 3125Hz, 6250Hz and 9375Hz. The largest peak in the FFT will be in the bin closest to the signal fundamental frequency.

If you want better resolution you either need to capture more samples, or append a load of zeros to the end of your time series (zero-padding).

I would recommend reading about windowing for FFT analysis also, especially if you go down the zero-padding route.

As an aside: the reduce_sample_array function seems to decimate the time series by simply discarding samples. You really should be doing proper down-sampling here, to avoid aliasing.