summaryrefslogtreecommitdiff
path: root/cesar/mac/pbproc/src/fc.c
blob: 039b745fdaf19b3b03cdfc2b180184762e1dfec3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
/* Cesar project {{{
 *
 * Copyright (C) 2007 Spidcom
 *
 * <<<Licence>>>
 *
 * }}} */
/**
 * \file    mac/pbproc/src/fc.c
 * \brief   Frame control functions.
 * \ingroup pbproc
 */
#include "common/std.h"

#include "inc/fc.h"

#include "hal/arch/arch.h"

/** Maximum encodable value. */
#define PBPROC_FC_PPB_MAX (((15 + 16) << 14) + (1 << 13))

/**
 * Compute log2 for PPB values.
 * \param  n  integer number
 * \return  logarithm of base 2
 */
static inline uint
pbproc_fc_pbb_log2 (uint n)
{
    dbg_claim (n >= 16 && n < PBPROC_FC_PPB_MAX);
    /* Use the assertion that: 2^18 < 516096 < 2^19, where 516096 is the
     * maximum encodable value. */
    uint a = 4, b = 19, i;
    dbg_claim (1 << (a - 1) < 16 && 16 <= 1 << a);
    dbg_claim (1 << (b - 1) < PBPROC_FC_PPB_MAX
               && PBPROC_FC_PPB_MAX < 1 << b);
    do {
        i = (a + b) / 2;
        if (n < 1u << i)
            b = i;
        else
            a = i;
    } while (a + 1 != b);
    return a;
}

u8 ARCH_ILRAM
pbproc_fc_pbb (uint n)
{
    if (n < 16)
        return n << 4;
    else if (n >= PBPROC_FC_PPB_MAX)
        return 255;
    else
    {
        uint exp, mant;
        exp = pbproc_fc_pbb_log2 (n) - 3;
        mant = 16 * n / (1 << (exp + 3)) - 16;
        return mant << 4 | exp;
    }
}