[ell-i-developers] Re: Interim implementation for SPI.h

  • From: Ivan Raul <supra.material@xxxxxxxxx>
  • To: "ell-i-developers@xxxxxxxxxxxxx" <ell-i-developers@xxxxxxxxxxxxx>
  • Date: Mon, 24 Feb 2014 21:51:04 +0200

Dear all.

This is a possible implementation that I thought for the setClock method.
It is targeted to be efficient in the case that it needs to be used at
runtime.

In general, it tires to set the output frequency to minimize the error of
Abs[(f_wanted - f_possible) / f_wanted]
given a set of prescaler values ranging from 2,4,8,...,128,256
In the case the wanted frequency lies exactly between two possible
frequencies, the lower one is chosen:
wanted 9Mhz, possible1=6Mhz, possible2= 12Mhz -> chosen=6Mhz

I am not sure if it is necessary, but IIRC SystemCoreClock is not a
constant value,
so I am not sure if it can be optimized at compile time. Otherwise it would
be interesting to try to optimize through constexpr.

I am still not sure if passing a uint8_t to a function that expects an enum
is going to work without typecast, but I will check later.

uint32_t setClock(const uint8_t ss_pin, const uint32_t hertz) const {
        extern "C" { extern volatile uint32_t SystemCoreClock; }
        uint32_t outputHertz = SystemCoreClock>>1;
        uint32_t prevOutputHertz = outputHertz;
        uint8_t wantedDivider = 0;
        if (hertz<outputHertz)
        {
            for (wantedDivider=1; wantedDivider < 7; wantedDivider++){
                outputHertz>>=1;
                if (hertz >= outputHertz){
                    uint32_t diff1 = hertz - outputHertz;
                    uint32_t diff2 = prevOutputHertz - hertz;
                    if (diff2<diff1)
                        wantedDivider--;
                    break;
                }
                prevOutputHertz = outputHertz;
            }
        }

        setClockDivider(ss_pin, wantedDivider);
    }

List of output frequencies for a clock of 48Mhz


0               -> div=256, 187500
1000000 -> div=64, 750000
2000000 -> div=32, 1500000
3000000 -> div=16, 3000000
4000000 -> div=16, 3000000
5000000 -> div=8, 6000000
6000000 -> div=8, 6000000
7000000 -> div=8, 6000000
8000000 -> div=8, 6000000
9000000 -> div=8, 6000000
10000000 -> div=4, 12000000
11000000 -> div=4, 12000000
12000000 -> div=4, 12000000
13000000 -> div=4, 12000000
14000000 -> div=4, 12000000
15000000 -> div=4, 12000000
16000000 -> div=4, 12000000
17000000 -> div=4, 12000000
18000000 -> div=4, 12000000
19000000 -> div=2, 24000000
20000000 -> div=2, 24000000
21000000 -> div=2, 24000000
22000000 -> div=2, 24000000
23000000 -> div=2, 24000000
24000000 -> div=2, 24000000
25000000 -> div=2, 24000000
26000000 -> div=2, 24000000

With Warm Regards, Ivan Raul

Other related posts: