[wip] added encoder
This commit is contained in:
154
firmware/shared_libs/utils/ulog/ulog.c
Normal file
154
firmware/shared_libs/utils/ulog/ulog.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/**
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 R. Dunbar Poor <rdpoor@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file ulog.c
|
||||
*
|
||||
* \brief uLog: lightweight logging for embedded systems
|
||||
*
|
||||
* See ulog.h for sparse documentation.
|
||||
*/
|
||||
|
||||
#include "ulog.h"
|
||||
|
||||
#ifdef ULOG_ENABLED // whole file...
|
||||
|
||||
// #include <stdio.h>
|
||||
#include "printf.h"
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// =============================================================================
|
||||
// types and definitions
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ulog_function_t fn;
|
||||
ulog_level_t threshold;
|
||||
} subscriber_t;
|
||||
|
||||
// =============================================================================
|
||||
// local storage
|
||||
|
||||
static subscriber_t s_subscribers[ULOG_MAX_SUBSCRIBERS];
|
||||
static char s_message[ULOG_MAX_MESSAGE_LENGTH];
|
||||
|
||||
// =============================================================================
|
||||
// user-visible code
|
||||
|
||||
void ulog_init()
|
||||
{
|
||||
memset(s_subscribers, 0, sizeof(s_subscribers));
|
||||
}
|
||||
|
||||
// search the s_subscribers table to install or update fn
|
||||
ulog_err_t ulog_subscribe(ulog_function_t fn, ulog_level_t threshold)
|
||||
{
|
||||
int available_slot = -1;
|
||||
int i;
|
||||
for (i = 0; i < ULOG_MAX_SUBSCRIBERS; i++)
|
||||
{
|
||||
if (s_subscribers[i].fn == fn)
|
||||
{
|
||||
// already subscribed: update threshold and return immediately.
|
||||
s_subscribers[i].threshold = threshold;
|
||||
return ULOG_ERR_NONE;
|
||||
}
|
||||
else if (s_subscribers[i].fn == NULL)
|
||||
{
|
||||
// found a free slot
|
||||
available_slot = i;
|
||||
}
|
||||
}
|
||||
// fn is not yet a subscriber. assign if possible.
|
||||
if (available_slot == -1)
|
||||
{
|
||||
return ULOG_ERR_SUBSCRIBERS_EXCEEDED;
|
||||
}
|
||||
s_subscribers[available_slot].fn = fn;
|
||||
s_subscribers[available_slot].threshold = threshold;
|
||||
return ULOG_ERR_NONE;
|
||||
}
|
||||
|
||||
// search the s_subscribers table to remove
|
||||
ulog_err_t ulog_unsubscribe(ulog_function_t fn)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ULOG_MAX_SUBSCRIBERS; i++)
|
||||
{
|
||||
if (s_subscribers[i].fn == fn)
|
||||
{
|
||||
s_subscribers[i].fn = NULL; // mark as empty
|
||||
return ULOG_ERR_NONE;
|
||||
}
|
||||
}
|
||||
return ULOG_ERR_NOT_SUBSCRIBED;
|
||||
}
|
||||
|
||||
const char *ulog_level_name(ulog_level_t severity)
|
||||
{
|
||||
switch (severity)
|
||||
{
|
||||
case ULOG_TRACE_LEVEL:
|
||||
return "TRACE";
|
||||
case ULOG_DEBUG_LEVEL:
|
||||
return "DEBUG";
|
||||
case ULOG_INFO_LEVEL:
|
||||
return "INFO";
|
||||
case ULOG_WARNING_LEVEL:
|
||||
return "WARNING";
|
||||
case ULOG_ERROR_LEVEL:
|
||||
return "ERROR";
|
||||
case ULOG_CRITICAL_LEVEL:
|
||||
return "CRITICAL";
|
||||
case ULOG_ALWAYS_LEVEL:
|
||||
return "ALWAYS";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void ulog_message(ulog_level_t severity, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int i;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(s_message, ULOG_MAX_MESSAGE_LENGTH, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
for (i = 0; i < ULOG_MAX_SUBSCRIBERS; i++)
|
||||
{
|
||||
if (s_subscribers[i].fn != NULL)
|
||||
{
|
||||
if (severity >= s_subscribers[i].threshold)
|
||||
{
|
||||
s_subscribers[i].fn(severity, s_message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// private code
|
||||
|
||||
#endif // #ifdef ULOG_ENABLED
|
||||
188
firmware/shared_libs/utils/ulog/ulog.h
Normal file
188
firmware/shared_libs/utils/ulog/ulog.h
Normal file
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 R. Dunbar Poor <rdpoor@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief uLog: lightweight logging for embedded systems
|
||||
*
|
||||
* A quick intro by example:
|
||||
*
|
||||
* #include "ulog.h"
|
||||
*
|
||||
* // To use uLog, you must define a function to process logging messages.
|
||||
* // It can write the messages to a console, to a file, to an in-memory
|
||||
* // buffer: the choice is yours. And you get to choose the format of
|
||||
* // the message. This example prints to the console. One caveat: msg
|
||||
* // is a static string and will be over-written at the next call to ULOG.
|
||||
* // You may print it or copy it, but saving a pointer to it will lead to
|
||||
* // confusion and astonishment.
|
||||
* //
|
||||
* void my_console_logger(ulog_level_t level, const char *msg) {
|
||||
* printf("%s [%s]: %s\n",
|
||||
* get_timestamp(),
|
||||
* ulog_level_name(level),
|
||||
* msg);
|
||||
* }
|
||||
*
|
||||
* int main() {
|
||||
* ULOG_INIT();
|
||||
*
|
||||
* // log to the console messages that are WARNING or more severe. You
|
||||
* // can re-subscribe at any point to change the severity level.
|
||||
* ULOG_SUBSCRIBE(my_console_logger, ULOG_WARNING);
|
||||
*
|
||||
* // log to a file messages that are DEBUG or more severe
|
||||
* ULOG_SUBSCRIBE(my_file_logger, ULOG_DEBUG);
|
||||
*
|
||||
* int arg = 42;
|
||||
* ULOG_INFO("Arg is %d", arg); // logs to file but not console
|
||||
* }
|
||||
*/
|
||||
|
||||
#ifndef ULOG_H_
|
||||
#define ULOG_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ULOG_TRACE_LEVEL = 100,
|
||||
ULOG_DEBUG_LEVEL,
|
||||
ULOG_INFO_LEVEL,
|
||||
ULOG_WARNING_LEVEL,
|
||||
ULOG_ERROR_LEVEL,
|
||||
ULOG_CRITICAL_LEVEL,
|
||||
ULOG_ALWAYS_LEVEL
|
||||
} ulog_level_t;
|
||||
|
||||
// The following macros enable or disable uLog. If `ULOG_ENABLED` is
|
||||
// defined at compile time, a macro such as `ULOG_INFO(...)` expands
|
||||
// into `ulog_message(ULOG_INFO_LEVEL, ...)`. If `ULOG_ENABLED` is not
|
||||
// defined, then the same macro expands into `do {} while(0)` and will
|
||||
// not generate any code at all.
|
||||
//
|
||||
// There are two ways to enable uLog: you can uncomment the following
|
||||
// line, or -- if it is commented out -- you can add -DULOG_ENABLED to
|
||||
// your compiler switches.
|
||||
// #define ULOG_ENABLED
|
||||
|
||||
#ifdef ULOG_ENABLED
|
||||
#define ULOG_INIT() ulog_init()
|
||||
#define ULOG_SUBSCRIBE(a, b) ulog_subscribe(a, b)
|
||||
#define ULOG_UNSUBSCRIBE(a) ulog_unsubscribe(a)
|
||||
#define ULOG_LEVEL_NAME(a) ulog_level_name(a)
|
||||
#define ULOG(...) ulog_message(__VA_ARGS__)
|
||||
#define ULOG_TRACE(...) ulog_message(ULOG_TRACE_LEVEL, __VA_ARGS__)
|
||||
#define ULOG_DEBUG(...) ulog_message(ULOG_DEBUG_LEVEL, __VA_ARGS__)
|
||||
#define ULOG_INFO(...) ulog_message(ULOG_INFO_LEVEL, __VA_ARGS__)
|
||||
#define ULOG_WARNING(...) ulog_message(ULOG_WARNING_LEVEL, __VA_ARGS__)
|
||||
#define ULOG_ERROR(...) ulog_message(ULOG_ERROR_LEVEL, __VA_ARGS__)
|
||||
#define ULOG_CRITICAL(...) ulog_message(ULOG_CRITICAL_LEVEL, __VA_ARGS__)
|
||||
#define ULOG_ALWAYS(...) ulog_message(ULOG_ALWAYS_LEVEL, __VA_ARGS__)
|
||||
#else
|
||||
// uLog vanishes when disabled at compile time...
|
||||
#define ULOG_INIT() \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG_SUBSCRIBE(a, b) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG_UNSUBSCRIBE(a) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG_LEVEL_NAME(a) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG(s, f, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG_TRACE(f, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG_DEBUG(f, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG_INFO(f, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG_WARNING(f, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG_ERROR(f, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG_CRITICAL(f, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#define ULOG_ALWAYS(f, ...) \
|
||||
do \
|
||||
{ \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ULOG_ERR_NONE = 0,
|
||||
ULOG_ERR_SUBSCRIBERS_EXCEEDED,
|
||||
ULOG_ERR_NOT_SUBSCRIBED,
|
||||
} ulog_err_t;
|
||||
|
||||
// define the maximum number of concurrent subscribers
|
||||
#ifndef ULOG_MAX_SUBSCRIBERS
|
||||
#define ULOG_MAX_SUBSCRIBERS 6
|
||||
#endif
|
||||
// maximum length of formatted log message
|
||||
#ifndef ULOG_MAX_MESSAGE_LENGTH
|
||||
#define ULOG_MAX_MESSAGE_LENGTH 120
|
||||
#endif
|
||||
/**
|
||||
* @brief: prototype for uLog subscribers.
|
||||
*/
|
||||
typedef void (*ulog_function_t)(ulog_level_t severity, char *msg);
|
||||
|
||||
void ulog_init(void);
|
||||
ulog_err_t ulog_subscribe(ulog_function_t fn, ulog_level_t threshold);
|
||||
ulog_err_t ulog_unsubscribe(ulog_function_t fn);
|
||||
const char *ulog_level_name(ulog_level_t level);
|
||||
void ulog_message(ulog_level_t severity, const char *fmt, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ULOG_H_ */
|
||||
Reference in New Issue
Block a user