#include <math.h>
#include <stdlib.h>



static void f_get_baudrate_settings(unsigned uartclk, unsigned long baud_rate, unsigned *dl,
                                    unsigned *fract_div, unsigned *fract_mul) {
    unsigned base_q = 0;
    unsigned i;
    uint32_t best_err = 0xFFFFFFFF;
    uint16_t fda, fdm;
    uint32_t base;

    for (i=0; i < 17; i++) {
        if (uartclk & (1UL << (31-i)))
            break;
        base_q++;
    }

    *fract_div = 0;
    *fract_mul = 1;
    *dl = 1;

    base = (uartclk << (base_q-4));

    baud_rate <<= base_q;

    for (fdm = 1; fdm <= 15; fdm++) {
        for (fda = 0; fda < fdm; fda++) {
            uint32_t err;
            uint32_t f = base * fdm / (uint32_t)(fdm + fda);
            uint32_t udl = (f + baud_rate / 2) / baud_rate;
            if (udl > 0xFFFF)
                continue;
            err = (uint32_t)labs((long)(f / udl) - (long)baud_rate);
            if (err < best_err) {
                best_err = err;
                *fract_div = (uint8_t)fda;
                *fract_mul = (uint8_t)fdm;
                *dl = udl;
            }
        }
    }
}
