Import mware modules.
authorbernie <bernie@38d2e660-2303-0410-9eaa-f027e97ec537>
Sun, 23 May 2004 15:43:16 +0000 (15:43 +0000)
committerbernie <bernie@38d2e660-2303-0410-9eaa-f027e97ec537>
Sun, 23 May 2004 15:43:16 +0000 (15:43 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@1 38d2e660-2303-0410-9eaa-f027e97ec537

14 files changed:
mware/fifobuf.c [new file with mode: 0755]
mware/fifobuf.h [new file with mode: 0755]
mware/font.c [new file with mode: 0755]
mware/font.h [new file with mode: 0755]
mware/formatwr.c [new file with mode: 0755]
mware/formatwr.h [new file with mode: 0755]
mware/gfx.c [new file with mode: 0755]
mware/gfx.h [new file with mode: 0755]
mware/list.c [new file with mode: 0755]
mware/list.h [new file with mode: 0755]
mware/sprintf.c [new file with mode: 0755]
mware/text.c [new file with mode: 0755]
mware/text.h [new file with mode: 0755]
mware/text_format.c [new file with mode: 0755]

diff --git a/mware/fifobuf.c b/mware/fifobuf.c
new file mode 100755 (executable)
index 0000000..6f6340e
--- /dev/null
@@ -0,0 +1,137 @@
+/*!
+ * \file
+ * <!--
+ * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
+ * Copyright (C) 2001 Bernardo Innocenti <bernie@develer.com>
+ * All Rights Reserved.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ *
+ * \brief FIFO buffer handling routines
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ */
+
+#include "fifobuf.h"
+#include "compiler.h"
+#include <drv/kdebug.h>
+
+void fifo_init(volatile FIFOBuffer *fb, unsigned char *buf, size_t size)
+{
+       fb->head = fb->tail = fb->begin = buf;
+       fb->end = buf + size - 1;
+}
+
+
+/*!
+ * Pop a character from the fifo buffer.
+ *
+ * \note Calling \c fifo_push() on a full buffer is undefined.
+ *       The caller must make sure the buffer has at least
+ *       one free slot before calling this function.
+ *
+ * \note It is safe to call fifo_pop() and fifo_push() from
+ *       concurrent contexts.
+ */
+void fifo_push(volatile FIFOBuffer *fb, unsigned char c)
+{
+#pragma interrupt called
+       /* Write at tail position */
+       *(fb->tail) = c;
+
+       if (fb->tail == fb->end)
+               /* wrap tail around */
+               fb->tail = fb->begin;
+       else
+               /* Move tail forward */
+               fb->tail++;
+}
+
+/*!
+ * Pop a character from the fifo buffer.
+ *
+ * \note Calling \c fifo_pop() on an empty buffer is undefined.
+ *       The caller must make sure the buffer contains at least
+ *       one character before calling this function.
+ *
+ * \note It is safe to call fifo_pop() and fifo_push() from
+ *       concurrent contexts.
+ */
+unsigned char fifo_pop(volatile FIFOBuffer *fb)
+{
+#pragma interrupt called
+       if (fb->head == fb->end)
+       {
+               /* wrap head around */
+               fb->head = fb->begin;
+               return *(fb->end);
+       }
+       else
+               /* move head forward */
+               return *(fb->head++);
+}
+
+
+#if 0
+
+/* untested */
+void fifo_pushblock(volatile FIFOBuffer *fb, unsigned char *block, size_t len)
+{
+       size_t freelen;
+
+       /* Se c'e' spazio da tail alla fine del buffer */
+       if (fb->tail >= fb->head)
+       {
+               freelen = fb->end - fb->tail + 1;
+
+               /* C'e' abbastanza spazio per scrivere tutto il blocco? */
+               if (freelen < len)
+               {
+                       /* Scrivi quello che entra fino alla fine del buffer */
+                       memcpy(fb->tail, block, freelen);
+                       block += freelen;
+                       len -= freelen;
+                       fb->tail = fb->begin;
+               }
+               else
+               {
+                       /* Scrivi tutto il blocco */
+                       memcpy(fb->tail, block, len);
+                       fb->tail += len;
+                       return;
+               }
+       }
+
+       for(;;)
+       {
+               while (!(freelen = fb->head - fb->tail - 1))
+                       Delay(FIFO_POLLDELAY);
+
+               /* C'e' abbastanza spazio per scrivere tutto il blocco? */
+               if (freelen < len)
+               {
+                       /* Scrivi quello che entra fino alla fine del buffer */
+                       memcpy(fb->tail, block, freelen);
+                       block += freelen;
+                       len -= freelen;
+                       fb->tail += freelen;
+               }
+               else
+               {
+                       /* Scrivi tutto il blocco */
+                       memcpy(fb->tail, block, len);
+                       fb->tail += len;
+                       return;
+               }
+       }
+}
+
+#endif /* UNUSED */
diff --git a/mware/fifobuf.h b/mware/fifobuf.h
new file mode 100755 (executable)
index 0000000..1cbd89d
--- /dev/null
@@ -0,0 +1,172 @@
+/*!
+ * \file
+ * <!--
+ * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
+ * Copyright (C) 2001 Bernardo Innocenti <bernie@develer.com>
+ * All Rights Reserved.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ *
+ * \brief General pourpose FIFO buffer implemented with a ring buffer
+ *
+ * \li \c begin punta al primo elemento del buffer,
+ * \li \c end punta all'ultimo elemento,
+ * \li \c head punta al prossimo elemento che verra' estratto,
+ * \li \c tail punta alla posizione successiva all'ultimo elemento inserito.
+ * \li quando uno dei due puntatori raggiunge @c end, viene resettato a @c begin.
+ *
+ * <pre>
+ *
+ *  +-----------------------------------+
+ *  |  vuoto  |   dati validi  |  vuoto |
+ *  +-----------------------------------+
+ *  ^         ^                ^        ^
+ *  begin    head             tail     end
+ *
+ * </pre>
+ *
+ * Il buffer e' VUOTO quando head e tail coincidono:
+ *             \code head == tail \endcode
+ *
+ * Il buffer e' PIENO quando tail si trova immediatamente dietro a head:
+ *             \code tail == head - 1 \endcode
+ *
+ * Il buffer e' PIENO anche quando tail e' posizionato
+ * sull'ultima posizione del buffer e head sulla prima:
+ *             \code head == begin && tail == end \endcode
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ * Revision 1.3  2004/05/22 17:55:58  rasky
+ * \samp non esiste in doxygen
+ *
+ * Revision 1.2  2004/04/27 11:13:29  rasky
+ * Spostate tutte le definizioni CPU-specific da compiler.h nel nuovo file cpu.h
+ *
+ * Revision 1.1  2004/04/21 17:38:25  rasky
+ * New application
+ *
+ * Revision 1.4  2004/03/24 15:37:03  bernie
+ * Remove Copyright messages from Doxygen output
+ *
+ * Revision 1.3  2004/03/18 18:11:07  bernie
+ * Add thread-safe FIFO handling macros
+ *
+ * Revision 1.2  2004/03/01 08:00:36  bernie
+ * Fixes for Doxygen
+ *
+ * Revision 1.1  2003/12/07 04:04:20  bernie
+ * Initial project_ks framework.
+ *
+ * Revision 1.1  2003/11/21 16:36:17  aleph
+ * Rename from fifo to fifobuf to avoid conflict with BSP fifo.h header
+ *
+ * Revision 1.1  2003/11/20 22:17:41  aleph
+ * Add fifo buffer used by serial
+ *
+ */
+
+#ifndef MWARE_FIFO_H
+#define MWARE_FIFO_H
+
+#include "cpu.h"
+#ifndef COMPILER_H
+#include "compiler.h"
+#endif
+
+typedef struct FIFOBuffer
+{
+       unsigned char *head;
+       unsigned char *tail;
+       unsigned char *begin;
+       unsigned char *end;
+} FIFOBuffer;
+
+/* Public function prototypes */
+void fifo_init(volatile FIFOBuffer *fb, unsigned char *buf, size_t size);
+
+#pragma interrupt called
+void fifo_push(volatile FIFOBuffer *fb, unsigned char c);
+
+#pragma interrupt called
+unsigned char fifo_pop(volatile FIFOBuffer *fb);
+
+
+/*!
+ * Check whether the fifo is empty
+ *
+ * \note Calling fifo_isempty() is safe while a concurrent
+ *       execution context is calling fifo_push() or fifo_pop()
+ *       only if the CPU can atomically update a pointer.
+ */
+#define fifo_isempty(fb)       ((fb)->head == (fb)->tail)
+
+/*!
+ * Check whether the fifo is full
+ *
+ * \note Calling fifo_isfull() is safe while a concurrent
+ *       execution context is calling fifo_pop() and the
+ *       CPU can update a pointer atomically.
+ *       It is NOT safe when the other context calls
+ *       fifo_push().
+ *       This limitation is not usually problematic in a
+ *       consumer/producer scenario because the
+ *       fifo_isfull() and fifo_push() are usually called
+ *       in the producer context.
+ */
+#define fifo_isfull(fb) \
+       ((((fb)->head == (fb)->begin) && ((fb)->tail == (fb)->end)) \
+       || ((fb)->tail == (fb)->head - 1))
+
+/*!
+ * Make the fifo empty, discarding all its current contents.
+ */
+#define fifo_flush(fb) ((fb)->head = (fb)->tail)
+
+#if !defined(__AVR__)
+
+       /* No tricks needed on 16/32bit CPUs */
+#      define fifo_isempty_locked(fb) fifo_isempty((fb))
+
+#else /* !__AVR__ */
+
+       INLINE bool fifo_isempty_locked(const volatile FIFOBuffer *_fb);
+       INLINE bool fifo_isempty_locked(const volatile FIFOBuffer *_fb)
+       {
+               bool _result;
+               cpuflags_t _flags;
+
+               DISABLE_IRQSAVE(_flags);
+               _result = fifo_isempty(_fb);
+               ENABLE_IRQRESTORE(_flags);
+
+               return _result;
+       }
+
+#endif /* !__AVR__ */
+
+/*!
+ * Thread safe version of fifo_isfull()
+ */
+INLINE bool fifo_isfull_locked(const volatile FIFOBuffer *_fb);
+INLINE bool fifo_isfull_locked(const volatile FIFOBuffer *_fb)
+{
+       bool _result;
+       cpuflags_t _flags;
+
+       DISABLE_IRQSAVE(_flags);
+       _result = fifo_isfull(_fb);
+       ENABLE_IRQRESTORE(_flags);
+
+       return _result;
+}
+
+#endif /* MWARE_FIFOBUF_H */
+
diff --git a/mware/font.c b/mware/font.c
new file mode 100755 (executable)
index 0000000..58e00e0
--- /dev/null
@@ -0,0 +1,330 @@
+/*!
+ * \file
+ * <!--
+ * Copyright (C) 2001 Bernardo Innocenti <bernie@codewiz.org>
+ * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ *
+ * \brief Font 8x6 IBM-PC 8bit
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ * Revision 1.5  2004/03/24 15:48:53  bernie
+ * Remove Copyright messages from Doxygen output
+ *
+ * Revision 1.4  2004/03/03 18:30:17  bernie
+ * Substitute left triangle glyph with left arrow
+ *
+ * Revision 1.3  2004/02/28 14:48:33  aleph
+ * Improve arrow glyphs
+ *
+ * Revision 1.2  2004/01/13 12:15:28  aleph
+ * Move font table in program memory; add font.h
+ *
+ * Revision 1.1  2004/01/07 23:31:54  aleph
+ * Add text routines
+ *
+ */
+
+#include "font.h"
+
+const prog_uchar font[256 * 6] =
+{
+/* 0x00 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*   */
+       0x3E, 0x45, 0x51, 0x45, 0x3E, 0x00, /*   */
+       0x3E, 0x7B, 0x6F, 0x7B, 0x3E, 0x00, /*   */
+       0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 0x00, /*   */
+       0x08, 0x1C, 0x3E, 0x1C, 0x08, 0x00, /*   */
+       0x18, 0x5A, 0x67, 0x5A, 0x18, 0x00, /*   */
+       0x0C, 0x5E, 0x6F, 0x5E, 0x0C, 0x00, /*   */
+       0x08, 0x1C, 0x3E, 0x1C, 0x08, 0x00, /*   */
+/* 0x08 */
+       0x77, 0x63, 0x41, 0x63, 0x77, 0x00, /*   */
+       0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00, /*   */
+       0x77, 0x63, 0x41, 0x63, 0x77, 0x00, /*   */
+       0x20, 0x50, 0x5A, 0x56, 0x2E, 0x00, /*   */
+       0x06, 0x29, 0x79, 0x29, 0x06, 0x00, /*   */
+       0x60, 0x60, 0x7F, 0x05, 0x07, 0x00, /*   */
+       0x18, 0x1F, 0x01, 0x61, 0x7F, 0x00, /*   */
+       0x15, 0x0E, 0x1B, 0x0E, 0x15, 0x00, /*   */
+/* 0x10 */
+       0x00, 0x08, 0x1C, 0x3E, 0x08, 0x08, /*   */
+       0x7F, 0x3E, 0x1C, 0x08, 0x00, 0x00, /*   */
+       0x14, 0x36, 0x7F, 0x36, 0x14, 0x00, /*   */
+       0x00, 0x5F, 0x00, 0x5F, 0x00, 0x00, /*   */
+       0x02, 0x05, 0x7F, 0x01, 0x7F, 0x00, /*   */
+       0x20, 0x4A, 0x55, 0x29, 0x02, 0x00, /*   */
+       0x60, 0x60, 0x60, 0x60, 0x60, 0x00, /*   */
+       0x54, 0x76, 0x7F, 0x76, 0x54, 0x00, /*   */
+/* 0x18 */
+       0x08, 0x0C, 0x7E, 0x0C, 0x08, 0x00, /*   */
+       0x10, 0x30, 0x7E, 0x30, 0x10, 0x00, /*   */
+       0x08, 0x08, 0x3E, 0x1C, 0x08, 0x00, /*   */
+       0x08, 0x1C, 0x3E, 0x08, 0x08, 0x00, /*   */
+       0x1C, 0x10, 0x10, 0x10, 0x10, 0x00, /*   */
+       0x08, 0x1C, 0x08, 0x1C, 0x08, 0x00, /*   */
+       0x18, 0x1C, 0x1E, 0x1C, 0x18, 0x00, /*   */
+       0x0C, 0x1C, 0x3C, 0x1C, 0x0C, 0x00, /*   */
+/* 0x20 */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*   */
+       0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, /* ! */
+       0x00, 0x07, 0x00, 0x07, 0x00, 0x00, /* " */
+       0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, /* # */
+       0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, /* $ */
+       0x63, 0x13, 0x08, 0x64, 0x63, 0x00, /* % */
+       0x36, 0x49, 0x55, 0x22, 0x50, 0x00, /* & */
+       0x00, 0x05, 0x03, 0x00, 0x00, 0x00, /* ' */
+/* 0x28 */
+       0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, /* ( */
+       0x00, 0x00, 0x41, 0x22, 0x1C, 0x00, /* ) */
+       0x14, 0x08, 0x3E, 0x08, 0x14, 0x00, /* * */
+       0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, /* + */
+       0x00, 0x50, 0x30, 0x00, 0x00, 0x00, /* , */
+       0x08, 0x08, 0x08, 0x08, 0x08, 0x00, /* - */
+       0x00, 0x60, 0x60, 0x00, 0x00, 0x00, /* . */
+       0x20, 0x10, 0x08, 0x04, 0x02, 0x00, /* / */
+/* 0x30 */
+       0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, /* 0 */
+       0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, /* 1 */
+       0x62, 0x51, 0x49, 0x49, 0x46, 0x00, /* 2 */
+       0x21, 0x41, 0x45, 0x4B, 0x31, 0x00, /* 3 */
+       0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, /* 4 */
+       0x27, 0x45, 0x45, 0x45, 0x39, 0x00, /* 5 */
+       0x3C, 0x4A, 0x49, 0x49, 0x30, 0x00, /* 6 */
+       0x01, 0x71, 0x09, 0x05, 0x03, 0x00, /* 7 */
+/* 0x38 */
+       0x36, 0x49, 0x49, 0x49, 0x36, 0x00, /* 8 */
+       0x06, 0x49, 0x49, 0x29, 0x1E, 0x00, /* 9 */
+       0x00, 0x36, 0x36, 0x00, 0x00, 0x00, /* : */
+       0x00, 0x56, 0x36, 0x00, 0x00, 0x00, /* ; */
+       0x08, 0x14, 0x22, 0x41, 0x00, 0x00, /* < */
+       0x14, 0x14, 0x14, 0x14, 0x14, 0x00, /* = */
+       0x00, 0x41, 0x22, 0x14, 0x08, 0x00, /* > */
+       0x02, 0x01, 0x51, 0x09, 0x06, 0x00, /* ? */
+/* 0x40 */
+       0x32, 0x49, 0x79, 0x41, 0x3E, 0x00, /* @ */
+       0x7E, 0x09, 0x09, 0x09, 0x7E, 0x00, /* A */
+       0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, /* B */
+       0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, /* C */
+       0x7F, 0x41, 0x41, 0x22, 0x1C, 0x00, /* D */
+       0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, /* E */
+       0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, /* F */
+       0x3E, 0x41, 0x49, 0x49, 0x7A, 0x00, /* G */
+/* 0x48 */
+       0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, /* H */
+       0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, /* I */
+       0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, /* J */
+       0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, /* K */
+       0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, /* L */
+       0x7F, 0x02, 0x0C, 0x02, 0x7F, 0x00, /* M */
+       0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, /* N */
+       0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, /* O */
+/* 0x50 */
+       0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, /* P */
+       0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, /* Q */
+       0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, /* R */
+       0x26, 0x49, 0x49, 0x49, 0x32, 0x00, /* S */
+       0x01, 0x01, 0x7F, 0x01, 0x01, 0x00, /* T */
+       0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, /* U */
+       0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, /* V */
+       0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, /* W */
+/* 0x58 */
+       0x63, 0x14, 0x08, 0x14, 0x63, 0x00, /* X */
+       0x07, 0x08, 0x70, 0x08, 0x07, 0x00, /* Y */
+       0x61, 0x51, 0x49, 0x45, 0x43, 0x00, /* Z */
+       0x00, 0x7F, 0x41, 0x41, 0x00, 0x00, /* [ */
+       0x02, 0x04, 0x08, 0x10, 0x20, 0x00, /* \ */
+       0x00, 0x41, 0x41, 0x7F, 0x00, 0x00, /* ] */
+       0x04, 0x02, 0x01, 0x02, 0x04, 0x00, /* ^ */
+       0x40, 0x40, 0x40, 0x40, 0x40, 0x00, /* _ */
+/* 0x60 */
+       0x00, 0x01, 0x02, 0x04, 0x00, 0x00, /* ` */
+       0x00, 0x74, 0x54, 0x54, 0x78, 0x00, /* a */
+       0x7F, 0x44, 0x44, 0x44, 0x38, 0x00, /* b */
+       0x38, 0x44, 0x44, 0x44, 0x28, 0x00, /* c */
+       0x38, 0x44, 0x44, 0x44, 0x7F, 0x00, /* d */
+       0x38, 0x54, 0x54, 0x54, 0x18, 0x00, /* e */
+       0x08, 0x7E, 0x09, 0x01, 0x02, 0x00, /* f */
+       0x08, 0x54, 0x54, 0x54, 0x3C, 0x00, /* g */
+/* 0x68 */
+       0x7F, 0x04, 0x04, 0x04, 0x78, 0x00, /* h */
+       0x00, 0x44, 0x7D, 0x40, 0x00, 0x00, /* i */
+       0x20, 0x40, 0x44, 0x3D, 0x00, 0x00, /* j */
+       0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, /* k */
+       0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, /* l */
+       0x7C, 0x04, 0x18, 0x04, 0x78, 0x00, /* m */
+       0x7C, 0x08, 0x04, 0x04, 0x78, 0x00, /* n */
+       0x38, 0x44, 0x44, 0x44, 0x38, 0x00, /* o */
+/* 0x70 */
+       0x7C, 0x14, 0x14, 0x14, 0x08, 0x00, /* p */
+       0x08, 0x14, 0x14, 0x14, 0x7C, 0x00, /* q */
+       0x7C, 0x08, 0x04, 0x04, 0x08, 0x00, /* r */
+       0x48, 0x54, 0x54, 0x54, 0x24, 0x00, /* s */
+       0x04, 0x3F, 0x44, 0x40, 0x20, 0x00, /* t */
+       0x3C, 0x40, 0x40, 0x20, 0x7C, 0x00, /* u */
+       0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, /* v */
+       0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, /* w */
+/* 0x78 */
+       0x44, 0x28, 0x10, 0x28, 0x44, 0x00, /* x */
+       0x0C, 0x50, 0x50, 0x50, 0x3C, 0x00, /* y */
+       0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, /* z */
+       0x00, 0x08, 0x36, 0x41, 0x00, 0x00, /* { */
+       0x00, 0x00, 0x77, 0x00, 0x00, 0x00, /* | */
+       0x00, 0x41, 0x36, 0x08, 0x00, 0x00, /* } */
+       0x02, 0x01, 0x02, 0x01, 0x00, 0x00, /* ~ */
+       0x70, 0x48, 0x44, 0x48, 0x70, 0x00, /* \7f */
+/* 0x80 */
+       0x38, 0xC4, 0xC4, 0x44, 0x28, 0x00, /* \80 */
+       0x3A, 0x40, 0x40, 0x20, 0x7A, 0x00, /* \81 */
+       0x38, 0x54, 0x54, 0x55, 0x19, 0x00, /* \82 */
+       0x22, 0x55, 0x55, 0x55, 0x78, 0x00, /* \83 */
+       0x20, 0x55, 0x54, 0x54, 0x79, 0x00, /* \84 */
+       0x21, 0x75, 0x55, 0x54, 0x78, 0x00, /* \85 */
+       0x20, 0x74, 0x57, 0x54, 0x78, 0x00, /* \86 */
+       0x08, 0x54, 0x54, 0x74, 0x14, 0x00, /* \87 */
+/* 0x88 */
+       0x3A, 0x55, 0x55, 0x55, 0x1A, 0x00, /* \88 */
+       0x39, 0x54, 0x54, 0x55, 0x18, 0x00, /* \89 */
+       0x39, 0x55, 0x55, 0x54, 0x18, 0x00, /* \8a */
+       0x00, 0x45, 0x7C, 0x41, 0x00, 0x00, /* \8b */
+       0x02, 0x45, 0x7D, 0x42, 0x00, 0x00, /* \8c */
+       0x01, 0x45, 0x7D, 0x40, 0x00, 0x00, /* \8d */
+       0x79, 0x14, 0x12, 0x14, 0x79, 0x00, /* \8e */
+       0x70, 0x2B, 0x2B, 0x2B, 0x70, 0x00, /* \8f */
+/* 0x90 */
+       0x7C, 0x54, 0x55, 0x55, 0x45, 0x00, /* \90 */
+       0x20, 0x54, 0x38, 0x54, 0x48, 0x00, /* \91 */
+       0x7E, 0x09, 0x7F, 0x49, 0x49, 0x00, /* \92 */
+       0x32, 0x49, 0x49, 0x49, 0x32, 0x00, /* \93 */
+       0x32, 0x48, 0x48, 0x48, 0x32, 0x00, /* \94 */
+       0x32, 0x4A, 0x4A, 0x48, 0x30, 0x00, /* \95 */
+       0x3A, 0x41, 0x41, 0x21, 0x7A, 0x00, /* \96 */
+       0x3A, 0x42, 0x42, 0x20, 0x78, 0x00, /* \97 */
+/* 0x98 */
+       0x0D, 0x50, 0x50, 0x50, 0x3D, 0x00, /* \98 */
+       0x19, 0x24, 0x42, 0x24, 0x19, 0x00, /* \99 */
+       0x3D, 0x40, 0x40, 0x40, 0x3D, 0x00, /* \9a */
+       0x18, 0x24, 0x7E, 0x24, 0x24, 0x00, /* \9b */
+       0x28, 0x5E, 0x29, 0x42, 0x20, 0x00, /* \9c */
+       0x09, 0x2A, 0x7C, 0x2A, 0x09, 0x00, /* \9d */
+       0x7F, 0x05, 0x15, 0x3D, 0x52, 0x00, /* \9e */
+       0x20, 0x48, 0x3E, 0x09, 0x02, 0x00, /* \9f */
+/* 0xa0 */
+       0x20, 0x74, 0x55, 0x55, 0x79, 0x00, /*   */
+       0x01, 0x45, 0x7D, 0x40, 0x00, 0x00, /* ¡ */
+       0x30, 0x48, 0x4A, 0x4A, 0x32, 0x00, /* ¢ */
+       0x38, 0x40, 0x42, 0x22, 0x7A, 0x00, /* £ */
+       0x7A, 0x12, 0x0A, 0x0A, 0x72, 0x00, /* ¤ */
+       0x7D, 0x09, 0x11, 0x21, 0x7D, 0x00, /* ¥ */
+       0x02, 0x15, 0x15, 0x12, 0x04, 0x00, /* ¦ */
+       0x02, 0x15, 0x15, 0x15, 0x02, 0x00, /* § */
+/* 0xa8 */
+       0x30, 0x48, 0x45, 0x40, 0x20, 0x00, /* ¨ */
+       0x00, 0x38, 0x08, 0x08, 0x08, 0x00, /* © */
+       0x00, 0x08, 0x08, 0x08, 0x38, 0x00, /* ª */
+       0x0B, 0x04, 0x6A, 0x55, 0x48, 0x00, /* « */
+       0x0B, 0x24, 0x32, 0x79, 0x20, 0x00, /* ¬ */
+       0x00, 0x00, 0x79, 0x00, 0x00, 0x00, /* ­ */
+       0x08, 0x14, 0x2A, 0x14, 0x22, 0x00, /* ® */
+       0x22, 0x14, 0x2A, 0x14, 0x08, 0x00, /* ¯ */
+/* 0xb0 */
+       0x2A, 0x55, 0x00, 0x2A, 0x55, 0x00, /* ° */
+       0x2A, 0x55, 0x2A, 0x55, 0x2A, 0x55, /* ± */
+       0x55, 0x2A, 0x7F, 0x55, 0x2A, 0x7F, /* ² */
+       0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, /* ³ */
+       0x08, 0x08, 0xFF, 0x00, 0x00, 0x00, /* ´ */
+       0x14, 0x14, 0xFF, 0x00, 0x00, 0x00, /* µ */
+       0x08, 0xFF, 0x00, 0xFF, 0x00, 0x00, /* ¶ */
+       0x08, 0xF8, 0x08, 0xF8, 0x00, 0x00, /* · */
+/* 0xb8 */
+       0x14, 0x14, 0xFC, 0x00, 0x00, 0x00, /* ¸ */
+       0x14, 0xF7, 0x00, 0xFF, 0x00, 0x00, /* ¹ */
+       0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, /* º */
+       0x14, 0xF4, 0x04, 0xFC, 0x00, 0x00, /* » */
+       0x14, 0x17, 0x10, 0x1F, 0x00, 0x00, /* ¼ */
+       0x08, 0x0F, 0x08, 0x0F, 0x00, 0x00, /* ½ */
+       0x14, 0x14, 0x1F, 0x00, 0x00, 0x00, /* ¾ */
+       0x08, 0x08, 0xF8, 0x00, 0x00, 0x00, /* ¿ */
+/* 0xc0 */
+       0x00, 0x00, 0x0F, 0x08, 0x08, 0x08, /* À */
+       0x08, 0x08, 0x0F, 0x08, 0x08, 0x08, /* Á */
+       0x08, 0x08, 0xF8, 0x08, 0x08, 0x08, /* Â */
+       0x00, 0x00, 0xFF, 0x08, 0x08, 0x08, /* Ã */
+       0x08, 0x08, 0x08, 0x08, 0x08, 0x08, /* Ä */
+       0x08, 0x08, 0xFF, 0x08, 0x08, 0x08, /* Å */
+       0x00, 0x00, 0xFF, 0x14, 0x14, 0x14, /* Æ */
+       0x00, 0xFF, 0x00, 0xFF, 0x08, 0x08, /* Ç */
+/* 0xc8 */
+       0x00, 0x1F, 0x10, 0x17, 0x14, 0x14, /* È */
+       0x00, 0xFC, 0x04, 0xF4, 0x14, 0x14, /* É */
+       0x28, 0x2F, 0x20, 0x2F, 0x28, 0x28, /* Ê */
+       0x14, 0xF4, 0x04, 0xF4, 0x14, 0x14, /* Ë */
+       0x00, 0xFF, 0x00, 0xF7, 0x14, 0x14, /* Ì */
+       0x14, 0x14, 0x14, 0x14, 0x14, 0x14, /* Í */
+       0x14, 0xF7, 0x00, 0xF7, 0x14, 0x14, /* Î */
+       0x14, 0x14, 0xF7, 0x14, 0x14, 0x14, /* Ï */
+/* 0xd0 */
+       0x08, 0x0F, 0x08, 0x0F, 0x08, 0x08, /* Ð */
+       0x14, 0x14, 0xF4, 0x14, 0x14, 0x14, /* Ñ */
+       0x08, 0x08, 0xF8, 0x08, 0x08, 0x08, /* Ò */
+       0x08, 0x0F, 0x08, 0x0F, 0x08, 0x08, /* Ó */
+       0x00, 0x00, 0x1F, 0x14, 0x14, 0x14, /* Ô */
+       0x00, 0x00, 0xFC, 0x14, 0x14, 0x14, /* Õ */
+       0x00, 0xF8, 0x08, 0xF8, 0x08, 0x08, /* Ö */
+       0x08, 0xFF, 0x08, 0xFF, 0x08, 0x08, /* × */
+/* 0xd8 */
+       0x14, 0x14, 0xFF, 0x14, 0x14, 0x14, /* Ø */
+       0x08, 0x08, 0x0F, 0x00, 0x00, 0x00, /* Ù */
+       0x00, 0x00, 0xF8, 0x08, 0x08, 0x08, /* Ú */
+       0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00, /* Û */
+       0x70, 0x70, 0x70, 0x70, 0x70, 0x00, /* Ü */
+       0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x00, /* Ý */
+       0x00, 0x00, 0x00, 0x7F, 0x7F, 0x00, /* Þ */
+       0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, /* ß */
+/* 0xe0 */
+       0x30, 0x48, 0x48, 0x30, 0x48, 0x00, /* à */
+       0x7E, 0x11, 0x25, 0x25, 0x1A, 0x00, /* á */
+       0x7E, 0x02, 0x02, 0x02, 0x06, 0x00, /* â */
+       0x04, 0x7C, 0x04, 0x7C, 0x04, 0x00, /* ã */
+       0x41, 0x63, 0x55, 0x49, 0x63, 0x00, /* ä */
+       0x3C, 0x42, 0x4A, 0x4A, 0x31, 0x00, /* å */
+       0x40, 0x7C, 0x20, 0x20, 0x1C, 0x00, /* æ */
+       0x08, 0x04, 0x7C, 0x08, 0x04, 0x00, /* ç */
+/* 0xe8 */
+       0x49, 0x55, 0x77, 0x55, 0x49, 0x00, /* è */
+       0x1C, 0x2A, 0x49, 0x2A, 0x1C, 0x00, /* é */
+       0x4C, 0x72, 0x02, 0x72, 0x4C, 0x00, /* ê */
+       0x30, 0x4A, 0x45, 0x49, 0x31, 0x00, /* ë */
+       0x18, 0x24, 0x18, 0x24, 0x18, 0x00, /* ì */
+       0x5C, 0x72, 0x2A, 0x27, 0x1D, 0x00, /* í */
+       0x1C, 0x2A, 0x49, 0x49, 0x00, 0x00, /* î */
+       0x7E, 0x01, 0x01, 0x01, 0x7E, 0x00, /* ï */
+/* 0xf0 */
+       0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x00, /* ð */
+       0x24, 0x24, 0x2E, 0x24, 0x24, 0x00, /* ñ */
+       0x40, 0x51, 0x4A, 0x44, 0x00, 0x00, /* ò */
+       0x44, 0x4A, 0x51, 0x40, 0x00, 0x00, /* ó */
+       0x00, 0x00, 0xFE, 0x01, 0x02, 0x00, /* ô */
+       0x20, 0x40, 0x3F, 0x00, 0x00, 0x00, /* õ */
+       0x08, 0x08, 0x2A, 0x08, 0x08, 0x00, /* ö */
+       0x24, 0x12, 0x24, 0x12, 0x00, 0x00, /* ÷ */
+/* 0xf8 */
+       0x06, 0x09, 0x09, 0x09, 0x06, 0x00, /* ø */
+       0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /* ù */
+       0x00, 0x10, 0x10, 0x00, 0x00, 0x00, /* ú */
+       0x10, 0x30, 0x7F, 0x01, 0x01, 0x00, /* û */
+       0x01, 0x0E, 0x01, 0x01, 0x0E, 0x00, /* ü */
+       0x0A, 0x09, 0x0D, 0x0A, 0x00, 0x00, /* ý */
+       0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x00, /* þ */
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00  /* ÿ */
+};        
diff --git a/mware/font.h b/mware/font.h
new file mode 100755 (executable)
index 0000000..cf63936
--- /dev/null
@@ -0,0 +1,39 @@
+/*!
+ * \file
+ * <!--
+ * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Stefano Fedrigo <aleph@develer.com>
+ *
+ * \brief Font 8x6 IBM-PC 8bit
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ * Revision 1.2  2004/03/24 15:48:53  bernie
+ * Remove Copyright messages from Doxygen output
+ *
+ * Revision 1.1  2004/01/13 12:15:28  aleph
+ * Move font table in program memory; add font.h
+ *
+ */
+#ifndef FONT_H
+#define FONT_H
+
+#include "avr/pgmspace.h"
+
+/* Font size (in pixel) */
+#define FONT_WIDTH 6
+#define FONT_HEIGHT 8
+
+/*! Font table */
+extern const prog_uchar font[256 * FONT_WIDTH];
+
+#endif /* FONT_H */
diff --git a/mware/formatwr.c b/mware/formatwr.c
new file mode 100755 (executable)
index 0000000..bd7b3c7
--- /dev/null
@@ -0,0 +1,827 @@
+/*!
+ * \file
+ * <!--
+ * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \brief Basic "printf", "sprintf" and "fprintf" formatter.
+ *
+ * This module is 100% reentrant and can be adapted to user-defined routines
+ * that needs formatters with special properties like different output chann-
+ * els or new format specifiers.
+ *
+ * To reduce size in applications not using real numbers or long integers
+ * the formatter may be compiled to exclude certain parts.  This is
+ * controlled by giving a -D option a compilation time.
+ *
+ *    -DFLOAT_SUPPORT        Full ANSI formatter
+ *    -DNO_FLOATS            Full ANSI except floats
+ *    -DREDUCED_SUPPORT      Reduced 'int' type of converter
+ *
+ * The reduced version of formatter is suitable when program size is critical
+ * rather than formatting power.  This routine uses less than 20 bytes of
+ * stack space which makes it practical even in systems with less than 256
+ * bytes of user RAM.
+ *
+ * The only formatting specifiers supported by the reduced formatter are:
+ * \code
+ *    %% %c %s %d %o %x %X and %hd %ho %hx %hX %ld %lo %lx %lX
+ * \endcode
+ *
+ * It means that real variables are not supported as well as field
+ * width and precision arguments.
+ *
+ * The last eight (h and l modifiers) can easily be removed by
+ * removing the line "#define MODIFIERS_IN_REDUCED".
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ */
+
+/* bernie */
+#define FLOAT_SUPPORT
+#undef NO_FLOATS
+#undef REDUCED_SUPPORT
+
+#ifndef FLOAT_SUPPORT
+#ifndef NO_FLOATS
+#ifndef REDUCED_SUPPORT
+#error -DFLOAT_SUPPORT, -DNO_FLOATS or -DREDUCED_SUPPORT missing
+#endif
+#endif
+#endif
+
+/* Make it easy for customers to disable h and l
+   modifiers in REDUCED_SUPPORT by removing the next #define */
+#define MODIFIERS_IN_REDUCED
+
+#include "formatwr.h"
+#include "compiler.h" /* progmem macros */
+#include <float.h>
+
+#ifndef FRMWRI_BUFSIZE
+/*bernie: save some memory, who cares about floats with lots of decimals? */
+/*#define FRMWRI_BUFSIZE 134*/
+#define FRMWRI_BUFSIZE 32
+#endif
+
+#ifndef MEM_ATTRIBUTE
+#define MEM_ATTRIBUTE
+#endif
+
+#ifdef MODIFIERS_IN_REDUCED
+#define IS_SHORT (h_modifier || (sizeof(int) == 2 && !l_modifier))
+#else
+#define IS_SHORT (sizeof(int) == 2)
+#endif
+
+
+#ifdef FLOAT_SUPPORT
+
+static char *float_conversion(MEM_ATTRIBUTE long double value,
+               MEM_ATTRIBUTE short nr_of_digits,
+               MEM_ATTRIBUTE char *buf,
+               MEM_ATTRIBUTE char format_flag,
+               MEM_ATTRIBUTE char g_flag,
+               MEM_ATTRIBUTE char alternate_flag)
+{
+       MEM_ATTRIBUTE char *cp;
+       MEM_ATTRIBUTE char *buf_pointer;
+       MEM_ATTRIBUTE short n, i, dec_point_pos, integral_10_log;
+
+       buf_pointer = buf;
+       integral_10_log = 0;
+
+       if (value >= 1)
+       {
+               while (value >= 1e11) /* To speed up things a bit */
+               {
+                       value /= 1e10;
+                       integral_10_log += 10;
+               }
+               while (value >= 10)
+               {
+                       value /= 10;
+                       integral_10_log++;
+               }
+       }
+       else if (value) /* Not just 0.0 */
+       {
+               while (value <= 1e-10) /* To speed up things a bit */
+               {
+                       value *= 1e10;
+                       integral_10_log -= 10;
+               }
+               while (value < 1)
+               {
+                       value *= 10;
+                       integral_10_log--;
+               }
+       }
+       if (g_flag)
+       {
+               if (integral_10_log < nr_of_digits && integral_10_log >= -4)
+               {
+                       format_flag = 0;
+                       nr_of_digits -= integral_10_log;
+               }
+               nr_of_digits--;
+               if (alternate_flag)
+               {
+                       /* %#G - No removal of trailing zeros */
+                       g_flag = 0;
+               }
+               else
+               {
+                       /* %G - Removal of trailing zeros */
+                       alternate_flag = 1;
+               }
+       }
+
+       /* %e or %E */
+       if (format_flag)
+       {
+               dec_point_pos = 0;
+       }
+       else
+       {
+               /* Less than one... */
+               if (integral_10_log < 0)
+               {
+                       *buf_pointer++ = '0';
+                       if ((n = nr_of_digits) || alternate_flag)
+                       {
+                               *buf_pointer++ = '.';
+                       }
+                       i = 0;
+                       while (--i > integral_10_log && nr_of_digits)
+                       {
+                               *buf_pointer++ = '0';
+                               nr_of_digits--;
+                       }
+                       if (integral_10_log < (-n - 1))
+                       {
+                               /* Nothing more to do */
+                               goto CLEAN_UP;
+                       }
+                       dec_point_pos = 1;
+               }
+               else
+               {
+                       dec_point_pos = - integral_10_log;
+               }
+       }
+
+       i = dec_point_pos;
+       while (i <= nr_of_digits )
+       {
+               value -= (long double)(n = (short)value); /* n=Digit value=Remainder */
+               value *= 10; /* Prepare for next shot */
+               *buf_pointer++ = n + '0';
+               if ( ! i++ && (nr_of_digits || alternate_flag))
+               {
+                       *buf_pointer++ = '.';
+               }
+       }
+
+       /* Rounding possible */
+       if (value >= 5)
+       {
+               n = 1; /* Carry */
+               cp = buf_pointer - 1;
+               do
+               {
+                       if (*cp != '.')
+                       {
+                               if ( (*cp += n) == ('9' + 1) )
+                               {
+                                       *cp = '0';
+                                       n = 1;
+                               }
+                               else
+                               {
+                                       n = 0;
+                               }
+                       }
+               } while (cp-- > buf);
+               if (n)
+               {
+                       /* %e or %E */
+                       if (format_flag)
+                       {
+                               cp = buf_pointer;
+                               while (cp > buf)
+                               {
+                                       if (*(cp - 1) == '.')
+                                       {
+                                               *cp = *(cp - 2);
+                                               cp--;
+                                       }
+                                       else
+                                       {
+                                               *cp = *(cp - 1);
+                                       }
+                                       cp--;
+                               }
+                               integral_10_log++;
+                       }
+                       else
+                       {
+                               cp = ++buf_pointer;
+                               while (cp > buf)
+                               {
+                                       *cp = *(cp - 1);
+                                       cp--;
+                               }
+                       }
+                       *buf = '1';
+               }
+       }
+
+CLEAN_UP:
+       /* %G - Remove trailing zeros */
+       if (g_flag)
+       {
+               while (*(buf_pointer - 1) == '0')
+               {
+                       buf_pointer--;
+               }
+               if (*(buf_pointer - 1) == '.')
+               {
+                       buf_pointer--;
+               }
+       }
+
+       /* %e or %E */
+       if (format_flag)
+       {
+               *buf_pointer++ = format_flag;
+               if (integral_10_log < 0)
+               {
+                       *buf_pointer++ = '-';
+                       integral_10_log = -integral_10_log;
+               }
+               else
+               {
+                       *buf_pointer++ = '+';
+               }
+               n = 0;
+               buf_pointer +=10;
+               do
+               {
+                       n++;
+                       *buf_pointer++ = (integral_10_log % 10) + '0';
+                       integral_10_log /= 10;
+               } while ( integral_10_log || n < 2 );
+               for ( i = n ; n > 0 ; n-- )
+                       *(buf_pointer - 11 - i + n) = *(buf_pointer - n);
+               buf_pointer -= 10;
+       }
+       return (buf_pointer);
+}
+
+#endif /* FLOAT_SUPPORT */
+
+/*!
+ * This routine forms the core and entry of the formatter.
+ *
+ * The conversion performed conforms to the ANSI specification for "printf".
+ */
+int
+PGM_FUNC(_formatted_write)(const char * PGM_ATTR format,
+               void put_one_char(char, void *),
+               void *secret_pointer,
+               va_list ap)
+{
+       MEM_ATTRIBUTE static char bad_conversion[] = "???";
+       MEM_ATTRIBUTE static char null_pointer[] = "<NULL>";
+
+#ifndef REDUCED_SUPPORT
+       MEM_ATTRIBUTE char format_flag;
+       MEM_ATTRIBUTE int precision;
+       MEM_ATTRIBUTE int n;
+       MEM_ATTRIBUTE int field_width, nr_of_chars;
+       MEM_ATTRIBUTE char plus_space_flag, left_adjust, l_L_modifier;
+       MEM_ATTRIBUTE char h_modifier, alternate_flag;
+       MEM_ATTRIBUTE char nonzero_value;
+       MEM_ATTRIBUTE unsigned long ulong, div_factor;
+
+#ifdef FLOAT_SUPPORT
+       MEM_ATTRIBUTE long double fvalue;
+#endif
+
+       MEM_ATTRIBUTE char *buf_pointer;
+       MEM_ATTRIBUTE char *ptr;
+       MEM_ATTRIBUTE const char *hex;
+       MEM_ATTRIBUTE char zeropad;
+       MEM_ATTRIBUTE char buf[FRMWRI_BUFSIZE];
+
+       nr_of_chars = 0;
+       for (;;)    /* Until full format string read */
+       {
+               while ((format_flag = PGM_READ_CHAR(format++)) != '%')    /* Until '%' or '\0' */
+               {
+                       if (!format_flag)
+                               return (nr_of_chars);
+                       put_one_char (format_flag, secret_pointer);
+                       nr_of_chars++;
+               }
+               if (PGM_READ_CHAR(format) == '%')    /* %% prints as % */
+               {
+                       format++;
+                       put_one_char('%', secret_pointer);
+                       nr_of_chars++;
+                       continue;
+               }
+
+               plus_space_flag = left_adjust = alternate_flag = zeropad = 0;
+               ptr = buf_pointer = &buf[0];
+               hex = "0123456789ABCDEF";
+
+               /* check for leading '-', '+', ' ','#' or '0' flags  */
+               for (;;)
+               {
+                       switch (PGM_READ_CHAR(format))
+                       {
+                               case ' ':
+                                       if (plus_space_flag)
+                                               goto NEXT_FLAG;
+                               case '+':
+                                       plus_space_flag = PGM_READ_CHAR(format);
+                                       goto NEXT_FLAG;
+                               case '-':
+                                       left_adjust++;
+                                       goto NEXT_FLAG;
+                               case '#':
+                                       alternate_flag++;
+                                       goto NEXT_FLAG;
+                               case '0':
+                                       zeropad++;
+                                       goto NEXT_FLAG;
+                       }
+                       break;
+NEXT_FLAG:
+                       format++;
+               }
+
+               /* Optional field width (may be '*') */
+               if (PGM_READ_CHAR(format) == '*')
+               {
+                       field_width = va_arg(ap, int);
+                       if (field_width < 0)
+                       {
+                               field_width = -field_width;
+                               left_adjust++;
+                       }
+                       format++;
+               }
+               else
+               {
+                       field_width = 0;
+                       while (PGM_READ_CHAR(format) >= '0' && PGM_READ_CHAR(format) <= '9')
+                               field_width = field_width * 10 + (PGM_READ_CHAR(format++) - '0');
+               }
+
+               if (left_adjust)
+                       zeropad = 0;
+
+               /* Optional precision (or '*') */
+               if (PGM_READ_CHAR(format) == '.')
+               {
+                       if (PGM_READ_CHAR(++format) == '*')
+                       {
+                               precision = va_arg(ap, int);
+                               format++;
+                       }
+                       else
+                       {
+                               precision = 0;
+                               while (PGM_READ_CHAR(format) >= '0' && PGM_READ_CHAR(format) <= '9')
+                                       precision = precision * 10 + (PGM_READ_CHAR(format++) - '0');
+                       }
+               }
+               else
+                       precision = -1;
+
+               /* At this point, "left_adjust" is nonzero if there was
+                * a sign, "zeropad" is 1 if there was a leading zero
+                * and 0 otherwise, "field_width" and "precision"
+                * contain numbers corresponding to the digit strings
+                * before and after the decimal point, respectively,
+                * and "plus_space_flag" is either 0 (no flag) or
+                * contains a plus or space character. If there was no
+                * decimal point, "precision" will be -1.
+                */
+
+               l_L_modifier = h_modifier = 0;
+
+               /* Optional 'l','L' r 'h' modifier? */
+               switch (PGM_READ_CHAR(format))
+               {
+                       case 'l':
+                       case 'L':
+                               l_L_modifier++;
+                               format++;
+                               break;
+                       case 'h':
+                               h_modifier++;
+                               format++;
+                               break;
+               }
+
+               /*
+                * At exit from the following switch, we will emit
+                * the characters starting at "buf_pointer" and
+                * ending at "ptr"-1
+                */
+               switch (format_flag = PGM_READ_CHAR(format++))
+               {
+#if 0 /* bernie */
+                       case 'n':
+                               if (sizeof(short) != sizeof(int))
+                               {
+                                       if (sizeof(int) != sizeof(long))
+                                       {
+                                               if (h_modifier)
+                                                       *va_arg(ap, short *) = nr_of_chars;
+                                               else if (l_L_modifier)
+                                                       *va_arg(ap, long *) = nr_of_chars;
+                                               else
+                                                       *va_arg(ap, int *) = nr_of_chars;
+                                       }
+                                       else
+                                       {
+                                               if (h_modifier)
+                                                       *va_arg(ap, short *) = nr_of_chars;
+                                               else
+                                                       *va_arg(ap, int *) = nr_of_chars;
+                                       }
+                               }
+                               else
+                               {
+                                       if (l_L_modifier)
+                                               *va_arg(ap, long *) = nr_of_chars;
+                                       else
+                                               *va_arg(ap, int *) = nr_of_chars;
+                               }
+                               continue;
+#endif
+                       case 'c':
+                               buf[0] = va_arg(ap, int);
+                               ptr++;
+                               break;
+
+                       case 's':
+                               if ( !(buf_pointer = va_arg(ap, char *)) )
+                                       buf_pointer = null_pointer;
+                               if (precision < 0)
+                                       precision = 10000;
+                               for (n=0; *buf_pointer++ && n < precision; n++)
+                                       ;
+                               ptr = --buf_pointer;
+                               buf_pointer -= n;
+                               break;
+
+                       case 'o':
+                               if (alternate_flag && !precision)
+                                       precision++;
+                       case 'x':
+                               hex = "0123456789abcdef";
+                       case 'u':
+                       case 'p':
+                       case 'X':
+                               if (format_flag == 'p')
+#if defined(__AVR__) || defined(__I196__) /* 16bit pointers */
+                                       ulong = (unsigned long)(unsigned short)va_arg(ap, char *);
+#else /* 32bit pointers */
+                               ulong = (unsigned long)va_arg(ap, char *);
+#endif /* 32bit pointers */
+                               else if (sizeof(short) == sizeof(int))
+                                       ulong = l_L_modifier ?
+                                               va_arg(ap, unsigned long) : (unsigned long)va_arg(ap, unsigned int);
+                               else
+                                       ulong = h_modifier ?
+                                               (unsigned long)(unsigned short) va_arg(ap, int)
+                                               : (unsigned long)va_arg(ap, int);
+                               div_factor = (format_flag == 'o') ?
+                                       8 : (format_flag == 'u') ? 10 : 16;
+                               plus_space_flag = 0;
+                               goto INTEGRAL_CONVERSION;
+
+                       case 'd':
+                       case 'i':
+                               if (sizeof(short) == sizeof(long))
+                               {
+                                       if ( (long)(ulong = va_arg(ap, unsigned long)) < 0)
+                                       {
+                                               plus_space_flag = '-';
+                                               ulong = (unsigned long)(-((signed long)ulong));
+                                       }
+                               }
+                               else if (sizeof(short) == sizeof(int))
+                               {
+                                       if ( (long)(ulong = l_L_modifier ?
+                                                               va_arg(ap,unsigned long) : (unsigned long)va_arg(ap,int)) < 0)
+                                       {
+                                               plus_space_flag = '-';
+                                               ulong = (unsigned long)(-((signed long)ulong));
+                                       }
+                               }
+                               else
+                               {
+                                       if ( (signed long)(ulong = (unsigned long) (h_modifier ?
+                                                                       (short) va_arg(ap, int) : va_arg(ap,int))) < 0)
+                                       {
+                                               plus_space_flag = '-';
+                                               ulong = (unsigned long)(-((signed long)ulong));
+                                       }
+                               }
+                               div_factor = 10;
+
+                               /* Now convert to digits */
+INTEGRAL_CONVERSION:
+                               ptr = buf_pointer = &buf[FRMWRI_BUFSIZE - 1];
+                               nonzero_value = (ulong != 0);
+
+                               /* No char if zero and zero precision */
+                               if (precision != 0 || nonzero_value)
+                                       do
+                                               *--buf_pointer = hex[ulong % div_factor];
+                                       while (ulong /= div_factor);
+
+                               /* "precision" takes precedence */
+                               if (precision < 0)
+                                       if (zeropad)
+                                               precision = field_width - (plus_space_flag != 0);
+                               while (precision > (int)(ptr - buf_pointer))
+                                       *--buf_pointer = '0';
+
+                               if (alternate_flag && nonzero_value)
+                               {
+                                       if (format_flag == 'x' || format_flag == 'X')
+                                       {
+                                               *--buf_pointer = format_flag;
+                                               *--buf_pointer = '0';
+                                       }
+                                       else if ((format_flag == 'o') && (*buf_pointer != '0'))
+                                       {
+                                               *--buf_pointer = '0';
+                                       }
+                               }
+                               break;
+
+#ifdef FLOAT_SUPPORT
+                       case 'g':
+                       case 'G':
+                               n = 1;
+                               format_flag -= 2;
+                               if (! precision)
+                               {
+                                       precision = 1;
+                               }
+                               goto FLOATING_CONVERSION;
+                       case 'f':
+                               format_flag = 0;
+                       case 'e':
+                       case 'E':
+                               n = 0;
+FLOATING_CONVERSION:
+                               if (precision < 0)
+                               {
+                                       precision = 6;
+                               }
+                               if (sizeof(double) != sizeof(long double))
+                               {
+                                       if ( (fvalue = l_L_modifier ?
+                                                               va_arg(ap,long double) : va_arg(ap,double)) < 0)
+                                       {
+                                               plus_space_flag = '-';
+                                               fvalue = -fvalue;
+                                       }
+                               }
+                               else if ( (fvalue = va_arg(ap,long double)) < 0)
+                               {
+                                       plus_space_flag = '-';
+                                       fvalue = -fvalue;
+                               }
+                               ptr = float_conversion (fvalue,
+                                               (short)precision,
+                                               buf_pointer += field_width,
+                                               format_flag,
+                                               (char)n,
+                                               alternate_flag);
+                               if (zeropad)
+                               {
+                                       precision = field_width - (plus_space_flag != 0);
+                                       while (precision > ptr - buf_pointer)
+                                               *--buf_pointer = '0';
+                               }
+                               break;
+
+#else /* !FLOAT_SUPPORT */
+                       case 'g':
+                       case 'G':
+                       case 'f':
+                       case 'e':
+                       case 'E':
+                               ptr = buf_pointer = bad_conversion;
+                               while (*ptr)
+                                       ptr++;
+                               break;
+#endif /* !FLOAT_SUPPORT */
+
+                       case '\0': /* Really bad place to find NUL in */
+                               format--;
+
+                       default:
+                               /* Undefined conversion! */
+                               ptr = buf_pointer = bad_conversion;
+                               ptr += 3;
+                               break;
+
+               }
+
+               /*
+                * This part emittes the formatted string to "put_one_char".
+                */
+
+               /* If field_width == 0 then nothing should be written. */
+               precision = ptr - buf_pointer;
+
+               if ( precision > field_width)
+               {
+                       n = 0;
+               }
+               else
+               {
+                       n = field_width - precision - (plus_space_flag != 0);
+               }
+
+               /* emit any leading pad characters */
+               if (!left_adjust)
+                       while (--n >= 0)
+                       {
+                               put_one_char(' ', secret_pointer);
+                               nr_of_chars++;
+                       }
+
+               /* emit flag characters (if any) */
+               if (plus_space_flag)
+               {
+                       put_one_char(plus_space_flag, secret_pointer);
+                       nr_of_chars++;
+               }
+
+               /* emit the string itself */
+               while (--precision >= 0)
+               {
+                       put_one_char(*buf_pointer++, secret_pointer);
+                       nr_of_chars++;
+               }
+
+               /* emit trailing space characters */
+               if (left_adjust)
+                       while (--n >= 0)
+                       {
+                               put_one_char(' ', secret_pointer);
+                               nr_of_chars++;
+                       }
+       }
+
+#else /* REDUCED_SUPPORT STARTS HERE */
+
+#ifdef MODIFIERS_IN_REDUCED
+       char l_modifier, h_modifier;
+       unsigned long u_val, div_val;
+#else
+       unsigned int u_val, div_val;
+#endif
+       char format_flag;
+       unsigned int nr_of_chars, base;
+       char outChar;
+       char *ptr;
+
+       nr_of_chars = 0;
+       for (;;)    /* Until full format string read */
+       {
+               while ((format_flag = PGM_READ_CHAR(format++)) != '%')    /* Until '%' or '\0' */
+               {
+                       if (!format_flag)
+                               return (nr_of_chars);
+                       put_one_char (format_flag, secret_pointer);
+                       nr_of_chars++;
+               }
+
+#ifdef MODIFIERS_IN_REDUCED
+               /*=================================*/
+               /* Optional 'l' or 'h' modifiers ? */
+               /*=================================*/
+               l_modifier = h_modifier = 0;
+               switch (PGM_READ_CHAR(format))
+               {
+                       case 'l':
+                               l_modifier = 1;
+                               format++;
+                               break;
+
+                       case 'h':
+                               h_modifier = 1;
+                               format++;
+                               break;
+               }
+#endif
+
+               switch (format_flag = PGM_READ_CHAR(format++))
+               {
+                       case 'c':
+                               format_flag = va_arg(ap, int);
+                       default:
+                               put_one_char (format_flag, secret_pointer);
+                               nr_of_chars++;
+                               continue;
+
+                       case 's':
+                               ptr = va_arg(ap, char *);
+                               while (format_flag = *ptr++)
+                               {
+                                       put_one_char (format_flag, secret_pointer);
+                                       nr_of_chars++;
+                               }
+                               continue;
+
+                       case 'o':
+                               base = 8;
+                               if (IS_SHORT)
+                                       div_val = 0x8000;
+                               else
+                                       div_val = 0x40000000;
+                               goto CONVERSION_LOOP;
+
+                       case 'd':
+                               base = 10;
+                               if (IS_SHORT)
+                                       div_val = 10000;
+                               else
+                                       div_val = 1000000000;
+                               goto CONVERSION_LOOP;
+
+                       case 'X':
+                       case 'x':
+                               base = 16;
+                               if (IS_SHORT)
+                                       div_val = 0x1000;
+                               else
+                                       div_val = 0x10000000;
+
+CONVERSION_LOOP:
+#ifdef MODIFIERS_IN_REDUCED
+                               if (h_modifier)
+                                       u_val = (format_flag == 'd') ?
+                                               (short)va_arg(ap, int) : (unsigned short)va_arg(ap, int);
+                               else if (l_modifier)
+                                       u_val = va_arg(ap, long);
+                               else
+                                       u_val = (format_flag == 'd') ?
+                                               va_arg(ap,int) : va_arg(ap,unsigned int);
+#else
+                               u_val = va_arg(ap,int);
+#endif
+                               if (format_flag == 'd')
+                               {
+                                       if (((int)u_val) < 0)
+                                       {
+                                               u_val = - u_val;
+                                               put_one_char ('-', secret_pointer);
+                                               nr_of_chars++;
+                                       }
+                               }
+                               while (div_val > 1 && div_val > u_val)
+                               {
+                                       div_val /= base;
+                               }
+                               do
+                               {
+                                       outChar = (u_val / div_val) + '0';
+                                       if (outChar > '9')
+                                               if (format_flag == 'x')
+                                                       outChar += 'a'-'9'-1;
+                                               else
+                                                       outChar += 'A'-'9'-1;
+                                       put_one_char (outChar, secret_pointer);
+                                       nr_of_chars++;
+                                       u_val %= div_val;
+                                       div_val /= base;
+                               }
+                               while (div_val);
+
+               } /* end switch(format_flag...) */
+       }
+#endif
+}
diff --git a/mware/formatwr.h b/mware/formatwr.h
new file mode 100755 (executable)
index 0000000..091fea1
--- /dev/null
@@ -0,0 +1,40 @@
+/*!
+ * \file
+ * <!--
+ * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \brief Basic "printf", "sprintf" and "fprintf" formatter.
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ */
+#ifndef MWARE_FORMATWR_H
+#define MWARE_FORMATWR_H
+
+#include <stdarg.h>
+
+int _formatted_write(
+       const char *format,
+       void put_one_char(char, void *),
+       void *secret_pointer,
+       va_list ap);
+
+#ifdef __AVR__
+       #include <avr/pgmspace.h>
+       int _formatted_write_P(
+               const char * PROGMEM format,
+               void put_one_char(char, void *),
+               void *secret_pointer,
+               va_list ap);
+#endif /* __AVR__ */
+
+#endif /* MWARE_FORMATWR_H */
+
diff --git a/mware/gfx.c b/mware/gfx.c
new file mode 100755 (executable)
index 0000000..930510e
--- /dev/null
@@ -0,0 +1,404 @@
+/*!
+ * \file
+ * <!--
+ * Copyright (C) 1999 Bernardo Innocenti <bernie@develer.com>
+ * Copyright (C) 2003 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ * \author Stefano Fedrigo <aleph@develer.com>
+ *
+ * \brief General pourpose graphics routines
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ * Revision 1.6  2004/03/24 15:03:45  bernie
+ * Use explicit include paths; clean Doxygen comments
+ *
+ * Revision 1.5  2004/02/09 00:21:28  aleph
+ * Various gfx fixes
+ *
+ * Revision 1.4  2004/01/27 23:24:19  aleph
+ * Add new graphics primitives
+ *
+ * Revision 1.3  2004/01/13 00:05:23  aleph
+ * Fix clipping bug
+ *
+ * Revision 1.2  2004/01/07 23:33:01  aleph
+ * Change copyright email
+ *
+ * Revision 1.1  2004/01/07 19:05:31  aleph
+ * Add graphics routines
+ *
+ */
+
+#include "gfx.h"
+#include "config.h"
+#include <drv/kdebug.h>
+
+#include <string.h>
+
+
+/*!
+ * Plot a point in bitmap.
+ * \note bm is evaluated twice
+ */
+#define BM_PLOT(bm, x, y) \
+       ( *((bm)->raster + ((y) / 8) * (bm)->width + (x)) |= 1 << ((y) % 8) )
+
+/*!
+ * Clear a point in bitmap.
+ * \note bm is evaluated twice
+ */
+#define BM_CLEAR(bm, x, y) \
+       ( *((bm)->raster + ((y) / 8) * (bm)->width + (x)) &= ~(1 << ((y) % 8)) )
+
+/*! Swap a with b */
+#define SWAP(a, b) \
+       do { \
+               (void)(&a == &b); /* type check */ \
+               typeof(a) tmp; \
+               tmp = (a); \
+               (a) = (b); \
+               (b) = tmp; \
+       } while (0)
+
+
+/*!
+ * Initialize a Bitmap structure with the provided parameters.
+ */
+void gfx_InitBitmap(Bitmap *bm, uint8_t *raster, coord_t w, coord_t h)
+{
+       bm->raster = raster;
+       bm->width = w;
+       bm->height = h;
+       bm->penX = 0;
+       bm->penY = 0;
+}
+
+
+/*!
+ * Clear the whole bitmap surface to all zeros
+ */
+void gfx_ClearBitmap(Bitmap *bm)
+{
+       memset(bm->raster, 0, (bm->width * bm->height) / 8);
+}
+
+
+/*!
+ * Copy a raster picture located in program memory in the bitmap.
+ * The size of the raster to copy *must* be the same of the raster bitmap.
+ */
+void gfx_blitBitmap_P(Bitmap *bm, const prog_uchar *raster)
+{
+       memcpy_P(bm->raster, raster, bm->height/8 * bm->width);
+}
+
+
+void gfx_DrawLine(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2)
+{
+       int x, y, e, len, adx, ady, signx, signy;
+
+
+#ifdef CONFIG_GFX_CLIPPING
+       /* FIXME: broken */
+
+       #define XMIN 0
+       #define YMIN 0
+       #define XMAX (bm->width - 1)
+       #define YMAX (bm->height - 1)
+
+       /* Clipping */
+       if (x1 < XMIN)
+       {
+               y1 = y2 - ((x2 - XMIN) * (y2 - y1)) / (x2 - x1);
+               x1 = XMIN;
+       }
+       if (y1 < YMIN)
+       {
+               x1 = x2 - ((y2 - YMIN) * (x2 - x1)) / (y2 - y1);
+               y1 = YMIN;
+       }
+       if (x2 < XMIN)
+       {
+               y2 = y2 - ((XMIN - x1) * (y2 - y1)) / (x2 - x1);
+               x2 = XMIN;
+       }
+       if (y2 < YMIN)
+       {
+               x2 = x2 - ((YMIN - y1) * (x2 - x1)) / (y2 - y1);
+               y2 = YMIN;
+       }
+
+       if (x1 > XMAX)
+       {
+               y1 = ((x2 - XMAX) * (y2 - y1)) / (x2 - x1);
+               x1 = XMAX;
+       }
+       if (y1 > YMAX)
+       {
+               x1 = ((y2 - YMAX) * (x2 - x1)) / (y2 - y1);
+               y1 = YMAX;
+       }
+       if (x2 > XMAX)
+       {
+               y2 = ((XMAX - x1) * (y2 - y1)) / (x2 - x1);
+               x2 = XMAX;
+       }
+       if (y2 > YMAX)
+       {
+               x2 = ((YMAX - y1) * (x2 - x1)) / (y2 - y1);
+               y2 = YMAX;
+       }
+
+       #undef XMIN
+       #undef YMIN
+       #undef XMAX
+       #undef YMAX
+
+#endif /* CONFIG_GRAPH_CLIPPING */
+
+
+       if (x2 > x1)
+       {
+               /* left to right */
+               signx = +1;
+               adx = x2 - x1;
+       }
+       else
+       {
+               /* right to left */
+               signx = -1;
+               adx = x1 - x2;
+       }
+
+       if (y2 > y1)
+       {
+               /* top to bottom */
+               signy = +1;
+               ady = y2 - y1;
+       }
+       else
+       {
+               /* bottom to top */
+               signy = -1;
+               ady = y1 - y2;
+       }
+
+       x = x1;
+       y = y1;
+
+       if (adx > ady)
+       {
+               /* X-major line (octants 1/4/5/8) */
+
+               len = adx;
+               e = -adx;
+               while (len--)
+               {
+                       /* Sanity check */
+                       if ((x >= 0) && (x < bm->width) && (y >= 0) && (y < bm->height))
+                               BM_PLOT(bm, x, y);
+                       x += signx;
+                       e += ady;
+                       if (e >= 0)
+                       {
+                               y += signy;
+                               e -= adx;
+                       }
+               }
+       }
+       else
+       {
+               /* Y-major line (octants 2/3/6/7) */
+
+               len = ady;
+               e = -ady;
+               while (len--)
+               {
+                       /* Sanity check */
+                       if ((x >= 0) && (x < bm->width) && (y >= 0) && (y < bm->height))
+                               BM_PLOT(bm, x, y);
+                       y += signy;
+                       e += adx;
+                       if (e >= 0)
+                       {
+                               x += signx;
+                               e -= ady;
+                       }
+               }
+       }
+}
+
+
+void gfx_MoveTo(Bitmap *bm, coord_t x, coord_t y)
+{
+       bm->penX = x;
+       bm->penY = y;
+}
+
+
+void gfx_LineTo(Bitmap *bm, coord_t x, coord_t y)
+{
+       gfx_DrawLine(bm, bm->penX, bm->penY, x, y);
+       gfx_MoveTo(bm, x, y);
+}
+
+
+/*!
+ * Draw a filled rectangle.
+ * \note The bottom-right border of the rectangle is not drawn.
+ */
+void gfx_FillRect(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2)
+{
+       coord_t x, y;
+
+       /* Sort coords */
+       if (x1 > x2) SWAP(x1, x2);
+       if (y1 > y2) SWAP(y1, y2);
+
+       /* Clip rect to bitmap bounds */
+       if (x1 < 0)             x1 = 0;
+       if (x2 < 0)             x2 = 0;
+       if (x1 > bm->width)     x1 = bm->width;
+       if (x2 > bm->width)     x2 = bm->width;
+       if (y1 < 0)             y1 = 0;
+       if (y2 < 0)             y2 = 0;
+       if (y1 > bm->width)     y1 = bm->width;
+       if (y2 > bm->width)     y2 = bm->width;
+
+       /* Draw rectangle */
+       for (x = x1; x < x2; x++)
+               for (y = y1; y < y2; y++)
+                       BM_PLOT(bm, x, y);
+}
+
+
+/*!
+ * Draw an empty rectangle.
+ * \note The bottom-right border of the rectangle is not drawn.
+ */
+void gfx_DrawRect(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2)
+{
+       /* Sort coords */
+       if (x1 > x2) SWAP(x1, x2);
+       if (y1 > y2) SWAP(y1, y2);
+
+       /* Draw rectangle */
+       gfx_DrawLine(bm, x1,   y1,   x2-1, y1);
+       gfx_DrawLine(bm, x2-1, y1,   x2-1, y2-1);
+       gfx_DrawLine(bm, x2-1, y2-1, x1,   y2-1);
+       gfx_DrawLine(bm, x1,   y2-1, x1,   y1);
+}
+
+
+/*!
+ * Clear a rectangular area.
+ * \note The bottom-right border of the rectangle is not drawn.
+ */
+void gfx_ClearRect(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2)
+{
+       coord_t x, y;
+
+       /* Sort coords */
+       if (x1 > x2) SWAP(x1, x2);
+       if (y1 > y2) SWAP(y1, y2);
+
+       /* Clip rect to bitmap bounds */
+       if (x1 < 0)             x1 = 0;
+       if (x2 < 0)             x2 = 0;
+       if (x1 > bm->width)     x1 = bm->width;
+       if (x2 > bm->width)     x2 = bm->width;
+       if (y1 < 0)             y1 = 0;
+       if (y2 < 0)             y2 = 0;
+       if (y1 > bm->width)     y1 = bm->width;
+       if (y2 > bm->width)     y2 = bm->width;
+
+       /* Draw rectangle */
+       for (x = x1; x < x2; x++)
+               for (y = y1; y < y2; y++)
+                       BM_CLEAR(bm, x, y);
+}
+
+
+/*!
+ * Imposta un rettangolo di clipping per il disegno nella bitmap
+ */
+void gfx_SetClipRect(Bitmap *bm, coord_t minx, coord_t miny, coord_t maxx, coord_t maxy)
+{
+       ASSERT(minx < maxx);
+       ASSERT(miny < maxy);
+       ASSERT(miny >= 0);
+       ASSERT(minx >= 0);
+       ASSERT(maxx < bm->width);
+       ASSERT(maxy < bm->height);
+
+       bm->cr.xmin = minx;
+       bm->cr.ymin = miny;
+       bm->cr.xmax = maxx;
+       bm->cr.ymax = maxy;
+
+/*     DB(kprintf("cr.xmin = %d, cr.ymin = %d, cr.xmax = %d, cr.ymax = %d\n",
+               bm->cr.xMin, bm->cr.ymin, bm->cr.xmax, bm->cr.ymax);)
+*/
+}
+
+
+#ifdef CONFIG_LCD_VCOORDS
+/*!
+ * Imposta gli estremi del sistema di coordinate cartesiane rispetto
+ * al rettangolo di clipping della bitmap.
+ */
+void gfx_SetViewRect(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2)
+{
+       ASSERT(x1 != x2);
+       ASSERT(y1 != y2);
+
+       bm->orgX    = x1;
+       bm->orgY    = y1;
+       bm->scaleX  = (vcoord_t)(bm->cr.xmax - bm->cr.xmin) / (vcoord_t)(x2 - x1);   /* +1 */
+       bm->scaleY  = (vcoord_t)(bm->cr.ymax - bm->cr.ymin) / (vcoord_t)(y2 - y1);   /* +1 */
+
+/*     DB(kprintf("orgX = %f, orgY = %f, scaleX = %f, scaleY = %f\n",
+               bm->orgX, bm->orgY, bm->scaleX, bm->scaleY);)
+*/
+}
+
+
+/*!
+ * Transform a coordinate from the current reference system to a
+ * pixel offset within the bitmap.
+ */
+coord_t gfx_TransformX(Bitmap *bm, vcoord_t x)
+{
+       return bm->cr.xmin + (coord_t)((x - bm->orgX) * bm->scaleX);
+}
+
+/*!
+ * Transform a coordinate from the current reference system to a
+ * pixel offset within the bitmap.
+ */
+coord_t gfx_TransformY(Bitmap *bm, vcoord_t y)
+{
+       return bm->cr.ymin + (coord_t)((y - bm->orgY) * bm->scaleY);
+}
+
+
+/*!
+ * Draw a line from (x1;y1) to (x2;y2)
+ */
+void gfx_VDrawLine(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2)
+{
+       gfx_DrawLine(bm,
+               gfx_TransformX(bm, x1), gfx_TransformY(bm, y1),
+               gfx_TransformY(bm, x2), gfx_TransformY(bm, y2));
+}
+#endif /* CONFIG_LCD_VCOORDS */
diff --git a/mware/gfx.h b/mware/gfx.h
new file mode 100755 (executable)
index 0000000..16f34e6
--- /dev/null
@@ -0,0 +1,91 @@
+/*!
+ * \file
+ * Copyright (C) 1999 Bernardo Innocenti <bernie@develer.com>
+ * Copyright (C) 2003 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ * \author Stefano Fedrigo <aleph@develer.com>
+ *
+ * \brief General pourpose graphics routines
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ * Revision 1.4  2004/02/09 00:21:28  aleph
+ * Various gfx fixes
+ *
+ * Revision 1.3  2004/01/27 23:24:19  aleph
+ * Add new graphics primitives
+ *
+ * Revision 1.2  2004/01/07 23:33:01  aleph
+ * Change copyright email
+ *
+ * Revision 1.1  2004/01/07 19:05:31  aleph
+ * Add graphics routines
+ *
+ */
+
+#ifndef GFX_H
+#define GFX_H
+
+#include "compiler.h"
+#include <avr/pgmspace.h>
+
+
+/*! Common type for coordinates expressed in pixel units */
+typedef int coord_t;
+
+#ifdef CONFIG_LCD_VCOORDS
+/*! Common type for coordinates expressed in logical units */
+typedef float vcoord_t;
+#endif /* CONFIG_LCD_VCOORDS */
+
+
+typedef struct Rect { coord_t xmin, ymin, xmax, ymax; } Rect;
+
+
+/*! Control structure to draw in a bitmap */
+
+typedef struct Bitmap
+{
+       uint8_t *raster;        /*!< Pointer to byte array to hold the data */
+       coord_t width, height;  /*!< Width/Height in pixels */
+       coord_t penX, penY;     /*!< Current pen position MoveTo()/LineTo() */
+
+       Rect cr;                /*!< Clip drawing inside this rectangle */
+
+#ifdef CONFIG_LCD_VCOORDS
+       /*! Logical coordinate system */
+       vcoord_t orgX, orgY;
+       vcoord_t scaleX, scaleY;
+#endif /* CONFIG_LCD_VCOORDS */
+
+} Bitmap;
+
+
+/* Function prototypes */
+extern void gfx_InitBitmap(Bitmap *bm, uint8_t *raster, coord_t w, coord_t h);
+extern void gfx_ClearBitmap(Bitmap *bm);
+extern void gfx_blitBitmap_P(Bitmap *bm, const prog_uchar *raster);
+extern void gfx_DrawLine(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2);
+extern void gfx_FillRect(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2);
+extern void gfx_DrawRect(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2);
+extern void gfx_ClearRect(Bitmap *bm, coord_t x1, coord_t y1, coord_t x2, coord_t y2);
+extern void gfx_MoveTo(Bitmap *bm, coord_t x, coord_t y);
+extern void gfx_LineTo(Bitmap *bm, coord_t x, coord_t y);
+extern void gfx_SetClipRect(Bitmap *bm, coord_t xmin, coord_t ymin, coord_t xmax, coord_t ymax);
+
+#ifdef CONFIG_LCD_VCOORDS
+extern void gfx_SetViewRect(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2);
+extern coord_t gfx_TransformX(Bitmap *bm, vcoord_t x);
+extern coord_t gfx_TransformY(Bitmap *bm, vcoord_t y);
+extern void gfx_VDrawLine(Bitmap *bm, vcoord_t x1, vcoord_t y1, vcoord_t x2, vcoord_t y2);
+#endif /* CONFIG_LCD_VCOORDS */
+
+#endif /* GFX_H */
diff --git a/mware/list.c b/mware/list.c
new file mode 100755 (executable)
index 0000000..74ae040
--- /dev/null
@@ -0,0 +1,49 @@
+/*!
+ * \file
+ * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
+ * Copyright (C) 2001 Bernardo Innocenti <bernie@develer.com>
+ * All Rights Reserved.
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ *
+ * \brief List handling functions
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ */
+
+#include "list.h"
+
+
+Node *_list_rem_head(List *l)
+{
+       Node *n;
+
+       if (ISLISTEMPTY(l))
+               return (Node *)0;
+
+       n = l->head;
+       l->head = n->succ;
+       n->succ->pred = (Node *)l;
+       return n;
+}
+
+
+Node *_list_rem_tail(List *l)
+{
+       Node *n;
+
+       if (ISLISTEMPTY(l))
+               return (Node *)0;
+
+       n = l->tail;
+       l->tail = n->pred;
+       n->pred->succ = (Node *)&l->null;
+       return n;
+}
diff --git a/mware/list.h b/mware/list.h
new file mode 100755 (executable)
index 0000000..8989728
--- /dev/null
@@ -0,0 +1,122 @@
+/*!
+ * \file
+ * Copyright (C) 2001 Bernardo Innocenti <bernie@develer.com>
+ * Copyright (C) 2003 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ *
+ * \brief General pourpose double-linked lists
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ */
+#ifndef MWARE_LIST_H
+#define MWARE_LIST_H
+
+typedef struct _Node
+{
+       struct _Node *succ;
+       struct _Node *pred;
+} Node;
+
+typedef struct _List
+{
+       Node *head;
+       Node *null;
+       Node *tail;
+} List;
+
+
+/*! Template for a list of \a T  structures */
+#define DECLARE_LIST(T) \
+       struct { T *head; T *null; T *tail; }
+
+/*! Template for a node in a list of \a T structures */
+#define DECLARE_NODE(T) \
+       struct { T *succ; T *pred; }
+
+/*! Template for a node in a list of \a T structures */
+#define DECLARE_NODE_ANON(T) \
+       T *succ; T *pred;
+
+/*!
+ * Iterate over all nodes in a list. This statement defines a for cicle
+ * accepting the following parameters:
+ * \param n   node pointer to be used in each iteration
+ * \param l   pointer to list
+ */
+#define FOREACHNODE(n,l) \
+       for( \
+               (n) = (typeof(n))((l)->head); \
+               ((Node *)(n))->succ; \
+               (n) = (typeof(n))(((Node *)(n))->succ) \
+       )
+
+/*! Initialize a list */
+#define INITLIST(l) \
+       do { \
+               (l)->head = (Node *)(&(l)->null); \
+               (l)->null = NULL; \
+               (l)->tail = (Node *)(&(l)->head); \
+       } while (0)
+
+/*! Add node to list head */
+#define ADDHEAD(l,n) \
+       do { \
+               (n)->succ = (l)->head; \
+               (n)->pred = (Node *)&(l)->head; \
+               (n)->succ->pred = (n); \
+               (l)->head = (n); \
+       } while (0)
+
+/*! Add node to list tail */
+#define ADDTAIL(l,n) \
+       do { \
+               (n)->succ = (Node *)(&(l)->null); \
+               (n)->pred = (l)->tail; \
+               (n)->pred->succ = (n); \
+               (l)->tail = (n); \
+       } while (0)
+
+/*!
+ * Insert node \a n before node \a ln
+ * Note: you can't pass in a list header as \a ln, but
+ * it is safe to pass list-\>head of an empty list.
+ */
+#define INSERTBEFORE(n,ln) \
+       do { \
+               (n)->succ = (ln); \
+               (n)->pred = (ln)->pred; \
+               (ln)->pred->succ = (n); \
+               (ln)->pred = (n); \
+       } while (0)
+
+/*! Remove \a n from whatever list it is in */
+#define REMOVE(n) \
+       do { \
+               (n)->pred->succ = (n)->succ; \
+               (n)->succ->pred = (n)->pred; \
+       } while (0)
+
+/*! Tell whether a list is empty */
+#define ISLISTEMPTY(l)  ( (l)->head == (Node *)(&(l)->null) )
+
+/*! \name Extract an element from the head/tail of the list. If the list empty, return NULL. */
+/*\{*/
+#define REMHEAD(l) _list_rem_head(l)
+#define REMTAIL(l) _list_rem_tail(l)
+/*\}*/
+
+/* Prototypes for out-of-line functions */
+Node *_list_rem_head(List *l);
+Node *_list_rem_tail(List *l);
+
+
+#endif /* MWARE_LIST_H */
diff --git a/mware/sprintf.c b/mware/sprintf.c
new file mode 100755 (executable)
index 0000000..7a8e62a
--- /dev/null
@@ -0,0 +1,86 @@
+/*!
+ * \file
+ * <!--
+ * Copyright (C) 2002,2004 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ *
+ * \brief Simple sprintf() implementation based on _formatted_write()
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ * Revision 1.4  2004/04/03 20:42:27  aleph
+ * Remove duplicated defines
+ *
+ * Revision 1.3  2004/03/24 15:48:53  bernie
+ * Remove Copyright messages from Doxygen output
+ *
+ * Revision 1.2  2004/03/19 16:51:30  bernie
+ * Add PROGMEM kludge.
+ *
+ * Revision 1.1  2004/02/23 09:45:09  aleph
+ * Add missing library functions.
+ *
+ * Revision 1.1  2003/11/13 16:56:37  aleph
+ * Add first implementation of dsp firmware
+ *
+ */
+
+#include "compiler.h"
+#include "formatwr.h"
+#include <stdio.h>
+
+
+static void __str_put_char(char c, void *ptr)
+{
+       /*
+        * This Does not work on Code Warrior. Hmm...
+        *      *(*((char **)ptr))++ = c;
+        */
+
+       **((char **)ptr) = c;
+       (*((char **)ptr))++;
+}
+
+static void __null_put_char(UNUSED(char c), UNUSED(void *ptr))
+{
+       /* nop */
+}
+
+
+int PGM_FUNC(vsprintf)(char * str, const char * PGM_ATTR fmt, va_list ap)
+{
+       int result;
+
+       result = PGM_FUNC(_formatted_write)(
+                       fmt, (str ? __str_put_char : __null_put_char), &str, ap);
+
+       /* terminate string */
+       *str = '\0';
+
+       return result;
+}
+
+/* FIXME: sprintf_P is incorrectly declared in <stdio.h> */
+int PGM_FUNC(sprintf)(char *str, const char * fmt, ...)
+{
+       int result;
+       va_list ap;
+
+       va_start(ap, fmt);
+       result = PGM_FUNC(vsprintf)(str, fmt, ap);
+       va_end(ap);
+
+       /* terminate string */
+       *str = '\0';
+
+       return result;
+}
diff --git a/mware/text.c b/mware/text.c
new file mode 100755 (executable)
index 0000000..c73ef07
--- /dev/null
@@ -0,0 +1,257 @@
+/*!
+ * \file
+ * <!--
+ * Copyright (C) 1999 Bernardo Innocenti <bernie@develer.com>
+ * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ * \author Stefano Fedrigo <aleph@develer.com>
+ *
+ * \brief Text graphic routines
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ * Revision 1.17  2004/05/15 16:57:01  aleph
+ * Fixes for non-DEBUG build
+ *
+ * Revision 1.16  2004/04/03 20:42:49  aleph
+ * Add text_clear()
+ *
+ * Revision 1.15  2004/03/24 15:03:45  bernie
+ * Use explicit include paths; clean Doxygen comments
+ *
+ * Revision 1.14  2004/03/19 16:52:28  bernie
+ * Move printf() like functions from text.c to text_format.c and add PROGMEM versions.
+ *
+ * Revision 1.13  2004/03/17 18:23:32  bernie
+ * Oops.
+ *
+ * Revision 1.12  2004/03/17 18:03:22  bernie
+ * Make diagnostic message shorter
+ *
+ * Revision 1.11  2004/03/13 22:52:54  aleph
+ * documentation fixes
+ */
+
+#include "gfx.h"
+#include "font.h"
+#include "text.h"
+#include <drv/kdebug.h>
+
+/*!
+ * Flags degli stili algoritmici
+ * La routine di rendering del testo e' in grado di applicare
+ * delle semplici trasformazioni al font interno per generare
+ * automaticamente degli stili predefiniti (bold, italic,
+ * underline) a partire dal set di caratteri plain.
+ */
+static uint8_t text_styles;
+
+/*! ANSI escape sequences flag: true for ESC state on */
+static bool ansi_mode = false;
+
+
+/*!
+ * Move (imaginary) cursor to column and row specified.
+ * Next text write will start a that row and col.
+ */
+void text_moveto(struct Bitmap *bm, int row, int col)
+{
+       ASSERT(col >= 0);
+       ASSERT(col < bm->width / FONT_WIDTH);
+       ASSERT(row >= 0);
+       ASSERT(row < bm->height / FONT_HEIGHT);
+
+       bm->penX = col * FONT_WIDTH;
+       bm->penY = row * FONT_HEIGHT;
+}
+
+
+/*!
+ * Move (imaginary) cursor to coordinates specified.
+ */
+void text_setcoord(struct Bitmap *bm, int x, int y)
+{
+       bm->penX = x;
+       bm->penY = y;
+}
+
+
+/*!
+ * Render char <code>c</code>
+ */
+static int text_putglyph(char c, struct Bitmap *bm)
+{
+       const uint8_t * PROGMEM glyph;  /* font is in progmem */
+       uint8_t glyph_width;
+       uint8_t i;
+       uint8_t *buf;
+
+       /*
+        * Il carattere da stampare viene usato come indice per prelevare
+        * la prima colonna di dots del glyph all'interno del font.
+        */
+       glyph = font + (((unsigned char)c) * FONT_WIDTH);
+       glyph_width = FONT_WIDTH;
+
+       if (text_styles & STYLEF_CONDENSED)
+               --glyph_width;
+
+       if (text_styles & STYLEF_EXPANDED)
+               glyph_width *= 2;
+
+       /* The y coord is rounded at multiples of 8 for simplicity */
+       bm->penY &= ~((coord_t)7);
+
+       /* Check if glyph to write fits in the bitmap */
+       if ((bm->penX < 0) || (bm->penX + glyph_width > bm->width) ||
+               (bm->penY < 0) || (bm->penY + FONT_HEIGHT > bm->height))
+       {
+               DB(kprintf("bad coords x=%d y=%d\n", bm->penX, bm->penY);)
+               return 0;
+       }
+
+       /* Locate position where to write in the raster */
+       buf = bm->raster + bm->penY / 8 * bm->width + bm->penX;
+
+       bm->penX += glyph_width;
+
+       /* If some styles are set */
+       if (text_styles)
+       {
+               uint8_t prev_dots = 0, italic_prev_dots = 0, new_dots;
+               uint8_t dots;
+
+               /* Per ogni colonna di dot del glyph... */
+               for (i = 0; i < glyph_width; ++i)
+               {
+                       dots = pgm_read_byte(glyph);
+
+                       /* Advance to next column in glyph.
+                        * Expand: advances only once every two columns
+                        */
+                       if (!(text_styles & STYLEF_EXPANDED) || (i & 1))
+                               glyph++;
+
+                       /* Italic: get lower 4 dots from previous column */
+                       if (text_styles & STYLEF_ITALIC)
+                       {
+                               new_dots = dots;
+                               dots = (dots & 0xF0) | italic_prev_dots;
+                               italic_prev_dots = new_dots & 0x0F;
+                       }
+
+                       /* Bold: "or" pixels with the previous column */
+                       if (text_styles & STYLEF_BOLD)
+                       {
+                               new_dots = dots;
+                               dots |= prev_dots;
+                               prev_dots = new_dots;
+                       }
+
+                       /* Underlined: turn on base pixel */
+                       if (text_styles & STYLEF_UNDERLINE)
+                               dots |= 0x80;
+
+                       /* Inverted: invert pixels */
+                       if (text_styles & STYLEF_INVERT)
+                               dots = ~dots;
+
+                       /* Output dots */
+                       *buf++ = dots;
+               }
+       }
+       else /* No style: fast vanilla copy of glyph to line buffer */
+               while (glyph_width--)
+                       *buf++ = pgm_read_byte(glyph++);
+
+       return c;
+}
+
+
+/*!
+ * Render char \c c, with (currently) limited ANSI escapes
+ * emulation support and '\n' for newline.
+ */
+int text_putchar(char c, struct Bitmap *bm)
+{
+       /* Handle ANSI escape sequences */
+       if (ansi_mode)
+       {
+               switch (c)
+               {
+                       case ANSI_ESC_CLEARSCREEN:
+                               gfx_ClearBitmap(bm);
+                               bm->penX = 0;
+                               bm->penY = 0;
+                               text_style(0, STYLEF_MASK);
+                               break;
+                       DB(default:
+                               kprintf("Unknown ANSI esc code: %x\n", c);)
+               }
+               ansi_mode = false;
+       }
+       else if (c == '\033')  /* Enter ANSI ESC mode */
+       {
+               ansi_mode = true;
+       }
+       else if (c == '\n')  /* Go one line down on a line-feed */
+       {
+               if (bm->penY + FONT_HEIGHT < bm->height)
+               {
+                       bm->penY += FONT_HEIGHT;
+                       bm->penX = 0;
+               }
+       }
+       else
+       {
+               text_putglyph(c, bm);
+       }
+       return c;
+}
+
+
+/*!
+ * Clear the screen and reset cursor position
+ */
+void text_clear(struct Bitmap *bmp)
+{
+       text_putchar('\x1b', bmp);
+       text_putchar('c', bmp);
+}
+
+
+/*!
+ * Set/clear algorithmic font style bits.
+ *
+ * \param flags  Style flags to set
+ * \param mask   Mask of flags to modify
+ * \return       Old style flags
+ *
+ * Examples:
+ * Turn on bold, leave other styles alone
+ *   \code prt_style(STYLEF_BOLD, STYLEF_BOLD); \endcode
+ *
+ * Turn off bold and turn on italic, leave others as they are
+ *   \code prt_style(STYLEF_ITALIC, STYLEF_BOLD | STYLEF_ITALIC); \endcode
+ *
+ * Query current style without chaning it
+ *   \code style = prt_style(0, 0); \endcode
+ *
+ * Reset all styles (plain text)
+ *   \code prt_style(0, STYLE_MASK); \endcode
+ */
+uint8_t text_style(uint8_t flags, uint8_t mask)
+{
+       uint8_t old = text_styles;
+       text_styles = (text_styles & ~mask) | flags;
+       return old;
+}
diff --git a/mware/text.h b/mware/text.h
new file mode 100755 (executable)
index 0000000..2cd1cac
--- /dev/null
@@ -0,0 +1,98 @@
+/*!
+ * \file
+ * Copyright (C) 1999 Bernardo Innocenti <bernie@develer.com>
+ * Copyright (C) 2003 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ * \author Stefano Fedrigo <aleph@develer.com>
+ *
+ * \brief Text graphic routines
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ * Revision 1.9  2004/04/03 20:42:49  aleph
+ * Add text_clear()
+ *
+ * Revision 1.8  2004/03/19 16:52:28  bernie
+ * Move printf() like functions from text.c to text_format.c and add PROGMEM versions.
+ *
+ * Revision 1.7  2004/03/17 17:30:30  bernie
+ * Add GCC format checks to printf()-like functions.
+ *
+ * Revision 1.6  2004/02/21 21:40:20  aleph
+ * Various small fixes
+ *
+ * Revision 1.5  2004/02/18 11:50:10  aleph
+ * Add right alignment to xprintf
+ *
+ * Revision 1.4  2004/01/13 12:15:28  aleph
+ * Move font table in program memory; add font.h
+ *
+ * Revision 1.3  2004/01/13 00:06:47  aleph
+ * Fix clipping and ANSI esc bug, add text_xprintf()
+ *
+ * Revision 1.2  2004/01/08 18:03:12  aleph
+ * Add text functions to set coordinates
+ *
+ * Revision 1.1  2004/01/07 23:31:54  aleph
+ * Add text routines
+ *
+ */
+
+#ifndef TEXT_H
+#define TEXT_H
+
+#include "compiler.h"
+#include <stdarg.h>
+
+/* Style flags */
+#define STYLEF_BOLD        BV(0)
+#define STYLEF_ITALIC      BV(1)
+#define STYLEF_UNDERLINE   BV(2)
+#define STYLEF_INVERT      BV(3)
+#define STYLEF_EXPANDED    BV(4)
+#define STYLEF_CONDENSED   BV(5)
+#define STYLEF_STRIKEOUT   BV(6)  /* Not implemented */
+
+#define STYLEF_MASK \
+       (STYLEF_BOLD | STYLEF_ITALIC | STYLEF_UNDERLINE | \
+       STYLEF_EXPANDED | STYLEF_CONDENSED | STYLEF_INVERT)
+
+/* Flags for text_xprintf() */
+#define TEXT_NORMAL   0       /*!< Normal mode */
+#define TEXT_FILL     BV(0)   /*!< Fill rest of line with spaces */
+#define TEXT_CENTER   BV(1)   /*!< Center string in line */
+#define TEXT_INVERT   BV(2)   /*!< Inverted mode */
+#define TEXT_RIGHT    BV(3)   /*!< Right aligned */
+
+/* Escape sequences codes */
+#define ANSI_ESC_CLEARSCREEN 'c'
+
+
+
+/* Fwd decl */
+struct Bitmap;
+
+void text_moveto(struct Bitmap *bm, int row, int col);
+void text_setcoord(struct Bitmap *bm, int x, int y);
+int text_putchar(char c, struct Bitmap *bm);
+int text_puts(const char *str, struct Bitmap *bm);
+int text_vprintf(struct Bitmap *bm, const char *fmt, va_list ap);
+int text_printf(struct Bitmap *bm, const char *fmt, ...) FORMAT(__printf__, 2, 3);
+int text_xprintf(struct Bitmap *bm, uint8_t row, uint8_t col, uint8_t mode, const char *fmt, ...) FORMAT(__printf__, 5, 6);
+uint8_t text_style(uint8_t flags, uint8_t mask);
+void text_clear(struct Bitmap *bm);
+
+int text_puts_P(const char * PROGMEM str, struct Bitmap *bm);
+int text_vprintf_P(struct Bitmap *bm, const char * PROGMEM fmt, va_list ap);
+int text_printf_P(struct Bitmap *bm, const char * PROGMEM fmt, ...) FORMAT(__printf__, 2, 3);
+int text_xprintf_P(struct Bitmap *bm, uint8_t row, uint8_t col, uint8_t mode, const char * PROGMEM fmt, ...) FORMAT(__printf__, 5, 6);
+
+#endif /* TEXT_H */
diff --git a/mware/text_format.c b/mware/text_format.c
new file mode 100755 (executable)
index 0000000..6defd13
--- /dev/null
@@ -0,0 +1,110 @@
+/*!
+ * \file
+ *
+ * <!--
+ * Copyright (C) 1999 Bernardo Innocenti <bernie@develer.com>
+ * Copyright (C) 2003,2004 Develer S.r.l. (http://www.develer.com/)
+ * All Rights Reserved.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Bernardo Innocenti <bernie@develer.com>
+ * \author Stefano Fedrigo <aleph@develer.com>
+ *
+ * \brief printf-family routines for text output
+ */
+
+/*
+ * $Log$
+ * Revision 1.1  2004/05/23 15:43:16  bernie
+ * Import mware modules.
+ *
+ * Revision 1.2  2004/03/26 18:50:50  bernie
+ * Move _PROGMEM stuff to compiler.h
+ *
+ * Revision 1.1  2004/03/19 16:52:28  bernie
+ * Move printf() like functions from text.c to text_format.c and add PROGMEM versions.
+ *
+ */
+
+#include "text.h"
+#include "formatwr.h" /* _formatted_write() */
+#include "font.h"
+#include "gfx.h"
+#include <stdarg.h>
+#include <string.h> /* strlen */
+
+/*!
+ * Render string <code>str</code> in bitmap
+ */
+int PGM_FUNC(text_puts)(const char * PGM_ATTR str, struct Bitmap *bm)
+{
+       char c;
+
+       while ((c = PGM_READ_CHAR(str++)))
+               text_putchar(c, bm);
+
+       return 0;
+}
+
+
+int PGM_FUNC(text_vprintf)(struct Bitmap *bm, const char * PGM_ATTR fmt, va_list ap)
+{
+       return PGM_FUNC(_formatted_write)(fmt, (void (*)(char, void *))text_putchar, bm, ap);
+}
+
+
+int PGM_FUNC(text_printf)(struct Bitmap *bm, const char * PGM_ATTR fmt, ...)
+{
+       int len;
+
+       va_list ap;
+       va_start(ap, fmt);
+       len = PGM_FUNC(text_vprintf)(bm, fmt, ap);
+       va_end(ap);
+
+       return len;
+}
+
+
+int PGM_FUNC(text_xprintf)(struct Bitmap *bm,
+               uint8_t row, uint8_t col, uint8_t mode, const char * PGM_ATTR fmt, ...) 
+{
+       int len;
+       uint8_t oldstyle = 0;
+       va_list ap;
+
+       va_start(ap, fmt);
+
+       text_moveto(bm, row, col);
+
+       if (mode & TEXT_INVERT)
+               oldstyle = text_style(STYLEF_INVERT, STYLEF_INVERT);
+
+       if (mode & (TEXT_CENTER | TEXT_RIGHT))
+       {
+               uint8_t pad;
+
+               pad = bm->width/FONT_WIDTH - PGM_FUNC(vsprintf)(NULL, fmt, ap);
+
+               if (mode & TEXT_CENTER)
+                       pad /= 2;
+
+               while (pad--)
+                       text_putchar(' ', bm);
+       }
+
+       len = PGM_FUNC(text_vprintf)(bm, fmt, ap);
+       va_end(ap);
+
+       if (mode & (TEXT_FILL | TEXT_CENTER))
+               while (bm->penX + FONT_WIDTH < bm->width)
+                       text_putchar(' ', bm);
+
+       if (mode & TEXT_INVERT)
+               text_style(oldstyle, STYLEF_MASK);
+
+       return len;
+}
+