/*! @page q_trace Logging
* @tableofcontents
*
* @section q_trace_overview Overview
* QuarkTS++ includes the qOS::logger class that implements application-level 
* logging. This provides logging APIs based on C++-style streams and various 
* helper macros. You can log a message by simply streaming things to 
* @c logger::out(<a particular severity level>), e.g.. 
* Messages can be simple text or the value of variables in specific base formats. 
*
* To use the qOS::logger class, a single-char output function must be defined using
* the logger::setOutputFcn() function.
*
* A single-char output function should follow this prototype:
*
*  @code{.c}
*  void SingleChar_OutputFcn ( void *sp , const char c ) {
*      /* TODO : print out the c variable using the
*       * selected peripheral.
*       */
*  }
*  @endcode
*
* The body of this user-defined function should have a hardware-dependent code 
* to print out the @c c variable through a specific peripheral.
*
* @section q_trace_viewvars Logging text and variables
* qOS::logger::out() is the api that should be called every time the end user
* needs to write an entry to the log
*
* We can configure the output with whatever severity levels we deem appropriate,
* including : @c info, @c warning, @c error and @c fatal. And also the @c debug and 
* @c verbose can be used to provide additional source-location information.
*
* @section q_trace_mblock Viewing a memory block
* For tracing memory from a specified target address, you should use the qOS::logger::mem()
* specifier to define the number of bytes to be visualized of the memory block 
* that should be given after as a pointer.
*
* @section q_trace_usage Usage
* In the example below, an UART output function is coded to act as the printer.
* Here, the target MCU is an ARM-Cortex M0 with the UART1 as the selected 
* peripheral for this purpose.
*
*  @code{.c}
*  int main( void ) {
*      uint16_t block[ 4 ] = { 451, 477, 1025, 354 };
*      float other = 4.5f;
*
*      logger::setOutputFcn( putUART1 );
*      logger::out() << logger::mem( sizeof(block) ) << block << logger::endl;
*      logger::out() << logger::mem( sizeof(float) ) << &other << logger::endl;
*  }
*  @endcode
*
*  @code{.c}
*  void putUART1 ( void *sp , const char c ) {
*      /* hardware specific code */
*      UART1_D = c;
*      while ( !( UART1_S1 & UART_S1_TC_MASK ) ) {} /*wait until TX is done*/
*  }
*  @endcode
*
* As seen above, the function follows the required prototype. Later, in the 
* main thread, a call to qOS::trace::setOutputFcn() is used to set up the
* output-function.
*
*  @code{.c}
*  int main( void ) {
*      logger::setOutputFcn( putUART1 );
*      ...
*      ...
*  }
*  @endcode
*
* After that, trace macros will be available for use.
*
*  @code{.c}
*  void IO_TASK_Callback ( event_t e ) {
*      static uint32_t Counter = 0;
*      float Sample;
*      ...
*      ...
*      logger::out() << "IO TASK running..." << logger::endl;
*      Counter++;
*      logger::out() << Counter << logger::endl;
*      Sample = SensorGetSample ();
*      logger::out() << Sample << logger::endl;
*      ...
*      ...
*  }
*  @endcode
*
*/