вторник, 4 февраля 2014 г.

Debug messages support for C, ver 2

This C module support debug/logging system with custom levels of messages. Suppressing of some level/levels are possible via DBG_LEVEL macro variable. Each custom level is created with DBG_LEVEL_ALIAS() macro. USer can define own print/dump implementations via DBG_PRN_IMPL/DBG_DUMP_IMPL.
#ifndef __DBG_H
#define __DBG_H

#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>

#define DBG_LEVEL_ALIAS(L) (1<<(L))

#ifndef DBG_LEVEL
#define DBG_LEVEL 0
#endif

#ifndef DBG_LEVEL_FMT
#define DBG_LEVEL_FMT "%s: "
#endif

#define _DBG_PRN_IMPL_L(L, F, ...) printf(F, L, __VA_ARGS__)
#define _DBG_PRN_IMPL(F, ...) printf(F, __VA_ARGS__)
#define _DBG_DUMP_IMPL_L(L, p, sz) do { \
    int i; \
    for (i=0; i<(sz); i++) { \
        if (0 == i%16) { \
            DBG_PRN_IMPL("", "%s%s%08" PRIXPTR ": %02X "/*"%s%s%08lX: %02X "*/, i?"\n":"", \
                    16*i/16 + (uintptr_t)p, (uint8_t)(p)[i]); \
        } else if (0 == (i-7)%16) { \
            DBG_PRN_IMPL("", "%s%02X|", (uint8_t)(p)[i]); \
        } else { \
            DBG_PRN_IMPL("", "%s%02X ", (uint8_t)(p)[i]); \
        } \
    } \
    DBG_PRN_IMPL("", "%s%s", "\n"); \
} while (0)
#define _DBG_DUMP_IMPL(p, sz) do { \
    int i; \
    for (i=0; i<(sz); i++) { \
        if (0 == i%16) { \
            DBG_PRN_IMPL("%s%08" PRIXPTR ": %02X "/*"%s%08lX: %02X "*/, i?"\n":"", \
                    16*i/16 + (uintptr_t)p, (uint8_t)(p)[i]); \
        } else if (0 == (i-7)%16) { \
            DBG_PRN_IMPL("%02X|", (uint8_t)(p)[i]); \
        } else { \
            DBG_PRN_IMPL("%02X ", (uint8_t)(p)[i]); \
        } \
    } \
    DBG_PRN_IMPL("%s", "\n"); \
} while (0)

#ifdef DBG_LEVEL_IS_ARG

#ifndef DBG_PRN_IMPL
#define DBG_PRN_IMPL _DBG_PRN_IMPL_L
#endif
#ifndef DBG_DUMP_IMPL
#define DBG_DUMP_IMPL _DBG_DUMP_IMPL_L
#endif

#define DBG_PRN(L, F, ...) if ((DBG_LEVEL) & (L)) DBG_PRN_IMPL(#L, DBG_LEVEL_FMT F, __VA_ARGS__)
#define DBG_DUMP(L, ...) if ((DBG_LEVEL) & (L)) DBG_DUMP_IMPL(#L, __VA_ARGS__)

#else

#ifndef DBG_PRN_IMPL
#define DBG_PRN_IMPL _DBG_PRN_IMPL
#endif
#ifndef DBG_DUMP_IMPL
#define DBG_DUMP_IMPL _DBG_DUMP_IMPL
#endif

#define DBG_PRN(L, ...) if ((DBG_LEVEL) & (L)) DBG_PRN_IMPL(__VA_ARGS__)
#define DBG_DUMP(L, ...) if ((DBG_LEVEL) & (L)) DBG_DUMP_IMPL(__VA_ARGS__)

#endif

/// Print without level
#define DBG_PRN_UL(L, F, ...) if ((DBG_LEVEL) & (L)) DBG_PRN_IMPL("", "%s" F, __VA_ARGS__)

#endif /* EOF */
Usage:
#include <string.h>

// use level name as 1st argument of out DBG_PRN_IMPL
#define DBG_LEVEL_IS_ARG
#define DBG_LEVEL_FMT "[%s] "
#include "dbg.h"

// define levels
#define HARDWARE_LEVEL   DBG_LEVEL_ALIAS(1)
#define WRAPPER_LEVEL   DBG_LEVEL_ALIAS(2)
#define APP_LEVEL       DBG_LEVEL_ALIAS(3)

#undef DBG_LEVEL
#define DBG_LEVEL (HARDWARE_LEVEL|APP_LEVEL)

void main() {
    char dim[] = "0123456789Hello World!";
    DBG_PRN(HARDWARE_LEVEL, "There %d\n", 1);
    DBG_PRN(WRAPPER_LEVEL, "There %d\n", 2);
    DBG_PRN(APP_LEVEL, "There %d\n", 3);
    DBG_DUMP(APP_LEVEL, dim, strlen(dim));
    DBG_PRN_UL(APP_LEVEL, "%s\n", "Done.");
}
Output:
[HARDWARE_LEVEL] There 1
[APP_LEVEL] There 3
0022FEF5: 30 31 32 33 34 35 36 37 38|39 48 65 6C 6C 6F 20
0022FF05: 57 6F 72 6C 64 21
Done.

воскресенье, 2 февраля 2014 г.

Dithering algorithm implemented for IMSH

Today I implemented Dithering algorithms for IMSH (IMage SHell) - see Project WiKi - Dithering. They are: general purpose (see matrixes in imsh.scm library) and special purpose: Atkinson, Floyd-Steinberg, Ordered, Random, General Sierra, General Sierra Two Rows, General Sierra Low, General Floyd-Steinberg, General False Floyd-Steinberg, General Jarvis, General Stucki, General Atkinson, General Burkes.

суббота, 21 декабря 2013 г.

Thread-Safe Circular Queue

Often in data processing applications are needed circular queue implemented in thread-safe way. This is the such implementation without any mutex, locks and so on:
/**
 * @file cqueue.h
 * @defgroup cqueue Circular queue support
 * @{
 * @brief Fast circular queue support
 */
#ifndef _CQUEUE_H
#define _CQUEUE_H

/** It's possible to use another (wrapper) structure or structure with another
name for cqueue implementation. CQUEUE_STRUCT_IMPL should be defined as name
of such structure in this case before to include cqueue.h. This structure
must have members:
 - unsigned integer "size"
 - integer "rpos"
 - integer "wpos"
 - integer "rwrap"
 - integer "wwrap"
 - any other custom fields
*/
#ifdef CQUEUE_STRUCT_IMPL
typedef CQUEUE_STRUCT_IMPL cqueue_t;
#else
/// Circular queue
typedef struct cqueue_t {
    /// Capacity of queue
    unsigned int size;
    /// Reader position
    int rpos;
    /// Writer position
    int wpos;
    /// Reader wrapping flag
    unsigned char rwrap;
    /// Writer wrapping flag
    unsigned char wwrap;
} cqueue_t;

#endif

/** Initializer for circular queue structure instance. Additional args are
needs if separate implementation struct is used */
#define CQUEUE_INITIALIZER(SIZE, ...) { \
    .size = (SIZE), \
    .rpos = 0, \
    .wpos = 0, \
    .wwrap = 0, \
    .rwrap = 0, \
    __VA_ARGS__ }

/// Init. function for queue structure instance
#define CQUEUE_INIT(Q, SIZE) do { \
    (Q)->size = (SIZE); \
    (Q)->rpos = (Q)->wpos = 0; \
    (Q)->wwrap = (Q)->rwrap = 0; \
} while (0)

/// Reset circular queue into initial state
#define CQUEUE_RESET(Q) CQUEUE_INIT(Q, (Q)->size)

/// General position incrementing
#define CQUEUE_INCR(Q, PPOS, PWRAP) do { \
    *(PPOS) = *(PPOS) +1; \
    if (*(PPOS) == (Q)->size) { \
        *(PWRAP) ^= 1; \
        *(PPOS) = 0; \
    } \
} while (0)

/// Reader position (for user-side)
#define CQUEUE_RPOS(Q) ((Q)->rpos)

/// Writer position (for user-side)
#define CQUEUE_WPOS(Q) ((Q)->wpos)

/// Reader position incrementing
#define CQUEUE_INCR_R(Q) do { \
    CQUEUE_INCR(Q, &((Q)->rpos), &((Q)->rwrap)); \
} while (0)

/// Writer position incrementing
#define CQUEUE_INCR_W(Q) do { \
    CQUEUE_INCR(Q, &((Q)->wpos), &((Q)->wwrap)); \
} while (0)

/// Test of circular queue fullness
#define CQUEUE_IS_FULL(Q) \
    ((Q)->wpos == (Q)->rpos && (Q)->rwrap != (Q)->wwrap)

/// Test of circular queue emptiness
#define CQUEUE_IS_EMPTY(Q) \
    ((Q)->wpos == (Q)->rpos && (Q)->rwrap == (Q)->wwrap)

/// Number of free slots in circular queue
#define CQUEUE_NFREE(Q) \
    ((Q)->rwrap == (Q)->wwrap ? \
     ((Q)->size - (Q)->wpos + (Q)->rpos) : \
     ((Q)->rpos - (Q)->wpos))

/// Number of used slots in circular queue
#define CQUEUE_LEN(Q) \
    ((Q)->rwrap != (Q)->wwrap ? \
     ((Q)->size - (Q)->rpos + (Q)->wpos) : \
     ((Q)->wpos - (Q)->rpos))

#endif
/// @}
USe doxygen to gen documentation of this module (it's only one .h-file).

суббота, 2 ноября 2013 г.

Portable effective C bit fields

As you know bit's fields in C are not portable when we're talking about external world (network/different architecture/file transmission): order of the fields is unspecified, also as real wrapper struct...
Often bitwise operations are used instead of bitfield struct syntax but result code may be less readable opposite to original idea: bitfields. But there is simple solution to workaround weird syntax. Here you are:
#define __BITSTRUCT_MASK(LEN) ((1<<(LEN))-1)

#ifndef BITSTRUCT_GETBITS_IMPL
# define BITSTRUCT_GETBITS_IMPL(BS, OFFSET, LEN) \
    (((BS)>>(OFFSET)) & __BITSTRUCT_MASK(LEN))
#endif
#ifndef BITSTRUCT_SETBITS_IMPL
# define BITSTRUCT_SETBITS_IMPL(BS, OFFSET, LEN, VALUE) \
    ((BS) & ~(__BITSTRUCT_MASK(LEN)<<(OFFSET)) | \
     (((VALUE) & __BITSTRUCT_MASK(LEN))<<(OFFSET)))
#endif

#define BITSTRUCT enum
#define BITFIELD(NAME, OFFSET, LEN) NAME##_OFF = (OFFSET), NAME##_LEN=(LEN)
#define BITFIELD_MASK(NAME) __BITSTRUCT_MASK(NAME##_LEN)
#define BITFIELD_GET(NAME, BS) \
  BITSTRUCT_GETBITS_IMPL(BS, NAME##_OFF, NAME##_LEN)
#define BITFIELD_SET(NAME, BS, VALUE) \
  BITSTRUCT_SETBITS_IMPL(BS, NAME##_OFF, NAME##_LEN, VALUE)
So now it's possible to write something like this to describe register X:
|15.....8|7....4|3.....0|
| ENABLE | FLAG | COUNT |
BITSTRUCT RegisterX {
        // BITFIELD(NAME, OFFSET, LENGTH)
        BITFIELD(RX_COUNT, 0, 4),
        BITFIELD(RX_FLAG, 4, 4),
        BITFIELD(RX_ENABLE, 8, 8)
};

int main(void)
{
        int x = 0x1234; // raw value of register
        // example of get/set field of bits' struct
        x = BITFIELD_SET(RX_ENABLE, x, 0x98);
        printf("%0X", BITFIELD_GET(RX_ENABLE, x));
        return (0);
}
As you can see code is readable as in usual bitfield's struct, but instead of struct BITSTRUCT should be used, and BITFIELD() descriptor instead of type NAME:len form. To set or to get field value, use BITFIELD_SET/GET() macros. BITFIELD_MASK() returns mask of field but from zero bit.
But note the *_IMPL macros, using they, you can customize behavior of SET/GET implementation, for example to use some DSP core what can improve program performance dramatically! What you need is only to define own GET/SET helpers-implementators (BITSTRUCT_GETBITS_IMPL/BITSTRUCT_SETBITS_IMPL).